Environment Variables in systemd Services
Master environment variable configuration in systemd unit files. Compare inline Environment= vs EnvironmentFile=, learn variable precedence, and best practices for secrets management.
Detailed Explanation
Configuring Services with Environment Variables
Environment variables are the standard way to configure Linux services. Systemd provides two directives for setting them: Environment= for inline values and EnvironmentFile= for loading from a file.
Inline Variables with Environment=
[Service]
Environment="NODE_ENV=production"
Environment="PORT=3000"
Environment="DB_HOST=localhost"
Environment="DB_PORT=5432"
Each Environment= line sets one or more variables. The value must be quoted if it contains spaces. Multiple variables can be set on one line:
Environment="NODE_ENV=production" "PORT=3000"
Loading from Files with EnvironmentFile=
For many variables or sensitive values, use a file:
[Service]
EnvironmentFile=/etc/myapp/env
EnvironmentFile=-/etc/myapp/env.local
The file format is simple KEY=VALUE, one per line:
# /etc/myapp/env
NODE_ENV=production
PORT=3000
DB_HOST=localhost
DB_PASSWORD=secretvalue
The - prefix makes the file optional — the service still starts if the file doesn't exist.
Variable Precedence
When the same variable is defined in multiple places:
Environment=in the unit file (highest priority)EnvironmentFile=(later files override earlier ones)- System environment inherited from PID 1
Security Considerations
Inline Environment= values are visible to anyone who can read the unit file or run systemctl show:
systemctl show myapp.service -p Environment
# Environment=NODE_ENV=production DB_PASSWORD=secret123
EnvironmentFile= values are NOT exposed through systemctl show. This makes it the preferred method for secrets:
# Set restrictive permissions on the env file
chmod 600 /etc/myapp/env
chown root:root /etc/myapp/env
Dynamic Environment
For values that change at runtime, use a generator script:
[Service]
ExecStartPre=/opt/scripts/generate-env.sh
EnvironmentFile=/run/myapp/dynamic.env
ExecStart=/usr/local/bin/myapp
The ExecStartPre= script generates the environment file before the main process starts.
Template Variables
Systemd provides built-in specifiers that can be used in unit files:
| Specifier | Meaning |
|---|---|
%n |
Full unit name |
%i |
Instance name (for template units) |
%H |
Hostname |
%t |
Runtime directory (/run) |
%S |
State directory (/var/lib) |
Environment="HOSTNAME=%H"
Environment="SERVICE_NAME=%n"
Use Case
Managing configuration for a service that needs both public settings (port, log level) and secrets (database passwords, API keys) with proper security isolation between them.