🇯🇵 Tokyo is live! 🚀 Launch your VPS and enjoy 2 months off — use code KONNICHIWA50 🎉 Get Started Today →

How to Self-Host n8n with Docker on a VPS (Step-by-Step Guide)

Comparison of SaaS and Self-Hosting with laptops, cloud icon, and server stacks on a dark blue background.

Want full control over your n8n automation workflows? This guide shows you how to self-host n8n on a VPS using Docker. Self-hosting ensures your data stays secure, avoids subscription fees, and lets you scale resources as needed. Here’s what you’ll learn:

  • Why n8n and self-hosting make sense: Automate tasks across 400+ apps with a visual workflow editor while keeping sensitive data private.
  • Why VPS.us is a great choice: Affordable plans starting at $10/month, fast provisioning, and U.S.-based data centers for low-latency performance.
  • Step-by-step deployment: From setting up a VPS, installing Docker, configuring DNS/HTTPS, and deploying n8n with PostgreSQL.

Step 1: Set Up Your VPS.us Environment

VPS.us

Getting your VPS.us server ready for n8n involves three main steps: provisioning the server, configuring it, and installing Docker. These steps lay the groundwork for a smooth and stable n8n deployment.

Provision a VPS.us Server

Start by choosing a VPS.us plan that matches your n8n needs. For most workflows, the KVM2-US plan at $20/month is a great choice. It offers 2 vCores, 2 GB RAM, and 25 GB of NVMe storage, which is sufficient for moderate automation tasks, multiple integrations, and several concurrent users without performance hiccups.

If you’re dealing with heavier workloads, such as complex data processing or numerous simultaneous workflows, consider the KVM4-US plan at $40/month. This doubles the resources to 4 vCores and 4 GB RAM, ensuring optimal performance.

To minimize latency, select a U.S. data center location close to your team or primary services. VPS.us provides Atlantafor East Coast users and Los Angeles for those on the West Coast. This proximity can significantly improve the responsiveness of time-sensitive automations and webhook triggers.

Plan NameCPURAMNVMe StoragePrice (Per Month)Best For
KVM1-US1 vCore1 GB20 GB$10Testing/Light Use
KVM2-US2 vCores2 GB25 GB$20Typical Workloads
KVM4-US4 vCores4 GB40 GB$40Heavy Workloads

Once you’ve selected your plan and location, click “Get started Now” on the VPS.us website. The provisioning process typically takes 2-5 minutes, after which you’ll receive root access credentials to your new server.

Initial VPS Setup and Configuration

After provisioning, connect to your server via SSH using the credentials provided. For macOS or Linux, open Terminal and type:

ssh root@your_server_ip

On Windows, use Windows Terminal (with built-in SSH support) or download PuTTY if you’re on an older version of Windows. If you run into connection problems, double-check the server IP in your VPS.us control panel and ensure your firewall allows traffic on port 22.

Once connected, update your system to ensure it’s secure and up-to-date:

apt update && apt upgrade -y

Next, set the appropriate time zone for your operations. For East Coast users:

timedatectl set-timezone America/New_York

For West Coast users:

timedatectl set-timezone America/Los_Angeles

Then, configure the locale for U.S. English settings:

dpkg-reconfigure locales

Select en_US.UTF-8 and set it as the default. This ensures proper formatting for dates, numbers, and currency in your workflows. Verify your settings using:

date
locale

With these configurations complete, you’re ready to install Docker and Docker Compose.

Install Docker and Docker Compose

Docker webpage promoting AI development tools with "Develop AI" headline, buttons for downloading Docker Desktop, and learning about Docker for AI.

Docker simplifies the management, updating, and scaling of your n8n deployment by containerizing it. First, remove any existing Docker installations to avoid conflicts:

apt remove docker docker-engine docker.io containerd runc

Install the necessary packages to add Docker’s official repository:

apt install apt-transport-https ca-certificates curl software-properties-common

Add Docker’s GPG key for secure package verification:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Then, add the Docker repository to your system:

echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

Update your package list and install Docker:

apt update
apt install docker-ce docker-ce-cli containerd.io

To confirm Docker is installed correctly, run:

docker run hello-world

You should see a confirmation message that Docker is working.

Now, install Docker Compose. Download the latest stable version:

curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Make it executable:

chmod +x /usr/local/bin/docker-compose

Verify the installation:

docker-compose --version

Finally, add your user to the Docker group so you can run commands without using sudo:

usermod -aG docker $USER

Log out and back in for the changes to take effect, or run:

newgrp docker

Your VPS.us server is now fully prepared for n8n deployment. The next step is setting up DNS and HTTPS to ensure your n8n instance is accessible and secure.

Step 2: Configure DNS and Set Up HTTPS

