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

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 Name | CPU | RAM | NVMe Storage | Price (Per Month) | Best For |
|---|---|---|---|---|---|
| KVM1-US | 1 vCore | 1 GB | 20 GB | $10 | Testing/Light Use |
| KVM2-US | 2 vCores | 2 GB | 25 GB | $20 | Typical Workloads |
| KVM4-US | 4 vCores | 4 GB | 40 GB | $40 | Heavy 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 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.comto 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

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.