Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Settings live outside the code

After this lesson: I can keep settings out of the code.

45 min lessonNo commands

Five hundred fake orders

A developer typed the live database's address into the shop's code, just to try something.

Later she ran the tests on her laptop. They wrote 500 fake orders into the real shop. The warehouse started packing them.

The code was fine. The mistake was where a setting lived.

By the end of this lesson

Note

I can keep settings out of the code.

Key words

WordWhat it meansExample
Configurationthe settings an app reads when it starts
Hard-codedtyped into the code itself
Environmentone place the app runs: development, test or live
Environment variablea named setting given to a program from outsideSHOP_PORT=8080
Defaultthe value used when a setting is not given
Secreta setting nobody else may see, such as a password

The cells students fill in are left blank in this preview.

The code stays the same, the settings change

The shop runs in three environments: a laptop, a test server and live. The code is the same in all three.

What differs is the configuration: which database, which port, which mail server.

So the settings stay out of the code. Each environment gives its own, often as environment variables.

One app, three sets of settings

SettingLaptopTest serverLive
SHOP_PORT80008080443
DATABASE_URLpostgres://localhost/shoppostgres://db.test.internal/shoppostgres://db.live.internal/shop
SEND_EMAILSnonoyes

The cells students fill in are left blank in this preview.

Read settings from the environment

Code: bash
# The same two lines of code, with settings from outside
export SHOP_PORT=8080
export DATABASE_URL=postgres://db.test.internal/shop

port="${SHOP_PORT:-8000}"   # use 8000 when SHOP_PORT is not set
echo "Shop starting on port $port"
echo "Using database $DATABASE_URL"

# Delete the line "export SHOP_PORT=8080", then run again. Which port is used?

A common mistake

Warning

Many people think a password in the code is safe if the repository is private. It is not. Everyone who can read the code can read it, and it stays in the Git history for ever. Copies of the code travel to laptops and backups, so a secret comes from the environment instead.

Secrets never go in the code

A secret is a setting like a password or a payment key. Leaked, it lets a stranger act as your company.

Teams keep secrets in a secret store. When the app starts, the platform hands it the secret as an environment variable.

Below, find the file that breaks this rule.

Find the typed-in key

Code: bash
mkdir -p app && cd app
# Two files from the payments service
printf 'PAYMENTS_KEY = "pk-4471"\nprint("taking payment")\n' > pay.py
printf 'import os\nPAYMENTS_KEY = os.environ["PAYMENTS_KEY"]\n' > refund.py

# Which file has the key typed into it?
grep -n 'KEY = "' *.py

# Which file reads the key from the environment?
grep -n "os.environ" *.py

A default, or a stop at the start

Some settings have a sensible default. If nobody sets the port, 8000 will do.

Others have no safe default. Guessing a database address is how the fake orders happened.

For those, the app should refuse to start and say which setting is missing. Run it and see both cases.

A setting the shop cannot start without

Code: bash
start_shop() {
  port="${SHOP_PORT:-8000}"
  db="${DATABASE_URL:?is not set, so the shop will not start}"
  echo "Shop starting on port $port with database $db"
}

unset SHOP_PORT DATABASE_URL
export DATABASE_URL=postgres://db.test.internal/shop
( start_shop )

unset DATABASE_URL
( start_shop ) || echo "Start-up refused: fix the setting first"

# Set SHOP_PORT=9000 before the first start, then run again.

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.