Environment files


Table of contents

  1. Introduction
  2. Which files exist
  3. How the files are merged
  4. What the production template carries
  5. Filling in the required settings
  6. Optional settings in deploy/.env
  7. Which file the CLI reads
  8. Reference
    1. Key variables
    2. Who reads them
  9. See also

Introduction

Environment files say how your product runs. They carry database hostnames, ports, credentials, the URLs of feature services and runtime flags. The CLI merges them from your product and its features, one file for development and one for each deployment.

splent product:env --merge --dev

This writes docker/.env, the file your development containers read. You edit the templates, never the generated file.

Never commit docker/.env or deploy/.env. Only the .example templates go into git.


Which files exist

In your product,

File Purpose In git
docker/.env.dev.example The development template Yes
docker/.env.prod.example The production template, credentials as <SET> Yes
docker/.env The development settings, generated No
deploy/.env.example The merged production template, written by product:build Yes
deploy/.env The deployment’s settings, on the host No
deploy/.env.base The template product:deploy merged last, for the next three-way merge No

In a feature,

File Purpose In git
docker/.env.example The feature’s defaults Yes
docker/.env.dev.example, docker/.env.prod.example Replace .env.example in that environment, as a whole file Yes
docker/.env The feature’s settings, generated No

Plain settings and their defaults belong in the feature’s pyproject.toml. See Feature settings.

Development reads docker/.env. Production reads deploy/.env, which Compose hands to every container when it starts, so a change takes effect when the container is created again. The production image carries no env file.


How the files are merged

How the env layers are merged for development and for production LAYERS, WEAKEST FIRST WRITES feature docker/.env or its .env.<env>.example feature [tool.splent.config] the defaults the feature declares product [tool.splent.config] what the product decides product .env.<env>.example the product's own file, always wins product:env --merge product:build docker/.env development, not in git deploy/.env.example in git, secrets empty product:deploy, or a copy deploy/.env on the host, not in git
Both commands collect the feature layers with the same function, so the deploy template agrees with development.

Weakest first, four layers take part.

  1. A feature’s docker/.env, or its .env.<env>.example when the .env does not exist yet.
  2. A feature’s [tool.splent.config].
  3. Your product’s [tool.splent.config].
  4. Your product’s own .env.<env>.example, which always wins.

Between features, the later one wins within each layer. product:env --merge --dev writes docker/.env, and product:build writes deploy/.env.example from each feature’s .env.prod.example (or .env.example). That is how a feature brings REDIS_URL or MAIL_HOST without your product listing them. The port offset and the placeholders are applied on the way.


What the production template carries

The docker/.env.prod.example that product:create scaffolds sets what a deployment behind a TLS proxy needs.

# user-tunable
SPLENT_TRUSTED_PROXIES=1

# GUNICORN_WORKERS=4
# GUNICORN_TIMEOUT=120
# SPLENT_COOKIE_SECURE=true
# MAX_CONTENT_LENGTH=64M

The web port is bound to 127.0.0.1, so only a proxy on the same host reaches the app, and SPLENT_TRUSTED_PROXIES=1 trusts that one proxy. Keep 1 with the nginx feature too, since nginx is the only hop the app talks to. Set 0 when nothing is in front. Never set more than the real number of proxies, or a caller can choose the client address the app sees. See Behind a proxy.

The commented lines are optional. Signing in works over HTTPS and plain HTTP without them, because the cookies follow the request. product:sync-template --docker brings these lines into a product that lacks them.


Filling in the required settings

A setting a template writes as <SET> has no sensible default. product:build fills in the database names (<product>_db, <product>_db_user, <product>_db_test) and leaves every other one empty, marked required.

# required: docker compose up refuses to start until this is set. A long random string will do: openssl rand -hex 32
SECRET_KEY=
# required: docker compose up refuses to start until this is set. A long random string will do: openssl rand -hex 32
MARIADB_PASSWORD=

docker compose up starts nothing while a required key is empty, and the error names the key. Choose the database passwords before the first start, since MariaDB keeps the first ones it gets. product:deploy fills them for you, with random values for the secret key, passwords and secrets.


Optional settings in deploy/.env

