Tips > Ops & Security

Use Docker Secrets Instead of Plain-Text Environment Variables

Environment variables in `docker-compose.yml` or `.env` files are stored in plaintext on disk.

TipIntermediate2 min read

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)

Want this running in your stack?

I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.