bolt Valebyte VPS від $4/міс — NVMe, запуск за 60 секунд.

Отримати VPS arrow_forward
eco Початковий Туторіал

ERPNext on a Dedicated Server: Installation and Load Requirements

calendar_month Sep 25, 2026 schedule 23 хв. читання visibility 28 переглядів
ERPNext на выделенном сервере: установка и требования по нагрузке
info

Потрібен сервер для цього гайду? Ми пропонуємо виділені сервери та VPS у 50+ країнах з миттєвим налаштуванням.

Потрібен сервер для цього гайду?

Розгорніть VPS або виділений сервер за хвилини.

ERPNext on a Dedicated Server: Installation and Load Requirements

TL;DR

ERPNext is an open-source ERP system for accounting, sales, purchasing, inventory, manufacturing, projects, and finance. In this guide, we will install ERPNext 15 on a dedicated server with Ubuntu 24.04 LTS, MariaDB, Redis, Node.js, Frappe Bench, and the Nginx reverse proxy, enable HTTPS, create backups, and test the system under load.

  • For a small company or test environment, 4 vCPU, 8 GB RAM, and an SSD of at least 80 GB are sufficient.
  • For 20–50 simultaneously active users, 8 vCPU, 16 GB RAM, and at least 160 GB of NVMe are more practical.
  • ERPNext 15 is installed on top of Frappe Framework 15; the server is best deployed on Ubuntu 24.04 LTS or Ubuntu 22.04 LTS.
  • The system's core services are MariaDB, Redis, Node.js, Python, Nginx, and Supervisor.
  • You need to back up not only the database, but also ERPNext files, configuration, private files, and encryption keys.
  • Before updating a production system, a full backup, test restoration, and maintenance window are required.

3. What We Are Configuring and Why

ERPNext is a web application for business management. A single installation can be used to manage companies, counterparties, invoices, sales, purchases, inventory balances, manufacturing, projects, employees, and financial operations. The system is built on Frappe Framework: the user works through a browser, while the server handles business logic, background tasks, and database queries.

This guide uses a typical single-node architecture. All services are hosted on one dedicated server: MariaDB stores transactional data, Redis handles queues and caching, workers execute background tasks, and Nginx accepts HTTPS connections and forwards requests to Frappe processes. This setup is suitable for an initial production installation if the volume of data and number of users do not yet require the components to be separated.

What Will Be Available at the End

After completing the steps, an ERPNext site with a separate domain name, an HTTPS certificate, and an administrator user will be available. The system will start automatically after a server reboot, background tasks will run through Supervisor, and access to MariaDB and Redis will remain local.

The configuration includes basic security measures: SSH key authentication, a separate sudo user, firewall port restrictions, fail2ban, no public access to the database, and automatic renewal of the Let’s Encrypt certificate. For production, you should additionally configure monitoring, centralized log storage, and regular recovery checks.

What Tasks ERPNext Solves

  • Sales: leads, quotations, customer orders, shipments, and invoices.
  • Purchasing: suppliers, requests, purchase orders, receipts, and invoices.
  • Inventory: warehouses, batches, serial numbers, stock transfers, and inventory valuation.
  • Manufacturing: bills of materials, work orders, operations, and material consumption.
  • Finance: chart of accounts, payments, journal entries, taxes, and reports.
  • Projects: tasks, time logs, deadlines, and links to customer documents.
  • HR: employees, leaves, attendance, and basic personnel processes.

Self-hosted and Cloud-managed

In a managed cloud, the provider usually handles installation, updates, TLS, backups, and some monitoring. This reduces the team's operational costs, but limits control over the OS, network architecture, update schedule, and data storage method. In addition, the cost of a managed installation usually increases along with the number of users and the amount of storage.

Self-hosted ERPNext on a VPS or dedicated server provides full access to the operating system and configuration. The administrator chooses the application version, backup policy, network rules, and integration method for external services. The downside is responsibility for updates, security, recovery, and performance analysis.

For one company with several dozen users, a single-node installation is usually a reasonable starting point. When the database becomes large, heavy reports appear, mass imports are performed, or dozens of background processes are running, the architecture can be split: MariaDB, Redis, workers, and files can be moved to separate nodes.

