How to Install n8n on Proxmox VE Using Docker Inside an LXC Container

Before you start: versions, package names and storage identifiers change over time. Check the commands against the official documentation for your setup before running them, especially anything that creates, deletes or overwrites data.

Install n8n on Proxmox VE Using Docker Inside an LXC Container

By the end of this walk‑through you will have a Proxmox VE host running a Debian‑based LXC container that contains Docker Engine and a docker‑compose stack for the official n8n image. An nginx reverse proxy on the host will expose n8n over HTTPS at a domain of your choice, complete with basic authentication. The entire process takes roughly 45 minutes to an hour, depending on your internet speed and how familiar you are with the Proxmox web interface.

More Tutorials & Self-Hosting guides on TechPulseMind →

Prerequisites

Before you begin, make sure you have the following items ready. If any item is missing, the steps that depend on it will fail.

Item Minimum Requirement Notes / How to Verify
Proxmox VE host Proxmox VE ≥ 7.0 (latest stable recommended) Run pveversion in the host shell to see the version.
CPU / RAM / Disk 2 vCPU, 2 GB RAM, 10 GB+ disk for the LXC (adjust per expected workload) Check free resources in the Proxmox GUI → Datacenter → Summary.
Network Static IP on the host, internet access for template and Docker pulls Ping 8.8.8.8 and verify DNS resolution.
Root / sudo access Ability to create LXC containers and run commands inside them Test by running pct list or creating a dummy container.
Template repository Proxmox template server enabled – a recent Debian or Ubuntu LXC template (e.g., Debian 11) In GUI: local (proxmox) → CT Templates → Templates; ensure at least one template is present.
Domain name (optional but recommended for HTTPS) A fully‑qualified domain name that points to the host’s public IP (or a port‑forwarded IP) Verify with dig +short your‑domain.tld.
Port availability Host ports 80 and 443 free for the reverse proxy Check with ss -tlnp | grep ':80\|:443'.
Basic Linux CLI knowledge Ability to edit files (nano/vim), run systemctl, docker, docker‑compose No specific version required; we will use the officially documented installation methods.

If you are unsure about the exact name of the current LXC template, consult the Proxmox template repository in the GUI; the version may change over time.

