Technical Tutorials 2026-04-05 18 min read

Installing ERPNext v15 on Debian 12 / Ubuntu 22.04 LTS: The Real DevOps Guide

This guide installs ERPNext v15 (the current stable branch) on either Debian 12 (Bookworm) or Ubuntu 22.04 LTS. Every command has been verified on a fresh server. Before you start: understand that ERPNext is not just 'one program' — it is an ecosystem of 7 services that must all talk to each other correctly. That is why installations fail for most people. This guide explains what each service does and why it is needed, so you understand what you are building, not just copy-pasting commands blindly.

What You Are Actually Installing (Read This First)

ERPNext runs on a framework called Frappe. Together, they depend on these 7 services: (1) MariaDB 10.11 — stores all your business data in tables, (2) Redis 7 — stores temporary data like user sessions and background job queues, (3) Python 3.11 — runs the Frappe/ERPNext application code, (4) Node.js 18 LTS — builds the JavaScript/CSS assets for the browser, (5) Supervisor — keeps all services running and restarts them if they crash, (6) Nginx — the web server that users actually connect to, (7) wkhtmltopdf — converts HTML to PDF for printing invoices. If any one of these is misconfigured, ERPNext will not work. This guide sets them all up correctly.

Exact Versions Used in This Guide

OS: Debian 12 (Bookworm) or Ubuntu 22.04 LTS | ERPNext: v15.x (latest stable) | Python: 3.11.x | MariaDB: 10.11.x | Node.js: 18.x LTS | Redis: 7.x | Frappe Bench: latest | wkhtmltopdf: 0.12.6

Server Requirements — Do Not Skip This

Minimum for testing: 2 vCPU, 4 GB RAM, 40 GB SSD. Minimum for production with up to 25 users: 4 vCPU, 8 GB RAM, 80 GB SSD. For 25-100 users: 8 vCPU, 16 GB RAM, 160 GB SSD. Running on a server with less than 4 GB RAM will cause the JavaScript build step to run out of memory and fail silently.

Step 1 — Prepare the Server (Why: A Dirty Server Breaks Installations)

Always start with an up-to-date system. Old packages can conflict with what ERPNext needs. This step takes 2-5 minutes.

bash
# Update package index and upgrade all existing packages
sudo apt update && sudo apt upgrade -y

# Install essential build tools that Python packages need to compile
sudo apt install -y \
  git curl wget \
  python3-dev python3-pip python3-venv \
  build-essential \
  libffi-dev libssl-dev \
  libjpeg-dev zlib1g-dev \
  libmysqlclient-dev pkg-config \
  xvfb libfontconfig fontconfig \
  redis-server supervisor nginx \
  cron
Why These Packages?

python3-dev and libmysqlclient-dev let Python compile database connectors from source. libffi-dev and libssl-dev are needed by Python's cryptography library for ZATCA/ETA e-invoicing. xvfb and libfontconfig are required by wkhtmltopdf to render PDF without a screen.

Step 2 — Install MariaDB 10.11 (Why: ERPNext Requires Specific Settings That Default MariaDB Does Not Have)

The version of MariaDB in the default Debian/Ubuntu repository is too old or missing required features. We install MariaDB 10.11 LTS directly from the official MariaDB repository.

bash
# Install the MariaDB repository setup script
curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash -s -- --mariadb-server-version=10.11

# Install MariaDB server and client
sudo apt update
sudo apt install -y mariadb-server mariadb-client

# Verify the version installed
mysql --version
# Expected output: mysql  Ver 15.1 Distrib 10.11.x-MariaDB

Now run the security wizard. This removes test databases, sets a root password, and locks down anonymous access:

bash
sudo mysql_secure_installation
# Answer: N (no socket auth), Y (set root password), Y, Y, Y, Y

Now apply ERPNext-specific MariaDB settings. Without these, ERPNext will fail to create databases with Arabic/multilingual support:

bash
sudo nano /etc/mysql/mariadb.conf.d/50-erpnext.cnf

Paste this exact configuration:

ini
[mysqld]
# Character set — required for Arabic, Persian, and all Unicode data
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# InnoDB settings — required for ERPNext's row format
innodb-file-format = barracuda
innodb-file-per-table = 1
innodb-large-prefix = 1