Limitations of a Single-node Setup

If the server completely fails, the web interface, database, and background tasks will all become unavailable at the same time. Therefore, having a backup on the same disk is not considered sufficient protection. At a minimum, an external copy of the database and files is required; for a critical system, use a separate standby server or a regularly tested recovery procedure on a new instance.

4. What VPS Configuration Is Needed for This Task

Схема: 4. Какой VPS-конфиг нужен под эту задачу
Diagram: 4. What VPS Configuration Is Needed for This Task

ERPNext requirements depend not only on the number of user accounts. The load is affected by the number of simultaneously active users, the number of sites, database size, frequency of background tasks, report complexity, CSV imports, number of items, and document history. You cannot assess a server solely by the number of registered users: one hundred users working in turns create less load than twenty users running heavy reports simultaneously.

Minimum Specifications

A server with 4 virtual CPUs, 8 GB of RAM, and a fast SSD with at least 80 GB of capacity is suitable for a lab installation or small company. This size is designed for approximately 5–10 active users under moderate load. For a demonstration environment, you can start with 2 vCPU and 4 GB of RAM, but this is not the best option for production: MariaDB, workers, and web processes will compete for memory.

Scenario CPU RAM Disk Concurrent Users
Testing and training 2 vCPU 4 GB 40–60 GB SSD 1–3
Small production installation 4 vCPU 8 GB 80–120 GB NVMe 5–10
Working team 8 vCPU 16 GB 160–250 GB NVMe 20–50
High load on a single node 12–16 vCPU 32 GB 300 GB or more NVMe 50–100

As a practical starting configuration for a small production team, you can choose a VPS with these specifications: 8 vCPU, 16 GB RAM, at least 160 GB of NVMe, a public IPv4 address, and a connection of at least 500 Mbps. This reserve will allow you to allocate memory to MariaDB, run several web processes, and retain space for logs, files, and backup archives.

CPU, Memory, and Disk

CPU is required for processing web requests, serializing data, generating PDFs, importing documents, and running background tasks. Single-core frequency is important for the interactive interface, while the number of cores matters for parallel workers and multiple users. If users complain about delays when opening forms and the CPU is constantly busy, first check slow SQL queries and the number of gunicorn processes instead of simply upgrading the plan.

RAM is especially important for MariaDB and Redis. On a system with 8 GB of RAM, you should leave at least 1–1.5 GB of reserve for the OS, Nginx, Supervisor, and temporary operations. With swap enabled, the server can withstand a short-term spike, but swap does not replace RAM: continuous operation through swap severely worsens query latency.

For ERPNext, it is best to use NVMe or another low-latency SSD. The disk must accommodate the operating system, database, public and private files, logs, temporary archives, and room for growth. A practical rule is to reserve at least twice the current data volume. Backup should not be stored on the same partition as the only copy.

Network and IP Address

ERPNext does not require a large connection for ordinary operation, but a public IPv4 address simplifies DNS, certificate issuance, and integrations. A connection of at least 100 Mbps is useful for file transfers, backups, and mass imports. Web access should use ports 80 and 443; SSH should preferably be restricted by administrator IP addresses or placed behind a VPN.

When a Dedicated Server Is Needed

A dedicated server is justified when the system constantly uses a large amount of CPU or RAM, predictable disk performance is required, several large companies share one installation, or additional services run on the node. It is also convenient for resource-intensive reports, mass synchronization with marketplaces, generating large numbers of PDFs, and storing a large file archive.

If the only reason for choosing a dedicated server is concern about VPS instability, first check the SLA and virtualization type. A good VPS with dedicated resources and NVMe may be sufficient for dozens of users. A dedicated server becomes especially useful when there are requirements for physical isolation, licensing, local RAID, large amounts of memory, or consistently high utilization.

Server Location

The region affects interface latency, file upload speed, and compliance with personal data location requirements. For employees in one country, choose a data center closer to them, but check not only geographic distance, but also actual latency and routing quality. For integrations with payment systems, telephony, and external APIs, you should additionally verify the availability of the required addresses from the selected network.

