Docker n8n and Reverse Proxy with Nginx for HTTPS

This assumes you already have Docker and or Portainer installed:

sudo docker network create reverse-proxy

This command creates a Docker network named “reverse-proxy” which will house both required containers.

sudo docker run -d --restart always --network reverse-proxy --name n8n -v n8n_data:/home/node/.n8n -e WEBHOOK_URL=https://<ip or domain>:5678 docker.n8n.io/n8nio/n8n

docker run:Create and start a new n8n Docker container.

-d: Detach the container and run it in the background (daemon mode).

–restart always: Restart the container automatically if it exits for any reason.

–network reverse-proxy: Attach the container to the Docker network named “reverse-proxy”.

–name n8n: Assign the name “n8n” to the container.

-v n8n_data:/home/node/.n8n: Create and mount the n8n_data volume to /home/node/.n8n in the container. If n8n_data doesn’t exist, it will be created.

-e WEBHOOK_URL=https://<ip or domain>:5678: Set the environment variable WEBHOOK_URL with the value https://<ip or domain>:5678. This is used to configure the application within the container. Replace <ip or domain> with the actual IP address or domain name.

n8nio/n8n:latest: Use the n8nio/n8n:latest Docker image to create the container. It will download the latest version of the n8n image from the n8n Docker Hub repository.

In summary, this Docker command: Creates a new Docker container named “n8n”. Detaches the container and runs it in the background (daemon mode). Restarts the container automatically if it exits for any reason. Attaches the container to the Docker network named “reverse-proxy”. Creates or uses the existing n8n_data volume and mounts it to /home/node/.n8n in the container. Sets the WEBHOOK_URL environment variable to https://<ip or domain>:5678. Uses the n8nio/n8n:latest Docker image to create the container.

sudo mkdir /opt/certificates 

This command creates a new directory named “certificates” inside the “/opt” directory which will house the ssl cert and key.

cd /opt/certificates

Change directory to the certificates folder.

sudo openssl genrsa -out server.key 2048 

openssl genrsa: This command generates an RSA private key.

-out server.key: Specifies the output file name as “server.key”. The private key will be saved in this file.

2048: Specifies the number of bits in the RSA key. In this case, it’s 2048 bits.

In summary, this command generates an RSA private key file named “server.key” with a key length of 2048 bits.

sudo openssl req -key server.key -new -out server.csr 

openssl req: This command generates a CSR.

-key server.key: Specifies the private key file to be used.

-new: Generate a new CSR.

-out server.csr: Specifies the output file name as “server.csr”. The CSR will be saved in this file.

In summary, this command generates a CSR file named “server.csr” using the private key “server.key”.

sudo openssl x509 -signkey server.key -in server.csr -req -days 365 -out server.crt 

openssl x509:This command is used to sign certificates.

-signkey server.key: Specifies the private key to sign the certificate with.

-in server.csr: Specifies the CSR file to sign.

-req: This option specifies that a certificate signing request is being processed.

-days 365: Specifies the number of days the certificate will be valid. In this case, 365 days.

-out server.crt: Specifies the output file name as “server.crt”. The signed certificate will be saved in this file.

In summary, this command generates a self-signed certificate file named “server.crt” using the private key “server.key” and the CSR “server.csr”.

cd /opt/ 

Change directory to the opt folder.

sudo touch nginx.conf 

Create a file nginx.conf.

sudo nano nginx.conf 

Edit the file with nano and add the following:

events { }
http {
server {
listen 5678 ssl;

ssl_certificate /opt/certificates/server.crt;
ssl_certificate_key /opt/certificates/server.key;

location / {
proxy_pass http://n8n:5678/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
}
}

events {
}

This section configures the basic parameters for how NGINX should handle connections. In this example, it is left empty, meaning it will use the default settings.

http {
server {
listen 5678 ssl;

Defines an HTTP server block, which will listen on port 5678 with SSL/TLS encryption enabled.

ssl_certificate /opt/certificates/server.crt;
ssl_certificate_key /opt/certificates/server.key;

Specifies the location of the SSL certificate and private key files.

location / {
proxy_pass http://n8n:5678/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “Upgrade”;
proxy_set_header Host $host;
}

I found this was needed as there were various errors in the browser related to websockets. This configures a reverse proxy for requests to the root URI (/). Incoming requests will be forwarded to the backend service at http://n8n:5678/.

proxy_pass http://n8n:5678/; This line specifies the address of the backend service. It’s where NGINX will forward the requests.

proxy_http_version 1.1;This line ensures that NGINX uses HTTP/1.1 when communicating with the backend.

proxy_set_header Upgrade $http_upgrade;This line includes the Upgrade header in the request. This header is used when upgrading an HTTP connection to a WebSocket connection.

proxy_set_header Connection “Upgrade”;:This line sets the Connection header to “Upgrade”. It is used in conjunction with the Upgrade header for WebSocket connections.

proxy_set_header Host $host;: Sets the Host header of the request to the value of the $host variable, which contains the hostname from the request.

With this configuration, NGINX will accept HTTPS requests on port 5678 and forward them to the backend service http://n8n:5678/.

Finally we setup the Nginx container:

sudo docker run -d --name nginx-container --network reverse-proxy -p 5678:5678 -v /opt/certificates:/opt/certificates -v /opt/nginx.conf:/etc/nginx/nginx.conf nginx:latest 

docker run: Create and start a new Docker container.

-d: Detach the container and run it in the background (daemon mode).

–name nginx-container: Assign the name “nginx-container” to the container. –network reverse-proxy: Attach the container to the Docker network named “reverse-proxy”.

-p 5678:5678: Bind port 5678 on the host to port 5678 on the container. This will make the NGINX service accessible on port 5678.

-v /opt/certificates:/opt/certificates: Mount the /opt/certificates directory on the host to the /opt/certificates directory in the container. This allows NGINX to access the SSL certificates.

-v /opt/nginx.conf:/etc/nginx/nginx.conf: Mount the /opt/nginx.conf file on the host to the /etc/nginx/nginx.conf file in the container. This allows you to provide a custom NGINX configuration.

nginx:latest: Use the nginx:latest Docker image to create the container. It will download the latest version of the NGINX image from the NGINX Docker Hub repository.

In summary, this Docker command: Creates a new Docker container named “nginx-container”. Detaches the container and runs it in the background (daemon mode). Attaches the container to the Docker network named “reverse-proxy”. Binds port 5678 on the host to port 5678 on the container. Mounts the /opt/certificates directory on the host to the /opt/certificates directory in the container. Mounts the /opt/nginx.conf file on the host to the /etc/nginx/nginx.conf file in the container and uses the nginx:latest Docker image to create the container.