Menu
User

DropVPS Team

Writer: Cooper Reagan

How to install n8n on RHEL 9

How to install n8n on RHEL 9

Publication Date

10/12/2025

Category

Articles

Reading Time

5 Min

Table of Contents

Deploying n8n on RHEL 9 is straightforward and reliable with Docker and PostgreSQL. The setup below focuses on persistence, SELinux compatibility, and production readiness. Expect a clean directory layout, secure configuration, and service management with systemd. You’ll go from a fresh RHEL 9 box to a working n8n web UI with HTTPS support.

Prepare RHEL 9 and firewall

Update the OS, set the timezone, and open required ports. This ensures a secure baseline and network reachability for the n8n UI and optional HTTPS.

sudo dnf -y update
sudo timedatectl set-timezone UTC
sudo firewall-cmd --add-port=5678/tcp --permanent
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload

Install Docker Engine

RHEL 9 ships with Podman, but Docker Engine with the Compose plugin offers a simple path for n8n. Enable the Docker repository, install, and activate the service.

sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
sudo dnf -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
newgrp docker

Create n8n project directories

Set up a workspace with persistent volumes. Use UID/GID 1000 to match the n8n container’s user. SELinux relabeling will be applied later via Compose.

mkdir -p ~/n8n/data/n8n ~/n8n/data/postgres
sudo chown -R 1000:1000 ~/n8n/data/n8n
cd ~/n8n

Configure environment variables

Create an .env file to hold database credentials, host URLs, and security keys. The encryption key secures credentials stored by n8n.

openssl rand -hex 24

Copy the hex string, then create the file:

cat > .env <<'EOF'
# n8n core
GENERIC_TIMEZONE=UTC
N8N_HOST=your.domain.com
N8N_PORT=5678
N8N_PROTOCOL=https
WEBHOOK_URL=https://your.domain.com/
N8N_EDITOR_BASE_URL=https://your.domain.com/
N8N_ENCRYPTION_KEY=PASTE_HEX_KEY_HERE
N8N_SECURE_COOKIE=true

# Database (PostgreSQL)
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=db
DB_POSTGRESDB_PORT=5432
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n
DB_POSTGRESDB_PASSWORD=ChangeThisStrongPassword!
EOF

Write the Docker Compose file

Define Postgres and n8n services with persistent storage. The :Z suffix on volumes makes them SELinux-friendly on RHEL 9.

cat > docker-compose.yml <<'YML'
version: "3.8"

services:
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=${DB_POSTGRESDB_USER}
      - POSTGRES_PASSWORD=${DB_POSTGRESDB_PASSWORD}
      - POSTGRES_DB=${DB_POSTGRESDB_DATABASE}
    volumes:
      - ./data/postgres:/var/lib/postgresql/data:Z
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_POSTGRESDB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

  n8n:
    image: n8nio/n8n:latest
    user: "1000:1000"
    env_file:
      - ./.env
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "${N8N_PORT}:5678"
    volumes:
      - ./data/n8n:/home/node/.n8n:Z
    restart: unless-stopped
YML

Launch n8n and verify

Start the stack and confirm the application is reachable. The first web visit will prompt you to create the owner account.

docker compose up -d
docker compose ps
docker compose logs -f --tail=50 n8n

Optional health check:

curl -i http://127.0.0.1:5678/healthz

Example output:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 2

ok

Make n8n run on boot (systemd)

Create a systemd unit that encapsulates your Compose project. Replace USER with your username and adjust paths if needed.

sudo tee /etc/systemd/system/n8n.service >/dev/null <<'UNIT'
[Unit]
Description=n8n workflow automation (Docker Compose)
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target

[Service]
Type=oneshot
WorkingDirectory=/home/USER/n8n
Environment="COMPOSE_FILE=docker-compose.yml"
RemainAfterExit=yes
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down

[Install]
WantedBy=multi-user.target
UNIT

sudo systemctl daemon-reload
sudo systemctl enable --now n8n
systemctl status n8n --no-pager

Optional: HTTPS reverse proxy with NGINX

Terminate TLS on the host with NGINX and Let’s Encrypt. This keeps n8n behind localhost while users access a secure domain.

sudo dnf -y install epel-release
sudo dnf -y install nginx certbot python3-certbot-nginx
sudo tee /etc/nginx/conf.d/n8n.conf >/dev/null <<'NGINX'
server {
  listen 80;
  server_name your.domain.com;

  location / {
    proxy_pass http://127.0.0.1:5678;
    proxy_http_version 1.1;
    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;
    client_max_body_size 50m;
    proxy_read_timeout 3600;
  }
}
NGINX
sudo systemctl enable --now nginx
sudo certbot --nginx -d your.domain.com -m [email protected] --agree-tos --redirect -n

Ensure your .env uses HTTPS and the domain for N8N_HOST, N8N_PROTOCOL, N8N_EDITOR_BASE_URL, and WEBHOOK_URL, then recreate n8n if changed.

docker compose up -d

Upgrade and backup

Pull new images and recreate containers with zero data loss. Back up both the n8n config directory and the Postgres database regularly.

cd ~/n8n
docker compose pull
docker compose up -d
docker image prune -f

Database backup (replace the container name if different):

docker ps --format '{{.Names}}'
docker exec -t n8n-db-1 pg_dump -U n8n n8n > ~/n8n/backup-$(date +%F).sql
tar -C ~/n8n -czf ~/n8n/files-$(date +%F).tar.gz data/n8n

Troubleshooting SELinux and permissions

If volumes fail due to SELinux, the :Z flag usually fixes it. For manual labeling, apply a persistent context and restore:

sudo dnf -y install policycoreutils-python-utils
sudo semanage fcontext -a -t container_file_t '~/n8n(/.*)?'
sudo restorecon -Rv ~/n8n

If n8n cannot write to its directory, ensure ownership is 1000:1000:

sudo chown -R 1000:1000 ~/n8n/data/n8n

Installation complete. You now have a production-friendly n8n on RHEL 9 with Docker, PostgreSQL, SELinux-safe volumes, and optional HTTPS. For more study, guidance, server purchases, and support, you can use dropvps. For more guides, visit dropvps.com

Linux VPS
U
Loading...

Related Posts