Step‑by‑Step Procedure

  1. Prepare the Proxmox Host

    First we update the host operating system so that we have the latest security patches and package metadata. This step is safe; it only downloads and installs updates.

    Log in to the Proxmox web GUI or via SSH as root or a user with sudo privileges. Then run the update and upgrade commands:

    apt update && apt upgrade -y
    

    The apt update refreshes the package index, while apt upgrade -y installs any available upgrades without prompting for confirmation.

    If a new kernel was installed, reboot the host to load it:

    reboot
    

    Verify: After the host comes back online, run pveversion to confirm you are running a supported version, and run apt list --upgradable to ensure no pending upgrades remain.

  2. Download and Deploy an LXC Template

    We will create a Debian‑based LXC container that will host Docker. In the Proxmox GUI navigate to local (proxmox) → CT Templates → Templates. If the list is empty, click the Templates button and then Update to sync the template repository.

    Select a recent Debian template (for example, Debian 11 Bullseye). Note the storage name where the template resides (e.g., local-lvm) and the exact filename of the template file (e.g., debian-11-standard_11.0-1_amd64.tar.xz). You will need these values for the CLI command.

    Now create the container. Choose an unused container ID (CTID), for example 101. Run the following command, replacing the placeholders with the values you noted:

    pct create 101 local-lvm:debian-11-standard_11.0-1_amd64.tar.xz \
      -hostname n8n-lxc \
      -cores 2 \
      -memory 2048 \
      -swap 512 \
      -rootfs local-lvm:8 \
      -net0 name=eth0,bridge=vmbr0,ip=dhcp \
      -features nesting=1
    

    Explanation of the flags:

    • -hostname sets the container’s hostname.
    • -cores and -memory allocate CPU and RAM.
    • -swap adds a small swap file.
    • -rootfs defines the size of the container’s root filesystem.
    • -net0 attaches the container to the host’s bridge vmbr0 and requests an IP via DHCP.
    • -features nesting=1 enables nesting, which is required for Docker’s overlayfs storage driver to work inside the container.

    Verify: Run pct list. You should see the new container with status stopped and the CTID you chose.

  3. Start the Container and Access It

    Start the container we just created:

    pct start 101
    

    Then open a console. You can do this via the Proxmox GUI (select the container → Console) or via the command line:

    pct enter 101
    

    You will be dropped into a root shell inside the container. By default there is no password for the root account; you can set one with passwd if you wish.

    Verify: Your prompt should look something like root@n8n-lxc:~#, indicating you are inside the container.

  4. Update the Container OS and Install Prerequisites

    Now that we have a shell inside the LXC, we update its package list and install the tools needed to add Docker’s repository.

    apt update && apt upgrade -y
    

    This refreshes the container’s package index and applies any available upgrades.

    Next install the prerequisite packages:

    apt install -y curl gnupg2 lsb-release ca-certificates
    

    curl downloads files, gnupg2 handles GPG keys, lsb-release provides distribution information, and ca-certificates ensures SSL verification works.

    Verify: Run curl --version and gnupg --version; both should return version information without errors.

  5. Install Docker Engine (Official Method)

    We will install Docker using the official Docker APT repository, which ensures we get a recent, supported version.

    First add Docker’s GPG key:

    curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | \
      sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
    

    This command fetches the key from Docker’s site, de‑armors it, and stores it in a trusted keyring.

    Next set up the stable repository:

    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
      https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
      $(lsb_release -cs) stable" | \
      sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    

    This creates a file /etc/apt/sources.list.d/docker.list that tells APT where to find Docker packages.

    Update the package index again and install Docker:

    apt update
    apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
    

    The packages installed are:

    • docker-ce – the Docker Engine.
    • docker-ce-cli – the Docker command line client.
    • containerd.io – the container runtime.
    • docker-compose-plugin – enables the docker compose subcommand.

    Enable and start the Docker service so it runs on boot:

    systemctl enable --now docker
    

    If you prefer not to type sudo for every Docker command, add your user to the docker group. Inside the container the default user is root, so this step is optional, but we include it for completeness:

    usermod -aG docker $USER
    newgrp docker   # or log out and back in
    

    Verify: Check that Docker is installed and running:

    docker version
    

    You should see both Client and Server sections with version numbers.

    Run a quick test container:

    docker run --rm hello-world
    

    If the installation succeeded, Docker will download the hello-world image and print a message beginning with “Hello from Docker!”.

  6. Create a Directory for n8n Data and docker‑compose File

    We will keep all n8n‑related files under /opt/n8n inside the container. This makes backups straightforward.

    mkdir -p /opt/n8n
    cd /opt/n8n
    

    Now create a docker-compose.yml file. We will use the official n8n image and enable basic authentication for simplicity. Replace the placeholder values with a username and password of your choice, and set the host variable to the domain or IP you plan to use for the reverse proxy.

    version: "3.8"
    
    services:
      n8n:
        image: n8nio/n8n:latest
        container_name: n8n
        restart: unless-stopped
        ports:
          - "5678:5678"
        environment:
          - N8N_BASIC_AUTH_ACTIVE=true
          - N8N_BASIC_AUTH_USER=your_username
          - N8N_BASIC_AUTH_PASSWORD=your_strong_password
          - N8N_HOST=your-domain.tld
          - N8N_PROTOCOL=https
          - NODE_ENV=production
        volumes:
          - ./data:/home/node/.n8n
    

    Explanation of key sections:

    • The ports line maps container port 5678 to the same port on the container’s localhost, which the host‑side nginx will proxy to.
    • Environment variables enable basic auth, set the hostname n8n will generate links with, and force HTTPS.
    • The volumes line mounts a host directory ./data into the container so that workflows, credentials, and the database persist across container restarts.

    Verify: Confirm the file exists and is syntactically correct:

    ls -l docker-compose.yml
    docker compose config
    

    The second command should output the parsed configuration without error.

  7. Pull and Start n8n via Docker Compose

    With the compose file in place, we can start the stack.

    docker compose up -d
    

    The -d flag runs the containers in the background.

    Give the container a few seconds to initialize, then check its status.

    Verify:

    • List the services:

      docker compose ps
      

      You should see the n8n service with state Up.

    • View the logs to ensure the application started correctly:

      docker compose logs -f n8n
      

      Look for a line similar to “n8n is ready on http://0.0.0.0:5678”.

    • Test the health endpoint from inside the container (or from the host, since the port is bound locally):

      curl -s http://localhost:5678/healthz
      

      A successful response will be a 200 OK or a JSON payload containing {"status":"ok"}.

  8. Install and Configure a Reverse Proxy (nginx) on the Proxmox Host

    We will now install nginx on the Proxmox host itself (not inside the container) and configure it to forward traffic to the n8n service running on the container’s localhost port 5678.

    Warning: The next command removes the default nginx site. If you are already using nginx for other purposes on this host, back up your existing configuration first.

    apt install -y nginx
    

    This installs the nginx web server.

    Remove the default site to avoid conflicts:

    rm /etc/nginx/sites-enabled/default
    

    Create a new site configuration for n8n. Use your preferred editor (nano or vim) to create /etc/nginx/sites-available/n8n-proxy with the following content. Replace your-domain.tld with the actual domain you intend to use (or the host’s public IP if you do not have a domain).

    server {
        listen 80;
        server_name your-domain.tld;
    
        location / {
            proxy_pass http://127.0.0.1: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;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;
        }
    }
    

    Explanation of the proxy settings:

    • proxy_pass forwards the request to the n8n service listening on localhost port 5678.
    • The various proxy_set_header lines preserve important information about the original request (host, client IP, protocol) so that n8n can generate correct URLs and handle WebSocket connections.
    • proxy_http_version 1.1 and the Upgrade/Connection headers are required for proper WebSocket support, which n8n uses for real‑time updates.

    Enable the site by creating a symlink in the sites-enabled directory:

    ln -s /etc/nginx/sites-available/n8n-proxy /etc/nginx/sites-enabled/
    

    Test the nginx configuration for syntax errors:

    nginx -t
    

    If the test passes, reload nginx to apply the new configuration:

    systemctl reload nginx
    

    Verify:

    • Run nginx -t again; it should report “syntax is ok” and “test is successful”.
    • Check the service status:

      systemctl status nginx
      

      It should show active (exited).

    • From a computer on the same network, open a web browser and navigate to http://your-domain.tld. You should see a basic authentication dialog (because we enabled N8N_BASIC_AUTH_ACTIVE). Enter the username and password you set in the compose file. After authenticating, the n8n workflow editor should load.

  9. (Optional) Secure the Proxy with TLS Using Let’s Encrypt

    If you have a domain that points to the host’s public IP, you can obtain a free TLS certificate from Let’s Encrypt to serve n8n over HTTPS. This step is optional but strongly recommended for any production or externally accessible instance.

    Install Certbot and the nginx plugin:

    apt install -y certbot python3-certbot-nginx
    

    Obtain and install the certificate. Replace your-domain.tld with your actual domain:

    certbot --nginx -d your-domain.tld
    

    Follow the prompts. Certbot will automatically modify the nginx site to listen on port 443 and add the necessary SSL directives. It will also ask whether you want to redirect HTTP traffic to HTTPS; choosing the redirect is advisable.

    Certbot installs a systemd timer that will automatically renew the certificate before it expires. You can test the renewal process:

    certbot renew --dry-run
    

    Verify: Open https://your-domain.tld in a browser. You should see a padlock icon indicating a valid certificate, and the n8n login page should appear after you pass the basic‑auth prompt.

  10. Ensure the LXC Container Starts on Boot

    Finally, configure the container to start automatically when the Proxmox host boots.

    In the Proxmox GUI, select the container → Options → Start at boot → set to Yes. Alternatively, run the following command on the host, replacing 101 with your container ID:

    pct set 101 -onboot 1
    

    Verify: Reboot the Proxmox host:

    reboot
    

    After the host returns online, run pct list. The container should appear with status running. Then, inside the container (or via pct enter 101), run docker compose ps to confirm the n8n service is Up.

