Docker, PostgreSQL, and Caddy (LAN HTTPS)
This guide walks through installing n8n on Ubuntu Server 24.04 using Docker Compose with PostgreSQL for persistence and Caddy for internal LAN HTTPS.
We will configure Pi-hole for local DNS, set up environment variables in a .env file, and build a sample workflow integrating with Ollama AI.
Ubuntu Server 24.04 with internet access
Pi-hole or other DNS server for local hostname resolution
Entry in Pi-hole local DNS:
n8n.lan -> <server-ip>
Example: n8n.lan -> 10.10.0.109
Ollama server accessible at 10.10.0.60:11434
Use the KeepItTechie Docker install script:
wget https://wiki.kitpro.us/install-docker.sh
sudo chmod +x install-docker.sh
./install-docker.sh
Log out and back in, or run:
newgrp docker
to use Docker without sudo.
sudo mkdir -p /opt/n8n
sudo chown -R $USER:$USER /opt/n8n
cd /opt/n8n
.env Filecat > .env << 'EOF'
# Postgres
POSTGRES_USER=n8n
POSTGRES_PASSWORD=supersecret_local_only
POSTGRES_DB=n8n
# n8n
N8N_ENCRYPTION_KEY=REPLACE_WITH_A_BASE64_KEY
N8N_PROTOCOL=https
N8N_HOST=n8n.lan
N8N_PORT=5678
WEBHOOK_URL=https://n8n.lan/
GENERIC_TIMEZONE=America/Los_Angeles
N8N_SECURE_COOKIE=true
# n8n -> Postgres connection
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}
# Caddy
DOMAIN=n8n.lan
[email protected]
EOF
Generate a base64 encryption key:
openssl rand -base64 32
Caddyfilecat > Caddyfile << 'EOF'
{$DOMAIN} {
tls internal
encode gzip
reverse_proxy n8n:5678
}
EOF
docker-compose.ymlcat > docker-compose.yml << 'EOF'
services:
postgres:
image: postgres:16
container_name: n8n-postgres
restart: unless-stopped
env_file: .env
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
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
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
env_file: .env
environment:
- DB_TYPE=${DB_TYPE}
- DB_POSTGRESDB_HOST=${DB_POSTGRESDB_HOST}
- DB_POSTGRESDB_PORT=${DB_POSTGRESDB_PORT}
- DB_POSTGRESDB_DATABASE=${DB_POSTGRESDB_DATABASE}
- DB_POSTGRESDB_USER=${DB_POSTGRESDB_USER}
- DB_POSTGRESDB_PASSWORD=${DB_POSTGRESDB_PASSWORD}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_PROTOCOL=${N8N_PROTOCOL}
- N8N_HOST=${N8N_HOST}
- N8N_PORT=${N8N_PORT}
- WEBHOOK_URL=${WEBHOOK_URL}
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- N8N_SECURE_COOKIE=${N8N_SECURE_COOKIE}
volumes:
- n8n_data:/home/node/.n8n
caddy:
image: caddy:2
container_name: n8n-caddy
restart: unless-stopped
depends_on:
- n8n
environment:
- DOMAIN=${DOMAIN}
- EMAIL=${EMAIL}
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
postgres_data:
n8n_data:
caddy_data:
caddy_config:
EOF
docker compose pull
docker compose up -d
docker compose ps
Access n8n at:
https://n8n.lan
ai-promptTest URL example:
https://n8n.lan/webhook-test/ai-prompt
http://10.10.0.60:11434/api/generate{
"model": "llama3.2",
"prompt": "{{$json['body']['prompt']}}",
"stream": false,
"options": { "temperature": 0.2 }
}
{{$json["response"]}}
During design mode:
curl -k -X POST -H "Content-Type: application/json" \
-d '{"prompt":"Give me a Linux tip."}' \
https://n8n.lan/webhook-test/ai-prompt
After activation (production URL):
curl -k -X POST -H "Content-Type: application/json" \
-d '{"prompt":"Give me a Linux tip."}' \
https://n8n.lan/webhook/ai-prompt
Update:
docker compose pull
docker compose up -d
docker image prune -f
Backup n8n volume:
docker run --rm -v n8n_n8n_data:/data busybox tar -czf - /data > n8n_data.tgz
docker compose logs postgres
docker compose logs n8n
docker compose logs caddy
dig n8n.lan
curl http://10.10.0.60:11434/api/tags
This guide was created alongside a YouTube tutorial by Josh from KeepItTechie.
Watch the full video: https://youtu.be/dEAg-ZIcfeo
Visit the channel: https://www.youtube.com/c/KeepItTechie