Installing and Using n8n on RHEL 9/CentOS with Docker

Installing and Using n8n on RHEL 9/CentOS with Docker

 

Introduction: n8n is an open-source workflow automation tool that lets you schedule tasks and move data between many of the apps, tools, and services you use every day. This guide will walk you through installing Docker on Red Hat Enterprise Linux 9 (or CentOS/Rocky/AlmaLinux 9), setting up n8n in a Docker container, and configuring SSL/HTTPS for secure access. We’ll use step-by-step instructions with explanations, sample commands, and outputs. By the end, you’ll have n8n running locally with persistence, secured by optional basic authentication and HTTPS (either with a self-signed certificate for testing or a Let’s Encrypt certificate for production). This guide assumes you have root or sudo privileges on your RHEL/CentOS server.

Prerequisites

  • A system running RHEL 9 or a RHEL 9-based distribution (e.g., CentOS Stream 9, Rocky Linux 9) with internet access.
  • A user account with root or sudo privileges.
  • (For HTTPS with Let’s Encrypt) A registered domain name pointing to your server’s IP (for production deployments).
  • Basic command-line familiarity (all steps will be given in detail).

Step 1: Install Docker Engine on RHEL/CentOS

Docker allows you to run applications like n8n in isolated containers. We will install the Docker Engine (Community Edition) using the official Docker repository to ensure we get the latest version.

  1. Update system packages (optional): It’s good practice to update your system first:
   sudo dnf update -y

This ensures your package list and installed packages are up-to-date.

  1. Install required utilities: Install dnf-plugins-core, which provides the dnf config-manager utility for managing repositories. We’ll use this to add Docker’s official repo.
   sudo dnf -y install dnf-plugins-core

Output: This will install the plugin if not already present. For example, you might see it install some packages and finish without error.

  1. Add the Docker CE repository: Use Docker’s official repository for RHEL/CentOS. This makes the Docker packages available via dnf.
   sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo

Output: No news is good news – this command typically adds a file under /etc/yum.repos.d/ and doesn’t produce significant output on success.

  1. Install Docker Engine and related packages: Now install Docker Engine (docker-ce), the Docker CLI, Containerd (container runtime), and the Docker Compose plugin.
   sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

During installation, you may be prompted to accept a GPG key for the Docker repository – verify the fingerprint if shown (Docker’s official key fingerprint is 060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35) and accept it. Once complete, Docker is installed but not yet running. Sample output: You should see dnf retrieving package lists and installing Docker packages. For example, lines indicating Installed: docker-ce.x86_64 ... confirm a successful installation.

  1. Start and enable the Docker service: Enable Docker to start on boot and launch it now:
   sudo systemctl enable --now docker

This starts the Docker daemon and also configures it to auto-start at system boot. Sample output: You may see a message like Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service indicating Docker is enabled.

  1. Verify Docker is running: Test Docker by running the hello-world container:
   sudo docker run hello-world

This will download a test image and run it. On success, it prints a friendly message and exits. Sample output:

   Hello from Docker!
   This message shows that your installation appears to be working correctly.
   ... (additional explanatory text) ...

If you see “Hello from Docker!” and an explanation of what Docker did, Docker is installed and working properly. You can proceed to install n8n.

Firewall Note: RHEL/CentOS may have a firewall (firewalld) enabled by default. If you plan to access n8n from other machines, ensure to open the necessary ports (e.g., 5678 for n8n, 80/443 for HTTP/HTTPS). For example, to allow port 5678:

sudo firewall-cmd --add-port=5678/tcp --permanent
sudo firewall-cmd --add-port=443/tcp --permanent   # if using HTTPS
sudo firewall-cmd --add-port=80/tcp --permanent    # if using Let's Encrypt/HTTP
sudo firewall-cmd --reload

This ensures the ports are not blocked by the firewall.

Step 2: Set Up a Docker Volume for n8n Data

Before running n8n, it’s important to ensure that its data is stored persistently. By default, n8n uses a SQLite database and stores configuration and workflows in the folder /home/node/.n8n inside the container. If we don’t persist this, any workflows or credentials you create would be lost when the container is removed or updated. We will create a Docker volume to store this data outside the container’s lifecycle.

  • Create a Docker volume for n8n:
  docker volume create n8n_data

This creates a named volume called n8n_data which Docker will manage. The volume will be used to persist /home/node/.n8n from the container to your host. Output: On success, Docker will simply return the name of the volume, e.g., n8n_data.

The volume n8n_data will hold your n8n database, workflows, and encryption key so that data persists across container restarts.

Step 3: Run the n8n Docker Container (Local Use)

