Why Your Linux Service Won't Start: Missing Environment Variables

A service that crashes immediately on startup - with no port listening - is most often missing a required environment variable. The app fails before it binds, the log says exactly which variable, and the fix is a one-liner export. Here's how to work through it.

DevOps Engineerlinuxpythonenvironment-variables

Why services fail silently on a new server

"It worked on my machine" is almost always an environment problem. The developer's shell had INVENTORY_DB (or DATABASE_URL, SECRET_KEY, etc.) exported from a previous session. The production server was freshly provisioned and never had it.

The app crashes before it binds the port, so from the outside it looks like the network is down - but the real error is in the logs.

Step 1: confirm nothing is listening and read the log

ps aux | grep app.py                 # is the process running at all?
ss -ltnp | grep 8080                 # is port 8080 open?
cat /var/log/flask/app.log           # what did it say when it tried to start?

If the process is absent and the port is closed, the app exited on startup. The log is the first place to look.

Step 2: start it manually to see the raw error

python3 app.py

A missing environment variable surfaces immediately:

KeyError: 'INVENTORY_DB'

Python's os.environ['INVENTORY_DB'] raises KeyError (not a default) when the variable is absent. os.getenv('INVENTORY_DB') returns None silently, which usually causes a crash a few lines later. Either way, the error names the variable.

Step 3: confirm what the app expects

Open the source to verify the variable name and what it's used for:

import os

DB_NAME = os.environ['INVENTORY_DB']   # crashes here if unset
conn = psycopg2.connect(dbname=DB_NAME, user='postgres', host='localhost')

This tells you the exact key and confirms a safe value to set.

Step 4: export the variable and restart

export INVENTORY_DB=inventory
python3 app.py > /var/log/flask/app.log 2>&1 &

Then verify the service is answering:

curl http://localhost:8080/health
curl http://localhost:8080/products

Making the fix permanent

An export in your current shell is lost on reboot or a new session. For a long-lived service, set the variable where the process manager will pick it up:

The goal is that the variable is present regardless of who restarts the service.

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

How do I find out which environment variable is causing a crash?

Start the process manually in a terminal (python3 app.py) and read the raw error output. A KeyError or similar will name the missing variable directly. The application log often has the same message.

How do I set an environment variable so a Linux service keeps it after reboot?

For a systemd service, add Environment=VAR=value inside the [Service] section of the unit file, then run systemctl daemon-reload and restart the service. A plain export in your shell is lost when the session ends.

Why does a Python app crash with KeyError when an env var is missing?

os.environ['VAR'] raises KeyError if the variable is not set - it does not return a default. Use os.getenv('VAR') if you want None on miss, or guard with a startup check that exits with a clear error message listing every missing variable.

Keep learning

Fix the Nginx 502 Bad GatewayDevOps projectCorrect a Postgres Port MismatchDevOps projectReopen the Redis Bind Address (Connection Refused)DevOps projectDevOps roadmapStep by step to hiredDevOps interview questionsSTAR answersAll DevOps projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →