Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

For a production n8n deployment, run separate n8n and PostgreSQL containers, persist both PostgreSQL’s data directory and /home/node/.n8n, keep credentials and the encryption key outside version control, wait for PostgreSQL health before starting n8n, and publish n8n through an HTTPS reverse proxy. PostgreSQL carries the application records; the .n8n directory carries the encryption key and other essential user data. Losing either side can make a restore incomplete.

The Compose example below gives you a repeatable baseline. You will still need to choose a reviewed image tag, create DNS and TLS at your proxy, test backups, and document your upgrade process before calling the service production-ready.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why PostgreSQL belongs in a production n8n stack

n8n can use SQLite, but the project positions SQLite as suitable for trying the product. A production instance serving more than a handful of users or workflows that run continuously should use PostgreSQL instead. PostgreSQL gives the deployment a database designed for concurrent, long-running workloads and gives you mature dump, restore, monitoring, and upgrade procedures.

Choosing PostgreSQL does not eliminate n8n state outside the database. n8n still needs /home/node/.n8n. That directory includes the encryption key used to protect credentials and essential n8n user data. A PostgreSQL dump without the matching key material may restore rows that n8n cannot decrypt.

#1 Best Overall
CanaKit Raspberry Pi 5 Starter Kit PRO - Turbine Black (128GB Edition) (8GB RAM)
  • Includes Raspberry Pi 5 with 2.4Ghz 64-bit quad-core CPU (8GB RAM)
  • Includes 128GB Micro SD Card pre-loaded with 64-bit Raspberry Pi OS, USB MicroSD Card Reader
  • CanaKit Turbine Black Case for the Raspberry Pi 5
  • CanaKit Low Noise Bearing System Fan
  • Mega Heat Sink - Black Anodized
Component What it contains What must be protected
PostgreSQL data directory Workflows, executions, users, settings, and encrypted credential records Persistent volume, database password, dump files
/home/node/.n8n Encryption key and essential n8n user/configuration data Persistent volume or an equivalent protected backup
Reverse proxy Public HTTPS endpoint, certificates, and forwarding headers Private network exposure, certificate keys, proxy configuration

Target architecture

Place both containers on an internal Docker network. PostgreSQL listens only to that network. The n8n container listens on port 5678 inside the network, while a reverse proxy or load balancer terminates TLS and forwards requests to n8n. Users, webhook senders, and OAuth providers use the public HTTPS hostname; n8n uses the internal service name postgres to reach the database.

Request flow

  1. A browser or webhook client connects to https://automation.example.com.
  2. The proxy handles the TLS certificate and forwards the request to n8n on the private Docker network.
  3. n8n stores workflow and execution data in PostgreSQL and reads its encryption key from /home/node/.n8n.
  4. PostgreSQL is not published to the internet and should not be reachable from arbitrary hosts.

Prerequisites and project layout

Prepare a Linux host or VM with Docker Engine and the Docker Compose plugin. You also need a DNS name for n8n, a TLS-capable reverse proxy, a protected location for secrets, and a backup destination that is separate from the Docker host. Create a dedicated directory such as /opt/n8n and keep the Compose file, proxy configuration, and operational notes there.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended files

  • docker-compose.yml for service definitions and volumes.
  • .env for database settings, public URL values, and the encryption key.
  • A secret-store or host-level protected file for production credentials when your platform supports one.
  • A backup directory or remote object-storage target that is not the live Docker volume.

Set restrictive permissions on files containing secrets, for example ownership by the deployment account and mode 600. Add .env, dump files, and archives containing .n8n to .gitignore. Never commit database passwords, API tokens, or N8N_ENCRYPTION_KEY.

Create the environment file

Use values that are unique to this deployment. The encryption key must be long, random, and stable for the entire lifetime of the instance. Generate it with a trusted password generator or secret-management system, then preserve the same value through container recreation, migration, and restore.

Rank #2
RasTech Raspberry Pi 5 8GB Kit with Active Cooler and Pi5 Case
  • 【What you Get】You will get 1*Pi 5 8GB Single Board,1*RasTech Case,1*Active Cooler,1*Screwdriver,1*Installation instructions,12-month free warranty, lifetime service, 24-hour prompt and friendly response.
  • 【More Connectors】There are two USB 3.0 ports(5Gbps simultaneously) and two USB 2.0 ports, which triple total bandwidth ,support any combination of up to two cameras or displays. Peak SD card performance is doubled through support for the SDR104 high-speed mode. It provides a smooth desktop experience for you. Offer Gigabit Ethernet and a PCIe interface, along with dual-band Wi-Fi and Bluetooth 5.0/BLE wireless capability. The RasTech Pi 5 Kit use the new 27W 5.1V 5A USB-C power connector.
  • 【 Support Dual 4Kp60 Display 】Each of the two microHDMI sockets can control a 4K display at 60 Hertz, now support HDR, offering super HD video for media streaming projects. RPi 5 is the first RPi model that comes with a PCI Express port (PCIe 2.0 x1 with 500 MB/s) to attach SSDs (requires separate M.2 HAT).
  • 【 Excellent Chips And Applications】Pi 5 is a full-size Pi computer using silicon built in-house at Pi. The RP1 “southbridge” provides the bulk of the I/O capabilities for Pi 5. Pi 5 is more friendly and convenient in the development of Internet of Things, Web development, machine identification, automatic control and other electronic equipment applications and network.
  • 【 Faster CPU, Better GPU 】 Pi 5 features a Broadcom BCM2712 64-bit quad-core Arm Cortex-A76 processor running at 2.4GHz, it delivers a 2–3× increase in CPU performance relative to RaspberryPi 4. The 800MHz VideoCore VII GPU is compatible to OpenGL ES 3.1 and Vulkan 1.2, substantial uplift in graphics performance. Pi 5 Offers lightning-fast CPU speed, a PCI Express interface, a Real Time Clock (RTC) and a power button and runs significantly cooler than Pi 4.
POSTGRES_USER=n8n_app
POSTGRES_PASSWORD=replace-with-a-random-database-password
POSTGRES_DB=n8n
N8N_ENCRYPTION_KEY=replace-with-a-long-random-stable-key
N8N_HOST=automation.example.com
N8N_PROTOCOL=https
N8N_PORT=5678
WEBHOOK_URL=https://automation.example.com/
N8N_EDITOR_BASE_URL=https://automation.example.com/

The sample names are illustrative configuration values, not credentials. Do not place the real values in a public repository, shell history, issue tracker, or image layer. If your proxy publishes a path rather than a hostname, make the path consistent in the public URL settings and proxy routes; a hostname-only deployment is usually simpler for webhook and OAuth compatibility.

Compose file with health checks and persistent storage

The following baseline defines PostgreSQL and n8n on one private network. It uses named volumes for both state locations, a PostgreSQL readiness check, and a dependency condition so n8n starts only after PostgreSQL reports ready.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
services:
  postgres:
    image: postgres:18
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}']
      interval: 10s
      timeout: 5s
      retries: 10
    networks:
      - n8n_internal

  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    restart: unless-stopped
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_PORT: 5432
      DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
      DB_POSTGRESDB_USER: ${POSTGRES_USER}
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      N8N_HOST: ${N8N_HOST}
      N8N_PROTOCOL: ${N8N_PROTOCOL}
      N8N_PORT: ${N8N_PORT}
      WEBHOOK_URL: ${WEBHOOK_URL}
      N8N_EDITOR_BASE_URL: ${N8N_EDITOR_BASE_URL}
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - n8n_data:/home/node/.n8n
    expose:
      - '5678'
    networks:
      - n8n_internal

volumes:
  postgres_data:
  n8n_data:

networks:
  n8n_internal:
    driver: bridge

Why the PostgreSQL settings matter

  • DB_TYPE=postgresdb selects PostgreSQL rather than SQLite.
  • DB_POSTGRESDB_HOST=postgres uses the Compose service name, which resolves inside the Docker network.
  • Port 5432 is internal; there is no host port mapping for PostgreSQL.
  • The pg_isready check tests database readiness, not merely whether the container process exists.
  • depends_on with service_healthy prevents the first n8n start from racing an uninitialized database.
  • expose makes port 5678 available to the proxy on the Docker network without publishing it directly on the host.

Pin images before production

The example uses readable tags so the file is easy to adapt. Before production, select and record specific n8n and PostgreSQL image versions that you have reviewed together. Treat a PostgreSQL major-version change as an upgrade project, not as an unattended tag update. Keep the old image reference and a tested rollback plan in your change record.

Why PGDATA is explicit

The PostgreSQL example sets PGDATA to /var/lib/postgresql/data/pgdata. PostgreSQL 18 changed the default data-directory layout. Keeping this setting explicit avoids a confusing situation in which an existing volume appears empty after an image change because the server is looking in a different directory. Do not remove the setting casually when upgrading or restoring.

Rank #3
RasTech Raspberry Pi 5 8GB Kit 64GB Edition with Active Cooler,27W GaN 5.1V5A USB-C Power Supply,Pi5 8GB Board,64GB Card Readers Kit,Pi 5 Case,Dual 4K Micro HD Out Cables and User Manual
  • Pi5 8GB Pack: RasTech Pi 5 8GB kit includes 1 x Pi5 8GB board ,1 x 64GB Card, 2 x Card Readers,1 x Active Cooler,1 x Case for Pi5, 2 x 4K Micro HD Out Cable,1 x GaN 27W 5A USB-C Power supply,1 x Screwdriver and 1 x instructions.
  • Pi5 8GB Board: The Pi5 board is equipped with a 64-bit quad-core Arm Cortex-A76 processor running at 2.4GHz and an 800MHz VideoCore VII GPU with support for OpenGL ES 3.1 and Vulkan 1.2, which delivers a significant increase in graphics performance. Dual HD Out 4Kp60 display outputs and a built-in dual 4-channel MIPI camera/display transceiver provide state-of-the-art camera support. The Pi 5 offers a 2-3 times increase in CPU performance compare to Pi4.
  • Important Graphics Features: Equipped with an 800MHz VideoCore VII GPU and providing better graphics performance, suitable for multimedia applications,gaming,and graphics intensive tasks.Provides 1 UART interface,1 card slot that supports high-speed operation, 2 USB. 3 0.5 ports that support synchronous 0Gbps operation,2 USB 2.0 port ports,2 4Kp60 display outputs that support HDR.Built-in dedicated dual 4-channel 1Gbps MIPI DSI/CSI connectors,triple the total bandwidth.
  • Cooling Kit for Pi 5: Compatible with Active Cooler for Raspberry Pi5, It can provide Pi 5 board with better cooling effect in using. The Case can accurately access usb-c power jack,Micro HD Out ports, usb ports, Ethernet jack, card slot, power button, 4-lane MIPI DSI/CSI connectors and so on, and it also supports installation of cooling fan.
  • 64GB Card Kit and GaN 27W USB-C Power Supply: With extra 64GB card to store more files and card readers for multiple medium, keep better performance for Raspberry Pi 5, 27W USB C Power Supply is Compatible with Pi5 8GB, offers a variety of output voltage options, including 5.1V at 5A, 9.0V at 3.0A, 12.0V at 2.25A, and 15.0V at 1.8A, providing for different device requirements.

Deploy the stack

  1. Change into the project directory and create the protected .env file.
  2. Review the image tags, hostname, URL values, volume paths, and proxy network attachment.
  3. Run docker compose config and inspect the rendered configuration. Confirm that no secret is accidentally being committed or printed into a shared log.
  4. Start the database first with docker compose up -d postgres.
  5. Watch readiness with docker compose ps and docker compose logs postgres. Continue only when the health status is healthy.
  6. Start n8n with docker compose up -d n8n.
  7. Read docker compose logs -f n8n and confirm that n8n connects to PostgreSQL without authentication or migration errors.
  8. Attach the reverse proxy to the same internal network, route the public hostname to the n8n service on port 5678, and enable TLS.
  9. Open the HTTPS hostname in a browser, create or verify the owner account, and run a harmless test workflow.

Configure HTTPS, webhooks, and OAuth callbacks

Terminate TLS at a reverse proxy or load balancer in front of n8n. The proxy should forward the original host and protocol information and route both the editor and webhook endpoints to the same n8n service. Keep direct host access to port 5678 disabled unless you have a specific administration reason.

Keep the public URL consistent

N8N_HOST, N8N_PROTOCOL, WEBHOOK_URL, the editor base URL, DNS, and the proxy’s external route must describe the same public address. If one setting says HTTP, an internal hostname, or a different path, n8n may generate callback URLs that browsers and third-party OAuth providers cannot reach.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Verify after the proxy is live

  • Load the editor over HTTPS and check that the browser shows a valid certificate with the expected hostname.
  • Create a temporary webhook workflow and send a request from outside the Docker host. Confirm that the request reaches the workflow and that the response returns through HTTPS.
  • For every OAuth credential, compare the provider’s registered redirect URI with the callback URI n8n displays. Update the provider only after the final public hostname and path are fixed.
  • Test a workflow that receives a webhook and one that calls an OAuth-connected service. These validate both inbound routing and encrypted credential use.

What to persist and how to protect it

PostgreSQL volume

The postgres_data volume contains the database cluster. Do not treat a container replacement as a restore strategy; deleting this volume deletes the primary copy of the application data. Restrict host access to the Docker storage location and protect database dumps with equivalent controls.

n8n data volume

The n8n_data volume maps to /home/node/.n8n. Persist it even when PostgreSQL is the configured database. It contains the encryption key and essential user data. A new empty volume paired with an old database can leave encrypted credentials unusable.

Rank #4
CanaKit Raspberry Pi 5 Essentials Starter Kit (4GB RAM)
  • CanaKit Raspberry Pi 5 Essentials Starter Kit

Encryption-key continuity

Do not generate a new key when replacing a container, moving hosts, or restoring a backup. If the key is lost, changing the environment variable to a newly generated value does not decrypt credentials that were encrypted with the original key. Store the key in a secret manager or a protected offline recovery record, and limit access to operators who need to restore the service.

Back up PostgreSQL and n8n storage together

A production backup is a coordinated set: a PostgreSQL dump plus the matching .n8n data or the exact encryption key and required configuration material. Schedule backups often enough for your workflow and execution-loss tolerance, retain multiple generations, encrypt them, and copy them away from the live host.

Logical PostgreSQL dump

Run a logical dump from the Compose project directory. The following pattern writes SQL to a file on the host while keeping the password in the environment file rather than on the command line:

docker compose exec -T postgres pg_dumpall -U "$POSTGRES_USER" > n8n-backup.sql

Run it with the variables loaded in the shell or adapt the command to your secret manager. Protect the resulting file because it contains the database contents and may include sensitive workflow data.

Best Value
CanaKit Raspberry Pi 5 16GB Starter Kit PRO - Turbine Black (128GB Edition) (16GB RAM)
  • Includes Raspberry Pi 5 16GB with 2.4Ghz 64-bit quad-core CPU (16GB RAM)
  • Includes 128GB Micro SD Card pre-loaded with 64-bit Raspberry Pi OS, USB MicroSD Card Reader
  • CanaKit Turbine Black Case for the Raspberry Pi 5
  • CanaKit Low Noise Bearing System Fan
  • Mega Heat Sink - Black Anodized

Back up .n8n

Back up the named volume or the host directory that supplies it while n8n is stopped, or use a snapshot method that guarantees a consistent filesystem view. Include the encryption-key material in the same recovery set. Record which database dump and which .n8n backup belong together; mixing dates can produce an internally inconsistent restore.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Test a restore instead of trusting a successful dump

  1. Create an isolated Compose project with no connection to production webhooks or OAuth endpoints.
  2. Start a PostgreSQL container, restore the SQL dump, and restore the matching .n8n volume or the original N8N_ENCRYPTION_KEY.
  3. Start n8n and verify that the owner account, workflows, credentials, and execution history expected from the backup are present.
  4. Run representative workflows, including one that uses an encrypted credential and one that receives a webhook.
  5. Record the restore commands, elapsed time, failures, and any manual steps. Repeat after major upgrades.

There is no universal recovery-time or CPU/RAM number for this Compose pattern. Measure your own restore duration and workflow load rather than applying an unsupported sizing claim.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Upgrade PostgreSQL and n8n safely

Routine n8n image updates

Read the release notes, back up both state locations, pull the reviewed image, and recreate the n8n container. Keep the previous image tag available until smoke tests pass. Check editor access, webhook delivery, OAuth authentication, credential decryption, and scheduled executions after every update.

PostgreSQL major-version updates

PostgreSQL cannot open a data directory written by an older major version without an upgrade procedure. Changing postgres:17 directly to postgres:18, for example, can fail with an incompatible-data-directory error. Back up first and follow the PostgreSQL major-upgrade method appropriate to your environment, such as a dump and restore or a documented in-place procedure. Verify the resulting data directory and keep PGDATA aligned with the volume layout.

Moving from SQLite to PostgreSQL

The PostgreSQL Compose addition is a fresh-instance path; existing SQLite data does not move automatically merely because the database variables changed. Plan an explicit n8n export/import or migration procedure supported by the n8n version you run. Preserve the original SQLite files and encryption key until the PostgreSQL instance has been validated, and schedule a maintenance window for the cutover.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Security and operational hardening

  • Use a non-default PostgreSQL username and a high-entropy password.
  • Keep PostgreSQL on the internal network; expose only the proxy’s HTTPS listener.
  • Restrict access to the Docker host, Compose files, secret files, and backup archives.
  • Pin reviewed image versions and document who approves updates.
  • Monitor container health, disk usage, database growth, failed workflow executions, and proxy certificate expiry.
  • Set a retention policy for execution data that matches debugging and compliance needs; excessive history can consume storage.
  • Separate development, staging, and production projects so test callbacks cannot reach production credentials or webhooks.
  • Use an external secret store where available, and rotate database credentials through a planned maintenance procedure.

