Host n8n in a server where apache is also running

Hello, I want to install n8n in a server that is also running a LAMP stack.

I tried to follow the instructions here but I get (quite understandably) the following error

ERROR: for n8n_traefik_1 Cannot start service traefik: driver failed programming external connectivity on endpoint n8n_traefik_1 (55f4c1c51c8d2e1ea8186e82c36e7fc86210db397b35e9f9ab11e8ae92c22d1b): Error starting userland proxy: listen tcp 0.0.0.0:443: bind: address already in use

That’s expected since httpd is running on port 443. So I opened the 2020 port in my firewall and tried to change the port to run n8n on docker-compose.yml. Changed 443 to 2020 in the whole document.

However if I go to my browser and try to go to mydomain.com:2020 or n8n.mydomain.com:2020 or even myserverip:2020 it still doesn’t work.

And now I’m not sure if I set up the docker-compose.yml correctly or how to set the .env file (starting from the sample version available in the instructions) to allow for a URL-with-a-port type of configuration (or if there is a way that I missed to make apache and n8n work together)

Thanks in advance

1 Like

Welcome to the community @nguy!

Another port than 443 will sadly not work. The reason is that it is the default SSH port and Lets Encrypt will not accept any other one:

So the only way to make it work is to get a different server or to convert your existing application to docker and serve it then also via traefik.

At least if you want to use the docker-compose setup with Lets Encrypt. You could obviously anytime run n8n differently like simply npm install it or start only the n8n container via HTTP (not recommended and will cause problems with many services) or buy an SSL certificate and then add it directly to n8n like described here:

Seems like the DOCs you’re quyoting there no longer exist. This discussion is still relevant, so when you say add a SSL certificate directly to n8n, you mean through the following environment variables?
N8N_SSL_KEY and N8N_SSL_CERT?

Hey @fogolin,

You got it, What I would do though is set up Apache as a reverse proxy and handle the SSL/TLS there which may be easier unless you know your way around certificates.

1 Like

I have the same problem, how can I configure the Apache server as a reverse proxy?

Hey @JoelGaribay,

I have never tried with the Apache web server but looking at the documentation for it assuming you have mod_proxy installed it should be a case of updating your Apache config to add something like the below, There could be more needed but it would be worth starting with that.

<VirtualHost *:80>
    ProxyPreserveHost On

    ProxyPass / http://127.0.0.1:5678/
    ProxyPassReverse / http://127.0.0.1:5678/
</VirtualHost>
1 Like

Thanks.

Ready, I already created a new virtualhost pointing to port 80 with the configuration you mention, however I can’t get it to open N8N, it opens my main website

I already activated the Apache proxy and proxy_http modules

Note: I currently have a website with wordpress in domain.com, it is configured in a virtualhost with port 443, when opening n8n.domain.com it opens my website

What else could I do?

Did you add ServerName or/and ServerAlias to your config?

Here’s an example of one of mine configurations with n8n.

<VirtualHost _default_:443>
  SSLEngine on

  ProxyPreserveHost On
  ProxyRequests Off
  ServerName n8n.let-the-work-flow.com
  ProxyPass / http://localhost:5678/
  ProxyPassReverse / http://localhost:5678/

</VirtualHost>
2 Likes

Thanks for your answer, yes, I just have it very similar.

I have a question, I have the main website with port 443, is there a problem if the new virtualhost (the one from n8n) is in :80?

<VirtualHost *:80>

        ProxyPreserveHost On
        ProxyRequests Off

        ServerAdmin [email protected]
        ServerName n8n.domain.com
        ServerAlias n8n.domain.com

        ProxyPass / http://127.0.0.1:5678/
        ProxyPassReverse / http://127.0.0.1:5678/

</VirtualHost>

Thank you very much for your input, I was able to fix it.

My problem was that CloudFlare was blocking my subdomain (from what I understood cloudflare had put a proxy on it automatically and it must be free of that)

Note: For those who are making the VirtualHost with port 80, they need to enter only with HTTP, however, the ideal would be to have it in port 443 so that the entry is with HTTPS.

It is 100% recommended that it be through port 443

All the best

1 Like

The following works for n8n on uBuntu 24 on a VPS with ISPConfig 3.2 (multiple site control panel), that hosts multiple sites, email, and dbs. The key to getting this working for me was to use proxy_wstunnel. After hours, it works and there are no more connection errors or web socket errors.

Enable proxy_wstunnel in Apache

a2enmod proxy_wstunnel
systemctl restart apache2

Apache vhost file:

<VirtualHost *:80>

    ServerName example1.server.com
    ErrorLog ${APACHE_LOG_DIR}/reverse-proxy-http.example1.server.com.error.log
    CustomLog ${APACHE_LOG_DIR}/reverse-proxy-http.example1.server.com.access.log combined

    RewriteEngine on
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

</VirtualHost>

<VirtualHost *:443>

    ServerName server1.example.com
    ServerAdmin [email protected]
    ServerAlias server1.example.com


    SSLEngine       On
    SSLProxyEngine  On
    ProxyRequests   Off
    ProxyPreserveHost       On


    SSLCertificateFile /root/.n8n/server1.example.com/.ssl/server1.example.com.crt
    SSLCertificateKeyFile /root/.n8n/server1.example.com/.ssl/server1.example.com.key
    SSLCertificateChainFile /root/.n8n/server1.example.com/.ssl/server1.example.com.ca-bundle


    TimeOut 600
    KeepAliveTimeout 600


    SSLProxyVerify none
    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off
    SSLProxyCheckPeerExpire off


    <Proxy *>
        Require all granted
    </Proxy>


    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*)           ws://localhost:5678/$1 [P,L]
    RewriteCond %{HTTP:Upgrade} !=websocket [NC]
    RewriteRule /(.*)           http://localhost:5678/$1 [P,L]
    ProxyPassReverse /          http://server1.example.com

    ErrorLog ${APACHE_LOG_DIR}/reverse-proxy-server1.example.com.error.log
    CustomLog ${APACHE_LOG_DIR}/reverse-proxy-server1.example.com.access.log combined


</VirtualHost>

My .env file

# The top level domain to serve from
DOMAIN_NAME=example.com

# The subdomain to serve from
SUBDOMAIN=server1

# DOMAIN_NAME and SUBDOMAIN combined decide where n8n will be reachable from
# above example would result in: https://anything.theaiaa.com

# Optional timezone to set which gets used by Cron-Node by default
# If not set New York time will be used
GENERIC_TIMEZONE=America/Chicago

# The email address to use for the SSL certificate creation
[email protected]

My docker-compose.yaml

services:
  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: always
    ports:
#      - "127.0.0.1:5678:5678"
      - "5678:5678"
    environment:
      - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  n8n_data:
    external: true

This uses an Comodo issued SSL certificate because ISPConfig 3.2+ has issues with certbot and instead uses the acme.sh open source implementation of Let’sEnrypt.

I believe you can use the ISPC 3.2+ acme.sh implementation for self-signed and auto-renewed certificates by simply adding a DNS zone to ISPC for server1.example.com, pointing example.com NS to ISPC name servers, enabling a site for server1.example.com, letting it generate the certificates, then disabling (but not deleting) the ISPC created site. You can then use the ISPC vhost file for server1.example.com to locate your acme.sh/LE certificates and update your vhost file above with those certificates. This will make ISPC ignore the site from an Apache standpoint, but ISPC will still renew the certificates with acme.sh/LE which requires control over the server1.example.com DNS. (To be continued…)