{"id":1466,"date":"2026-10-22T23:05:13","date_gmt":"2026-10-22T23:05:13","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=1466"},"modified":"2026-10-22T23:05:13","modified_gmt":"2026-10-22T23:05:13","slug":"diagnosing-systemd-service-start-failures-after-reboot","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/","title":{"rendered":"systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">A unit that starts fine when you type <code>systemctl start<\/code> and dies after a reboot has one of four causes, and each has a different fix. The efficient way to narrow it is not to read the unit file top to bottom but to query systemd for what it actually did at boot: whether the unit was pulled in, whether its dependencies were satisfied at that moment, and what exit status it produced when it was.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This page works through that sequence using only <code>systemctl<\/code> and <code>journalctl<\/code>. It assumes a systemd 252 or newer guest, which is what Debian 12, Ubuntu 24.04 and current RHEL 9 ship with. If you are sizing an instance to run these services on, our <a href=\"https:\/\/virtualserversvps.com\/\">VPS plan sizing by workload<\/a> covers how much RAM each service class needs beyond the unit file itself.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">First: Distinguish the Four Failure Classes<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Symptom after reboot<\/th><th>Cause<\/th><th>Confirming command<\/th><\/tr><\/thead><tbody><tr><td>Unit not in <code>systemctl list-units<\/code> at all<\/td><td>Never enabled<\/td><td><code>systemctl is-enabled myapp<\/code> &rarr; <code>disabled<\/code><\/td><\/tr><tr><td>Unit listed but <code>inactive (dead)<\/code><\/td><td>Started but exited 0, or Requires= dependency vanished<\/td><td><code>journalctl -b -u myapp<\/code><\/td><\/tr><tr><td><code>failed<\/code> with exit code 1<\/td><td>Application error at startup, often missing mount or network<\/td><td><code>systemctl show -p Result,ExecMainStatus myapp<\/code><\/td><\/tr><tr><td>Active, then dead minutes later<\/td><td>Ordering race: filesystem or network not ready when the unit ran<\/td><td><code>systemd-analyze critical-chain myapp.service<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Identify which row you are in before changing anything. The fix for row one (<code>systemctl enable<\/code>) is wrong and mildly harmful for row four, where enabling is already done and the problem is ordering.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Read the Boot-Scoped Journal, Not the Current One<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The most common journalctl mistake is omitting <code>-b<\/code>. Without it you get every boot interleaved, and a failure from three weeks ago can look like the cause of today&#8217;s problem. List boots first, then filter.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl --list-boots | tail -5\njournalctl -b -1 -u myapp --no-pager | tail -40\njournalctl -b -u myapp -p warning --no-pager<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>-b -1<\/code> is the previous boot \u2014 the one that preceded the last reboot. <code>-b -2<\/code> goes back further. <code>-p warning<\/code> filters to severity warning and above, which removes the informational chatter that usually makes the useful line hard to find. Add <code>-o short-precise<\/code> when you need millisecond ordering between two units.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Ask systemd Why, Not the Application<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The application&#8217;s error message is often the second-order symptom. systemd&#8217;s own record of the start attempt contains the dependency that failed and the exact result code.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>systemctl show myapp.service -p Result -p ExecMainStatus -p ExecMainCode \\\n  -p ActiveEnterTimestamp -p InactiveEnterTimestamp\nsystemctl status myapp.service --no-pager -l\nsystemd-analyze critical-chain myapp.service<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>Result=exit-code<\/code> with <code>ExecMainStatus=1<\/code> means the process ran and failed. <code>Result=resources<\/code> means a limit was hit. <code>Result=timeout<\/code> \u2014 with a service that takes 40 seconds to open a database connection \u2014 means <code>TimeoutStartSec<\/code> is too short, which is common on busy hosts at boot when every service starts at once. <code>Result=dependency<\/code> means something it Requires never came up.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Check the Three Ordering Traps<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Almost all &#8220;works manually, fails at boot&#8221; reports come from one of these. Each has a specific unit-file fix.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[Unit]\nDescription=My application\nAfter=network-online.target mysql.service\nWants=network-online.target\nRequires=mysql.service\nStartLimitIntervalSec=300\nStartLimitBurst=5\n\n[Service]\nUser=app\nWorkingDirectory=\/srv\/app\nExecStart=\/srv\/app\/bin\/server --config \/etc\/app\/config.yml\nRestart=on-failure\nRestartSec=5\n# Give slow dependencies time on a loaded host\nTimeoutStartSec=90\n\n[Install]\nWantedBy=multi-user.target<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Trap 1 \u2014 <code>network.target<\/code> instead of <code>network-online.target<\/code>.<\/strong> <code>network.target<\/code> only means the network stack was configured, not that an address exists. Services that bind to a specific IP or resolve a hostname at startup need <code>Wants=network-online.target<\/code> plus <code>After=network-online.target<\/code>.<\/li>\n\n<li><strong>Trap 2 \u2014 database dependency without a health check.<\/strong> <code>Requires=mysql.service<\/code> is satisfied when the unit becomes active, which for MySQL is before it accepts connections. Add an <code>ExecStartPre<\/code> wait, or a drop-in with <code>ExecStartPre=\/usr\/local\/bin\/wait-for-port 127.0.0.1 3306<\/code>.<\/li>\n\n<li><strong>Trap 3 \u2014 <code>WantedBy=default.target<\/code> on a system service.<\/strong> That places the unit in the user-session shutdown order, not the boot order, and it frequently ends up masked or skipped. Use <code>multi-user.target<\/code>.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Test a Boot Without Rebooting<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The fastest iteration loop is a private systemd instance with a modified root, so a broken unit cannot take down the SSH session you are debugging through.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl daemon-reload\n\n# Validate syntax before you trust it\nsystemd-analyze verify \/etc\/systemd\/system\/myapp.service\n\n# Simulate the boot ordering without rebooting\nsystemd-analyze critical-chain myapp.service --no-pager\nsystemd-analyze plot &gt; \/tmp\/boot.svg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>systemd-analyze verify<\/code> catches misspelled directives, which systemd otherwise logs at debug level and ignores \u2014 a silent failure mode that produces exactly the &#8220;works manually&#8221; symptom. If you need a real cold-boot test on a production host, take a snapshot first; <code>systemctl isolate rescue.target<\/code> and back is faster than a full reboot but will stop every non-essential unit.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Watch a Start in Real Time<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When the failure is intermittent, attach a journal tail before you trigger the restart so you capture the whole attempt, including the units that were scheduled around it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -f -u myapp -u mysql -u systemd-udevd -o short-precise &amp;\nsudo systemctl restart myapp\nsystemctl show myapp -p NRestarts -p ExecMainStartTimestampMonotonic -p ExecMainExitTimestampMonotonic<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>NRestarts<\/code> incrementing quickly with <code>Restart=on-failure<\/code> means the unit is in a restart loop that <code>StartLimitBurst<\/code> will eventually stop. If the unit reaches <code>failed<\/code> and stays there, check <code>systemctl show -p Result<\/code> \u2014 a value of <code>start-limit-hit<\/code> tells you the loop already happened and the current status is the aftermath, not the cause.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6: Make the Next Boot Prove Itself<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Enabling a unit is a promise about the next reboot. Verify the promise without taking an outage by checking the install target links directly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>systemctl is-enabled myapp\nls -l \/etc\/systemd\/system\/multi-user.target.wants\/ | grep myapp\nsystemctl list-dependencies multi-user.target --no-pager | grep -c myapp<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then add a post-boot assertion timer that reports any unit that is not active within two minutes of boot. It catches the silent cases \u2014 a unit that starts, runs for a minute, and exits \u2014 which no reboot-and-look approach reliably finds.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/usr\/bin\/env bash\n# \/usr\/local\/sbin\/postboot-assert.sh\nsleep 120\nbad=0\nfor u in myapp nginx redis-server mysql; do\n  systemctl is-active --quiet \"$u\" || { echo \"DOWN: $u\"; bad=1; }\ndone\n[ $bad -eq 0 ] || journalctl -b --no-pager -u \"$u\" -n 30\nexit $bad<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Quick Reference: Journal Filters Worth Memorising<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Goal<\/th><th>Command<\/th><\/tr><\/thead><tbody><tr><td>Everything from this boot<\/td><td><code>journalctl -b<\/code><\/td><\/tr><tr><td>Previous boot only<\/td><td><code>journalctl -b -1<\/code><\/td><\/tr><tr><td>One unit, warnings and up<\/td><td><code>journalctl -b -u myapp -p warning<\/code><\/td><\/tr><tr><td>By priority, all units<\/td><td><code>journalctl -p err -b<\/code><\/td><\/tr><tr><td>Follow live, microsecond order<\/td><td><code>journalctl -f -o short-precise<\/code><\/td><\/tr><tr><td>Since a timestamp<\/td><td><code>journalctl --since \"2026-10-23 14:00\" --until \"15:00\"<\/code><\/td><\/tr><tr><td>Field-based (json)<\/td><td><code>journalctl -o json-pretty -u myapp<\/code><\/td><\/tr><tr><td>Prioritised boot summary<\/td><td><code>systemd-analyze blame<\/code> \/ <code>critical-chain<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Two habits eliminate most of this class of incident. Enable and verify in the same session rather than weeks apart, and treat ordering directives as assertions to be tested \u2014 <code>After=<\/code> does not mean &#8220;wait for it to be ready&#8221;, only &#8220;do not start first&#8221;. For the sizing side of running several services on one small guest, our <a href=\"https:\/\/virtualserversvps.com\/\">VPS plan sizing guide by workload<\/a> lists RAM and CPU floors per service class.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A unit that starts fine when you type systemctl start and dies after a reboot has one of four causes, and each has a different fix. The efficient way to&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":0,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-1466","post","type-post","status-publish","format-standard","hentry","category-performance-optimization"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics - Virtual Servers VPS Blog<\/title>\n<meta name=\"description\" content=\"A unit that starts fine when you type systemctl start and dies after a reboot has one of four causes, and each has a different fix. The efficient way to\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics\" \/>\n<meta property=\"og:description\" content=\"systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-22T23:05:13+00:00\" \/>\n<meta name=\"author\" content=\"Virtual-Servers-Vps-Editor\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Virtual-Servers-Vps-Editor\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/\",\"name\":\"systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-10-22T23:05:13+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"description\":\"A unit that starts fine when you type systemctl start and dies after a reboot has one of four causes, and each has a different fix. The efficient way to\",\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/\",\"name\":\"Virtual Servers VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\",\"name\":\"Virtual-Servers-Vps-Editor\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"caption\":\"Virtual-Servers-Vps-Editor\"},\"sameAs\":[\"https:\/\/virtualserversvps.com\/blog\"],\"url\":\"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics - Virtual Servers VPS Blog","description":"A unit that starts fine when you type systemctl start and dies after a reboot has one of four causes, and each has a different fix. The efficient way to","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/","og_locale":"en_US","og_type":"article","og_title":"systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics","og_description":"systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics","og_url":"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-10-22T23:05:13+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/","url":"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/","name":"systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-10-22T23:05:13+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"description":"A unit that starts fine when you type systemctl start and dies after a reboot has one of four causes, and each has a different fix. The efficient way to","breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/diagnosing-systemd-service-start-failures-after-reboot\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"systemd Services That Die After a Reboot: journalctl and Ordering Diagnostics"}]},{"@type":"WebSite","@id":"https:\/\/virtualserversvps.com\/blog\/#website","url":"https:\/\/virtualserversvps.com\/blog\/","name":"Virtual Servers VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0","name":"Virtual-Servers-Vps-Editor","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","caption":"Virtual-Servers-Vps-Editor"},"sameAs":["https:\/\/virtualserversvps.com\/blog"],"url":"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/"}]}},"_links":{"self":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1466","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/comments?post=1466"}],"version-history":[{"count":1,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1466\/revisions"}],"predecessor-version":[{"id":1468,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1466\/revisions\/1468"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=1466"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=1466"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=1466"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}