docker compose setup for running n8n with FFmpeg and Docker CLI baked into the image. Caddy sits in front for automatic HTTPS. the whole stack auto-starts on boot via systemd.
docker compose up -dextends the official n8n Alpine image with two packages:
- FFmpeg — so n8n workflows can transcode, convert, and manipulate audio/video via execute command nodes
- docker-cli — so n8n workflows can control the host Docker daemon through the mounted socket
the node user (n8n's runtime user) gets added to the docker group for socket access without root.
two containers on a shared compose network:
| service | image | role |
|---|---|---|
n8n |
custom build from Dockerfile |
workflow engine on port 5678, FFmpeg + Docker CLI available |
caddy |
caddy:latest |
TLS-terminating reverse proxy on 80/443, auto Let's Encrypt certs |
| volume | type | what it stores |
|---|---|---|
n8n_data |
external, named | workflows, credentials, execution history (/home/node/.n8n) |
caddy_data |
external, named | TLS certificates and ACME state |
./local_files |
bind mount | shared file staging area at /files — drop media in, FFmpeg outputs land here |
/var/run/docker.sock |
bind mount | host Docker socket, gives n8n container control over host daemon |
both named volumes are external: true — you need to create them before first run. this is intentional to prevent accidental data loss from docker compose down -v.
docker volume create n8n_data
docker volume create caddy_dataedit .env or set values directly in docker-compose.yml:
N8N_HOST=n8n.local
N8N_PORT=5678
N8N_PROTOCOL=https
NODE_ENV=production
WEBHOOK_URL=https://n8n.local/
GENERIC_TIMEZONE=America/New_Yorkreplace n8n.local with your actual domain or add it to /etc/hosts.
create caddy_config/Caddyfile to proxy traffic to n8n:
n8n.local {
reverse_proxy n8n:5678
}
docker compose up -dn8n is at https://n8n.local. direct access also available at http://localhost:5678.
create a systemd unit at /etc/systemd/system/docker-compose.service:
[Unit]
Description=Docker Compose Service
After=network.target docker.service
Requires=docker.service
[Service]
Type=oneshot
User=root
WorkingDirectory=/path/to/your/n8n-ffmpeg-stack
ExecStart=/usr/bin/docker compose build --no-cache
ExecStartPost=/usr/bin/docker compose up -d
RemainAfterExit=true
[Install]
WantedBy=multi-user.targetthen enable it:
sudo systemctl enable --now docker-compose.servicerebuilds the image fresh and starts the stack on every boot.
drop a video into local_files/, then use an n8n execute command node:
ffmpeg -i /files/input-video.mp4 -q:a 0 -map a /files/output-audio.mp3the output lands in local_files/ on the host. n8n can then continue the workflow — upload to cloud storage, send a notification, call an API, whatever.
the Docker socket mount gives the n8n container root-equivalent access to the host. don't expose this to untrusted users or the open internet without additional safeguards.
MIT