5. Server Preparation

Diagram: 5. Server Preparation
Diagram: 5. Server Preparation

The following assumes a clean server with Ubuntu Server 24.04 LTS, a configured DNS record erp.example.com, and access under the user created by the provider. Commands are executed by a user with sudo privileges. Replace the domain, username, and time zone with your own values.

Updating the System and Basic Utilities

# Update the package index and install the latest fixes
sudo apt update && sudo apt full-upgrade -y

# Install administration and build tools
sudo apt install -y \
  git curl wget vim htop unzip jq ca-certificates \
  software-properties-common build-essential \
  python3-dev python3-pip python3-venv python3-setuptools \
  libffi-dev libssl-dev libmariadb-dev pkg-config

# Set the correct time zone
sudo timedatectl set-timezone Europe/Moscow

# Check the time, kernel version, and Ubuntu release
timedatectl
uname -a
lsb_release -a

ERPNext generates dates and reports based on the server time zone and site settings. For a distributed team, it is better to determine in advance whether the server will operate in UTC or use the time zone of the primary organization. Changing the timezone after documents have been created can cause confusion when analyzing day boundaries.

Creating a Separate User

# Create a system user for Frappe Bench
sudo adduser --disabled-password --gecos "" frappe

# Allow the user to execute administrative commands through sudo
sudo usermod -aG sudo frappe

# Switch to the new user
sudo -iu frappe

# Check the owner and home directory
id
pwd

Do not run Bench as root. A separate user limits the consequences of an error in a user application and simplifies permission management. Commands that require changes to system services are executed through sudo, while Bench commands are executed as frappe.

SSH Keys and Disabling Passwords

First, add the public key to /home/frappe/.ssh/authorized_keys. If you connected under the initial user, you can create the directory and set its permissions as follows:

# Create the SSH directory and set secure permissions
sudo install -d -m 700 -o frappe -g frappe /home/frappe/.ssh

# Add your own public key here on a single line
sudoedit /home/frappe/.ssh/authorized_keys

# Restrict access to the key file
sudo chown frappe:frappe /home/frappe/.ssh/authorized_keys
sudo chmod 600 /home/frappe/.ssh/authorized_keys

Test logging in through a new SSH session before disabling passwords. To secure SSH, you can create a separate drop-in file:

# Create SSH settings without modifying the main file
sudo tee /etc/ssh/sshd_config.d/10-hardening.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
EOF

# Check the syntax and reload the SSH configuration
sudo sshd -t
sudo systemctl reload ssh

If SSH is accessible from the internet, restrict it to specific sources whenever possible. Do not close the current session until you have verified the new login. Loss of access due to an incorrect firewall rule or SSH configuration usually requires the provider's console.

Firewall and fail2ban

# Install the firewall and protection against password guessing
sudo apt install -y ufw fail2ban

# Allow SSH, HTTP, and HTTPS before enabling the deny policy
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Deny all other incoming connections and allow outgoing connections
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Enable the firewall and check the active rules
sudo ufw enable
sudo ufw status verbose

# Start fail2ban at boot and activate it immediately
sudo systemctl enable --now fail2ban
sudo fail2ban-client status

If the SSH port is changed, first allow the new port in UFW and only then restart SSH. Changing the port number by itself is not a complete security measure; the key protections are disabled password authentication, source restrictions, and monitoring of login attempts.

Swap for a Small Server

Swap is useful as an emergency buffer during an import or a short-term spike, especially on a server with 8 GB of RAM. For production with 16 GB of memory, a 2–4 GB swap file is usually sufficient if the load is monitored.

# Create a 4 GB swap file
sudo fallocate -l 4G /swapfile

# Allow access only to root and enable swap
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# Enable swap after reboot
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# Check the memory and swap status
free -h
swapon --show

6. Software Installation — Step by Step

Diagram: 6. Software Installation — Step by Step
Diagram: 6. Software Installation — Step by Step

