Unlock the power of workflow automation with n8n on Hetzner Cloud! At Blorax, we’re always looking for ways to help our clients optimize their operations and achieve peak efficiency. That’s why we’re excited to share this comprehensive guide on deploying n8n, a powerful and versatile open-source workflow automation platform, on Hetzner Cloud. This guide includes integrating Redis for improved performance and scalability, ensuring a smooth and reliable automation experience.
Table of Contents
Why n8n on Hetzner Cloud?
- Hetzner Cloud: Offers cost-effective, high-performance cloud servers focusing on reliability and scalability.
- n8n: Provides a visual, node-based interface for designing and automating complex workflows across various applications and services.
- Redis: Enhances n8n’s performance by providing efficient queue management, which is especially crucial for handling concurrent workflow executions.
This guide is perfect for:
- Developers seeking a self-hosted automation solution.
- Businesses looking to streamline workflows and integrate various systems.
- IT professionals aiming to deploy a secure and scalable automation platform.
Prerequisites:
Before you begin, ensure you have the following:
- A Hetzner Cloud account (https://www.hetzner.com/cloud).
- An SSH client (e.g., PuTTY, Terminal).
- A domain name (recommended for easy access and HTTPS configuration).
- A basic understanding of Linux command-line operations.
Step 1: Server Creation on Hetzner Cloud
- Log in to your Hetzner Cloud console.
- Add a new server.
- Select your desired location.
- Choose Ubuntu 24+ LTS (recommended).
- Select a server type (CX11 or CX21 to start). For production, consider CX31 or larger.
- Add an SSH key (strongly recommended for enhanced security).
- Set a hostname (e.g., n8n-server).
- Create the server.
- Define your domain. We will use as an example n8n.blorax.com and add A record for it in your DNS provider.
Step 2: SSH Connection and Initial Setup
Connect to your server via SSH:
ssh root@<your_server_ip_address> #Password Authentication
ssh -i /path/to/your/private/key root@<your_server_ip_address> #SSH Key AuthenticationUpdate and upgrade packages:
sudo apt update && apt upgrade -yStep 3: Install Docker and Docker Compose
Docker simplifies the deployment process by containerizing n8n and its dependencies.
Install Docker:
sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
sudo systemctl start docker
sudo systemctl enable dockerInstall Docker Compose:
sudo apt install docker-compose -yStep 4: Deploying n8n with Docker Compose
Create a project directory:
mkdir /opt/n8n-server
cd /opt/n8n-serverCreate docker-compose.yml:
nano docker-compose.ymlAdd those codes:
#version: "3.9" - Optimized by Blorax.com
services:
n8n:
image: n8nio/n8n
restart: always
ports:
- "5678:5678"
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_HOST=${N8N_HOST}
- N8N_PORT=${N8N_PORT}
- N8N_PROTOCOL=${N8N_PROTOCOL}
- N8N_EMAIL=${N8N_EMAIL_ADDRESS}
- N8N_PASSWORD=${N8N_PASSWORD}
- EXECUTIONS_DATA_SAVE_ON_ERROR=all
- N8N_URL_BASE_PATH=${N8N_URL_BASE_PATH}
- TRUST_PROXY_SSL_HEADERS=1
- WEBHOOK_URL=${WEBHOOK_URL}
- N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true
volumes:
- n8n_data:/home/node/.n8n
networks:
- internal
depends_on:
- postgres
- redis
- qdrant
postgres:
image: postgres:15
restart: always
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- internal
redis:
image: redis:latest
restart: always
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 5
networks:
- internal
qdrant:
image: qdrant/qdrant
restart: unless-stopped
ports:
- "127.0.0.1:6333:6333"
volumes:
- qdrant_storage:/qdrant/storage
environment:
QDRANT__SERVICE__API_KEY: ${QDRANT_API_KEY}
networks:
- internal
networks:
internal:
driver: bridge
volumes:
n8n_data:
postgres_data:
redis_data:
qdrant_storage:Create .env:
nano .envAdd those codes:
# Optimized by Blorax.com
# n8n core
N8N_HOST=n8n.blorax.com
N8N_PROTOCOL=https
N8N_PORT=5678
N8N_EDITOR_BASE_URL=https://n8n.blorax.com/
WEBHOOK_URL=https://n8n.blorax.com/
N8N_URL_BASE_PATH=/
TRUST_PROXY_SSL_HEADERS=1
# n8n auth & security
N8N_EMAIL_ADDRESS=[email protected]
N8N_PASSWORD=YourStrongN8NPassword123!
N8N_ENCRYPTION_KEY=VeryLongEncryptionKeyGeneratedWithOpenSSL
N8N_USER_MANAGEMENT_JWT_SECRET=YourRandomLongSecret123#
# database (n8n)
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n-p-database
DB_POSTGRESDB_USER=n8n-p-user
DB_POSTGRESDB_PASSWORD=YourVeryStrongPostgresPassword123!@#
# database (postgres container) #THE SAME AS DB_POSTGRESDB_* Credentials Above
POSTGRES_DB=n8n-p-database
POSTGRES_USER=n8n-p-user
POSTGRES_PASSWORD=YourVeryStrongPostgresPassword123!@#
# redis
N8N_QUEUE_MODE=redis
REDIS_HOST=redis
REDIS_PORT=6379
# execution behavior
EXECUTIONS_DATA_SAVE_ON_ERROR=all
N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true
# MCP / API
QDRANT_API_KEY=YourRandomQDRANTKey123
Use a STRONG password for every configuration. Use the command in the terminal to generate and copy the output value for N8N_ENCRYPTION_KEY:
openssl rand -base64 32Start the n8n stack:
docker-compose up -dStep 5: Obtain SSL Certificates with Let’s Encrypt
Secure your n8n instance with HTTPS using Let’s Encrypt (we will use nginx as a proxy).
Install Certbot:
sudo apt install certbot python3-certbot-nginxObtain a certificate:
sudo certbot --nginx -d n8n.blorax.comStep 6: Configure Nginx as a Reverse Proxy for HTTPS
Nginx provides essential security and reverse proxy functionality.
Install Nginx:
sudo apt install nginxCreate a new Nginx configuration file (/etc/nginx/sites-available/n8n):
sudo nano /etc/nginx/sites-available/n8n-serverAdd those codes (don’t forget to change the domain name):
server {
listen 80;
server_name n8n.blorax.com;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name n8n.blorax.com;
ssl_certificate /etc/letsencrypt/live/n8n.blorax.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.blorax.com/privkey.pem;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
include /etc/nginx/snippets/ssl-params.conf;
include /etc/letsencrypt/options-ssl-nginx.conf;
location / {
proxy_pass http://localhost:5678/;
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_set_header X-Nginx-Proxy true;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
# SSE-specific fixes
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
# Prevent buffering & compression (MCP SSE)
gzip off;
}
location ~ /\.git {
deny all;
return 404;
}
}Create/edit /etc/nginx/snippets/ssl-params.conf:
sudo nano /etc/nginx/snippets/ssl-params.confAdd those codes (it should look like the following):
ssl_session_cache shared:MozSSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/n8n.blorax.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;If the file “ssl-params.conf” is causing problems, comment out those options
Link this file:
sudo ln -s /etc/nginx/sites-available/n8n-server /etc/nginx/sites-enabledUnlink file default (if exists):
sudo rm /etc/nginx/sites-enabled/defaultTest nginx:
sudo nginx -tIf you have problems, read the error logs and try to solve the problem with our tips or with the documentation
Restart nginx:
sudo systemctl reload nginxStep 7: Securing The Server
Enable the firewall and give permission to access
sudo ufw allow OpenSSH
sudo ufw allow 5678/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw statusStep 8: Accessing n8n
Open your web browser and navigate to https://n8n.blorax.com (use your domain). You should now see your n8n instance with a secure HTTPS connection.
Best Practices and Considerations:
- Security: Use strong, unique passwords and keep your server updated.
- Backups: Implement regular backups of your n8n data and configuration files.
- Monitoring: Monitor your server’s resources to ensure optimal performance.
Note. If you need to access Qdrant:
ssh -L 6333:127.0.0.1:6333 root@YOUR_SERVER_IPThen open in your browser: http://localhost:6333
Step 9: Update self-hosted n8n (Docker)
Best and safe commands for self-hosted n8n on Docker to be updated (run the following commands one by one and wait for them to complete):
# 1. Navigate to your n8n directory (set your correct path)
cd /opt/n8n-server
# 2. Shut down your current n8n services
docker-compose down
# 3. Pull the latest version of the n8n image
docker-compose pull n8n
# 4. Restart the services with the new image
docker-compose up -d
# 5. Monitor the startup process (Optional but Recommended)
docker-compose logs -f n8n
# 6. Clean up old, unused images (Very useful, but optional)
docker image pruneConclusion
By following these steps, you can successfully deploy a secure and scalable n8n automation platform on Hetzner Cloud with Redis. This guide provides a solid foundation for unlocking the full potential of workflow automation, enabling you to streamline your operations and achieve new levels of efficiency.
Need Expert Help?
At Blorax, we specialize in helping businesses like yours implement cutting-edge automation solutions. Contact us today for a free consultation and let us help you transform your workflows! Visit our website at https://blorax.com to learn more.



Comments (3)
This might need a serious rework.
You indicate to set a hostname without showing how.
Same thing for DNS and domain – being the critical step for the nginx setup.
ssl should be shown before the .env
The version for the docker compose should be checked or maybe removed depending on the user installation.
Other than that it’s looking good so far. I’ll have to find a way to do DNS stuff before continuing though…
Thanks a lot for the tutorial it worked almost like a charm.
Since nginx is handling https proxy, n8n should not be configured to do so.
In the docker compose yml: set N8N_PROTOCOL=http instead of N8N_PROTOCOL=https
Also add a webhook url in .env WEBHOOK_URL=https://n8n.blorax.com
Then in the compose again at the n8n service: add to environment – WEBHOOK_URL=${WEBHOOK_URL}
Now nginx will reverse proxy to HTTP and handle SSL certification instead of n8n trying to do it bypassing nginx.
This is a problem because if you try to do some oauth with google you will get SSL_ERROR_RX_RECORD_TOO_LONG because the redirect url will be https://n8n.blorax.com:5678/rest/oauth2-credential/callback
Here we have the 5678 port served by n8n and buggering the ssl certificate. We want a clean https://n8n.blorax.com/rest/oauth2-credential/callback without any port. This should fix it.
Hello, and thank you for this incredibly valuable feedback! You have pinpointed one of the most common stumbling blocks when setting up n8n behind a reverse proxy, especially when it comes to using OAuth2 with services like Google. Your analysis is spot on — the port
:5678appearing in the callback URL is the absolute root of the problem.The issue you’re seeing,
SSL_ERROR_RX_RECORD_TOO_LONG, happens because your browser is trying to speak HTTPS to a port (:5678) that is serving plain, unencrypted HTTP. Nginx is handling the SSL on port 443, but the n8n application itself, listening on 5678, is not configured for SSL.The key question is: Why is n8n generating a URL with the port in the first place?
n8n constructs its public-facing URLs (like for OAuth callbacks) using a combination of its environment variables:
N8N_PROTOCOL,N8N_HOST, andN8N_PORT. With your current settings, n8n combines these and creates the URL:https://n8n.blorax.com:5678. This is the source of the incorrect callback URL.You’ve suggested changing
N8N_PROTOCOLtohttp. This is a very logical thought process: Nginx talks to n8n over HTTP, so n8n’s internal protocol should be HTTP. However, there’s a subtle but important detail here.The
N8N_PROTOCOLvariable should reflect the protocol the end-user uses to access your site, not the internal protocol between the proxy and the application. This is because n8n needs to generate URLs that are correct for the outside world.Our current setup correctly handles this by using:
.envfile:N8N_PROTOCOL=httpsandTRUST_PROXY_SSL_HEADERS=1proxy_set_header X-Forwarded-Proto $scheme;So, if we change
N8N_PROTOCOLtohttp, n8n might start generatinghttp://links, which would cause other problems.The most reliable way to fix this is to explicitly tell n8n what its complete public base URL is, leaving no room for misinterpretation. This overrides the automatic URL construction from PROTOCOL+HOST+PORT.
You do this with the
N8N_EDITOR_BASE_URLenvironment variable. This variable is designed for precisely this scenario. It tells n8n, “Disregard any automatic URL building. For all editor-related links, including OAuth callbacks, use this exact base URL.”How to Implement the Fix
1. Update your
.envfile:Ensure these lines are present and correct, pointing to your domain. The trailing slash is important.
2. Update your
docker-compose.ymlfile:Pass these variables from the
.envfile to the n8n container. This is the crucial step.By setting
N8N_EDITOR_BASE_URLandWEBHOOK_URLexplicitly, you are giving n8n the exact, unambiguous public URLs for its operations. It will no longer try to add the internal:5678port, and your OAuth callbacks will resolve to the correct, port-free URL:https://n8n.blorax.com/rest/oauth2-credential/callback.Hope this helps, and thank you again for the excellent contribution!