This guide walks you through the process of deploying n8n on Google Cloud with SSL encryption. It covers everything from creating your Google Cloud project to configuring your virtual machine, setting up Cloud SQL for PostgreSQL, and deploying n8n with Docker. Two reverse proxy flows are provided: one using Caddy and an alternate flow using Nginx.
- Prerequisites
- Google Cloud Setup
- Compute Engine Configuration
- Connecting and Installing Docker
- Cloud SQL Configuration
- Deploying n8n with Docker
- Reverse Proxy Setup
- Troubleshooting & Potential Errors
- Additional Techniques
- A Google Cloud account.
- A domain name (if deploying with a domain).
- Basic knowledge of Docker, SSH, and PostgreSQL.
- [Optional] Familiarity with reverse proxy servers (Caddy or Nginx).
- Go to the Google Cloud Console.
- Click the project dropdown (top-left) and select New Project.
- Name your project (e.g.,
<YOUR_PROJECT_NAME>
). - Click Create.
- Navigate to APIs & Services → Library.
- Enable the following APIs:
- Compute Engine API
- Cloud SQL API
- Go to Compute Engine → VM Instances → Create Instance.
- Set the following:
- Name:
n8n-server
- Region: e.g.,
us-central1
- Machine Type:
e2-small
(or as needed) - Boot Disk: Ubuntu 22.04 LTS (default disk size is 10 GB)
- Firewall: Check Allow HTTP traffic and Allow HTTPS traffic
- Name:
- Click Create.
- Stop your VM.
- Edit the VM, click on the Network interface.
- Under External IPv4 address, select Reserve Static IP Address.
- Name it (e.g.,
<STATIC_IP_NAME>
) and click Reserve. - Start your VM.
n8n uses port 5678
for HTTP and 5679
for HTTPS.
- Navigate to VPC Network → Firewall → Create Firewall Rule.
- Configure:
- Name:
allow-n8n
- Targets: All instances in the network
- Source IP ranges:
0.0.0.0/0
(adjust for your security needs) - Protocols and Ports: TCP:
5678,5679
- Name:
- Click Create.
-
Connect to Your VM via SSH:
- Go to Compute Engine → VM Instances
- Click the SSH button for
n8n-server
-
Install Docker:
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh
-
Add Your User to the Docker Group and Reboot:
sudo usermod -aG docker $USER sudo reboot
-
Reconnect via SSH and Verify Docker Installation:
docker --version
- In the GCP Console, navigate to Cloud SQL → Create Instance.
- Select PostgreSQL.
- Configure:
- Instance ID:
n8n-db
- Database Version: PostgreSQL 15
- Region: Same as your VM (e.g., us-central1)
- Machine Type: Choose the smallest option (e.g., 1 vCPU, 0.6 GB RAM)
- Storage: 10 GB (default)
- Instance ID:
- Click Create (this may take a few minutes).
- Go to your n8n-db instance → Databases → Create Database:
- Database Name:
n8n_db
- Database Name:
- Go to Users → Create User Account:
- Username:
n8n_user
- Password:
<YOUR_DB_PASSWORD>
- Username:
- Save your credentials securely.
- In your n8n-db instance → Connections → Networking.
- Under Add Network, paste your VM's external IP address.
- Click Done and then Save.
In your VM's SSH terminal, run:
docker run -d \
--name n8n \
-p 5678:5678 \
-e DB_TYPE=postgresdb \
-e DB_POSTGRESDB_DATABASE=<YOUR_DB_NAME> \
-e DB_POSTGRESDB_HOST=<YOUR_CLOUD_SQL_PUBLIC_IP> \
-e DB_POSTGRESDB_PORT=5432 \
-e DB_POSTGRESDB_USER=<YOUR_DB_USER> \
-e DB_POSTGRESDB_PASSWORD=<YOUR_DB_PASSWORD> \
-e N8N_BASIC_AUTH_ACTIVE=true \
-e N8N_BASIC_AUTH_USER=<YOUR_N8N_USERNAME> \
-e N8N_BASIC_AUTH_PASSWORD=<YOUR_N8N_PASSWORD> \
-e N8N_SECURE_COOKIE=false \
n8nio/n8n
-
Set Up DNS:
- In your domain registrar (e.g., Namecheap), create an A record:
- Host: @ or a subdomain (e.g., n8n)
- Value: Your VM's External IP
- TTL: Automatic
- In your domain registrar (e.g., Namecheap), create an A record:
-
Run n8n with Domain Configuration:
docker run -d \
--name n8n \
-p 5678:5678 \
-e DB_TYPE=postgresdb \
-e DB_POSTGRESDB_DATABASE=<YOUR_DB_NAME> \
-e DB_POSTGRESDB_HOST=<YOUR_CLOUD_SQL_PUBLIC_IP> \
-e DB_POSTGRESDB_PORT=5432 \
-e DB_POSTGRESDB_USER=<YOUR_DB_USER> \
-e DB_POSTGRESDB_PASSWORD=<YOUR_DB_PASSWORD> \
-e N8N_HOST=<YOUR_DOMAIN> \
-e N8N_PROTOCOL=https \
-e N8N_BASIC_AUTH_ACTIVE=true \
-e N8N_BASIC_AUTH_USER=<YOUR_N8N_USERNAME> \
-e N8N_BASIC_AUTH_PASSWORD=<YOUR_N8N_PASSWORD> \
-e WEBHOOK_TUNNEL_URL=https://<YOUR_DOMAIN> \
-e WEBHOOK_URL=https://<YOUR_DOMAIN> \
n8nio/n8n
- Install Caddy:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
- Configure Caddy:
sudo nano /etc/caddy/Caddyfile
Add (replace <YOUR_DOMAIN>):
<YOUR_DOMAIN> {
reverse_proxy localhost:5678
}
- Restart Caddy:
sudo systemctl restart caddy
- Install Nginx:
sudo apt update
sudo apt install nginx
- Obtain SSL Certificates with Certbot:
sudo apt install certbot python3-certbot-nginx
sudo systemctl stop nginx # Temporarily stop Nginx for certificate setup
sudo certbot certonly --standalone -d <YOUR_DOMAIN> --preferred-challenges http --agree-tos -m <YOUR_EMAIL> --non-interactive
sudo systemctl start nginx # Restart Nginx after certificate acquisition
- Configure Nginx:
sudo nano /etc/nginx/sites-available/n8n.conf
Add (replace <YOUR_DOMAIN>):
server {
listen 80;
server_name <YOUR_DOMAIN>;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name <YOUR_DOMAIN>;
ssl_certificate /etc/letsencrypt/live/<YOUR_DOMAIN>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<YOUR_DOMAIN>/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://localhost: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 https;
}
}
- Test and Reload Nginx:
sudo nginx -t
sudo systemctl reload nginx
Scenario: Running psql
returns "Command 'psql' not found"
Solution: Install PostgreSQL client tools
Fix:
sudo apt update
sudo apt install postgresql-client
Scenario: Error when trying to restart PostgreSQL via systemctl
Solution: Manage Cloud SQL instances through GCP Console
Steps:
- Navigate to Cloud SQL in GCP Console
- Select your instance
- Click Restart button
Scenario: "Permission denied" errors when running docker commands
Solution: Add user to docker group and refresh permissions
Fix:
sudo usermod -aG docker $USER
newgrp docker # Refresh group membership without reboot
# If still issues:
sudo reboot
Scenario: Domain not resolving to server IP
Verification:
dig +short <YOUR_DOMAIN>
nslookup <YOUR_DOMAIN>
Tools: Use DNS Checker to monitor global propagation
Scenario: SSL/TLS connection failures or certificate warnings
Diagnosis:
# Verify certificate files exist
sudo ls -l /etc/letsencrypt/live/<YOUR_DOMAIN>/
# Check certificate expiration
sudo certbot certificates
# Test SSL configuration
sudo nginx -T | grep ssl_certificate
Renewal Setup:
# Create renewal cron job
(crontab -l 2>/dev/null; echo "0 12 * * * /usr/bin/certbot renew --quiet") | crontab -
Scenario: Failed reload after configuration changes
Test Configuration:
sudo nginx -t
Common Fixes:
- Check for missing semicolons in config files
- Verify DNS resolution in server_name directives
- Confirm port 443 is open in firewall
-
Automated Backups: Use Cloud SQL's automated exports or:
pg_dump -h <DB_IP> -U <DB_USER> -d <DB_NAME> > backup.sql
-
Monitoring:
docker logs -f n8n
-
Scaling:
- Use managed instance groups for Compute Engine
- Scale Cloud SQL based on load