Creating Custom Services
Any long-running process that should start automatically, restart on failure, and integrate with system logging needs a systemd service unit. Running applications with nohup or screen is a workaround, not a solution — it does not survive reboots and does not restart on crash. Writing a proper service unit takes five minutes and is the correct production approach.
When you need a custom service
- A Node.js/Python/Go application that should run as a daemon
- A custom script that must run at boot
- Any process that should restart automatically if it crashes
- Applications installed outside of apt (no systemd unit provided)
Writing the service unit
# Create the unit file
sudo nano /etc/systemd/system/myapp.service
/etc/systemd/system/myapp.service (Node.js example)
[Unit]
Description=My Node.js Application
Documentation=https://github.com/myorg/myapp
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node /opt/myapp/server.js
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=5
StartLimitIntervalSec=60
StartLimitBurst=3
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
# Environment
EnvironmentFile=/etc/myapp/env
[Install]
WantedBy=multi-user.target
/etc/myapp/env (environment variables — keep secrets out of unit file)
NODE_ENV=production
PORT=3000
DATABASE_URL=postgresql://myapp:password@localhost/myapp
# Create the application user
sudo useradd -r -s /bin/false -d /opt/myapp myapp
sudo chown -R myapp:myapp /opt/myapp
Restart behavior
| Restart= value | When to restart |
|---|---|
| no | Never (default) |
| on-success | Only if exit code is 0 |
| on-failure | If exit code is non-zero or killed by signal |
| always | Always restart regardless of exit code |
| on-abnormal | If killed by signal, timeout, watchdog |
# Prevent restart loops with StartLimitBurst and StartLimitIntervalSec
# Example: allow 3 restarts within 60 seconds, then stop trying
StartLimitIntervalSec=60
StartLimitBurst=3
# If the service hits the restart limit, it enters 'failed' state
# Manually reset it:
sudo systemctl reset-failed myapp
sudo systemctl start myapp
Security hardening directives
# Add these to [Service] to reduce attack surface:
NoNewPrivileges=yes # Process cannot gain privileges
ProtectSystem=strict # /usr, /boot, /etc are read-only
ProtectHome=yes # /home, /root inaccessible
PrivateTmp=yes # Isolated /tmp
ReadWritePaths=/opt/myapp # Only this path is writable
CapabilityBoundingSet= # Drop ALL capabilities (for non-privileged services)
💡 TIP: Run
systemd-analyze security myapp.serviceto get a security score for your unit and specific recommendations. A score of MEDIUM or better (below 7.0) is reasonable for most services.
Installing and testing
# After creating the unit file, reload systemd to recognize it
sudo systemctl daemon-reload
# Verify systemd accepts the unit file syntax
systemd-analyze verify /etc/systemd/system/myapp.service
# Start and enable
sudo systemctl enable --now myapp
# Check it started correctly
sudo systemctl status myapp
sudo journalctl -u myapp -n 50 --no-pager
# Test restart behavior (simulate a crash)
sudo kill -9 $(systemctl show myapp -p MainPID | cut -d= -f2)
sleep 6
sudo systemctl status myapp # Should show restarted
Conclusion
A minimal but production-correct service unit needs: the correct Type= (usually simple), a dedicated non-root user via User=, Restart=always with RestartSec=5 for automatic recovery, environment variables in a separate EnvironmentFile= (never hardcode passwords in unit files), and WantedBy=multi-user.target in [Install]. Run systemd-analyze verify before deploying, and always test the restart behavior by manually killing the process and confirming systemd brings it back.
FAQ
Is Creating Custom Services important for Ubuntu administrators?+
Yes. It supports practical Ubuntu administration because it connects directly to server reliability, security, troubleshooting, or daily operations.
Should I practice this on a live server?+
Use a lab VM first. After you understand the command output and rollback path, apply the workflow carefully on real systems.
What should I do after reading this article?+
Run the practice commands, write down what each one shows, and continue to the next article in the Ubuntu roadmap.
Need help with Ubuntu administration?
Work directly with Muhammad Irfan Aslam for Ubuntu Server, Linux, cloud, Docker, DevOps, CI/CD, or infrastructure troubleshooting support.
Hire Me for Support