Troubleshooting common failures

Symptom Likely cause Action
n8n exits while PostgreSQL is starting Database readiness race or failed health check Inspect docker compose ps and PostgreSQL logs, confirm pg_isready succeeds, then restart n8n after the service is healthy.
Authentication failed for user Environment values differ between the two services or an old volume retains prior credentials Compare rendered Compose values, confirm the database and username, and do not delete the volume until you have a verified backup.
Credentials appear invalid after restore The original encryption key was not restored Restore the matching .n8n data or original N8N_ENCRYPTION_KEY; a newly generated key cannot decrypt old records.
OAuth provider rejects the callback Public URL, protocol, hostname, or path differs between n8n, proxy, and provider registration Make all external URL settings identical, then update the provider’s redirect URI and retry over HTTPS.
Webhook URL uses an internal name or HTTP Missing or inconsistent host, protocol, or webhook URL configuration Set the external HTTPS values, recreate n8n, and test from outside the Docker network.
PostgreSQL reports an incompatible data directory Major-version image changed without an upgrade Return to the previous image, restore or verify the backup, and perform the documented PostgreSQL major-version upgrade.
Existing data seems missing after a PostgreSQL 18 change The server is looking in a different default directory Check the mounted volume and explicit PGDATA path before initializing anything new.

Self-managed Compose versus a hosted n8n service

Self-managed Compose gives you direct control over the database files, backup schedule, network boundaries, image versions, and restore process. The trade-off is that you own PostgreSQL operations, TLS routing, patching, monitoring, secret handling, and disaster recovery.

A hosted service can reduce container and database administration, but you must evaluate its backup export, encryption-key ownership, webhook networking, OAuth behavior, upgrade timing, scaling model, and data-residency terms. Compare those operational responsibilities and the total monthly cost for your workload rather than comparing subscription prices alone. If you need queue-based execution or multiple workers, treat that as a separate scaling design; this two-container Compose file is a reliable single-instance foundation, not a universal high-availability architecture.

Quick Recap

Bestseller No. 1
CanaKit Raspberry Pi 5 Starter Kit PRO - Turbine Black (128GB Edition) (8GB RAM)
CanaKit Raspberry Pi 5 Starter Kit PRO - Turbine Black (128GB Edition) (8GB RAM)
Includes Raspberry Pi 5 with 2.4Ghz 64-bit quad-core CPU (8GB RAM); CanaKit Turbine Black Case for the Raspberry Pi 5
$259.95
Bestseller No. 4
CanaKit Raspberry Pi 5 Essentials Starter Kit (4GB RAM)
CanaKit Raspberry Pi 5 Essentials Starter Kit (4GB RAM)
CanaKit Raspberry Pi 5 Essentials Starter Kit
$189.99
Bestseller No. 5
CanaKit Raspberry Pi 5 16GB Starter Kit PRO - Turbine Black (128GB Edition) (16GB RAM)
CanaKit Raspberry Pi 5 16GB Starter Kit PRO - Turbine Black (128GB Edition) (16GB RAM)
Includes Raspberry Pi 5 16GB with 2.4Ghz 64-bit quad-core CPU (16GB RAM); CanaKit Turbine Black Case for the Raspberry Pi 5
$419.99

Production readiness checklist

  • PostgreSQL is selected instead of SQLite for the continuous production workload.
  • Both postgres_data and n8n_data are persistent and included in the recovery plan.
  • N8N_ENCRYPTION_KEY is random, stable, protected, and excluded from version control.
  • Database passwords and API secrets are kept out of the repository and image layers.
  • PostgreSQL has a working pg_isready health check, and n8n waits for it.
  • The public hostname, HTTPS protocol, proxy route, webhook URL, and OAuth redirect URIs agree.
  • PostgreSQL is not publicly exposed; only the reverse proxy accepts internet traffic.
  • Image versions are reviewed and pinned, with a documented rollback path.
  • Logical database dumps and matching .n8n backups run on schedule and are stored separately.
  • A restore test proves that credentials decrypt and representative workflows execute.
  • SQLite-to-PostgreSQL migration and PostgreSQL major upgrades are treated as explicit projects.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.