DEV Community

Cover image for How I deploy n8n on a VPS with Docker + Nginx + HTTPS
Tahsin Abrar
Tahsin Abrar

Posted on

How I deploy n8n on a VPS with Docker + Nginx + HTTPS

I show a simple, copy-paste friendly flow to install Docker, run the n8nio/n8n image, fix common problems, and put n8n behind Nginx with a Let’s Encrypt certificate. Use HTTPS in production — don’t disable secure cookies unless it’s only for quick local testing.


What you need first

  • A VPS (Ubuntu 20.04 / 22.04 works fine).
  • A domain name with an A record pointing to your VPS IP.
  • A user with sudo (or root).
  • Docker installed (instructions below).
  • Basic CLI skills (copy/paste commands).

1. Install Docker (quick & reliable)

If you hit package errors like docker-ce has no installation candidate, use Docker’s install script:

# Remove old packages (safe)
sudo apt remove docker docker-engine docker.io containerd runc -y

# Update
sudo apt update && sudo apt upgrade -y

# Install with Docker convenience script
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Verify
docker --version
sudo docker run hello-world
Enter fullscreen mode Exit fullscreen mode

If hello-world runs and prints a message, Docker is good.


2. Check images & containers

Useful commands to inspect state:

# List images
docker image ls

# List running containers
docker ps

# List all containers (running or stopped)
docker ps -a

# Show logs for a container
docker logs n8n        # or docker logs <container_id>

# Remove broken container
docker rm -f n8n      # force remove if exists
Enter fullscreen mode Exit fullscreen mode

If docker ps shows nothing, no container is running. If your container is Exited (1), check docker logs for the error.


3. Prepare persistent storage and permissions

n8n stores data in /home/node/.n8n inside the container. On the host, we map it to ~/.n8n. Make sure permissions are right:

mkdir -p ~/.n8n
sudo chown -R 1000:1000 ~/.n8n
Enter fullscreen mode Exit fullscreen mode

1000:1000 is the typical UID/GID for the node user in the n8n image — gives the container write access.


4. Run n8n (simple)

A safe, detached run:

docker run -d \
  --name n8n \
  -p 5678:5678 \
  -v ~/.n8n:/home/node/.n8n \
  n8nio/n8n
Enter fullscreen mode Exit fullscreen mode

Check docker ps — status should be Up and port mapping 0.0.0.0:5678->5678/tcp.


5. Common problems & fixes

a. docker run fails with name conflict
Docker says the name is in use. Remove the existing container (use its ID or name):

docker ps -a
docker rm -f <container_id_or_name>
Enter fullscreen mode Exit fullscreen mode

Then run again.

b. Container starts then immediately exits (Exited (1))
Check logs:

docker logs <container_id_or_name>
Enter fullscreen mode Exit fullscreen mode

Common causes:

  • Permission error on ~/.n8n → fix with chown -R 1000:1000 ~/.n8n.
  • Port in use → check sudo lsof -i -P -n | grep LISTEN or change mapping -p 8080:5678.
  • Missing env vars for DB if you configured one.

c. docker image not found / package install errors
Use the get.docker.com script as shown in Step 1 — it avoids repo misconfiguration.


6. Secure n8n for the web (recommended)

n8n uses secure cookies by default. It will warn if you access it via plain HTTP or in some browsers (Safari). Best fix: put n8n behind Nginx with HTTPS.

Nginx config (simple)

Create /etc/nginx/sites-available/n8n.conf (via CLI):

sudo tee /etc/nginx/sites-available/n8n.conf > /dev/null <<'EOF'
server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:5678;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF
Enter fullscreen mode Exit fullscreen mode

Enable and test:

sudo ln -s /etc/nginx/sites-available/n8n.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

Get TLS with Certbot (CLI)

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com --non-interactive --agree-tos -m your-email@example.com
Enter fullscreen mode Exit fullscreen mode

Now open https://yourdomain.com — secure cookie warnings should disappear.

Do not set N8N_SECURE_COOKIE=false in production. That disables an important security check. Only use it for local testing if needed.


7. Add basic auth (optional but safe)

For a simple protection layer, enable n8n basic auth:

docker rm -f n8n
docker run -d \
  --name n8n \
  -p 5678:5678 \
  -v ~/.n8n:/home/node/.n8n \
  -e N8N_BASIC_AUTH_ACTIVE=true \
  -e N8N_BASIC_AUTH_USER=admin \
  -e N8N_BASIC_AUTH_PASSWORD=StrongPasswordHere \
  n8nio/n8n
Enter fullscreen mode Exit fullscreen mode

With Nginx + HTTPS + Basic Auth you have better protection.


8. Docker Compose example (optional)

A small docker-compose.yml you can expand later:

version: "3.8"
services:
  n8n:
    image: n8nio/n8n
    container_name: n8n
    ports:
      - "5678:5678"
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=StrongPasswordHere
    volumes:
      - ~/.n8n:/home/node/.n8n
    restart: unless-stopped
Enter fullscreen mode Exit fullscreen mode

Run with:

docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Top comments (0)