This section installs ERPNext 15 and Frappe Framework 15. For production, we use Python 3.12, Node.js 18 LTS, MariaDB 10.11 from the Ubuntu 24.04 repository, Redis from Ubuntu, Yarn, and the official Bench installer through a Python package. Before starting, check the current Frappe compatibility matrix for the selected minor release: dependency versions may change between releases.

Installing MariaDB

# Install the database server and client libraries
sudo apt install -y mariadb-server mariadb-client libmariadb-dev

# Enable MariaDB at boot and start it now
sudo systemctl enable --now mariadb

# Check the service status
sudo systemctl status mariadb --no-pager

# Start the interactive removal of insecure settings
sudo mariadb-secure-installation

In the MariaDB wizard, remove anonymous users, disable remote root login, and remove the test database. MariaDB root will be used locally to create the site database, but access to it must not be exposed over the network.

ERPNext requires correct character encodings and InnoDB parameters. Create a separate configuration file:

# Create the MariaDB parameters required by Frappe
sudo tee /etc/mysql/mariadb.conf.d/60-erpnext.cnf > /dev/null <<'EOF'
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
innodb-file-per-table = 1
innodb-large-prefix = 1
innodb-buffer-pool-size = 4G
max_connections = 200
EOF

# Restart MariaDB and check for errors
sudo systemctl restart mariadb
sudo journalctl -u mariadb -n 50 --no-pager

For a server with 8 GB of RAM, the innodb-buffer-pool-size value should be reduced to approximately 2–3 GB. Do not copy the 4G value to a small server: the database, workers, and OS must have free memory.

Installing Redis and Supervisor

# Install the Redis queue and process manager
sudo apt install -y redis-server supervisor

# Enable the services at boot
sudo systemctl enable --now redis-server supervisor

# Check the Redis response
redis-cli ping

# Check the status of both services
sudo systemctl status redis-server supervisor --no-pager

The PONG response means that Redis accepts local requests. External access to Redis is not required. Make sure that the Redis listening address is not exposed on a public interface in the Redis configuration.

Installing Node.js 18 and Yarn

# Add the official NodeSource repository for Node.js 18 LTS
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -

# Install Node.js and npm
sudo apt install -y nodejs

# Install Yarn for building frontend assets
sudo npm install --global yarn

# Check the tool versions
node --version
npm --version
yarn --version

Frappe 15 typically uses Node.js 18 LTS. If a specific ERPNext release requires Node.js 20, follow its official compatibility table and do not mix arbitrary versions. After changing Node.js, you must rebuild the assets through Bench.

Installing wkhtmltopdf

ERPNext uses wkhtmltopdf for some print formats and PDF generation. The version in the Ubuntu repository may differ from the recommended version. Install the package specified in the documentation for the compatible release and verify the result.

# Install the package for generating PDFs from HTML
sudo apt install -y wkhtmltopdf

# Check that the binary is available
wkhtmltopdf --version

If print formats in your version require a patched Qt build of wkhtmltopdf, use the official package from the Frappe documentation for Ubuntu. Do not download random deb files from forums: the PDF generator runs on the server and must be updated from a trusted source.

Installing Bench CLI

# Switch to the application system user
sudo -iu frappe

# Install Bench CLI in the user's Python directory
python3 -m pip install --user frappe-bench

# Add local Python binaries to the PATH of the current session
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
export PATH="$HOME/.local/bin:$PATH"

# Check the installed Bench version
bench --version

The bench init command creates the project structure, virtual environment, and Frappe source code. The project directory in the example is called frappe-bench.

Creating Bench and Installing Frappe

# Create Bench on the Frappe version-15 branch
bench init --frappe-branch version-15 frappe-bench

# Change to the project directory
cd ~/frappe-bench

# Check the status of the created environment
bench version
bench doctor

If bench init ends with a compilation error, check the available disk space, Python version, the python3-dev package, and access to GitHub. Do not blindly run the command again: first read the last lines of the output and the installation logs.

Creating the ERPNext Site

# Create a new site; the command will prompt for the MariaDB root password
bench new-site erp.example.com

# Install the ERPNext application from the official version-15 branch
bench get-app --branch version-15 erpnext https://github.com/frappe/erpnext

