Deployment guide

Hosting ERPNext on a VPS: complete guide

Deploy on a VPS Cloud →

Tutorial

Hosting ERPNext on a VPS: complete guide

Self-hosting9 min read7 steps

ERPNext is a full open-source ERP: accounting, sales, purchasing, inventory, manufacturing and HR in a single application. Self-hosted on your VPS, it gives you an integrated management system with no per-user subscription and without your financial data leaving your infrastructure. This guide covers step-by-step deployment with the official Frappe Docker stack, post-installation setup, monitoring, troubleshooting common errors, and a comparison with Odoo Community to help you choose the right tool.

Contents· Why self-host ERPNext on a VPS1/10
  1. 01Why self-host ERPNext on a VPS
  2. 02The concrete benefits of a self-hosted ERPNext
  3. 03ERPNext's key modules
  4. 04Hardware and software requirements
  5. 05Deploy ERPNext with Frappe Docker and HTTPS
  6. 06Post-installation: company, fiscal year and users
  7. 07Monitoring and maintenance
  8. 08Troubleshooting: common errors
  9. 09ERPNext vs Odoo Community: when to choose one or the other
  10. 10The official documentation

Why self-host ERPNext on a VPS

An ERP centralises the company's most sensitive data: accounting entries, margins, customer and supplier records, payroll. SaaS offers often bill per user per month, which becomes costly as teams grow. On a dedicated VPS, you pay for the server once, you add as many users as needed, and the database stays under your control, backed up according to your own rules.

ERPNext is built on Frappe, a Python/JavaScript framework that keeps the source code readable and extensible. A self-hosted instance lets you update on your own schedule, choose add-on apps (HRMS, e-Commerce, Education, Healthcare) and write your own modules without relying on a vendor.

The concrete benefits of a self-hosted ERPNext

  • No per-user cost: add your teams without increasing the bill.
  • Sovereignty over accounting and HR data, which stays on your server.
  • All modules available (accounting, inventory, CRM, manufacturing, payroll) with no paid tier.
  • Free customisation through the Frappe framework and complementary apps.
  • Controlled backups and retention, tailored to your legal obligations.
  • Scalability: increase RAM/vCPU as the transaction volume grows.

ERPNext's key modules

ERPNext covers the full operational cycle of a business. Accounting: multi-currency chart of accounts, general ledger, statutory reports (balance sheet, profit & loss), VAT management and bank reconciliation. Sales and purchasing: quotes, orders, deliveries, invoices and credit notes with approval workflows. Inventory management: multiple warehouses, batches and serial numbers, rolling stock counts, FIFO or moving-average valuation. CRM: leads, opportunities, campaigns and sales pipeline with an activity dashboard. Manufacturing: bill of materials (BOM), work orders, workstation and scrap tracking. HR: employee records, leave, attendance, country-configurable payroll and performance appraisals.

Each module is activated from the ERPNext desk; you only install what you need, and access rights are defined by role at the document level.

Hardware and software requirements

ERPNext is more demanding than average. Plan for at least 2 vCPU and 4 GB of RAM for test use, and 4 vCPU / 8 GB of RAM for production with several concurrent users. Allow 20 GB of disk for the MariaDB database, Redis and uploaded files.

On the software side: Docker and Docker Compose v2 (>= 2.20), a domain name (e.g. erp.myapp.com) pointing to the VPS IP, and port 443 open inbound. ERPNext uses MariaDB 10.6+ as its primary database and Redis for caching and real-time workers — both are included in the frappe_docker stack; you do not need to install them separately.

Deploy ERPNext with Frappe Docker and HTTPS

  1. Prepare the VPS and Docker

    Over SSH, update the system (apt update && apt upgrade -y) and install Docker via curl -fsSL https://get.docker.com | sh. Add your user to the docker group: usermod -aG docker $USER. Verify with docker compose version (v2 required).

  2. Get frappe_docker

    Clone the official repository and pick the branch matching the target version:

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

    The overrides/ folder contains compose partials for Caddy (auto-HTTPS), Traefik and the HRMS app — assemble them according to your needs.

  3. Configure the environment

    Copy example.env to .env and adjust the key variables:

    cp example.env .env

    In .env, set FRAPPE_SITE_NAME_HEADER, DB_PASSWORD, REDIS_CACHE, and — if you use the Caddy override — LETSENCRYPT_EMAIL and the domain in Caddyfile. Never deploy with default passwords.

  4. Launch the stack

    Start all services:

    docker compose --project-name erpnext \
      -f compose.yaml \
      -f overrides/compose.mariadb.yaml \
      -f overrides/compose.redis.yaml \
      -f overrides/compose.https.yaml \
      up -d

    Then create the ERPNext site and install the app:

    docker compose exec backend bench new-site erp.myapp.com \
      --mariadb-root-password <rootpwd> \
      --admin-password <adminpwd>
    docker compose exec backend bench --site erp.myapp.com install-app erpnext
    docker compose exec backend bench --site erp.myapp.com migrate

    Follow the logs to confirm all services (db, redis, workers, scheduler) are healthy: docker compose logs -f.

  5. Configure the reverse proxy

    If you are not using the included Caddy override, place Nginx in front of ERPNext. Minimal example:

    server {
      listen 443 ssl;
      server_name erp.myapp.com;
      ssl_certificate     /etc/letsencrypt/live/erp.myapp.com/fullchain.pem;
      ssl_certificate_key /etc/letsencrypt/live/erp.myapp.com/privkey.pem;
      location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; }
    }

    With Caddy, a simple Caddyfile is enough: erp.myapp.com { reverse_proxy backend:8000 } — the Let's Encrypt certificate is obtained and renewed automatically.

  6. Secure and back up

    Restrict internal ports (MariaDB 3306, Redis 6379) to loopback or the internal Docker network. Schedule regular backups with bench backup and store them off the VPS:

    docker compose exec backend bench --site erp.myapp.com backup --with-files

    Backup files are placed in sites/erp.myapp.com/private/backups/ inside the sites volume — copy them to external object storage (S3, Garage) for disaster recovery.

  7. Logging in for the first time

    Open your application's address and sign in with the username Administrator and the admin password set during bench new-site. Allow a few minutes after installation before the address responds — the initial migrations run in the background. ERPNext then moves on to its setup wizard: language, time zone, currency, fiscal year and company.

