Tuesday, August 4, 2026

Step-by-Step Guide: Host n8n on AWS EC2 Virtual Private Servers

n8n is a powerful open-source workflow automation platform that connects over 400 applications — and self-hosting it on an AWS EC2 virtual private server gives you unlimited executions at a fraction of the cost of Zapier or n8n Cloud. Amazon EC2, launched in August 2006, lets you rent virtual machines by the second, scaling up or down as your automation needs grow. With n8n raising $180 million in Series C funding in October 2025 and reaching a $2.5 billion valuation, adoption is exploding — but many teams struggle with deployment. Security groups, reverse proxies, environment variables, and persistent storage all trip up first-time deployers. This step-by-step guide walks you through every phase: launching your EC2 instance, installing Docker and n8n, securing traffic with Nginx and SSL, and hardening your server for production. By the end, you will have a fully functional n8n instance running on AWS — ready to automate thousands of workflows per month for under $10 in infrastructure costs.

Quick Answer: To host n8n on AWS EC2, launch a t3.micro Ubuntu 22.04 instance, open ports 22, 80, and 443 in your security group, SSH into the server, install Docker and Docker Compose, create a docker-compose.yml file with the n8n image and a PostgreSQL database, set environment variables for authentication and webhooks, start the container, then configure Nginx as a reverse proxy with Let's Encrypt SSL for HTTPS access.

Why Host n8n on AWS EC2 Instead of Other Platforms

Cost, Control, and Scalability

Self-hosting n8n on AWS EC2 gives you three advantages over managed solutions: predictable costs, full data ownership, and unlimited vertical scaling. AWS held a 31% cloud infrastructure market share as of Q1 2023, making it the most battle-tested provider for long-running workloads. A t3.micro instance costs approximately $8.47 per month (on-demand, us-east-1) and handles dozens of concurrent workflow executions. By contrast, n8n Cloud's Starter plan charges €20 per month for 2,500 executions. If you exceed that limit, costs climb fast — making self-hosting the clear winner for high-volume automation.

AWS vs. Hetzner, DigitalOcean, and Linode

Smaller VPS providers like Hetzner offer cheaper base instances (Hetzner CX22 at approximately €4.59 per month), but AWS wins on ecosystem maturity. You get Route 53 for DNS, ACM for free SSL certificates, CloudWatch for monitoring, and RDS if you ever need a managed database. DigitalOcean and Linode are simpler for beginners, but they lack the breadth of integrated services AWS provides. For teams that expect to grow beyond a single server, starting on AWS avoids a painful migration later.

When EC2 Makes Sense and When It Does Not

Choose AWS EC2 if you need enterprise-grade reliability, regional availability across 30+ regions, or plan to integrate other AWS services. Avoid EC2 if your automation workload is tiny — a $5 DigitalOcean droplet or even a Raspberry Pi at home may suffice. Also avoid EC2 if your team lacks basic Linux administration skills, since a misconfigured security group can expose your n8n instance to the internet.

Prerequisites: What You Need Before Launching EC2

AWS Account Setup

Create an AWS account at aws.amazon.com if you do not have one. AWS offers 750 hours of free t2.micro and t3.micro usage per month for the first 12 months, which is enough to run n8n around the clock for a full year at no compute cost. Enable multi-factor authentication on your root account, then create an IAM user with EC2 administrative privileges for day-to-day operations — never use the root account for routine tasks.

Local Tools and SSH Keys

Install the AWS CLI on your local machine for command-line access. Generate an SSH key pair using ssh-keygen -t ed25519 — ed25519 keys are shorter, faster, and more secure than RSA keys. You will upload the public key to AWS when launching your instance. Also install an SSH client (Terminal on macOS/Linux, PuTTY or Windows Terminal on Windows) and a text editor you are comfortable with.

Domain Name and DNS

For HTTPS access and webhook integrations, you need a domain name pointing to your EC2 instance's public IP. Register a domain through Route 53, Namecheap, or Cloudflare. Create an A record (e.g., n8n.yourdomain.com) pointing to the Elastic IP you will assign to your instance. This step is optional for local testing but mandatory for production workflows that receive webhooks from external services like Stripe, Slack, or Shopify.

Step-by-Step: Launching and Configuring Your EC2 Instance

Step 1 — Launch the EC2 Instance