Once your server is ready, the next step is connecting your domain and securing it with HTTPS. This ensures your n8n instance is accessible via a user-friendly URL and protected with SSL encryption.

Set Up DNS Records

If you’re using VPS.us, they provide a free domain with all KVM plans, simplifying DNS setup through their control panel.

For external domains, you’ll need to manually create an A record that links your domain to your server’s public IP address. Here’s how to configure the DNS settings through your domain registrar:

  • A record: Point your root domain (e.g., yourdomain.com) to your VPS.us server’s IP address.
  • A record: Point your n8n subdomain (e.g., n8n.yourdomain.com) to the same IP address.
  • CNAME record (optional): Redirect www.yourdomain.com to your root domain.

Set the TTL (Time To Live) to 300 seconds (5 minutes) initially. This shorter value speeds up propagation during setup. Once the setup is complete, you can increase it to 3,600 seconds (1 hour) for better performance.

DNS propagation in the United States typically takes 15-30 minutes, but globally, it might take up to 24-48 hours. To check if the DNS records have propagated, run this command:

dig n8n.yourdomain.com

The output should display your server’s IP address. If it doesn’t, wait a bit longer for propagation to finish. Once your DNS records are active, move on to securing your connection with HTTPS.

Enable HTTPS with Let’s Encrypt

Let’s Encrypt offers free SSL certificates, making it easy to secure your n8n instance.

Start by installing Certbot, the official Let’s Encrypt client:

apt install snapd
snap install core; snap refresh core
snap install --classic certbot

To make Certbot available system-wide, create a symbolic link:

ln -s /snap/bin/certbot /usr/bin/certbot

Before generating your SSL certificates, you’ll need to set up Nginx as a reverse proxy for n8n:

apt install nginx
systemctl start nginx
systemctl enable nginx

Create a new Nginx configuration file for your n8n domain:

nano /etc/nginx/sites-available/n8n.yourdomain.com

Add the following configuration:

server {
    listen 80;
    server_name n8n.yourdomain.com;

    location / {
        proxy_pass http://localhost:5678;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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;
        proxy_cache_bypass $http_upgrade;
    }
}

Enable the site and test the configuration:

ln -s /etc/nginx/sites-available/n8n.yourdomain.com /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

Now, generate your SSL certificate using Certbot:

certbot --nginx -d n8n.yourdomain.com

Certbot will automatically update your Nginx configuration to include SSL settings and redirect HTTP traffic to HTTPS. The entire process takes about 30-60 seconds, including domain verification.

To ensure your certificates renew automatically, test the renewal process:

certbot renew --dry-run

If successful, Certbot will handle renewals automatically 30 days before expiration using a systemd timer.

Alternative Option: Cloudflare Tunnel

For an additional security layer, you can use Cloudflare Tunnel instead of exposing HTTPS directly. This method routes traffic through Cloudflare’s network, eliminating the need to open ports 80 or 443 on your server.

Start by installing the Cloudflare daemon:

wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
dpkg -i cloudflared-linux-amd64.deb

Log in to your Cloudflare account and authenticate the daemon:

cloudflared tunnel login

Create a new tunnel for your n8n instance:

cloudflared tunnel create n8n-tunnel

Set up the tunnel configuration file:

nano ~/.cloudflared/config.yml

Add this configuration:

tunnel: n8n-tunnel
credentials-file: /root/.cloudflared/[tunnel-id].json

ingress:
  - hostname: n8n.yourdomain.com
    service: http://localhost:5678
  - service: http_status:404

Next, create a DNS record in Cloudflare that links to your tunnel:

cloudflared tunnel route dns n8n-tunnel n8n.yourdomain.com

Finally, start the tunnel as a system service:

cloudflared service install
systemctl start cloudflared
systemctl enable cloudflared

Using Cloudflare Tunnel eliminates the need for Let’s Encrypt certificates, as Cloudflare manages SSL termination. It also offers DDoS protection and access to traffic analytics through the Cloudflare dashboard.

To confirm your HTTPS setup is working, visit https://n8n.yourdomain.com in your browser and check for the padlock icon next to the URL. Alternatively, you can test the connection using curl:

curl -v https://n8n.yourdomain.com

If the response is successful, your SSL is properly configured, and your domain is securely connected to your VPS.us server, ready for n8n deployment.

Step 3: Deploy n8n with Docker Compose and PostgreSQL

n8n website homepage featuring "Flexible AI workflow automation for technical teams" text, lightning bolt graphic, and navigation menu.

After setting up a secure connection, the next step is deploying n8n using Docker Compose and integrating PostgreSQL for efficient data management. Using PostgreSQL instead of the default SQLite ensures better performance, especially for production environments handling over 5,000–10,000 daily executions.

Prepare the Docker Environment

Start by creating a dedicated directory for your deployment files:

mkdir /opt/n8n && cd /opt/n8n