With Docker installed and the persistent volume ready, we can run n8n in a container. We’ll use the official n8n Docker image.

Command to run n8n:

docker run -d --name n8n \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  n8nio/n8n

Let’s break down what this does:

  • docker run -d – Runs the container in detached mode (in the background).
  • --name n8n – Names the container “n8n” for easy reference.
  • -p 5678:5678 – Maps port 5678 in the container to port 5678 on the host. n8n’s web interface listens on port 5678 by default. After running this, you’ll be able to access n8n via http://localhost:5678 (or your server’s IP on port 5678).
  • -v n8n_data:/home/node/.n8n – Mounts the Docker volume we created to n8n’s data directory inside the container. This ensures all workflows, credentials, and database files are saved persistently.
  • n8nio/n8n – This is the Docker image for n8n. Docker will fetch it from Docker Hub on first run (it may take a minute to download).

Once you run this command, Docker will output a long container ID (hex string) if successful. You can verify the container is running with:

docker ps --filter "name=n8n"

This should list the n8n container as “Up” along with the port mapping.

Example output:

CONTAINER ID   IMAGE       COMMAND                  ...   STATUS          PORTS
d1e4c3f8b123   n8nio/n8n   "tini -- /docker-ent…"   ...   Up 10 seconds   0.0.0.0:5678->5678/tcp

Now n8n is running in Docker. Open your browser and navigate to http://localhost:5678 (if you’re on the same machine) or http://:5678 from another machine. You should see the n8n web interface loading. From here, you can start creating workflows in the n8n editor UI. 

Persisting Workflows: Because we mounted the volume, any workflows or credentials you create will be saved. If you stop or remove the container, you can launch a new n8n container using the same volume and your data will reappear (persisted). For example, updating n8n is as simple as pulling a new image and re-running the container with the volume attached; your data remains intact.

Tip: If you ever need to stop n8n, run docker stop n8n. You can start it again with docker start n8n since we named the container. Removing the container (with docker rm) does not delete the volume n8n_data, so your data stays safe unless you remove the volume manually.

Step 4: (Optional) Secure the n8n Interface with Basic Authentication

By default, n8n does not require login – anyone who can access the web interface can create workflows. If you’re running n8n on a server that others can reach (not just your local machine), it’s highly recommended to enable basic authentication to protect it. We can do this by setting a few environment variables for the container.

n8n supports Basic Auth out of the box via environment variables:

  • N8N_BASIC_AUTH_ACTIVE=true – Enables authentication.
  • N8N_BASIC_AUTH_USER=<your_username> – Sets the username for login.
  • N8N_BASIC_AUTH_PASSWORD=<your_password> – Sets the password for login.

To apply these, we’ll have to re-create the container with those variables. Stop and remove the current container:

docker stop n8n && docker rm n8n

Now run n8n with authentication variables (replace <username> and <password> with credentials you choose):

docker run -d --name n8n \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  -e N8N_BASIC_AUTH_ACTIVE=true \
  -e N8N_BASIC_AUTH_USER=<username> \
  -e N8N_BASIC_AUTH_PASSWORD=<password> \
  n8nio/n8n

This command is similar to the earlier one, with the addition of -e flags to set environment variables. Now, when you access the n8n web UI, you will be prompted to log in with the username and password you set, adding a layer of security.

Purpose of these variables: This basic auth is a simple way to prevent unauthorized access. It’s especially important if your n8n instance is accessible on a public IP or domain. Use a strong password here.

Note: You can set more environment variables to configure n8n (such as timezone, webhooks URL, etc.), but for a basic setup, the above are the most critical for security. We’ll cover a couple more environment variables in the HTTPS section (like specifying the domain name n8n uses).

Step 5: Enabling HTTPS for n8n (SSL/TLS Configuration)

Running n8n over HTTPS is important if you’re going to send sensitive data or expose it over the internet. There are two common ways to enable HTTPS for n8n:

  • Using a self-signed certificate (for testing or internal use).
  • Using a trusted certificate from Let’s Encrypt (for production).

We’ll explain both methods. The recommended approach for production is to use a reverse proxy (like Nginx or Traefik) with Let’s Encrypt, but for completeness we will also show how to configure n8n with a self-signed cert directly.

Method 1: Using a Self-Signed SSL Certificate (Local/Test Use)

If you just need to test HTTPS or are using n8n in a closed environment (where you can tolerate a browser warning), you can create a self-signed certificate. This will encrypt the traffic, although it won’t be trusted by browsers without manually accepting the certificate.

Step 5.1: Generate a self-signed certificate We will use OpenSSL to create a private key and a certificate valid for 1 year. Run the following command (you can adjust details as needed):

openssl req -newkey rsa:4096 -nodes -keyout n8n-selfsigned.key -x509 -days 365 -out n8n-selfsigned.crt -subj "/CN=localhost"
  • This command creates a 4096-bit RSA key and a certificate (n8n-selfsigned.crt) valid for 365 days.
  • -subj "/CN=localhost" sets the Common Name to “localhost”. You can replace it with your server’s hostname or domain as appropriate. You will be prompted for no password (due to -nodes).

After running, you should have two files in the current directory: n8n-selfsigned.key (private key) and n8n-selfsigned.crt (certificate).

Sample output:

Generating a RSA private key
....................................................................++++
...++++
writing new private key to 'n8n-selfsigned.key'
-----

You have now generated a self-signed SSL certificate.

Step 5.2: Run n8n with HTTPS enabled We will start a new n8n container that uses these certificate files for HTTPS. To do this, we need to:

  • Mount the certificate and key into the container.
  • Set environment variables so n8n knows to use HTTPS and where the cert/key are.

First, stop and remove the existing n8n container (since we’ll replace it):

docker stop n8n && docker rm n8n

Now run n8n with SSL environment variables (adjust paths as needed if you generated the cert in a different location):

docker run -d --name n8n \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  -v $PWD:/certs:ro \
  -e N8N_PROTOCOL=https \
  -e N8N_SSL_CERT=/certs/n8n-selfsigned.crt \
  -e N8N_SSL_KEY=/certs/n8n-selfsigned.key \
  -e N8N_BASIC_AUTH_ACTIVE=true \
  -e N8N_BASIC_AUTH_USER=<username> \
  -e N8N_BASIC_AUTH_PASSWORD=<password> \
  n8nio/n8n

Let’s unpack that:

  • -v $PWD:/certs:ro mounts the current directory (where your cert files are, you can also specify a full path) into the container at /certs. The :ro makes it read-only inside the container.
  • -e N8N_PROTOCOL=https tells n8n to use HTTPS for its URLs and listening protocol.
  • -e N8N_SSL_CERT=/certs/n8n-selfsigned.crt and -e N8N_SSL_KEY=/certs/n8n-selfsigned.key provide the paths to the certificate and key inside the container. We mounted the certs to /certs, so we use those paths.
  • We also included the Basic Auth variables again for security (if you set them before, include them again here).

Once this container starts, n8n will be serving over HTTPS on port 5678. You can verify it’s running with docker logs n8n, which should show something like “Server listening on 0.0.0.0:5678” and no errors. Now try accessing https://:5678. Your browser will likely warn that the certificate is not trusted (since it’s self-signed). After you accept the risk/exception, you should see the n8n interface load over HTTPS.

Purpose of these steps: Using a self-signed certificate encrypts the traffic, preventing eavesdropping. It’s useful for testing or internal services. However, because it isn’t from a trusted authority, users will see a security warning. For production or public services, a trusted certificate (e.g., from Let’s Encrypt) is recommended for a seamless, secure experience.

Method 2: Using Let’s Encrypt (Trusted HTTPS via Nginx Reverse Proxy)

For a production deployment or any scenario where you have a domain name and want a trusted SSL certificate, Let’s Encrypt is a great option. We’ll obtain a free Let’s Encrypt certificate and set up Nginx as a reverse proxy in front of n8n. Nginx will handle HTTPS and forward traffic to the n8n container. This way, n8n itself can continue running on HTTP internally, and Nginx provides the encrypted layer. This setup is recommended by n8n for production.

Step 5.3: Install Nginx and Certbot (the Let’s Encrypt client): On RHEL/CentOS, Nginx and Certbot may not be in the base repositories, but they are available via the EPEL repository. Run the following:

sudo dnf install -y epel-release               # Enable EPEL repository (if not already)
sudo dnf install -y nginx certbot python3-certbot-nginx

This will install Nginx web server and Certbot with the Nginx plugin on your system.

Output: After installation, you can check versions: nginx -v (to see Nginx installed) and certbot --version (to confirm Certbot, e.g., it might show certbot 1.x.x).

Step 5.4: Start and enable Nginx:

sudo systemctl enable --now nginx

This starts Nginx and sets it to run on boot. By default, Nginx will listen on port 80 (HTTP).

Step 5.5: Configure Nginx as a reverse proxy for n8n: We will configure Nginx to forward requests for your domain to the n8n container. Create a new Nginx configuration file. For example:

sudo nano /etc/nginx/conf.d/n8n.conf

Add the following server block (replace yourdomain.com with your actual domain):

server {
    listen       80;
    server_name  yourdomain.com;

    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 $scheme;
    }
}

