Skip to main content

systemd: Creating a Unit File for Service Autostart on Linux

VDS / VPS · 19.04.2026 · 4 min read
Illustration for “systemd: Creating a Unit File for Service Autostart on Linux”

systemd is the initialization and service management system in modern Linux distributions (Ubuntu 16.04+, Debian 8+, CentOS 7+). A unit file describes how to start and stop a service.

Minimal Unit File

# /etc/systemd/system/myapp.service

[Unit]
Description=My Application
After=network.target

[Service]
ExecStart=/usr/bin/node /opt/myapp/app.js
WorkingDirectory=/opt/myapp
User=www-data
Restart=on-failure

[Install]
WantedBy=multi-user.target

Key [Unit] Directives

DirectiveValue
DescriptionService description
After=network.targetStart after network initialization
After=mysql.serviceStart after MySQL
Requires=docker.serviceHard dependency
Wants=redis.serviceSoft dependency

Key [Service] Directives

[Service]
Type=simple           # Type: simple, forking, oneshot, notify
ExecStart=/path/cmd   # Start command
ExecStop=/path/stop   # Stop command (optional)
ExecReload=/bin/kill -HUP $MAINPID  # Reload config
WorkingDirectory=/app # Working directory
User=appuser          # Run as this user
Group=appgroup        # Group
Environment=NODE_ENV=production  # Environment variables
EnvironmentFile=/etc/myapp.env   # File with variables

# Restart policy
Restart=always        # Always restart
Restart=on-failure    # Only on failure
RestartSec=5s         # Pause before restart

# Resource limits
LimitNOFILE=65536     # Open file limit
MemoryLimit=512M      # Memory limit

Activation and Management

# Reload unit files
sudo systemctl daemon-reload

# Enable autostart
sudo systemctl enable myapp

# Start
sudo systemctl start myapp

# Check status
sudo systemctl status myapp

# View logs
sudo journalctl -u myapp -f

# Today's logs
sudo journalctl -u myapp --since today

Example: Python Application with virtualenv

>[Unit]
Description=Python Flask App
After=network.target postgresql.service

[Service]
Type=simple
User=flask
WorkingDirectory=/opt/flask_app
Environment=FLASK_ENV=production
ExecStart=/opt/flask_app/venv/bin/gunicorn     --workers 4     --bind 0.0.0.0:8000     app:application
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
💡 Storing secrets: Don't put passwords in the unit file — it's readable by everyone. Use EnvironmentFile=/etc/myapp.env with 600 permissions. Even better — systemd credentials or HashiCorp Vault.

Common systemd Unit File Errors

MessageCause
Failed to start myapp.service: Unit not foundThe file is not in /etc/systemd/system/, or systemctl daemon-reload was never run after creating it
Main process exited, code=exited, status=203/EXECThe ExecStart path is wrong, or the file lacks execute permission — run chmod +x
Failed with result 'exit-code' right after startThe application crashes without an environment variable that lived in .bashrc — systemd does not read a user's shell config files
Start request repeated too quicklyRestart=always combined with a constantly crashing service exceeds the StartLimitBurst limit within StartLimitIntervalSec; systemd temporarily blocks the autostart
Failed to determine user credentials: No such processThe user named in User= does not exist on the system — a typo in the name, or the user was never created beforehand

When a systemd Unit Is Not the Right Tool

  • You need to run a process without root access to the server — creating a file under /etc/systemd/system requires privileges that most shared hosting plans do not grant; only cron is available there for scheduled work
  • The application needs to scale across several instances with load balancing — one unit file runs one process; several copies need template units (@.service) or a separate orchestrator such as Docker Compose
  • The service runs inside a minimal Docker container — systemd usually is not running there as PID 1, so you need a different supervisor (tini, s6, a built-in healthcheck)
  • You need one cross-platform service definition for both Linux and Windows — systemd is Linux-specific; Windows needs a separate mechanism such as NSSM

Verifying the Result

Confirming the service starts once is not enough — it matters just as much that it survives a crash and does not hit memory limits. The system logs are covered in the article on journalctl and rsyslog, and a common cause of processes suddenly stopping is covered in the article on the Linux OOM killer.

# Confirm the service actually restarts after a crash
sudo systemctl kill -s SIGKILL myapp
sleep 3
sudo systemctl status myapp | grep Active

# Check whether the process is hitting a memory limit
journalctl -u myapp | grep -i "oom\|killed"
Was this article helpful?
← Back to Knowledge Base Ask Support