Environment variables in `docker-compose.yml` or `.env` files are stored in plaintext on disk.
Environment variables in docker-compose.yml or .env files are stored in plaintext on disk. Anyone with access to the host filesystem can read every secret. Docker secrets provide encrypted at-rest storage and are only available inside the container at runtime.
Real-world example: A developer accidentally commits the docker-compose.yml containing the database password and encryption key to a public Git repository.
# docker-compose.yml with Docker secrets
version: "3.9"
secrets:
n8n_encryption_key:
file: ./secrets/n8n_encryption_key.txt
db_password:
file: ./secrets/db_password.txt
redis_password:
file: ./secrets/redis_password.txt
services:
n8n:
image: n8nio/n8n:latest
secrets:
- n8n_encryption_key
- db_password
environment:
# Reference secrets via file path
- N8N_ENCRYPTION_KEY_FILE=/run/secrets/n8n_encryption_key
- DB_POSTGRESDB_PASSWORD_FILE=/run/secrets/db_password
# Non-sensitive config can remain as environment variables
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n_user
postgres:
image: postgres:16-alpine
secrets:
- db_password
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
- POSTGRES_DB=n8n
- POSTGRES_USER=n8n_user
```text
> **Info: The `_FILE` Suffix Convention**
>
> n8n supports the Docker `_FILE` suffix convention for many environment variables. When you set `N8N_ENCRYPTION_KEY_FILE=/run/secrets/n8n_encryption_key`, n8n reads the file contents as the value. Check n8n's documentation for which variables support this pattern. If a variable does not support the `_FILE` suffix, use an entrypoint script to export the secret as an environment variable at container startup.
```bash
# Create secrets directory (exclude from version control)
mkdir -p secrets
echo "your-encryption-key" > secrets/n8n_encryption_key.txt
echo "your-db-password" > secrets/db_password.txt
chmod 600 secrets/*.txt
# Add to .gitignore
echo "secrets/" >> .gitignore
```text
**Related:** [Use Docker Compose with Health Checks for n8n and PostgreSQL](../self-hosting-operations/01-use-docker-compose-with-health-checks-for-n8n-and-postgresql.md) | [Use Path Parameters in Webhook URLs for Dynamic Routing](../webhook-mastery/01-use-path-parameters-in-webhook-urls-for-dynamic-routing.md)
I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.