Hello,
For different reasons, we need to deploy ERPNext without reverse proxy and use an existing NGINX setup on the host server.
The used docker compose file is:
name: example
services:
backend:
depends_on:
configurator:
condition: service_completed_successfully
required: true
image: frappe/erpnext:v15.4.0
networks:
default: null
volumes:
- type: volume
source: sites
target: /home/frappe/frappe-bench/sites
volume: {}
configurator:
command:
- |
ls -1 apps > sites/apps.txt; bench set-config -g db_host $$DB_HOST; bench set-config -gp db_port $$DB_PORT; bench set-config -g redis_cache "redis://$$REDIS_CACHE"; bench set-config -g redis_queue "redis://$$REDIS_QUEUE"; bench set-config -g redis_socketio "redis://$$REDIS_QUEUE"; bench set-config -gp socketio_port $$SOCKETIO_PORT;
depends_on:
db:
condition: service_healthy
required: true
redis-cache:
condition: service_started
required: true
redis-queue:
condition: service_started
required: true
entrypoint:
- bash
- -c
environment:
DB_HOST: db
DB_PORT: "3306"
REDIS_CACHE: redis-cache:6379
REDIS_QUEUE: redis-queue:6379
SOCKETIO_PORT: "9000"
image: frappe/erpnext:v15.4.0
networks:
default: null
volumes:
- type: volume
source: sites
target: /home/frappe/frappe-bench/sites
volume: {}
db:
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --skip-character-set-client-handshake
- --skip-innodb-read-only-compressed
environment:
MYSQL_ROOT_PASSWORD: thePassword
healthcheck:
test:
- CMD-SHELL
- mysqladmin ping -h localhost --password=thePassword
interval: 1s
retries: 15
image: mariadb:10.6
networks:
default: null
volumes:
- type: volume
source: db-data
target: /var/lib/mysql
volume: {}
frontend:
command:
- nginx-entrypoint.sh
depends_on:
backend:
condition: service_started
required: true
websocket:
condition: service_started
required: true
environment:
BACKEND: backend:8000
CLIENT_MAX_BODY_SIZE: 50m
FRAPPE_SITE_NAME_HEADER: $$host
PROXY_READ_TIMOUT: "120"
SOCKETIO: websocket:9000
UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
UPSTREAM_REAL_IP_RECURSIVE: "off"
image: frappe/erpnext:v15.4.0
networks:
default: null
ports:
- mode: ingress
host_ip: 127.0.0.1
target: 8080
published: "8080"
protocol: tcp
volumes:
- type: volume
source: sites
target: /home/frappe/frappe-bench/sites
volume: {}
queue-long:
command:
- bench
- worker
- --queue
- long,default,short
depends_on:
configurator:
condition: service_completed_successfully
required: true
image: frappe/erpnext:v15.4.0
networks:
default: null
volumes:
- type: volume
source: sites
target: /home/frappe/frappe-bench/sites
volume: {}
queue-short:
command:
- bench
- worker
- --queue
- short,default
depends_on:
configurator:
condition: service_completed_successfully
required: true
image: frappe/erpnext:v15.4.0
networks:
default: null
volumes:
- type: volume
source: sites
target: /home/frappe/frappe-bench/sites
volume: {}
redis-cache:
image: redis:6.2-alpine
networks:
default: null
volumes:
- type: volume
source: redis-cache-data
target: /data
volume: {}
redis-queue:
image: redis:6.2-alpine
networks:
default: null
volumes:
- type: volume
source: redis-queue-data
target: /data
volume: {}
scheduler:
command:
- bench
- schedule
depends_on:
configurator:
condition: service_completed_successfully
required: true
image: frappe/erpnext:v15.4.0
networks:
default: null
volumes:
- type: volume
source: sites
target: /home/frappe/frappe-bench/sites
volume: {}
websocket:
command:
- node
- /home/frappe/frappe-bench/apps/frappe/socketio.js
depends_on:
configurator:
condition: service_completed_successfully
required: true
image: frappe/erpnext:v15.4.0
networks:
default: null
volumes:
- type: volume
source: sites
target: /home/frappe/frappe-bench/sites
volume: {}
networks:
default:
name: openly_default
volumes:
db-data:
name: openly_db-data
redis-cache-data:
name: openly_redis-cache-data
redis-queue-data:
name: openly_redis-queue-data
sites:
name: openly_sites
x-backend-defaults:
depends_on:
configurator:
condition: service_completed_successfully
image: frappe/erpnext:v15.4.0
volumes:
- sites:/home/frappe/frappe-bench/sites
x-customizable-image:
image: frappe/erpnext:v15.4.0
x-depends-on-configurator:
depends_on:
configurator:
condition: service_completed_successfully
.
.
For No-proxy Override:
services:
frontend:
ports:
- 127.0.0.1:8080:8080
.
.
We used easy-install.py script for setup as follows:
python3 easy-install.py -n example -p -s v15.example.com --email email@example.com
.
.
For NGINX Conf:
server {
listen 1.2.3.4:443 ssl;
listen [::]:443 ssl;
server_name v15.example.com;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
ssl_certificate /etc/letsencrypt/live/v15.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/v15.example.com/privkey.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;
add_header X-Frame-Options "SAMEORIGIN";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "same-origin, strict-origin-when-cross-origin";
location / {
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host v15.example.com;
proxy_set_header X-Forwarded-Port 8080;
proxy_pass http://127.0.0.1:8080;
}
access_log /var/log/nginx/v15_access.log main;
error_log /var/log/nginx/v15_error.log;
# enable gzip compresion
# based on https://mattstauffer.co/blog/enabling-gzip-on-nginx-servers-including-laravel-forge
gzip on;
gzip_http_version 1.1;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types
application/atom+xml
application/javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/font-woff
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
text/css
text/plain
text/x-component
;
# text/html is always compressed by HttpGzipModule
}
# http to https redirect
server {
listen 1.2.3.4:80;
server_name v15.example.com;
return 301 https://$host$request_uri;
}
.
.
Will appreciate any hints or guidance.
Thanks