These work fine unset. product:build, product:deploy and product:env --merge --prod append each one the file does not set, commented out with its explanation, so whoever edits deploy/.env on the server sees what exists.

# Optional settings. Uncomment a line to use it.
#
# Seconds a worker may spend on one request. Unset means 120.
# GUNICORN_TIMEOUT=120
Variable Unset means Set it when
SPLENT_TRUSTED_PROXIES 0, no proxy believed The app runs behind a reverse proxy
GUNICORN_WORKERS 2 x CPUs + 1, by nproc in the container The host is shared or small. nproc does not see a --cpus quota
GUNICORN_TIMEOUT 120 seconds per request A request legitimately takes longer
SPLENT_COOKIE_SECURE auto, Secure when the request came over HTTPS Cookies must always be Secure (true) or never (false)
SPLENT_IMAGE The image deploy/docker-compose.yml names The host should run another image. See Running a published image
SPLENT_WEB_PORT, SPLENT_DB_PORT The host ports the compose file names, the database on loopback Other host ports are expected
MAX_CONTENT_LENGTH 16 MB, 0 for no limit Uploads must be capped at another size

When your releases publish an image, product:build writes SPLENT_IMAGE as a live # user-tunable line set to the stable image.

An optional line you uncomment is yours, and so is any value you change. product:deploy records the template it merged in deploy/.env.base and merges three ways next time, so your values stay. A # user-tunable key you delete is not added back. See Environment sync strategy.


Which file the CLI reads

shell environment  >  <product>/deploy/.env (production only)  >  <product>/docker/.env  >  workspace .env

An exported variable always wins. While production is deployed (SPLENT_ENV=prod, which product:deploy writes into docker/.env), the CLI loads deploy/.env over docker/.env, so commands such as db:seed use the production values. Edit deploy/.env to change what they see.

WORKING_DIR, SPLENT_APP and SPLENT_HOST_PROJECT_DIR keep the value they had before the product’s files are read.


Reference

Key variables

Variable Set by Used by
SPLENT_APP Product CLI, framework, startup scripts
SPLENT_ENV Developer, CI CLI (which feature lists apply), startup scripts
WORKING_DIR Docker CLI, framework (paths)
MARIADB_HOSTNAME, MARIADB_PORT, MARIADB_DATABASE Product env Framework (database URI, port 3306 when unset), startup scripts
MARIADB_USER, MARIADB_PASSWORD Product env Framework, health checks, startup scripts
REDIS_URL, REDIS_HOST_PORT A feature that runs Redis The task queue, app code, Compose
RUN_DB_SEED Product env 04_handle_migrations.sh, which seeds only an empty database
SPLENT_MIGRATE_ON_START Operator, deploy agent upgrade (default) migrates at start, check refuses a schema not at head, off does neither. See Startup script integration
GUNICORN_WORKERS, GUNICORN_TIMEOUT Operator Production entrypoint
SPLENT_TRUSTED_PROXIES Product env (1), operator Framework (ProxyFix, HTTPS detection)
SPLENT_COOKIE_SECURE Operator Framework (Secure cookies)
SPLENT_IMAGE product:build, operator The deploy bundle, product:deploy, a feature that deploys the product
SPLENT_WEB_PORT, SPLENT_DB_PORT Operator The deploy bundle (host ports)
SPLENT_WEB_BIND_HOST, SPLENT_DB_BIND_HOST Product env (127.0.0.1), operator Compose (the interface each port is published on)
MAX_CONTENT_LENGTH Operator Framework (largest request body)
SELENIUM_GRID_URL, SELENIUM_BROWSER, SELENIUM_TARGET_URL Developer, CI The E2E driver
SPLENT_LOCUSTFILES Developer, CI The Locust bootstrap

Who reads them

Reader Reads
product:env The .env.example templates, to generate and merge .env files
product:build The .env.prod.example of the product and its features, to write deploy/.env.example
product:deploy deploy/.env.example, to write or merge deploy/.env
Docker Compose The env file it is given, deploy/.env for the bundle
Startup scripts and health checks $MARIADB_*, $RUN_DB_SEED

See also


Back to top

splent. Distributed by an LGPL license v3. Contact us: drorganvidez@us.es