What Is a Unit File in Simple Terms
A unit file is a recipe card for systemd. It tells systemd everything it needs to know about a service: what to run, who to run it as, what it depends on, what to do if it crashes, and whether to start it at boot.
Before systemd, starting a service required writing a shell script with dozens of lines handling process management, PID files, logging, and restart logic. A systemd unit file does all of that in 15-20 lines of declarative configuration.
Unit file structure:
/etc/systemd/system/payment-service.service+----------------------------------------+| [Unit] || Description=Payment Processing API || After=postgresql.service |+----------------------------------------+| [Service] || User=payment-svc || ExecStart=/usr/bin/node index.js || EnvironmentFile=/etc/payment/env || Restart=on-failure || RestartSec=5 |+----------------------------------------+| [Install] || WantedBy=multi-user.target |+----------------------------------------+How It Works
Unit files are INI-style configuration with three sections. systemd reads them from specific directories, with later directories overriding earlier ones.
Unit file search order (later wins):/usr/lib/systemd/system/ Installed by packages -- do not edit/etc/systemd/system/ Admin overrides -- edit theseComplete unit file anatomy:
[Unit]## Description shown in systemctl statusDescription=My Payment Service ## Start after these units are activeAfter=network.target postgresql.service redis.service ## If these fail, this unit fails tooRequires=postgresql.service ## If these fail, try to start anywayWants=redis.service [Service]## Run as this user and group (never root)User=payment-svcGroup=payment-svc ## Working directoryWorkingDirectory=/opt/payment-service ## The command to runExecStart=/usr/bin/node /opt/payment-service/index.js ## Command to gracefully stop (optional -- default is SIGTERM)ExecStop=/bin/kill -TERM $MAINPID ## Command to reload config without restartingExecReload=/bin/kill -HUP $MAINPID ## Load environment variables from a file## This is how secrets stay out of unit filesEnvironmentFile=/etc/payment-service/env ## Or set individual environment variablesEnvironment=NODE_ENV=productionEnvironment=PORT=4000 ## Restart policy## on-failure: restart if exits with non-zero or killed by signalRestart=on-failureRestartSec=5 ## wait 5 seconds before restartingStartLimitInterval=60 ## within 60 secondsStartLimitBurst=3 ## allow max 3 restarts before giving up ## Service type## simple: ExecStart process IS the service (most common)## forking: service forks and the parent exits (old-style daemons)## oneshot: runs once and exits (good for setup scripts)Type=simple ## File descriptor limitsLimitNOFILE=65536 ## override ulimit for this service [Install]## Which target to start this service in## multi-user.target = standard server mode (no GUI)WantedBy=multi-user.targetOverriding package unit files without editing them:
## Create an override directorysudo mkdir -p /etc/systemd/system/nginx.service.d/ ## Create an override file -- only the sections you changesudo tee /etc/systemd/system/nginx.service.d/override.conf << 'EOF'[Service]LimitNOFILE=65536Restart=alwaysRestartSec=3EOF ## Reload and restartsudo systemctl daemon-reloadsudo systemctl restart nginx ## The easier way -- systemctl edit opens editor and creates overridesudo systemctl edit nginxPractical Commands
## Show full unit file contentsystemctl cat nginx ## Show all overrides appliedsystemctl cat nginx | head -5 ## first line shows which file ## Validate unit file syntax before applyingsystemd-analyze verify /etc/systemd/system/myapp.service ## Show unit file locationsystemctl show -p FragmentPath nginx ## List all unit files and their statesystemctl list-unit-files --type=serviceTroubleshooting
| Symptom | Command | What to Look For |
|---|---|---|
| Unit file change ignored | sudo systemctl daemon-reload |
Must reload after any file edit |
| Service exits immediately | journalctl -u service -n 20 |
Exit code and error message |
| Wrong user running service | systemctl show service -p User |
User directive in unit file |
| Environment not loading | systemctl show service -p EnvironmentFiles |
Path and whether file exists |
PLACEMENT PRO TIP**Tip:** Use `systemd-analyze verify /etc/systemd/system/myapp.service` before reloading. It catches syntax errors in unit files before you try to start the service. A syntax error can make the service silently do nothing or fail to load.
COMMON MISTAKE / WARNING**Security:** Never put secrets (passwords, API keys) directly in unit files. Unit files are readable by any user with `systemctl cat`. Use `EnvironmentFile=/etc/service/env` to load secrets from a file with restricted permissions (chmod 640, chown root:service-group). The environment file is not readable by ordinary users but is loaded by systemd before starting the service.