Systemd Service Won't Start – Check These 3 Things First
Your systemd service failed to start. Usually it's a typo in the unit file, a missing dependency, or a permission issue. Here's the fix.
Look, I've been there. You run systemctl start myapp.service, it silently fails, and you stare at the terminal wondering why. Don't panic. Nine times out of ten, the problem is one of three things. Let's check them in order.
Step 1: Check the Status and Logs
First, get the actual error. Run:
systemctl status myapp.service --no-pager
You'll probably see "exit code 1" or "failed with result exit-code". That tells you nothing by itself. Now run:
journalctl -u myapp.service --no-pager -n 50
This shows the last 50 lines of logs for that service. Look for lines starting with "ERROR" or "FATAL". That's where the real clue lives.
Step 2: Fix the Three Most Common Causes
1. The ExecStart Path is Wrong
This is the number one mistake. I've seen it a hundred times. Open the unit file:
sudo systemctl edit --full myapp.service
Check the ExecStart= line. Does the binary actually exist at that path? Test it:
ls -la /usr/local/bin/myapp
If the file is missing or the path is wrong, fix it. After you save the file, run:
sudo systemctl daemon-reload
sudo systemctl start myapp.service
You should see "active (running)" when you check the status.
2. Permissions – Your Service Can't Read Its Files
This one bites everyone. Your service runs as a specific user (often nobody or a custom user). If the binary or config files aren't readable by that user, the service dies instantly.
Check the User= and Group= lines in the unit file. Then check file permissions:
sudo -u myappuser /usr/local/bin/myapp
If that command fails with "Permission denied", fix it:
sudo chown myappuser:myappgroup /usr/local/bin/myapp
sudo chmod 755 /usr/local/bin/myapp
Also check logs, config files, and any directories the service writes to. They need write permission for the service user.
3. A Dependency Didn't Start – Network, Database, or Mount
Your service probably needs something else to be running first. PostgreSQL, Redis, or just network connectivity. If it's trying to connect to a database that's down, it'll crash.
Check the After= and Requires= lines in the unit file. A typical web app might need:
After=network.target postgresql.service
Requires=postgresql.service
Make sure those services are actually running:
systemctl status postgresql.service
If they're not, start them first, then start your service again.
Step 3: Why This Fix Works
Systemd is brutally literal. It does exactly what the unit file says, and nothing more. If the path is wrong, it can't guess. If permissions lock out the service user, it won't override them. If a dependency isn't met, it stops immediately. These three checks cover 90% of failures because they hit the basic requirements: a file must exist, must be readable, and must have its prerequisites satisfied.
The real fix is to stop guessing and start reading logs. journalctl is your best friend. Use it every time.
Less Common Variations
| Error Pattern | What's Actually Wrong | Fix |
|---|---|---|
start-pre or start-post script fails |
A command in ExecStartPre= or ExecStartPost= exits non-zero |
Check those scripts separately. Run them by hand with the same user. Common issue: a script references a missing file or variable. |
Failed to start: Unit myapp.service is masked |
Someone ran systemctl mask on it, making it unstartable |
sudo systemctl unmask myapp.service |
Failed to start: Unit file is invalid |
A syntax error in the unit file – missing = sign, stray character, or wrong section name |
Run systemd-analyze verify /etc/systemd/system/myapp.service. It tells you the exact line with the error. |
Timeout or start operation timed out |
Your ExecStart command doesn't daemonize or takes too long to start |
Increase TimeoutStartSec= (default is 90 seconds). Or better, make your app start properly – systemd expects the process to stay in foreground. |
Failed with result 'signal' |
The service process was killed by a signal (like SIGSEGV or SIGKILL) | This is usually a bug in your application – segfault, OOM killer, or manual kill. Check dmesg for kernel messages. |
Prevention – Stop This From Happening Again
Don't write unit files by hand from memory. Use templates. On Ubuntu, /usr/share/doc/systemd/examples/ has solid examples. On RHEL, check /usr/lib/systemd/system/ for working services you can copy.
Always run systemd-analyze verify on a new unit file before enabling it:
systemd-analyze verify /etc/systemd/system/myapp.service
If it says "PASS: 0 errors", you're good. If it throws errors, fix them first.
Also, use a dedicated system user for each service. Don't run everything as root. Create a user like myappuser with limited permissions:
sudo useradd -r -s /usr/sbin/nologin myappuser
Then set User=myappuser in the unit file. This solves permission issues early.
Finally, test the service manually as that user. If the binary works when you run it by hand, it'll work as a service. That one habit has saved me countless hours.
If you're still stuck after all this, paste the output of journalctl -u myapp.service -n 100 into a search engine. Someone else had the same problem. You'll find the answer.
Was this solution helpful?