# Install ERPNext on the created site
bench --site erp.example.com install-app erpnext

# Set the site as the default site for this Bench
bench use erp.example.com

# Build the application's JavaScript and CSS assets
bench build

# Check the installed applications and migrations
bench --site erp.example.com list-apps
bench --site erp.example.com migrate

During bench new-site, set a long MariaDB administrator password and a separate password for the ERPNext Administrator user. Do not store passwords in the shell history or pass them on the command line. If the domain is not configured yet, you can use the site name locally for the initial check and enable HTTPS after the DNS record appears.

Checking in Development Mode

# Start a temporary development server for local testing only
cd ~/frappe-bench
bench start

The command starts processes in the current terminal and is not intended for production. From another terminal, check port 8000 through an SSH tunnel:

# Run on your local computer
ssh -L 8000:127.0.0.1:8000 frappe@SERVER_IP

# After connecting, open the local address
curl -I http://127.0.0.1:8000

Stop the development server with Ctrl+C. In production, Supervisor and Nginx will manage the processes.

Generating the Production Configuration

# Install the Supervisor and Nginx production configuration
sudo bench setup production frappe

# Reload the Supervisor configuration
sudo supervisorctl reread
sudo supervisorctl update

# Check the list of Bench processes
sudo supervisorctl status

# Restart all processes after installing the application
sudo supervisorctl restart all

The command creates configurations in system directories. Process names depend on the Bench version and username. If Supervisor shows FATAL or BACKOFF, check the log for the specific process and verify the paths to Python, Node.js, and the project.

7. Configuration

Diagram: 7. Configuration
Diagram: 7. Configuration

DNS and Domain

Create an A record erp.example.com pointing to the server's public IPv4 address. If IPv6 is used, add an AAAA record only after checking the firewall and routing. Before issuing the certificate, make sure that the domain resolves from an external network and that port 80 is accessible.

# Проверяем DNS-запись домена
dig +short erp.example.com A
dig +short erp.example.com AAAA

# Проверяем HTTP-доступ к серверу по имени
curl -I http://erp.example.com

Configuring Nginx and HTTPS

Bench generates a basic Nginx configuration for the site. After DNS is directed to the server, enable HTTPS using the built-in Bench command or use Certbot. For a typical installation with an already generated configuration:

# Проверяем синтаксис сгенерированной конфигурации Nginx
sudo nginx -t

# Перезапускаем Nginx после проверки
sudo systemctl enable --now nginx
sudo systemctl reload nginx

# Выпускаем сертификат и включаем HTTPS через Bench
cd /home/frappe/frappe-bench
sudo bench setup lets-encrypt erp.example.com

The Let’s Encrypt command requires an accessible domain and port 80 for the HTTP-01 challenge. If the certificate is not issued, check DNS, the external firewall, UFW rules, and whether another reverse proxy is present. After installation, check automatic renewal using the Certbot systemd timer or the procedure created by Bench.

# Проверяем сертификаты и таймеры автоматического продления
sudo certbot certificates
systemctl list-timers | grep -i certbot

# Проверяем HTTPS и заголовки ответа
curl -I https://erp.example.com

Basic Site Settings

ERPNext and Frappe settings are stored in the site's JSON files. Secrets should not be placed in a git repository, public Nginx configurations, or shell scripts. The site_config.json file should be accessible only to the application user and root.

# Переходим в каталог сайта
cd /home/frappe/frappe-bench/sites/erp.example.com

# Проверяем права файла конфигурации
ls -l site_config.json

# Ограничиваем права на конфигурацию сайта
chmod 600 site_config.json

# Просматриваем настройки без вывода секретов в общий лог
bench --site erp.example.com show-config

Redis parameters, MariaDB connection settings, and encryption keys are created automatically by Bench. Do not replace them with random values without understanding the consequences: losing the encryption key can make encrypted values in the database inaccessible.

Number of Web and Background Processes

On a small server, start with two web processes and one worker for each queue, if RAM allows. Increasing the number of processes does not guarantee improved performance: each process consumes memory, and MariaDB also needs a buffer pool. Make changes after monitoring CPU, RAM, latency, and queue lengths.