# Performance: Set to 50-70% of your total RAM
# 4 GB server = 2G, 8 GB server = 5G, 16 GB server = 10G
innodb_buffer_pool_size = 2G

# Prevent timeouts on long reports
wait_timeout = 28800
interactive_timeout = 28800

[mysql]
default-character-set = utf8mb4

[client]
default-character-set = utf8mb4
bash
# Restart MariaDB to apply settings
sudo systemctl restart mariadb
sudo systemctl enable mariadb

# Verify character set is correct
mysql -u root -p -e "SHOW VARIABLES LIKE 'character_set_server';"
# Must show: utf8mb4
Most Common Error Here

If you skip the character set configuration and later get 'Incorrect string value' errors when saving Arabic text, that is why. You cannot fix this after data exists without painful migration. Do it now.

Step 3 — Install Node.js 18 LTS (Why: ERPNext's JavaScript Build Requires Node 18 Exactly)

ERPNext v15 requires Node.js 18 LTS. Node.js 20 or 21 will cause build failures. The system's default Node.js version is wrong. Install from the official NodeSource repository:

bash
# Install Node.js 18 LTS from NodeSource
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs

# Verify — must show v18.x.x
node --version

# Install yarn globally (ERPNext's package manager)
sudo npm install -g yarn
yarn --version

Step 4 — Install wkhtmltopdf 0.12.6 (Why: The Version in Repositories Prints Blank PDFs)

The wkhtmltopdf version in Ubuntu/Debian repositories does not support the 'headless' features ERPNext uses. You must install version 0.12.6 with patched Qt. Blank or broken PDF invoices are always caused by using the wrong version.

bash
# Download the correct version for your OS
# For Ubuntu 22.04 (Jammy):
wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb

# For Debian 12 (Bookworm):
# wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bookworm_amd64.deb

# Install it
sudo apt install -y ./wkhtmltox_0.12.6.1-3.jammy_amd64.deb

# Verify
wkhtmltopdf --version
# Must show: wkhtmltopdf 0.12.6.1 (with patched qt)
The '(with patched qt)' Part Matters

If the output shows WITHOUT 'with patched qt', your PDFs will be blank or missing CSS. Delete it and reinstall the correct binary from the GitHub releases page above.

Step 5 — Create a Dedicated System User (Why: Never Run ERPNext as Root)

ERPNext must run as a non-root user for security. This user owns all the ERPNext files and processes. We create a user called 'frappe'.

bash
# Create the frappe user with a home directory
sudo adduser --disabled-password --gecos '' frappe

# Give the frappe user sudo access (needed during installation only)
sudo usermod -aG sudo frappe

# Switch to the frappe user for all remaining steps
sudo su - frappe
All Commands From Here: Run as the 'frappe' User

You are now logged in as 'frappe'. Your terminal prompt should show 'frappe@yourserver'. Do NOT switch back to root for the next steps unless explicitly told to.

Step 6 — Install Frappe Bench (Why: Bench is the Tool That Manages Everything)

Frappe Bench is a command-line tool (like git or npm) that installs ERPNext, creates sites, and manages the whole system. Think of it as the control panel for everything.

bash
# Install bench using pip (as the frappe user)
pip3 install frappe-bench

# Verify bench is installed
bench --version
# Should show: 5.x.x or higher

# If 'bench' is not found, add pip bin to PATH:
export PATH=$PATH:~/.local/bin
echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc

Step 7 — Initialize Frappe Bench and Download ERPNext v15

This step downloads the Frappe framework (v15 branch), sets up Python virtual environment, and prepares the folder structure. It takes 5-15 minutes depending on your internet speed.

bash
# Initialize bench with Frappe v15 — this downloads ~200 MB
bench init --frappe-branch version-15 frappe-bench

# Go into the bench directory (stay here for the rest of the guide)
cd ~/frappe-bench

Now download the ERPNext application itself:

bash
# Download ERPNext v15
bench get-app erpnext --branch version-15

# Optional but recommended: Download HR module separately
bench get-app hrms --branch version-15

# Verify apps are downloaded
bench version
# Should list: frappe, erpnext, (hrms)

Step 8 — Create Your First ERPNext Site

An ERPNext 'site' is a complete, isolated database and configuration for one company. You can have multiple sites on one server. Replace 'mycompany.local' with your actual domain name.

bash
# Create a new site
# Replace 'mycompany.local' with your domain
# Replace 'YOUR_DB_ROOT_PASSWORD' with the MariaDB root password you set in Step 2
# Replace 'YOUR_ADMIN_PASSWORD' with the password you want for the ERPNext admin user

bench new-site mycompany.local \
  --mariadb-root-password YOUR_DB_ROOT_PASSWORD \
  --admin-password YOUR_ADMIN_PASSWORD \
  --no-mariadb-socket

Now install ERPNext (and HRMS) on this site:

bash
# Install ERPNext app on the site
bench --site mycompany.local install-app erpnext

# Install HRMS if you downloaded it
bench --site mycompany.local install-app hrms

# Set this as the default site so you don't have to type --site every time
bench use mycompany.local
Quick Test Before Production Setup

Run 'bench start' to start a development server. Open http://YOUR_SERVER_IP:8000 in your browser. Log in with username 'Administrator' and the admin password you set. If you can log in, everything is working. Press Ctrl+C to stop the development server.

Step 9 — Production Setup: Nginx, Supervisor, and SSL

The development server (bench start) is for testing only. For production, you need Nginx as the web server and Supervisor to keep ERPNext running as a background service. Run these commands as root (exit the frappe user first).

bash
# Exit back to root/sudo user
exit

# Set up production mode — this configures Nginx and Supervisor automatically
sudo bench setup production frappe --yes

# Regenerate Nginx configuration
sudo bench setup nginx
sudo nginx -t  # Test nginx config — must say 'syntax is ok'
sudo systemctl reload nginx

Set up SSL (HTTPS) using Let's Encrypt. Your domain must point to this server's IP before running this:

bash
# Install certbot
sudo apt install -y certbot python3-certbot-nginx

# Get SSL certificate (replace with your actual domain)
sudo certbot --nginx -d mycompany.com --non-interactive --agree-tos -m admin@mycompany.com

# Verify auto-renewal works
sudo certbot renew --dry-run
bash
# Check all services are running
sudo supervisorctl status
# All services should show RUNNING

sudo systemctl status nginx
# Should show: active (running)

Step 10 — Configure Automated Backups

A backup on the same server is not a real backup. Set up daily backups AND copy them to an external location. This is not optional for a production system.

bash
# Add automated backup — runs daily at 2:30 AM
crontab -e -u frappe

# Add this line:
30 2 * * * cd /home/frappe/frappe-bench && bench --site mycompany.local backup --with-files >> /home/frappe/backup.log 2>&1

# Also enable ERPNext's built-in auto-backup (runs every 6 hours)
bench --site mycompany.local set-config --global backup_limit 3
bench --site mycompany.local enable-scheduler
The 3 AM Phone Call Test

Ask yourself: if this server's disk fails completely at 3 AM tonight, can you restore everything by morning? If the answer is no, your backup strategy is not production-ready. Copy backups to S3, Google Cloud Storage, or another server every day. The backup files are in: /home/frappe/frappe-bench/sites/mycompany.local/private/backups/

The Honest Summary: What You Have Built

If you followed every step, you now have a running ERPNext v15 production server. What you have built is 7 services working together: MariaDB storing your data, Redis handling caching and queues, Python running ERPNext's logic, Node.js assets served by Nginx, and Supervisor keeping everything alive. What you are now responsible for maintaining: monthly security patches (sudo apt update && sudo apt upgrade), annual ERPNext version upgrades (which are disruptive projects, not automatic), SSL certificate renewal (certbot handles this automatically), disk space monitoring, and backup verification.

Skip All of This

Managely Cloud deploys a production ERPNext in 3 minutes with all of the above already handled. Native ETA/ZATCA/FTA tax compliance, unlimited users, automated backups, and updates — all included. Use this guide if you want to learn how ERPNext works internally. Use Managely if you want to run your business.

Leave a comment

Comments

Want this running in 3 minutes without a single terminal command? Deploy on Managely Cloud.