Next, create a .env file to securely store environment variables:

nano .env

Add the following configuration to your .env file:

# PostgreSQL Configuration
POSTGRES_USER=n8n
POSTGRES_PASSWORD=your_secure_password_here
POSTGRES_DB=n8n

# n8n Database Configuration
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=your_secure_password_here
DB_POSTGRESDB_SCHEMA=public

# n8n Security Configuration
N8N_ENCRYPTION_KEY=your_very_long_random_encryption_key_here
N8N_BASIC_AUTH_ACTIVE=true
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=your_admin_password_here

# n8n Network Configuration
N8N_HOST=n8n.yourdomain.com
N8N_PROTOCOL=https
WEBHOOK_URL=https://n8n.yourdomain.com/

# n8n Performance Configuration
N8N_RUNNERS_ENABLED=true
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
GENERIC_TIMEZONE=America/New_York
TZ=America/New_York

Replace the placeholder values with your actual details. Make sure the N8N_ENCRYPTION_KEY is a long, random string (at least 32 characters) to encrypt sensitive credentials. Keep this key safe – losing it means you won’t be able to decrypt stored credentials.

Now, create the docker-compose.yml file:

nano docker-compose.yml

Insert the following configuration:

version: '3.8'

services:
  postgres:
    image: postgres:16-alpine
    container_name: n8n-postgres
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 30s

  n8n:
    image: n8nio/n8n:latest
    container_name: n8n-app
    restart: unless-stopped
    user: "1000:1000"
    env_file:
      - .env
    ports:
      - "5678:5678"
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:5678/healthz || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

volumes:
  n8n_data:
  postgres_data:

This setup is designed to ensure PostgreSQL is ready before n8n starts, avoiding connection issues during initialization.

Configure PostgreSQL for n8n

In the provided docker-compose.yml file, PostgreSQL is set up with features suitable for production. Persistent storage is enabled through the postgres_data volume, ensuring that workflows, execution logs, and credentials remain intact across container restarts or updates.

The DB_POSTGRESDB_HOST=postgres environment variable directs n8n to communicate with PostgreSQL using Docker Compose’s internal network. Additionally, running n8n as a non-root user (user: "1000:1000") enhances security and avoids permission issues with mounted volumes.

Start and Verify the Deployment

Run the following command to launch the containers:

docker compose up -d

Check the status of the containers:

docker compose ps

If any container appears “unhealthy” or keeps restarting, inspect the logs:

docker compose logs -f postgres
docker compose logs -f n8n

PostgreSQL logs should confirm successful database initialization, while n8n logs should indicate a successful database connection and migration with messages like “Database migration completed” and “n8n ready on 0.0.0.0, port 5678.”

Once everything is running, head to https://n8n.yourdomain.com in your browser. During the initial setup, you’ll be prompted to create an owner account. Afterward, you can choose to disable basic authentication in the .env file, though keeping it enabled adds an extra layer of protection.

Test PostgreSQL Integration

To confirm PostgreSQL is working, create a simple workflow in the n8n interface. For example, use a “Schedule Trigger” or “Manual Trigger” node, save the workflow, and execute it. Then restart the n8n container:

docker compose restart n8n

After the restart, log back into n8n and verify that your test workflow and its execution history are still present. This confirms that PostgreSQL is correctly handling data persistence.

With this setup, your n8n deployment is now equipped to handle up to 50,000 daily workflow executions, offering the scalability and reliability needed for demanding automation tasks.

Step 4: Secure, Back Up, and Maintain Your Deployment

Once your deployment is up and running, the next step is ensuring it’s safe, reliable, and ready for long-term use. Here’s how to strengthen your setup and keep it running smoothly.

Strengthen Security for Production

Start by managing credentials carefully. Go beyond the basics – like the authentication credentials in your .env file – and make adjustments to harden security. For instance, change your VPS’s default SSH port from 22 to a custom port, such as 2222. This small tweak can significantly reduce the likelihood of automated brute-force attacks.

Use UFW (Uncomplicated Firewall) to permit only the services you need. For added control, restrict administrative access to specific IPs, especially if your team works from known locations. Here’s an example:

sudo ufw allow from YOUR_OFFICE_IP to any port 2222  # Custom SSH port
sudo ufw allow from YOUR_OFFICE_IP to any port 443   # HTTPS for n8n
sudo ufw deny 5678/tcp   # Block direct access to n8n port
sudo ufw enable

This setup ensures that n8n is only accessible via HTTPS. To further secure your environment, enable HS Shield(available in the VPS.us control panel) for DDoS protection. This feature blocks malicious traffic before it can disrupt your server.

Make it a habit to rotate encryption keys and passwords every 90 days. For example, the N8N_ENCRYPTION_KEY in your .env file secures stored credentials in your workflows. You can generate a new 32-character random key with:

openssl rand -base64 32

Set Up Backups to Protect Your Data

Daily backups are critical to safeguarding your data. Back up both your PostgreSQL database and n8n data regularly, and store these backups externally. Here’s a sample script:

#!/bin/bash
BACKUP_DIR="/opt/backups"
DATE=$(date +%Y%m%d_%H%M%S)

# Create backup directory
mkdir -p $BACKUP_DIR

# Backup PostgreSQL database
docker compose exec -T postgres pg_dump -U n8n n8n > $BACKUP_DIR/n8n_db_$DATE.sql

# Backup n8n data volume
docker run --rm -v n8n_n8n_data:/data -v $BACKUP_DIR:/backup alpine tar czf /backup/n8n_data_$DATE.tar.gz -C /data .

# Upload to external storage (example with AWS S3)
aws s3 cp $BACKUP_DIR/n8n_db_$DATE.sql s3://your-backup-bucket/n8n/
aws s3 cp $BACKUP_DIR/n8n_data_$DATE.tar.gz s3://your-backup-bucket/n8n/

# Clean up local backups older than 7 days
find $BACKUP_DIR -name "n8n_*" -mtime +7 -delete

Schedule this script to run daily at 2:00 AM with cron:

0 2 * * * /opt/n8n/backup.sh

Store these backups on a cloud service like AWS S3, Google Cloud Storage, or even a secondary VPS. This setup ensures you can quickly restore your deployment if something goes wrong.

To ensure your backups work when needed, test restoring them monthly. Use a staging environment to practice recovery. This step can save you from prolonged downtime during emergencies.

Routine Maintenance and Monitoring

Maintaining your deployment involves more than just security and backups. Regular updates and monitoring are just as important. Automate system updates and Docker image pulls during low-traffic hours with a script like this:

#!/bin/bash
# Update system packages
sudo apt update && sudo apt upgrade -y

# Pull latest Docker images
cd /opt/n8n
docker compose pull

# Restart containers with new images
docker compose up -d

# Clean up unused Docker resources
docker system prune -f

Schedule this script to run monthly, preferably during a low-traffic period, such as Sunday nights at 3:00 AM if your users are primarily in the US.

For monitoring, use VPS.us’s AlwaysOn Access along with external tools. AlwaysOn Access ensures you can manage your VPS even if the operating system becomes unresponsive. Pair this with services like UptimeRobot to monitor your n8n endpoint every five minutes. Set up alerts for:

  • HTTP response time (keep it under 2 seconds)
  • SSL certificate expiration (get notified 30 days before expiry)
  • Disk space usage (alert if usage exceeds 80%)
  • Memory consumption (flag PostgreSQL or n8n containers using over 1.5 GB of RAM)

Review security logs weekly to spot unusual activity. For example:

# Review firewall logs
sudo grep "UFW BLOCK" /var/log/ufw.log | tail -20

# Check n8n container logs for errors
docker compose logs n8n | grep -i error | tail -10

Every quarter, conduct a security audit. Review user accounts, update firewall rules, and rotate API keys for external services. Document any changes and keep an incident response plan handy, complete with team contact information and recovery steps.

Conclusion: Key Takeaways and Next Steps

You’ve set up a complete n8n automation platform on VPS.us infrastructure, giving you total control over your workflows while ensuring the reliability and flexibility needed for demanding automation tasks. This setup combines the power of self-hosting with the enterprise-level features required for scaling and performance.

From provisioning your VPS.us server to implementing advanced security and backup strategies, you’ve unlocked the key advantages of self-hosting. With a Docker-based n8n deployment, you can integrate with over 300 services and platforms, all while keeping your data securely under your management.

The KVM kernel isolation in your VPS.us environment provides a solid base for handling advanced workflows. Features like AlwaysOn Access ensure you can manage your platform even during unexpected system challenges. This robust performance means your n8n instance can handle complex automation tasks without breaking a sweat, setting the stage for smooth scaling as your needs grow.

The containerized Docker setup is a game-changer for deployment and scaling. When it’s time to expand, upgrading your VPS plan is straightforward, with seamless migration and data retention making the process hassle-free.

Your focus on security – using encrypted HTTPS connections and strong configurations – has prepared your deployment for production use. Automated backups protect against data loss, and the monitoring setup ensures potential issues are caught early, keeping your workflows running smoothly. Together, these strategies transform your n8n platform into a reliable, mission-critical tool.

Looking ahead, consider enhancing your setup further. VPS.us’s HS Shield Firewall offers an extra layer of protection against external threats, while automated snapshots through the control panel provide additional recovery options. As your team expands, you can rely on 24/7 support to ensure expert help is always within reach.

Facebook
Twitter
LinkedIn

Table of Contents

Get started today

With VPS.US VPS Hosting you get all the features, tools

Image