How to Set Environment Variables on Linux — Quick Steps, Examples, and Best Practices
Linux environment variables are the simplest way to decouple configuration from code and keep secrets out of repositories. This friendly guide walks you through quick steps, practical examples, and best practices to set them correctly on VPSes and production servers.
Environment variables are a fundamental part of Linux system configuration and application deployment. They provide a simple, portable way to pass configuration values such as database credentials, API keys, locale settings, and runtime options to processes without hard-coding them into binaries or source files. This article walks through the core principles, practical examples, and best practices for setting environment variables on Linux, tailored for webmasters, enterprise administrators, and developers who manage VPS-based infrastructure.
Why environment variables matter
Environment variables decouple configuration from code, enabling safer deployments, easier automation, and consistent runtime behavior across environments (development, staging, production). They are especially useful for:
- Keeping sensitive data (passwords, tokens) out of source code and repositories.
- Adjusting runtime behavior (log levels, feature flags) without rebuilding applications.
- Standardizing configuration across containerized or distributed systems.
Understanding how environment variables are defined and propagated is critical for reliable operations on VPS instances and production servers.
Basic concepts and where environment variables live
An environment variable is a string key-value pair associated with a process. When a process starts, it inherits the environment of its parent process (typically a shell or init system). Key places where environment variables are commonly set on Linux include:
- Interactive shell files: ~/.bashrc, ~/.bash_profile, ~/.profile — used for user login or interactive shells.
- System-wide files: /etc/environment, /etc/profile, /etc/profile.d/*.sh — used for system-wide settings that apply to all users.
- Service units: systemd unit files (.service) with Environment= or EnvironmentFile= — used for services started by systemd.
- Process wrappers: export in shell scripts, or passing env inline (VAR=value command).
- Orchestration and container platforms: Dockerfile ENV, docker run -e, Kubernetes ConfigMap/Secret or env entries.
Shell environment vs. login shells vs. non-login shells
Different shell startup files are sourced depending on whether the shell is a login shell (e.g., SSH session) or an interactive non-login shell (e.g., opening a new terminal). Common patterns:
- Bash login shell typically reads /etc/profile then ~/.bash_profile or ~/.profile.
- Bash interactive non-login shell reads ~/.bashrc.
- Graphical sessions (display managers) may source /etc/environment or other session-specific files.
When setting variables for services or cron jobs, rely on system-wide or service-specific mechanisms rather than user shell files.
Quick commands and practical examples
Below are concise, practical examples for common tasks. Use these on a VPS or any Linux server.
Temporarily set a variable for a single command
To set a variable just for one command’s execution:
DB_HOST=10.0.0.5 ./start-app.sh
This does not modify the parent shell environment.
Export a variable in the current shell session
To set and export a variable so it’s available to child processes of the shell:
export APP_ENV=production
Verify with:
echo $APP_ENV
Persist variables for a user
To persist for a single user across login sessions, add to ~/.bashrc or ~/.profile:
echo 'export REDIS_URL=redis://127.0.0.1:6379' >> ~/.bashrc
Then reload with:
source ~/.bashrc
System-wide environment variables
Edit /etc/environment to define simple key-value pairs (no shell syntax like export):
sudo tee -a /etc/environment <<EOF
NODE_ENV=production
TZ=UTC
EOF
/etc/environment is read by PAM modules at login; changes typically require re-login or service restart.
Using systemd for service environments
For services managed by systemd, prefer the unit file’s Environment or EnvironmentFile directives. Example unit override using systemctl edit:
sudo systemctl edit myapp.service
Then add:
[Service]
Environment="APP_ENV=production" "DB_HOST=127.0.0.1"
EnvironmentFile=/etc/myapp.env
After editing:
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
Using EnvironmentFile lets you keep secrets in a file with controlled permissions (e.g., 600), and avoid embedding them in unit files stored in /etc/systemd/system/ which might be versioned or exposed.
Files with key=value pairs
Create a file /etc/myapp.env with:
APP_SECRET=supersecretkey
APP_PORT=8080
Then reference it from systemd or source it from a wrapper script:
set -a
source /etc/myapp.env
set +a
./start.sh
set -a exports all subsequently defined variables in bash; use cautiously.
Advanced techniques and debugging
When environment variables do not behave as expected, common debugging steps include:
- Print the environment inherited by a running process using /proc:
cat /proc/<pid>/environ | tr '' 'n'. - Check systemd service environment logs:
journalctl -u myapp.service -e. - Confirm file permissions for files with secrets: only root or service user should read them.
- Remember that cron runs with a limited environment; set PATH and any required variables in crontab or a wrapper script.
Passing environment variables into Docker containers
Examples:
- Docker run:
docker run -e DB_PASS=secret myimage - Docker Compose: use env_file or environment in docker-compose.yml
- For production, prefer Docker secrets or volumes with files to avoid exposing secrets via process lists.
Applications and common use cases
Environment variables are used widely across the stack:
- Web applications: database connection strings, feature flags, OAuth credentials.
- CI/CD pipelines: credentials, build parameters, deployment targets.
- System services: locale, timezone, memory limits, JVM options.
- Container orchestration: injecting configuration into pods and services.
For multi-tenant VPS hosting or production environments, keeping configuration in environment variables simplifies automated provisioning and reduces configuration drift when combined with Infrastructure as Code (IaC) tools.
Advantages and limitations
Advantages:
- Simple and widely supported across languages and runtimes.
- Facilitates 12-factor app principles (config in environment).
- Can be combined with secrets managers for enhanced security.
Limitations and risks:
- Environment variables can be leaked via process listings or crash dumps if not handled carefully.
- Large or binary configuration values are awkward to store in environment variables.
- Statefulness — they are inherited by child processes, which might produce unintended side effects.
Choosing where and how to set variables — best practice checklist
Follow these guidelines for robust, secure usage:
- Least privilege: store secrets in files owned by a specific user and referenced by systemd EnvironmentFile when possible. Limit file permissions (chmod 600).
- Immutable config files: use version-controlled templates (without secrets) and generate secret-containing files at provisioning time.
- Prefer systemd for services: avoids differences between interactive shells and service environments.
- Avoid putting secrets in process command lines because they can show up in ps output. Use EnvironmentFile or secret management systems.
- Use secrets managers: integrate HashiCorp Vault, AWS Secrets Manager, or similar for high-sensitivity credentials, injecting values at runtime.
- Document and centralize: keep a documented list of environment variables used by each application and their expected formats.
When to use system-wide vs. per-user vs. service-specific
Decide based on scope:
- Use /etc/environment or /etc/profile.d for settings that must apply to every user and login session (e.g., TZ, proxy settings).
- Use ~/.bashrc or ~/.profile for per-user development convenience variables.
- Use systemd unit Environment or EnvironmentFile for services to ensure predictable behavior on boot and during restarts.
Summary and recommendations
Environment variables are a straightforward yet powerful mechanism to control application and service behavior across Linux systems. For production VPS deployments, follow these points:
- Prefer systemd Environment or EnvironmentFile for services on modern Linux distributions.
- Keep secrets out of code and out of process command lines; use files with restricted permissions or integrate a secrets manager.
- Document your environment variables and use IaC to maintain consistency across servers.
- Test variable propagation and behavior with the same user and startup method used in production (e.g., systemd, cron, container runtime).
Implementing these practices will reduce operational surprises and improve security and maintainability of applications running on VPS infrastructure. If you need reliable VPS hosting to deploy services with predictable behavior, consider solutions optimized for production workloads — for example, the USA VPS offering from VPS.DO, which provides configurable environments suitable for systemd-managed services, containers, and automated deployments.