# Показываем текущие настройки Bench и сайтов
cd /home/frappe/frappe-bench
bench config export

# Смотрим загрузку очередей и состояние workers
bench doctor
sudo supervisorctl status

# Проверяем процессы и потребление памяти
ps aux --sort=-%mem | head -n 15
free -h
uptime

For long-running background tasks, such as bulk imports or report generation, separate queues by priority. In production, heavy jobs should not be run without limiting concurrency: they can consume all CPU and memory, causing the interactive interface to stop responding.

Application and Health Check

# Проверяем ответ через публичный HTTPS-адрес
curl --fail --silent --show-error https://erp.example.com/api/method/frappe.ping

# Проверяем статус HTTP и заголовок сервера
curl -sS -o /dev/null -w 'HTTP %{http_code}\n' https://erp.example.com

# Проверяем очередь Redis и состояние базы локально
redis-cli ping
sudo systemctl is-active mariadb
sudo systemctl is-active nginx

# Проверяем миграции и состояние сайта
cd /home/frappe/frappe-bench
bench --site erp.example.com doctor
bench --site erp.example.com migrate

For monitoring, use an external HTTP check that verifies the HTTPS response code and response time. Also monitor free disk space, inode usage, RAM, swap, queue fill levels, and the age of the latest backup. Checking only port 443 does not show whether MariaDB and background workers are operating correctly.

Logs

# Смотрим журналы Bench и последние ошибки
cd /home/frappe/frappe-bench
tail -n 100 logs/web.error.log
tail -n 100 logs/worker.error.log

# Смотрим системные ошибки Nginx и Supervisor
sudo journalctl -u nginx -n 100 --no-pager
sudo journalctl -u supervisor -n 100 --no-pager

# Проверяем размер каталогов проекта и логов
du -sh sites/ logs/ 2>/dev/null

Logs should be rotated. If a log occupies a significant portion of the disk, configure logrotate and do not manually delete active files while processes are running. First identify the source of the recurring error, then fix the cause, and only afterward clean up accumulated logs.

8. Backups and Maintenance

Diagram: 8. Backups and Maintenance
Diagram: 8. Backups and Maintenance

What Needs to Be Backed Up

A minimal ERPNext backup consists of a MariaDB dump and the site files. The database contains documents, settings, users, permissions, and most business data. The sites/erp.example.com/private/files directory may contain private attachments, while public/files contains publicly accessible images and documents.

  • Database: a complete MariaDB dump created using Bench or mysqldump.
  • Private files: private attachments and user documents.
  • Public files: images, print formats, and resources accessible by URL.
  • Configuration: site_config.json, Bench, Supervisor, and Nginx configuration.
  • Keys: SSH keys, encryption keys, and credentials for external integrations.

The ERPNext administrator password alone does not replace a backup. You should also not copy only the project directory without the database: such a copy will not restore a consistent state of the documents. It is recommended to retain several daily restore points, weekly copies, and a separate monthly copy.

Creating a Backup Through Bench

# Создаем полный backup базы и файлов сайта
cd /home/frappe/frappe-bench
bench --site erp.example.com backup --with-files --compress

# Показываем созданные архивы и их размеры
find sites/erp.example.com/private/backups -maxdepth 1 -type f -printf '%TY-%Tm-%Td %TH:%TM %s %p\n' | sort

The command saves archives locally. This is only the first step. If the server or disk is damaged, the local copy will disappear along with the working system, so the archives must be sent to external storage.

Example of Sending to S3-Compatible Storage Using rclone

# Устанавливаем rclone из пакетов Ubuntu
sudo apt install -y rclone

# Создайте конфигурацию удаленного S3-хранилища интерактивно
rclone config

# Проверяем доступ к удаленному bucket
rclone lsd remote:

# Синхронизируем backup ERPNext с внешним хранилищем
rclone copy /home/frappe/frappe-bench/sites/erp.example.com/private/backups \
  remote:erpnext-backups/erp.example.com \
  --transfers 2 \
  --checkers 4 \
  --log-file /var/log/rclone-erpnext.log