In this configuration:

  • Nginx listens on port 80 for requests to yourdomain.com.
  • All requests (location /) are proxied to http://localhost:5678, where our n8n container is running. The headers ensure the real client IP and original protocol are forwarded to n8n (useful for logging and correct behavior).

Save and exit the editor. Then test Nginx configuration and restart Nginx to apply changes:

sudo nginx -t && sudo systemctl restart nginx

If nginx -t reports no errors, the config is okay. At this point, Nginx is forwarding traffic from your domain (unencrypted HTTP) to n8n. Next, we’ll obtain the SSL certificate and let Certbot automatically configure HTTPS.

Step 5.6: Obtain a Let’s Encrypt certificate: Make sure your domain’s DNS is pointing to this server and port 80 is accessible. Then run:

sudo certbot --nginx -d yourdomain.com

Certbot will:

  • Challenge the domain (ensure you control it) over HTTP and obtain a certificate from Let’s Encrypt.
  • Automatically configure Nginx to use the new certificate (it will edit the /etc/nginx/conf.d/n8n.conf file or create a new one with a HTTPS server block).

During this process, you’ll be asked for an email (for renewal notices) and agree to Let’s Encrypt terms. Certbot will then fetch and install the certificate. If you have multiple domains or subdomains, list them with additional -d flags. For example: certbot --nginx -d yourdomain.com -d www.yourdomain.com.

Sample output: On success, you’ll see a message “Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/yourdomain.com/fullchain.pem” etc., and Nginx will start serving HTTPS. Certbot will configure Nginx to redirect HTTP to HTTPS by default (it usually asks if you want to redirect, and you should choose Yes for security).

Now try accessing https://yourdomain.com in a browser. You should see the n8n interface load, this time with a secure lock icon. No warnings should appear since the certificate is signed by Let’s Encrypt (a trusted authority).

Finally, we need to ensure n8n itself is aware of the correct external URL for things like OAuth callbacks and webhook URLs. When running behind a proxy with a domain, it’s wise to set a couple of additional environment variables for n8n:

  • N8N_HOST – set this to your domain name (e.g., yourdomain.com).
  • WEBHOOK_URL – set this to https://yourdomain.com/ (or include any specific path if you are not using root).

These variables inform n8n about the external address it’s reachable at. They help generate correct URLs for webhooks and avoid “secure cookie” errors by matching the domain. In our case, since Nginx is handling HTTPS and we kept n8n on port 5678 internally, we actually don’t need to change the N8N_PORT environment (n8n still listens on 5678). But we do want it to know it’s being accessed at yourdomain.com via HTTPS. We can add these when running the container. For example, to update our earlier docker run (with basic auth as well):

docker stop n8n && docker rm n8n
docker run -d --name n8n \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  -e N8N_BASIC_AUTH_ACTIVE=true \
  -e N8N_BASIC_AUTH_USER=<username> \
  -e N8N_BASIC_AUTH_PASSWORD=<password> \
  -e N8N_HOST=yourdomain.com \
  -e N8N_PROTOCOL=http \
  -e WEBHOOK_URL=https://yourdomain.com/ \
  n8nio/n8n

Notice we set N8N_PROTOCOL=http here – this is because n8n itself is still running on HTTP inside the container. We let Nginx handle the HTTPS externally. We set WEBHOOK_URL to the https address, so n8n will use that when providing URLs for webhooks (ensuring external services call back via https). We’ve also set N8N_HOST so n8n knows its public hostname. With these set, n8n should operate smoothly behind the proxy. The Basic Auth variables are included to keep the instance protected as well (the proxy (Nginx) will simply pass through the authentication prompt from n8n).

Cert Renewal: Let’s Encrypt certificates expire every 90 days. Certbot (with the nginx plugin) usually installs a cron job or systemd timer to auto-renew them. You can test renewal with sudo certbot renew --dry-run. As long as Nginx is running and port 80/443 are accessible, the renewal should happen automatically. Certbot will reload Nginx to apply new certificates when renewed.

Conclusion

In this article, we installed Docker on RHEL/CentOS 9, set up n8n in a Docker container with persistent storage, and secured it with basic authentication and HTTPS. You learned how to generate a self-signed certificate for quick SSL encryption and how to configure Nginx and Let’s Encrypt for a trusted certificate in production. Each step included the purpose and expected output to help beginners understand what’s happening.

With n8n up and running, you can now start building automation workflows on your RHEL/CentOS server. Remember to keep your Docker and n8n updated (you can pull the latest n8n image and recreate the container to upgrade).

Posts Carousel

Leave a Comment

Your email address will not be published. Required fields are marked with *

Latest Posts

Most Commented

Featured Videos