Log into the AWS Management Console and navigate to EC2. Click Launch Instance and configure the following settings:

  • Name: n8n-production-server
  • AMI: Ubuntu Server 22.04 LTS (HVM), SSD Volume Type — Ubuntu 22.04 receives long-term security updates through 2027
  • Instance type: t3.micro (2 vCPU, 1 GB RAM) for testing or t3.small (2 vCPU, 2 GB RAM) for production workloads
  • Key pair: Select the ed25519 key pair you created earlier
  • Storage: 20 GB gp3 EBS volume (general-purpose SSD, 3,000 IOPS baseline)
  • VPC: Default VPC (or a custom VPC if your organization requires it)

Click Launch instance and wait approximately 60 seconds for the instance to enter the running state.

Step 2 — Configure the Security Group

Your security group acts as a virtual firewall. Navigate to the Security Groups section and add these inbound rules to the default group attached to your instance:

PortProtocolSourcePurpose
22TCPMy IP onlySSH access for administration
80TCP0.0.0.0/0HTTP — redirects to HTTPS
443TCP0.0.0.0/0HTTPS — secure n8n web UI and webhooks

Never open port 5678 (n8n's default port) to 0.0.0.0/0. Nginx will proxy traffic from 443 to 5678 internally, keeping n8n invisible to the public internet.

Step 3 — Assign an Elastic IP

EC2 public IPs change on every reboot. Allocate an Elastic IP from the EC2 console (Elastic IPs → Allocate Elastic IP address), then associate it with your instance. This gives you a static public IP for your DNS A record. AWS charges approximately $3.60 per month for an Elastic IP that is allocated but not associated with a running instance, so keep the instance running or release the IP when not in use.

Step 4 — SSH Into the Server

Connect to your instance using the SSH command AWS provides in the console:

ssh -i ~/.ssh/your-key.ed25519 ubuntu@your-elastic-ip

Update all packages immediately:

sudo apt update && sudo apt upgrade -y

This ensures you have the latest security patches before installing any software.

Installing Docker, n8n, and PostgreSQL

Step 5 — Install Docker Engine and Docker Compose

Docker, first released in 2013, packages applications into lightweight containers that run consistently across environments. Install the official Docker Engine on Ubuntu 22.04:

  1. Add Docker's official GPG key: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
  2. Add the Docker repository to apt sources
  3. Run sudo apt update followed by sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
  4. Add your user to the docker group: sudo usermod -aG docker ubuntu
  5. Log out and SSH back in for the group change to take effect
  6. Verify with docker --version and docker compose version

Step 6 — Create the docker-compose.yml File

Create a project directory and a Docker Compose file that defines three services: n8n, PostgreSQL, and Nginx. PostgreSQL is recommended over SQLite for production because it handles concurrent workflows without file-locking issues. Your docker-compose.yml should define a persistent volume for n8n data (/home/node/.n8n) and another for PostgreSQL data. Set the following critical environment variables on the n8n container:

  • N8N_HOST — your domain name (e.g., n8n.yourdomain.com)
  • N8N_PORT — 5678
  • N8N_PROTOCOL — https
  • WEBHOOK_URL — https://n8n.yourdomain.com/ (must match exactly or webhooks fail silently)
  • N8N_BASIC_AUTH_ACTIVE — true
  • N8N_BASIC_AUTH_USER — your admin username
  • N8N_BASIC_AUTH_PASSWORD — a strong, unique password
  • DB_TYPE — postgresdb
  • DB_POSTGRESDB_HOST — postgres (the service name in Compose)
  • DB_POSTGRESDB_PORT — 5432
  • DB_POSTGRESDB_DATABASE — n8n
  • DB_POSTGRESDB_USER — n8n
  • DB_POSTGRESDB_PASSWORD — a strong database password

Step 7 — Start the Containers

Run docker compose up -d to start all services in detached mode. Check the status with docker compose ps and view logs with docker compose logs n8n. At this point, n8n is running on port 5678 but accessible only from localhost. You need a reverse proxy to expose it securely on port 443.

Securing n8n with Nginx Reverse Proxy and SSL

Step 8 — Install and Configure Nginx

Install Nginx on the host (not in a container, so it can obtain SSL certificates independently): sudo apt install nginx -y. Create a server block configuration file at /etc/nginx/sites-available/n8n that listens on port 80, sets the server_name to your domain, and proxies all traffic to http://127.0.0.1:5678. Key proxy settings include proxy_pass, proxy_set_header Host, X-Real-IP, X-Forwarded-For, and X-Forwarded-Proto. Enable the site with sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/ and test the configuration with sudo nginx -t.

Step 9 — Obtain a Free SSL Certificate with Let's Encrypt

Install Certbot: sudo apt install certbot python3-certbot-nginx -y. Run sudo certbot --nginx -d n8n.yourdomain.com and follow the interactive prompts. Certbot automatically modifies your Nginx config to use the certificate and sets up a systemd timer for automatic renewal. Let's Encrypt certificates are valid for 90 days and renew automatically — verify renewal with sudo certbot renew --dry-run. Once complete, visit https://n8n.yourdomain.com in your browser. You should see the n8n setup screen.

Step 10 — Enable Automatic Container Restarts

Add restart: unless-stopped to each service in your docker-compose.yml so containers recover automatically after reboots or crashes. Enable the Docker daemon to start on boot with sudo systemctl enable docker. Test the full reboot cycle by running sudo reboot, waiting two minutes, and confirming that n8n comes back online at your domain.

Comparison: n8n Hosting Options on AWS

Choosing the right deployment architecture on AWS depends on your traffic volume, budget, and reliability requirements. The table below compares the four most common approaches.

ApproachMonthly Cost (Approx.)Best For
Single t3.micro + Docker Compose$8–12Solo developers and small teams running <500 workflows/day
Single t3.small + Docker Compose$17–22Small teams running 500–2,000 workflows/day with PostgreSQL
t3.medium + ECS Fargate$45–65Mid-size teams needing auto-scaling and zero downtime deployments
EKS cluster with managed node groups$150+Enterprise teams running mission-critical automations with multi-AZ redundancy
n8n Cloud (Starter plan)€20 (~$22)Teams that want zero infrastructure management, capped at 2,500 executions/month

Common Mistakes When Hosting n8n on EC2

Mistake 1 — Exposing Port 5678 Directly to the Internet

Why it hurts: n8n's default port has no SSL encryption. Opening port 5678 to 0.0.0.0/0 means anyone on the internet can access your workflow editor, view your credentials, and execute workflows. This is the single most dangerous misconfiguration.

Fix: Keep port 5678 in the security group restricted to 127.0.0.1 or do not open it at all. Force all traffic through Nginx on port 443 with a valid SSL certificate. Test from an external network using nmap -p 5678 your-elastic-ip — it should show as filtered or closed.

Mistake 2 — Using SQLite Instead of PostgreSQL for Production

Why it hurts: SQLite stores the entire database in a single file. When multiple workflows execute simultaneously, file locks cause executions to fail silently, and your execution history can become corrupted. n8n's official documentation recommends PostgreSQL for all production deployments.

Fix: Use the postgres:14 Docker image in your compose file. Migrate existing SQLite data using n8n's export/import commands: n8n export:workflow --all and n8n import:workflow. Set DB_TYPE to postgresdb and restart.

Mistake 3 — Not Setting the WEBHOOK_URL Environment Variable

Why it hurts: Without a correctly set WEBHOOK_URL, n8n generates webhook endpoints using the internal container hostname (e.g., http://container-id:5678), which external services like Stripe and GitHub cannot reach. Webhooks fail silently with no error in the n8n UI.

Fix: Set WEBHOOK_URL to your full HTTPS domain (e.g., https://n8n.yourdomain.com/) in the n8n environment section of docker-compose.yml. Restart with docker compose restart n8n. Test by creating a Webhook node and sending a POST request from curl.

Mistake 4 — Forgetting to Back Up the .n8n Directory and Database

Why it hurts: All your workflow definitions, credentials, and execution history live in the /home/node/.n8n directory and the PostgreSQL database. An EBS volume failure or accidental docker volume deletion destroys everything with no recovery path.

Fix: Use a cron job to run docker exec postgres pg_dump -U n8n n8n > backup.sql daily and upload the file to an S3 bucket. Set up an S3 lifecycle policy for 30-day retention. Additionally, run docker run --rm -v n8n_data:/data -v $(pwd):/backup alpine tar czf /backup/n8n-data-backup.tar.gz -C /data . weekly for a full volume backup.

Mistake 5 — Choosing the Wrong Instance Type

Why it hurts: A t3.micro has 1 GB RAM, which is barely enough for n8n plus PostgreSQL plus Nginx. When memory runs out, the Linux OOM killer silently terminates the PostgreSQL or n8n process, causing intermittent downtime that is hard to diagnose.

Fix: Monitor memory with htop and CloudWatch. If usage consistently exceeds 80%, upgrade to t3.small (2 GB RAM) or t3.medium (4 GB RAM). Use the AWS CLI: aws ec2 modify-instance-attribute --instance-id i-12345 --instance-type "{\"Value\": \"t3.small\"}" after stopping the instance.

Pro Tips

  • Use AWS Systems Manager Session Manager instead of SSH for access — it eliminates the need to open port 22 and logs every session for audit compliance.
  • Store n8n credentials in AWS Secrets Manager and inject them as environment variables at container startup using a custom entrypoint script.
  • Set N8N_CONCURRENCY_PRODUCTION_LIMIT to 5 or 10 to prevent a single runaway workflow from consuming all CPU on small instances.
  • Enable N8N_METRICS=true to expose Prometheus-compatible metrics, then use CloudWatch Container Insights or a Grafana dashboard for real-time visibility.
  • Place your EC2 instance in a private subnet with a NAT gateway for production — this prevents direct inbound traffic and routes all outbound calls through a controlled path.

FAQ

What is n8n and why would I self-host it on AWS EC2?

n8n is a source-available workflow automation platform founded in 2019 that connects over 400 applications through a visual, node-based editor. Self-hosting on AWS EC2 gives you unlimited workflow executions, full ownership of your data, and integration with AWS services like S3, RDS, and CloudWatch. You pay only for compute — approximately $8 to $22 per month — versus €20 to €200 for n8n Cloud plans with execution caps.

How does hosting n8n on EC2 compare to using n8n Cloud or Zapier?

EC2 hosting costs less at scale but requires Linux administration skills and ongoing maintenance. n8n Cloud offers zero-infrastructure management but caps executions at 2,500 per month on the Starter plan. Zapier charges $29.99 per month for 750 tasks, making it 3 to 10 times more expensive than self-hosted n8n for high-volume automations. Choose EC2 for cost control and customization; choose managed services for simplicity.

How do I update n8n to the latest version on my EC2 instance?

SSH into your server, navigate to your docker-compose.yml directory, and pull the latest image with docker compose pull n8n. Then recreate the container with docker compose up -d. Docker Compose preserves your volumes and environment variables, so no data is lost. The entire process takes under two minutes with near-zero downtime, and the updated n8n instance restarts automatically with your existing workflows intact.

Why is my n8n webhook not receiving data from external services?

The most common cause is an incorrect WEBHOOK_URL environment variable — it must exactly match your HTTPS domain including the trailing slash. Second, verify that your security group allows inbound traffic on port 443 from 0.0.0.0/0. Third, check that Nginx is running and proxying to port 5678 with sudo systemctl status nginx. Finally, test the webhook endpoint directly using curl -X POST https://n8n.yourdomain.com/webhook/test to confirm the full request path works.

Will n8n on EC2 scale to handle thousands of workflows per day?

A single t3.small instance comfortably handles 1,000 to 2,000 workflow executions per day with PostgreSQL and proper concurrency limits. For higher volumes, upgrade to t3.medium or large instances, enable n8n's queue mode with Redis and additional worker processes, or migrate to ECS Fargate for auto-scaling. AWS's elastic infrastructure means you can start small and scale vertically or horizontally as your automation traffic grows — no architectural rewrite required.

Conclusion

Hosting n8n on AWS EC2 gives you a production-grade workflow automation platform for under $25 per month, complete with SSL encryption, PostgreSQL persistence, and automatic container restarts. The ten steps in this guide — from launching your instance to configuring Nginx and Let's Encrypt — cover everything needed for a secure, reliable deployment. AWS's pay-as-you-go model, launched in 2006 and refined over nearly two decades, means you only pay for what you use, and scaling up to thousands of daily executions requires nothing more than a instance type change or an ECS migration. Avoid the five common mistakes above, back up your data daily, and monitor memory with CloudWatch to keep your automations running without interruption.

  • A t3.micro or t3.small EC2 instance running Ubuntu 22.04, Docker, and n8n costs $8 to $22 per month and handles hundreds of daily workflow executions.
  • Always use Nginx as a reverse proxy with Let's Encrypt SSL — never expose port 5678 directly to the internet.
  • Use PostgreSQL instead of SQLite for production deployments to avoid file-locking corruption during concurrent executions.
  • Back up the PostgreSQL database and /home/node/.n8n volume to S3 daily using cron and pg_dump.

Sources

Share:

0 comments:

Post a Comment