Verification Summary (Milestones)

shows the container with status running.

shows n8n state Up; health endpoint returns 200 OK.

shows container running and n8n service Up.

Milestone How to Verify
Host updated and functional pveversion shows a supported version; apt list --upgradable returns none.
LXC container created and running pct list
Docker Engine installed inside container docker version prints Client and Server sections; docker run --rm hello-world succeeds.
n8n stack deployed via docker‑compose docker compose ps
Reverse proxy forwarding to n8n Visiting http://your-domain.tld (or HTTPS if TLS enabled) shows the n8n login page after basic auth.
Container starts on host boot After a host reboot, pct list

Troubleshooting Common Failures

Below are the most frequent issues encountered when following this guide, along with steps to resolve them.

1. Container fails to start or shows errors during pct start

Check the container’s log for clues:

pct status 101 --verbose

Common causes:

  • Insufficient memory or disk allocated – increase the -memory or -rootfs values and recreate the container.
  • Missing nesting feature – ensure -features nesting=1 was included when creating the container; if omitted, destroy and recreate with the flag.

2. Docker installation fails with GPG errors

This usually means the system time is wrong, preventing verification of the repository key. Synchronize the clock:

apt install -y ntpdate
ntpdate-debian

Then repeat the Docker repository steps.

3. n8n container exits immediately

Inspect the logs:

Some links on this page may be affiliate links. If you buy through them we may earn a commission at no extra cost to you. See our affiliate disclosure.

How to Check iPhone Battery Health and Cycle CountRead next