ERPNext behind NGINX Reverse Proxy

Hey guys :slight_smile:

we have an ubuntu server where we want to run different applications behind a NGINX reverse Proxy which runs on the same server. ERPNext is one of the applications (run as a docker file GitHub - frappe/frappe_docker: Docker images for production and development setups of the Frappe framework and ERPNext).

The problem:
The ports 80 and 433 needed for ERPNext are already in use.

I am trying to port forward with the NGINX with the following config:

server {
          listen        443 ssl;
          server_name   mydomain.com;

          ssl_certificate /etc/nginx/ssl/nginx.crt;
          ssl_certificate_key /etc/nginx/ssl/nginx.key;

          location / {
          proxy_pass http://localhost:8433;
    }

I know that the ERPNext Docker Container works with the standard docker-compose.yaml

I used the my domain as SITE_NAME=mydomain.com and in SITES=mydomain.com in the env-production and .env file too.

What am I doing wrong?
What is missing?

Thanks in Advance
Greetings from Germany
Felix

2 Likes
  1. use env-local
  2. instead of mysite.localhost, enter your exact sitename e.g. erp.example.com
  3. remove the traefik service from docker-compose.yaml
  4. publish the port 8080 of erpnext-nginx container to localhost
  5. use proxy of choice and manage tls and reverse-proxy to localhost:8080
modified docker-compose.yaml
version: "3"

services:
  # traefik:
  #   image: "traefik:v2.2"
  #   command:
  #     - "--log.level=DEBUG"
  #     - "--providers.docker=true"
  #     - "--providers.docker.exposedbydefault=false"
  #     - "--entrypoints.web.address=:80"
  #     - "--entrypoints.websecure.address=:443"
  #     - "--certificatesresolvers.myresolver.acme.httpchallenge=true"
  #     - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
  #     - "--certificatesresolvers.myresolver.acme.email=${LETSENCRYPT_EMAIL}"
  #     - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
  #   labels:
  #     # enable traefik
  #     - "traefik.enable=true"
  #     # global redirect to https for production only
  #     - "${HTTPS_REDIRECT_RULE_LABEL}"
  #     - "${HTTPS_REDIRECT_ENTRYPOINT_LABEL}"
  #     - "${HTTPS_REDIRECT_MIDDLEWARE_LABEL}"
  #     # middleware redirect for production only
  #     - "${HTTPS_USE_REDIRECT_MIDDLEWARE_LABEL}"
  #   ports:
  #     - "80:80"
  #     - "443:443"
  #   volumes:
  #     - cert-vol:/letsencrypt
  #     - /var/run/docker.sock:/var/run/docker.sock:ro

  erpnext-nginx:
    image: frappe/erpnext-nginx:${ERPNEXT_VERSION}
    restart: on-failure
    environment:
      - FRAPPE_PY=erpnext-python
      - FRAPPE_PY_PORT=8000
      - FRAPPE_SOCKETIO=frappe-socketio
      - SOCKETIO_PORT=9000
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.erpnext-nginx.rule=Host(${SITES})"
      - "${ENTRYPOINT_LABEL}"
      - "${CERT_RESOLVER_LABEL}"
      - "traefik.http.services.erpnext-nginx.loadbalancer.server.port=80"
    volumes:
      - sites-vol:/var/www/html/sites:rw
      - assets-vol:/assets:rw
    ports:
      - 8080:8080

  erpnext-python:
    image: frappe/erpnext-worker:${ERPNEXT_VERSION}
    restart: on-failure
    environment:
      - MARIADB_HOST=${MARIADB_HOST}
      - REDIS_CACHE=redis-cache:6379
      - REDIS_QUEUE=redis-queue:6379
      - REDIS_SOCKETIO=redis-socketio:6379
      - SOCKETIO_PORT=9000
      - AUTO_MIGRATE=1
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw
      - assets-vol:/home/frappe/frappe-bench/sites/assets:rw

  frappe-socketio:
    image: frappe/frappe-socketio:${FRAPPE_VERSION}
    restart: on-failure
    depends_on:
      - redis-socketio
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw

  erpnext-worker-default:
    image: frappe/erpnext-worker:${ERPNEXT_VERSION}
    restart: on-failure
    command: worker
    depends_on:
      - redis-queue
      - redis-cache
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw

  erpnext-worker-short:
    image: frappe/erpnext-worker:${ERPNEXT_VERSION}
    restart: on-failure
    command: worker
    environment:
      - WORKER_TYPE=short
    depends_on:
      - redis-queue
      - redis-cache
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw

  erpnext-worker-long:
    image: frappe/erpnext-worker:${ERPNEXT_VERSION}
    restart: on-failure
    command: worker
    environment:
      - WORKER_TYPE=long
    depends_on:
      - redis-queue
      - redis-cache
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw

  erpnext-schedule:
    image: frappe/erpnext-worker:${ERPNEXT_VERSION}
    restart: on-failure
    command: schedule
    depends_on:
      - redis-queue
      - redis-cache
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw

  redis-cache:
    image: redis:latest
    restart: on-failure
    volumes:
      - redis-cache-vol:/data

  redis-queue:
    image: redis:latest
    restart: on-failure
    volumes:
      - redis-queue-vol:/data

  redis-socketio:
    image: redis:latest
    restart: on-failure
    volumes:
      - redis-socketio-vol:/data

  mariadb:
    image: mariadb:10.3
    restart: on-failure
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
    volumes:
      - ./installation/frappe-mariadb.cnf:/etc/mysql/conf.d/frappe.cnf
      - mariadb-vol:/var/lib/mysql

  site-creator:
    image: frappe/erpnext-worker:${ERPNEXT_VERSION}
    restart: "no"
    command: new
    depends_on:
      - erpnext-python
    environment:
      - SITE_NAME=${SITE_NAME}
      - DB_ROOT_USER=${DB_ROOT_USER}
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - ADMIN_PASSWORD=${ADMIN_PASSWORD}
      - INSTALL_APPS=${INSTALL_APPS}
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw

volumes:
  mariadb-vol:
  redis-cache-vol:
  redis-queue-vol:
  redis-socketio-vol:
  assets-vol:
  sites-vol:
  cert-vol:
3 Likes

Thank you very much,
that solved my problem :smiley:

1 Like

@Felix_Hieser, could you please share your nginx config? I am having some problems setting this up

Additionally, are the traefik related labels needed in the erpnext-nginx section of docker-compose?

General idea is to setup nginx that proxies to erpnext-nginx service hosted on localhost,
This is setup by publishing docker port of erpnext-nginx container. using the “ports:” array in docker-compose.yml. As mentioned in earlier post, remove traefik container in this case. No labels related to traefik are necessary.

Here is a sample nginx config, GitHub - frappe/frappe_docker: Docker images for production and development setups of the Frappe framework and ERPNext It is port based access. Instead will have to setup your own config that covers your domain name, letsencrypt files, ports. This will be done by your current nginx reverse proxy.

You need to know nginx config. or config for proxy you’re using.

1 Like

Hello Revant, I have normal installation or ERPNext without docker, is this method same for it. I have edited .yaml file as per your format but I am not able to access proxy manager web interface.

I’ve not tested on normal installation

On Ubuntu 22.04

sudo nano /etc/nginx/sites-available/default

edit the nginx config and change the route to

location / {
  proxy_pass http://localhost:8000;
  proxy_buffering off;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-Host $host;
  proxy_set_header X-Forwarded-Port $server_port;
}

Considering the port conflicts you are facing, using NGINX to forward requests to the appropriate ports is a common approach

So kudos for that. Since you’ve already set up the SSL certificates, that part seems solid. Now, about your specific issue, have you checked if there are any other services hogging ports 80 and 443? As for your NGINX configuration, it looks good at first glance. However, you might want to verify a couple of things: Ensure that the ERPNext Docker container is indeed running on port 8433. Double-check your NGINX logs for any error messages that could give a clue about what’s going wrong. Additionally, the suggestion about using env-local instead of mysite.localhost seems reasonable, especially if you’re dealing with a production environment. As for the LTE proxies suggestion, integrating them could potentially help with network stability and security. It’s worth exploring if you’re dealing with issues related to IP blocking or rate limiting.

How does this work in ERPNext 15?