3.4. Environment Variables
Table of Contents
Why Environment Variables Matter
Every backend application needs configuration values, for example:
- Database credentials
- API keys for third party services
- Secret keys used for signing tokens
- Debug or logging settings
- Which port the server should listen on
You must not hard‑code these values into your source code. Instead, you read them from environment variables.
Environment variables keep secrets out of code, allow different settings per environment (development, staging, production), and make your app easier to deploy on any machine or container.
Rule: Never hard‑code secrets like passwords, API keys, or tokens in source code. Use environment variables instead.
In this chapter you will learn what environment variables are, how to set and read them on Linux, macOS, and Windows, and how they connect to backend development and tools like Python and Docker.
What Are Environment Variables?
An environment is the context in which a process (a running program) executes. This environment includes:
- The current working directory
- The system PATH
- Locale settings (language, encoding)
- Custom configuration values
Environment variables are simple KEY=VALUE pairs that are attached to a process and inherited by child processes.
Examples:
PATH=/usr/local/bin:/usr/bin:/binHOME=/home/alicePYTHONPATH=/my/projectDATABASE_URL=postgresql://user:pass@localhost:5432/appdb
When you start your backend server from a shell, the server process sees the environment variables that existed in that shell at the moment of starting.
You can think of environment variables as a global dictionary of strings that your program can read.
Built‑in Environment Variables You Will See Often
Most operating systems define some common variables automatically.
Typical examples:
| Variable | Meaning (typical) | Example value |
|---|---|---|
HOME | User’s home directory (Linux/macOS) | /home/alice |
USER | Current username | alice |
PATH | List of directories searched for programs | /usr/local/bin:/usr/bin:/bin |
SHELL | User’s default shell (Linux/macOS) | /bin/bash |
PWD | Current working directory | /home/alice/projects/app |
TEMP | Temporary files directory (Windows) | C:\Users\Alice\AppData\Local\Temp |
USERNAME | Current username (Windows) | Alice |
Backend apps rarely change these built‑ins, but they always rely on PATH and they will add many custom variables for configuration.
Viewing Environment Variables
You should know how to inspect environment variables from the command line.
On Linux and macOS
Open a terminal.
- To print all environment variables:
printenvor
envYou will see lines like:
SHELL=/bin/bash
USER=alice
HOME=/home/alice
PATH=/usr/local/bin:/usr/bin:/bin- To print a specific variable, for example
PATH:
echo "$PATH"Example output:
/usr/local/bin:/usr/bin:/bin
Note the quotes around $PATH. They are often optional, but they are a good habit.
On Windows (Command Prompt)
Open Command Prompt (cmd.exe).
- To print all environment variables:
setYou will see:
ALLUSERSPROFILE=C:\ProgramData
USERNAME=Alice
PATH=C:\Windows\System32;C:\Windows;...- To print a specific variable:
echo %PATH%On Windows (PowerShell)
Open PowerShell.
- To list environment variables:
Get-ChildItem Env:- To show a specific one, for example
PATH:
$Env:PATHSetting Environment Variables Temporarily in a Shell
You often want to set a variable only for your current terminal session, for example while developing locally.
Once you close that terminal, the value disappears.
Linux and macOS: `export`
In a Bash or Zsh shell:
export APP_ENV=development
export DATABASE_URL="postgresql://user:pass@localhost:5432/appdb"You can verify:
echo "$APP_ENV"
If you close the terminal window and open a new one, APP_ENV will not exist anymore unless you add it to a configuration file like ~/.bashrc or ~/.zshrc.
Only for a Single Command
You can also define an environment variable just for one command:
APP_ENV=production python main.pyIn this example:
APP_ENVis visible only topython main.pyand processes it spawns- After the command finishes, your shell environment remains unchanged
You will see this pattern very often when running backend services:
PORT=8000 DEBUG=false uvicorn app.main:appWindows (Command Prompt): `set`
In cmd.exe:
set APP_ENV=development
set DATABASE_URL=postgresql://user:pass@localhost:5432/appdbCheck the value:
echo %APP_ENV%These values last only until you close that Command Prompt window.
To set a variable only for one command in cmd.exe you typically have to write a batch script. Command Prompt does not have a simple inline syntax like Bash.
Windows (PowerShell): `$Env:`
In PowerShell:
$Env:APP_ENV = "development"
$Env:DATABASE_URL = "postgresql://user:pass@localhost:5432/appdb"Check the value:
$Env:APP_ENVThis lasts for the duration of that PowerShell session only.
Setting Environment Variables Permanently
To avoid setting the same variables manually every time, you can define them permanently.
You will commonly do this for:
PATHupdates when installing tools- Editor or shell preferences
- Some local development configuration
For application secrets, you usually prefer dedicated configuration files or secret managers because permanent system‑wide environment variables can leak more easily.
Linux and macOS: Shell Configuration Files
You can add export lines to shell startup files such as:
~/.bashrcor~/.bash_profilefor Bash~/.zshrcfor Zsh
Example for Bash:
- Open the file:
nano ~/.bashrc- Add lines at the end:
export APP_ENV=development
export EDITOR=vim- Reload the file in the current terminal:
source ~/.bashrc
Now, every new terminal will have APP_ENV set.
Rule: Do not commit your shell config files if they contain secrets. Keep API keys, database passwords, and similar values out of version control.
Windows: System Environment Variables
On Windows you can define environment variables permanently through the graphical interface.
Steps (Windows 10/11):
- Press
Winkey, search for"Environment Variables" - Choose Edit the system environment variables
- In the dialog, click Environment Variables...
- Under User variables click New... to define
APP_ENV,DATABASE_URL, and similar settings - Click OK to save
These will be available to new Command Prompt or PowerShell sessions.
You can also use PowerShell for user‑scoped variables, for example:
[Environment]::SetEnvironmentVariable("APP_ENV", "development", "User")New PowerShell or Command Prompt windows will see the new variable.
Environment Variables and the PATH
PATH is a special environment variable that controls where your shell looks for programs.
PATH is a list of directories separated by:
:(colon) on Linux and macOS;(semicolon) on Windows
Example on Linux:
/usr/local/bin:/usr/bin:/binWhen you type:
python
the shell searches through each directory listed in PATH for a program named python.
If you install a new tool (for example pip, uvicorn, or docker) and the command is “not found”, often the folder with that executable is not in your PATH.
Example: Add a directory to PATH (Linux/macOS)
Suppose Python tools are in /home/alice/.local/bin. You can add it:
export PATH="$HOME/.local/bin:$PATH"
Or permanently in ~/.bashrc:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrcExample: Add to PATH (Windows, PowerShell, current session)
$Env:PATH = "C:\Tools\bin;" + $Env:PATHFor permanent PATH changes use the Windows environment dialog or:
[Environment]::SetEnvironmentVariable(
"Path",
$Env:Path + ";C:\Tools\bin",
"User"
)Be careful with PATH. If you accidentally delete its existing value, many commands will stop working.
Using Environment Variables in Backend Applications
In backend development you rarely care about HOME or USER, but you always care about custom variables such as:
| Variable | Typical purpose |
|---|---|
APP_ENV | Application environment (development, staging) |
PORT | Port the server listens on (8000, 80, 443) |
DATABASE_URL | Full database connection string |
REDIS_URL | Redis connection string |
SECRET_KEY | Secret key used for signing cookies or tokens |
LOG_LEVEL | Log verbosity level (info, debug, error) |
These values let you use the same codebase with different configurations.
Example scenario:
- On your laptop:
APP_ENV=development
DATABASE_URL=postgresql://dev_user:dev_pass@localhost:5432/appdb- On production server:
APP_ENV=production
DATABASE_URL=postgresql://prod_user:prod_pass@db-server:5432/appdb
The code reads DATABASE_URL at runtime. It does not need to know where it is running.
Example: Reading Environment Variables in Python
You will learn this more deeply in the Python chapters. For now, here is a basic pattern.
import os
# Read environment variable, or use a default if not set
app_env = os.getenv("APP_ENV", "development")
# Raises KeyError if SECRET_KEY is not set
secret_key = os.environ["SECRET_KEY"]
Difference between os.getenv and os.environ[...]:
| Method | When variable is missing |
|---|---|
os.getenv("KEY") | Returns None (or default value) |
os.environ["KEY"] | Raises KeyError |
You can combine environment variables with default values:
port = int(os.getenv("PORT", "8000"))
debug = os.getenv("APP_ENV", "development") == "development"Later, when you run the app in your shell:
export APP_ENV=production
export PORT=8080
python main.pyThe app will use these values.
Example: Simple Configuration Pattern
A common backend pattern is to centralize configuration in one place.
import os
class Settings:
def __init__(self):
self.env = os.getenv("APP_ENV", "development")
self.database_url = os.getenv("DATABASE_URL")
self.secret_key = os.getenv("SECRET_KEY")
self.port = int(os.getenv("PORT", "8000"))
# Simple validation
if not self.database_url:
raise RuntimeError("DATABASE_URL must be set")
if not self.secret_key:
raise RuntimeError("SECRET_KEY must be set")
settings = Settings()
Then other parts of the app import settings:
from config import settings
print(settings.database_url)This design keeps all environment‑based configuration in one place.
Using `.env` Files (Local Development)
Typing export commands every time can be annoying. A common solution in development is to create a .env file and load it automatically.
A .env file is a simple text file with KEY=VALUE lines:
Example .env:
APP_ENV=development
DATABASE_URL=postgresql://dev_user:dev_pass@localhost:5432/appdb
SECRET_KEY=dev-secret-key
PORT=8000You can then use tools or libraries to load this file into your environment.
Common approaches:
- Use a shell command:
set -a
source .env
set +a
This exports all variables defined in .env into the current shell.
- Use a Python library like
python-dotenvin your app:
from dotenv import load_dotenv
load_dotenv() # loads .env into environment
import os
db_url = os.getenv("DATABASE_URL")
Rule: Never commit .env files with real secrets to a public repository.
If you need to share variable names, create an example file like .env.example that contains placeholder values.
Common Pitfalls and How to Avoid Them
Environment variables look simple, but beginners hit the same issues repeatedly. Here are the most common cases.
1. Variable Only Exists in One Shell
You start your app from a different terminal, and the variable is missing.
Example:
Terminal 1:
export SECRET_KEY=abc123Terminal 2:
python main.py
SECRET_KEY is not set in Terminal 2, so your app fails.
Fix: Either export the variable in every shell where you run the app or add it to a startup file like ~/.bashrc, or use a .env file and load it each time.
2. Value Not Visible Because of Wrong Command
On Windows:
set APP_ENV=development
This works only in Command Prompt (cmd.exe). If you open PowerShell and run:
$Env:APP_ENVyou will not see it because PowerShell has its own environment session.
Fix: Use the right syntax for the shell you use, or define permanent user variables with the system dialog.
3. PATH Overwritten Instead of Extended
You want to add /opt/mytool/bin to PATH but accidentally do:
export PATH="/opt/mytool/bin"
Now basic commands like ls or python may stop working.
Fix: Append or prepend to the existing PATH:
export PATH="/opt/mytool/bin:$PATH" # Linux/macOSor
$Env:PATH = "C:\MyTool\bin;" + $Env:PATH # Windows PowerShell4. Spaces and Special Characters
Values with spaces or symbols can be parsed incorrectly if not quoted.
Example:
export SECRET_KEY=my secret key
The shell reads my as the value and ignores the rest.
Fix: Quote values containing spaces or special characters:
export SECRET_KEY="my secret key"5. Case Sensitivity
On Linux and macOS, variable names are case sensitive.
APP_ENVandapp_envare different.
On Windows they are typically case insensitive.
To avoid confusion, always use uppercase variable names with underscores, for example APP_ENV, DATABASE_URL.
Environment Variables in Docker and Cloud
You will use environment variables heavily when you start deploying with Docker and cloud platforms.
Examples you will see later:
- Docker:
docker run -e APP_ENV=production -e PORT=8000 my-backend-image- Docker Compose
docker-compose.yml:
services:
web:
image: my-backend-image
environment:
- APP_ENV=production
- DATABASE_URL=${DATABASE_URL}- Cloud platforms (Heroku style):
heroku config:set APP_ENV=production SECRET_KEY=super-secretIn all these cases, the pattern stays the same:
- Set variable in the environment
- Start the application process
- Application reads the variables at runtime
Practical Exercises
To solidify your understanding, try these short tasks on your machine.
Exercise 1: Temporary Variable
- Open a terminal (Linux/macOS) or PowerShell (Windows).
- Set a variable
APP_ENVtodevelopment. - Print its value.
- Close the terminal and open a new one.
- Try to print
APP_ENVagain, observe the result.
Exercise 2: Simple Python Script
Create a file show_env.py:
import os
env = os.getenv("APP_ENV", "not set")
print(f"APP_ENV is: {env}")Now:
- Run
python show_env.pywithout settingAPP_ENV. - Set
APP_ENVin your shell. - Run the script again and see the difference.
Exercise 3: `.env` File
- Create a file
.env:
APP_ENV=development
SECRET_KEY=test-secret- In a Bash shell:
set -a
source .env
set +a- Print variables:
echo "$APP_ENV"
echo "$SECRET_KEY"You will later integrate similar patterns into Python backend frameworks like FastAPI.
Summary
- Environment variables are
KEY=VALUEpairs attached to a process. - They allow you to configure your backend without changing the source code.
- You must use them for secrets, connection strings, and environment‑specific settings.
- You can set them temporarily in a shell or permanently in configuration files or system settings.
PATHis a special environment variable that controls where commands are found.- Backend applications read environment variables using language features, for example
os.getenvin Python. .envfiles are a convenient way to manage variables in development but must not be committed with real secrets.
Understanding environment variables is a crucial step toward writing configurable, secure, and portable backend applications.
Views: 6
KAHIBARO