Post-installation: company, fiscal year and users

Once logged in as Administrator, go to Settings → System Settings to confirm the time zone and date format, then to Accounting → Chart of Accounts to adapt the structure to local standards (ERPNext provides charts of accounts for around a hundred countries).

Create your company under Accounting → Company: enter the base currency, tax number and opening fiscal year. ERPNext automatically creates the closing accounts and opening balance entries.

For users, go to Settings → Users and Permissions → User: assign business roles (Accounts Manager, Stock User, HR Manager…) rather than document-by-document rights. Roles combine: a user can be both Sales User and Purchase User without admin rights.

Monitoring and maintenance

ERPNext provides several entry points for supervising a production instance.

bench doctor is the built-in diagnostic command: it checks the status of Celery workers, the scheduler and the Redis connection. Run it from the container:

docker compose exec backend bench doctor

A missing worker or blocked queue shows up immediately.

Application logs — ERPNext logs are in sites/<site>/logs/ inside the sites volume:
- web.log: HTTP errors and Python traces from the Gunicorn backend;
- worker.error.log: Celery worker exceptions (scheduled tasks, email sending);
- scheduler.log: scheduler cycles.

Automated backup — set up a cron job on the host to run bench backup daily and copy archives to remote storage:

0 3 * * * docker compose -p erpnext exec -T backend \
  bench --site erp.myapp.com backup --with-files \
  && rclone copy /path/to/backups remote:erpnext-backups

Updates — before each major version upgrade, do a full backup, read the release notes, test on a copy, then: bench update --reset inside the container. Schema migrations apply automatically, but some major ERPNext versions require upgrading to the highest minor version first (e.g. v14 → v14.x latest before moving to v15).

Troubleshooting: common errors

Worker crash: RedisBroadcastError or ConnectionRefusedError to Redis
Error in worker.error.log: redis.exceptions.ConnectionRefusedError: [Errno 111] Connection refused. Cause: the Redis container stopped or restarted after an OOM. Check: docker compose ps redis — if it is in Exited, restart with docker compose up -d redis then restart workers. If the crash recurs, increase the VPS RAM or limit the worker count in common_site_config.json.

Schema migration stuck: frappe.exceptions.SchemaChangedError
Error during bench migrate: SchemaChangedError: <DocType> has been manually modified. Cause: a column was manually changed in the database, ERPNext refuses to overwrite. Fix: bench --site erp.myapp.com migrate --skip-failing, then inspect the affected doctype in the UI and rerun migrate without the flag.

Bench timeout: Traceback ... requests.exceptions.ReadTimeout
Error during a long action (mass CSV import, inventory recalculation): ReadTimeout: HTTPConnectionPool. Increase the Gunicorn timeout in common_site_config.json: "gunicorn_workers": 2, "web_timeout": 120. Restart the web service: docker compose restart backend.

MariaDB connection refused: OperationalError: (2003, "Can't connect to MySQL server on 'db'")
Error at bench new-site or worker startup. Usual cause: the MariaDB container is not ready yet or the health check failed. Check: docker compose logs db | tail -20. If MariaDB shows [ERROR] InnoDB: Page 0 log sequence number, the database files are corrupted — restore from the last backup. If it is just a startup delay, wait 30 seconds and rerun the command.

Blank site after bench migrate: TemplateNotFound
ERPNext shows a blank page or Jinja error after an update. Cause: static assets were not rebuilt. Run: docker compose exec backend bench --site erp.myapp.com clear-cache && bench build --app erpnext. Restarting the frontend container (if separate) may also suffice.

ERPNext vs Odoo Community: when to choose one or the other

Scroll the table

CriterionERPNextOdoo Community
LicenceGPL v3 — code and modules freeLGPL v3 (core) — Enterprise modules proprietary
Included modulesAccounting, inventory, CRM, manufacturing, HR — all freeFunctional core; advanced modules reserved for paid Odoo Enterprise
Language / stackPython + Frappe, vanilla JS on the client sidePython + OWL (in-house JS framework)
InterfaceApp desk, configurable forms without codeKanban/list view, low-code studio (Enterprise)
Installation complexityWell-documented official Docker stackDocker available, but less community track record
CommunityActive on GitHub and Frappe forum; strong in India, AfricaVery large; dense partner ecosystem in Europe
Ideal forSMBs seeking a fully free ERP, manufacturing, multi-currencyCompanies wanting advanced CRM or Odoo e-commerce without custom development

ERPNext evolves through major versions with schema migrations: before each update, make a full bench backup and test the version upgrade on a copy before applying it in production. Migrations between major versions must follow the official upgrade path (e.g. v14 → v15 without skipping a version).

The official documentation

For advanced configuration and tool-specific options, refer to the official ERPNext documentation and the frappe_docker repository. This guide covers going live on a VPS; the vendor documentation remains the reference for fine-tuning, major version upgrades and specific use cases.

Deploy your instance on a ServOrbit Cloud VPS

A ServOrbit Cloud VPS with preconfigured Docker and scalable resources lets you install this tool without friction, and adjust RAM and vCPU as usage grows.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab