Installing ERPNext v15 on Debian 13 Using Docker (Production Guide)

Installing ERPNext v15 on Debian 13 Using Docker (Production Guide)

This guide explains how to install ERPNext v15 on a single Debian 13 server using Docker and Docker Compose, following Frappe’s recommended production approach.

The setup is suitable for:

  • Single ERPNext instance
  • Production workloads
  • Existing or new web servers (Apache / Nginx / Traefik / Caddy)

Architecture Overview (Important to understand first)

This setup runs all ERPNext services inside Docker containers, fully isolated from the host OS.

ComponentPurpose
frappe/erpnextERPNext + Frappe framework
MariaDB 10.6ERPNext database (containerized)
Redis (cache + queue)Background jobs, caching
Docker volumesPersistent data storage
Reverse proxySSL & domain handling

Why Docker MariaDB instead of MariaDB installed on the host?

  • No dependency conflicts
  • Correct, tested database version
  • No interference with host MySQL/MariaDB on port 3306
  • Persistent data via Docker volumes

ERPNext Docker Architecture (Interactive)

Internet
HTTPS :443

⬇ Reverse Proxy
Apache / Nginx
SSL Termination

⬇ HTTP :8080 (internal)
ERPNext Frontend
(Nginx)
ERPNext Backend
(Frappe / Bench)

Redis Cache
Redis Queue
MariaDB 10.6


Step 0 – Install Docker & Docker Compose (run as root)

apt update
apt install -y ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
> /etc/apt/sources.list.d/docker.list
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

Step 1 – Add user to docker group (run as root)

adduser erp
usermod -aG docker erp

• Adding to docker group means you no longer need sudo to run docker commands
• Permission Alignment: All the files created will be under the user ownership

Step 2 – Install Git (run as root)

apt install -y git

Switch to non-root user

su - erp

Step 3 – Clone Frappe Docker repository (non-root)

git clone https://github.com/frappe/frappe_docker
cd frappe_docker

Step 4 – Create .env file

ERPNEXT_VERSION=v15.95.2
DB_PASSWORD=STRONG_DB_PASSWORD
FRAPPE_SITE_NAME_HEADER=example.com
HTTP_PUBLISH_PORT=8080
UPSTREAM_REAL_IP_ADDRESS=127.0.0.1
UPSTREAM_REAL_IP_HEADER=X-Forwarded-For

Note: Use a strong password for MySQL root user.

Step 5 – Fix MariaDB version (important)

By default, Frappe Docker pulls mariadb:11.8.
ERPNext v15 is tested with MariaDB ≤ 10.8.

You may see this warning:

Warning: MariaDB version ['11.8', '5'] is more than 10.8 which is not yet tested with Frappe Framework.

Edit:

overrides/compose.mariadb.yaml

Change:

image: mariadb:11.8

To:

image: mariadb:10.6

Step 6 – Start ERPNext stack

docker compose \
-f compose.yaml \
-f overrides/compose.mariadb.yaml \
-f overrides/compose.redis.yaml \
-f overrides/compose.noproxy.yaml \
up -d

Step 7 – Verify containers

docker compose ls

You should see:

  • frontend
  • backend
  • websocket
  • queue-short / queue-long
  • scheduler
  • redis-cache / redis-queue
  • mariadb (healthy)

Step 8 – Create ERPNext site

docker compose exec backend bench new-site example.com \
--mariadb-root-password DB_PASSWORD \
--admin-password ADMIN_PASSWORD \
--install-app erpnext

Important:
--mariadb-root-password must match DB_PASSWORD in .env
--admin-password is used to log in — note it down

Step 9 – Enable scheduler

docker compose exec backend bench --site example.com enable-scheduler
docker compose exec backend bench --site example.com scheduler enable
docker compose exec backend bench doctor
 bench doctor is your "General Health Check" tool 

Expected output:

-----Checking scheduler status-----
Workers online: 2
-----internal.shenzhen24h.com Jobs-----

Step 10 – Access ERPNext

Open in browser:

http://SERVER-IP:8080/app

Login:

  • Username: Administrator
  • Password: The one you set in Step 8

Step 11 – Reverse proxy & SSL Examples

Apache

<VirtualHost *:443>
ServerName example.com
ProxyPreserveHost On
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
RequestHeader set X-Forwarded-Proto "https"
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>
a2enmod proxy proxy_http headers rewrite
systemctl restart apache2

Nginx

server {
  listen 443 ssl;
  server_name example.com;
  location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto https;
  }
}

Step 12 – If no web server exists

Option A – Traefik

  • Automatic SSL
  • Docker-native
  • Uses compose.https.yaml

Option B – Caddy

  • Very simple configuration
  • Automatic HTTPS
  • Ideal for single-server deployments

Step 13 – Data persistence & backups

ERPNext data is stored in Docker volumes, not inside containers.
Containers can be safely recreated or upgraded without data loss.

Persistent Docker volumes

  • Database: frappe_docker_db-data
  • Sites & file uploads: frappe_docker_sites
  • Redis queue data: frappe_docker_redis-queue-data

Important: Containers are disposable; volumes are persistent.


Recommended backup method (ERPNext-aware)

The preferred way to back up ERPNext is using bench backup inside the backend container.

docker compose exec backend bench \
  --site internal.shenzhen24h.com backup --with-files

This creates a complete backup including:

  • Site configuration
  • MariaDB database (compressed SQL)
  • Public files
  • Private files

Example output:

Backup Summary for internal.shenzhen24h.com

Config  : site_config_backup.json
Database: database.sql.gz
Public  : files.tar
Private : private-files.tar

Backup completed successfully

Backups are stored inside the sites volume:

sites/internal.shenzhen24h.com/private/backups/

Optional: Volume-level backups (infrastructure safety)

For disaster recovery, you may also back up Docker volumes at the filesystem level:

  • Snapshot frappe_docker_db-data
  • Archive frappe_docker_sites

This is useful for full server restores, but bench backups should still be taken regularly.

Common Issues & Fixes

IssueFix
MariaDB 11.x warningDowngrade to 10.6
Scheduler disabledEnable manually
Login loopMissing proxy headers
RequestHeader errorEnable mod_headers
Port 8080 exposedUse reverse proxy only

Best Practices

  • Run Docker as non-root user
  • Use strong DB passwords
  • Do not expose ERPNext directly to the internet
  • Use reverse proxy + SSL
  • Backup Docker volumes regularly

Conclusion

This setup follows Frappe’s official Docker recommendations and provides a stable, secure, production-ready ERPNext installation on Debian 13.