Access to S3 should use a separate key with minimal permissions. Do not place secrets in the command line, a public git repository, or a file accessible to all users. To protect against deletion, configure versioning and object lock if the selected storage supports them.

Simple Backup Script

Create the script as root, but run Bench itself as the frappe user. In the example, archives are stored locally for seven days and then sent to S3-compatible storage.

# Создаем каталог для административных скриптов
sudo install -d -m 750 /usr/local/sbin

# Создаем скрипт backup
sudo tee /usr/local/sbin/backup-erpnext.sh > /dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

BENCH_DIR="/home/frappe/frappe-bench"
SITE="erp.example.com"
BACKUP_DIR="${BENCH_DIR}/sites/${SITE}/private/backups"

sudo -u frappe bash -lc "cd '${BENCH_DIR}' && bench --site '${SITE}' backup --with-files --compress"

rclone copy "${BACKUP_DIR}" "remote:erpnext-backups/${SITE}" \
  --transfers 2 \
  --checkers 4 \
  --log-file /var/log/rclone-erpnext.log

find "${BACKUP_DIR}" -type f -mtime +7 -delete
EOF

# Закрываем скрипт от обычных пользователей и делаем его исполняемым
sudo chmod 750 /usr/local/sbin/backup-erpnext.sh

# Запускаем проверку вручную
sudo /usr/local/sbin/backup-erpnext.sh

In an actual configuration, replace remote with the name of the configured rclone remote. After running it manually, verify that a new object has appeared in the bucket and that the process exited with code 0. For sensitive data, enable server-side encryption in S3 or use an rclone crypt remote.

Running via Cron

# Открываем системное расписание root
sudo crontab -e

# Запускаем backup каждый день в 02:30 и сохраняем журнал
30 2   * /usr/local/sbin/backup-erpnext.sh >> /var/log/backup-erpnext.log 2>&1

A backup is considered valid only after restoration. Once a month, deploy a copy on a separate temporary server, restore the database and files, and check logging in to ERPNext and the availability of attachments. Record the actual recovery time, RTO, and the acceptable data loss, RPO.

Updates

Updating ERPNext involves changing the application code, running database migrations, rebuilding assets, and restarting processes. Before updating, read the release notes and the requirements for the Frappe version. Do not automatically update production immediately after a new commit appears without testing it in staging.

# Создаем backup перед любым обновлением
cd /home/frappe/frappe-bench
bench --site erp.example.com backup --with-files --compress

# Проверяем текущее состояние и версии
bench version
git status --short

# Обновляем приложения и выполняем миграции
bench update --reset
bench --site erp.example.com migrate
bench build

# Перезапускаем production-процессы
sudo supervisorctl restart all
sudo systemctl reload nginx

# Проверяем сайт после обновления
curl --fail --silent --show-error https://erp.example.com/api/method/frappe.ping

For a small system, use a maintenance window when users are not working in ERPNext. A rolling update is possible only with multiple nodes and a compatible database schema; on a single server, it offers practically no advantages. Reverting the code without reverting database migrations can lead to incompatibility, so the rollback plan must include restoring the database from a backup.

Regular Maintenance

  • Check free space, database growth, and the size of file directories weekly.
  • Monitor the last successful backup and the state of the queues daily.
  • Test restoration on a separate server monthly.
  • Before updating Ubuntu, check the compatibility of Python, MariaDB, Node.js, and Frappe.
  • Delete unused sites and old archives only after checking the retention policy.
  • Monitor TLS certificate expiration dates and DNS availability.

9. Troubleshooting + FAQ

Why does a 502 Bad Gateway error appear?

Error 502 means that Nginx did not receive a valid response from the web process. First check sudo supervisorctl status, then the logs logs/web.error.log and /var/log/nginx/error.log. If processes are stopped, check the reason in Supervisor. Common causes include insufficient memory, an incorrect path to the virtual environment, a corrupted assets build, or a migration error. After fixing the issue, restart the specific process rather than the entire server.

Why is ERPNext slow after installation?

Check CPU, RAM, swap, disk latency, and queue lengths: htop, free -h, iostat -xz 1, and bench doctor. If memory is exhausted, reduce the number of processes or increase RAM. If a specific report opens slowly, the cause may be an SQL query or a large history volume rather than Nginx. Run imports and PDF generation as background tasks, and do not start many heavy operations simultaneously.

What is the minimum suitable VPS configuration?

For testing, 2 vCPU and 4 GB of RAM are sufficient, but this configuration should not be considered a comfortable production environment. The minimum practical option for a small company is 4 vCPU, 8 GB of RAM, an SSD of at least 80 GB, a public IPv4 address, and a stable connection. If 20 or more users work simultaneously and reports, imports, and attachments are used, start with 8 vCPU, 16 GB of RAM, and NVMe storage of at least 160 GB. Leave memory headroom for MariaDB and background workers.

What should I choose for this task: VPS or dedicated?

A VPS is suitable for most small and medium ERPNext installations if it has predictable CPU performance, a fast SSD, and sufficient RAM. A dedicated server makes sense with sustained high load, large databases, heavy reports, physical isolation requirements, or the need for a large amount of memory. Make the decision based on measured metrics: average and peak CPU load, disk latency, RAM usage, database size, and the number of background tasks. The number of users alone does not provide an accurate answer.

Why is the Let’s Encrypt certificate not being issued?

Check that the domain A record points to the correct IPv4 address, the AAAA record does not point to an unavailable IPv6 address, and port 80 is allowed in the external firewall and UFW. Issuance may also be blocked by another process already using port 80 or an incorrect server_name in Nginx. Run dig +short erp.example.com and curl -I http://erp.example.com from an external computer. After fixing the issue, retry certificate issuance and check the renewal timer.

The user is not receiving emails from ERPNext. What should be checked?

Check the SMTP host, port, TLS mode, login, and password in the Email Account settings. Do not use the regular mailbox password if the provider requires an application password or OAuth. Check the queue and background worker logs: email delivery is performed asynchronously. Also check the domain's SPF, DKIM, and DMARC records; otherwise, emails may be sent from ERPNext but rejected or placed in spam on the recipient's side.

After an update, the interface does not load or styles are missing

Run bench build, then clear the site cache with bench --site erp.example.com clear-cache and restart Supervisor. Check that Nginx serves the current assets directory and that file permissions belong to the frappe user. If the browser continues using old resources, open the page in a private window and check the HTTP status codes of JavaScript and CSS requests through developer tools. In case of a migration error, save the logs first rather than repeatedly retrying the update.

How can I determine whether a backup is actually usable?

The presence of a file in the backup directory does not prove that restoration is possible. Take the archive, transfer it to a separate server with a compatible ERPNext version, restore the database and public/private files, then check login, documents, attachments, and background tasks. Record the restoration time and errors. For a critical system, test not only the daily backup but also an older weekly or monthly restore point, because a logical error may have been included in all recent copies.

10. Conclusions and next steps

Diagram: 10. Conclusions and next steps
Diagram: 10. Conclusions and next steps

As a result, a single-node production configuration of ERPNext 15 has been deployed on Ubuntu 24.04 LTS with MariaDB, Redis, Supervisor, Nginx, and HTTPS. The server is protected with basic SSH and firewall settings, the site is checked through an HTTP healthcheck, and the backup includes the ERPNext database and files.

Next, measure the actual load during the first week: CPU, RAM, disk latency, database size, queue lengths, and response times for key operations. Then configure a staging environment for updates, test backup restoration, and as the load grows, separate background workers, the database, and file storage into separate nodes.

  1. Collect usage metrics and set alert thresholds for disk, memory, queues, and HTTPS availability.
  2. Perform a restoration test on a clean server and document the procedure for emergency startup.
  3. As the number of users grows, optimize heavy reports, add resources, and only then move to a multi-server architecture.

Чи був цей гайд корисним?

Ваш відгук допомагає нам покращувати гайди.

Share this post:

Надішліть гайд тому, кому він може стати в пригоді.

Telegram VKVK WhatsApp Facebook LinkedIn XX

ERPNext on a dedicated server: installation and load requirements
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.