SSD Nodes Learn 🎉 VPS mulai $5.50/bln
Panduan Matt ConnorOleh Matt Connor

Cara Self-Hosting ERPNext di VPS dengan Docker

Panduan menjalankan ERPNext di VPS dengan Docker, mencakup 11 container, ukuran server, TLS, email keluar, penguncian versi, dan uji pemulihan backup.

Hal yang Anda setujui untuk dijalankan

Menjalankan ERPNext secara self-hosting pada VPS adalah pekerjaan operasional, bukan instalasi dengan satu perintah. Stack Docker Compose resmi terdiri atas sebelas container dan menyimpan buku besar umum serta data pelanggan Anda. Karena itu, standar untuk semua hal di bawah ini harus tinggi: backup belum dapat disebut backup sebelum berhasil dipulihkan, dan tag image yang tidak dikunci versinya dapat memicu migrasi skema yang tidak direncanakan.

Beberapa nama akan muncul di seluruh panduan ini. ERPNext adalah aplikasi bisnisnya. Frappe adalah framework Python yang mendasarinya. Bench adalah alat command line untuk mengelola site, yang sudah terpasang di dalam container. Site adalah satu tenant: satu database MariaDB dan satu direktori file yang diunggah. Hampir semua perintah di sini dijalankan bench di dalam container backend untuk satu site yang namanya ditentukan.

Panduan ini menggunakan repository frappe_docker, yaitu deployment yang dikelola oleh proyek tersebut. Setiap perintah di bawah ini telah diperiksa terhadap repository itu pada Agustus 2026. Jika Docker Compose masih baru bagi Anda, menjalankan Docker Compose pada VPS membahas dasar-dasar yang diasumsikan oleh panduan ini.

Berapa kapasitas VPS yang dibutuhkan ERPNext?

ChartCommon published ERPNext sizing tiers (guidance, not a measurement)
The data behind this chart
[
  {
    "label": "Evaluation",
    "vcpu": 2,
    "ram_gb": 4,
    "disk_gb": 40
  },
  {
    "label": "Small production",
    "vcpu": 4,
    "ram_gb": 8,
    "disk_gb": 100
  },
  {
    "label": "Room to grow",
    "vcpu": 4,
    "ram_gb": 16,
    "disk_gb": 160
  }
]

Panduan resmi memulai dari 2 vCPU dan 4 GB RAM sebelum satu pengguna pun login. Itu adalah tingkat evaluasi. Angka tersebut merupakan titik awal, bukan hasil pengukuran dari panduan ini, dan volume dokumen Anda sendiri yang menentukan kebutuhan sebenarnya. Baris terakhir sama sekali bukan batas minimum resmi. Angka itu kira-kira menunjukkan titik ketika memori bukan lagi hal yang perlu Anda pikirkan.

Bersikaplah realistis terhadap paket kecil. VPS dengan RAM 1 GB atau 2 GB akan berhasil menjalankan stack, lalu gagal saat impor pertama atau laporan panjang pertama. Sembilan container yang berjalan lama, buffer pool MariaDB, dan worker Python yang membuat laporan tidak dapat ditampung dalam memori sebesar itu. Kegagalannya tidak berlangsung secara terkendali. Kernel out-of-memory killer menghentikan sebuah container, lalu docker inspect pada container tersebut menampilkan "OOMKilled": true dengan exit code 137. Worker yang dihentikan di tengah pekerjaan dapat meninggalkan dokumen yang sudah dikirim dengan pekerjaan latarnya yang belum selesai.

Untuk perusahaan yang menggunakan ERPNext setiap hari, 8 GB RAM, 4 vCPU, dan 100 GB SSD adalah batas minimum yang realistis. RAM akan habis terlebih dahulu. Penggunaan disk bertambah lebih cepat dari perkiraan karena setiap lampiran dan setiap backup lokal disimpan pada volume yang sama dengan database.

Sebelas container dan fungsi masing-masing

Jalankan docker compose ps setelah stack aktif dan sembilan container berjalan. Dua container lainnya, configurator dan create-site, menjalankan tugasnya satu kali lalu berhenti. Inilah asal jumlah total sebelas container.

  • backend menjalankan aplikasi Frappe dengan gunicorn. bench berada di sini.
  • frontend adalah nginx. Container ini menyajikan aset statis dan meneruskan permintaan lainnya ke backend.
  • queue-short dan queue-long adalah worker RQ (Redis Queue). Keduanya menjalankan tugas latar belakang, seperti email keluar, impor, dan pembuatan laporan.
  • scheduler menjalankan tugas berbasis waktu, termasuk laporan terjadwal dan dokumen yang diulang secara otomatis.
  • websocket adalah proses socket.io yang menangani pembaruan langsung di browser.
  • db adalah MariaDB.
  • redis-cache dan redis-queue adalah dua instance Redis terpisah. Salah satunya digunakan untuk cache, dan yang lainnya untuk antrean tugas.

Pemisahan ini penting untuk dipahami karena menunjukkan log yang harus dibaca. Email yang macet merupakan masalah pada worker antrean, jadi docker compose logs -f queue-short adalah perintah yang tepat. Halaman yang terbuka tetapi lencana notifikasinya tidak pernah diperbarui merupakan masalah websocket. Membaca log backend untuk salah satu masalah tersebut hanya membuang waktu.

Instal dengan file compose produksi, bukan file demo

Repositori ini menyediakan pwd.yml, dan README menjelaskannya dengan tegas: "Penyiapan ini hanya ditujukan untuk evaluasi jangka pendek. Anda tidak akan dapat menginstal aplikasi kustom pada penyiapan ini." Gunakan penyiapan tersebut untuk mencoba ERPNext selama satu sore. Jangan gunakan untuk menjalankan operasional perusahaan.

sudo apt update && sudo apt install -y git
curl -fsSL https://get.docker.com | bash
git clone https://github.com/frappe/frappe_docker
cd frappe_docker
mkdir -p ~/gitops
cp example.env ~/gitops/erpnext.env

Buka ~/gitops/erpnext.env dan ubah empat nilai. ERPNEXT_VERSION menetapkan tag image. DB_PASSWORD disediakan sebagai 123 dalam file contoh. SITES_RULE adalah aturan routing Traefik, dan LETSENCRYPT_EMAIL menerima peringatan sertifikat.

ERPNEXT_VERSION=v16.32.1
DB_PASSWORD=<a long random password>
SITES_RULE=Host(`erp.example.com`)
LETSENCRYPT_EMAIL=ops@example.com

Sekarang render satu file compose, lalu jalankan file tersebut.

docker compose --project-name erpnext \
  --env-file ~/gitops/erpnext.env \
  -f compose.yaml \
  -f overrides/compose.mariadb.yaml \
  -f overrides/compose.redis.yaml \
  -f overrides/compose.https.yaml \
  config > ~/gitops/erpnext.yaml

docker compose --project-name erpnext -f ~/gitops/erpnext.yaml up -d

config tidak menjalankan apa pun. Perintah ini menggabungkan file dasar dengan override, lalu mencetak hasilnya setelah semua variabel disubstitusi. Selanjutnya, jalankan file hasil render tersebut. Langkah tambahan ini bermanfaat: stack yang berjalan berada dalam satu file yang dapat Anda baca dan commit, sehingga isinya tidak dapat berubah tanpa Anda sadari ketika seseorang mengedit file env atau ketika Anda melakukan pull terhadap repositori. cara beberapa file Docker Compose digabungkan menjelaskan aturan override secara terperinci.

Tunggu db hingga berjalan dan configurator hingga selesai, yang memerlukan waktu beberapa detik, lalu buat site tersebut.

docker compose --project-name erpnext exec backend \
  bench new-site --mariadb-user-host-login-scope=% \
  --db-root-password '<your DB_PASSWORD>' \
  --install-app erpnext \
  --admin-password '<a strong admin password>' \
  erp.example.com

Periksa hasilnya:

docker compose --project-name erpnext ps
docker compose --project-name erpnext exec backend bench --site erp.example.com list-apps

list-apps harus menampilkan frappe dan erpnext beserta versinya. ps yang sehat menampilkan sembilan service dalam status running dan tidak ada service dalam status restarting.

Dua masalah sering terjadi di sini. --mariadb-user-host-login-scope=% tidak bersifat opsional jika menggunakan Docker. Container aplikasi mengakses MariaDB melalui jaringan Docker, sehingga dianggap sebagai host jarak jauh. Akibatnya, user database yang cakupannya dibatasi pada localhost tidak dapat login dari sana. Pembuatan site kemudian gagal dengan error akses MariaDB ditolak yang menyebut user root. Cakupan % memberikan akses kepada user site baru dari host mana pun pada jaringan privat tersebut.

Masalah kedua adalah nama site. Secara default, frontend memilih site yang akan dilayani berdasarkan header HTTP Host. Karena itu, site yang dibuat sebagai erpnext tidak dapat diakses di erp.example.com, meskipun keduanya ada. Gunakan nama domain sebagai nama site, seperti di atas, atau tetapkan FRAPPE_SITE_NAME_HEADER dalam file env ke nama site, lalu render kembali file compose.

HTTPS dan kondisi yang harus terpenuhi sebelum dapat digunakan

Override compose.https.yaml menjalankan Traefik pada port 443, mengalihkan port 80 ke port tersebut, dan meminta sertifikat dari Let's Encrypt. TLS (transport layer security) menjaga invoice dan cookie sesi agar tidak dikirim dalam bentuk teks biasa melalui jaringan.

Dua kondisi harus terpenuhi. Jika tidak, sertifikat tidak akan pernah diterbitkan. DNS A record untuk erp.example.com harus sudah mengarah ke VPS. Port 80 dan 443 harus dapat dijangkau dari Internet karena Let's Encrypt membuktikan bahwa Anda mengendalikan nama tersebut melalui challenge HTTP-01 pada port 80. Periksa firewall jaringan milik provider dan firewall pada server. Keduanya merupakan kontrol yang terpisah, dan firewall pada panel sering terlupakan.

Sertifikat disimpan dalam volume cert-data di /letsencrypt/acme.json. Jika browser menampilkan sertifikat default, bukan sertifikat Anda, cari nama service proxy di docker compose --project-name erpnext ps dan baca log-nya untuk menemukan error ACME (automatic certificate management environment). Menjalankan aplikasi web lain pada server yang sama? satu instance Traefik di depan beberapa aplikasi Docker Compose menjelaskan cara menggunakan proxy yang sama tanpa berebut port 443.

Email keluar, atau faktur tidak pernah meninggalkan server

Ini adalah langkah yang sering dilewati oleh panduan ERPNext, padahal langkah ini menentukan apakah sistem benar-benar berguna. Tanpa email keluar yang berfungsi, tidak ada faktur yang sampai ke pelanggan, tidak ada email pengaturan ulang kata sandi yang diterima, dan tidak ada laporan terjadwal yang dikirimkan. Stack ini tidak menyertakan server email.

Jangan mencoba mengirim email langsung dari VPS melalui port 25. Sebagian besar provider memblokir port keluar 25 pada akun baru. Email yang berhasil keluar pun dapat ditolak atau masuk ke folder spam karena alamat VPS baru belum memiliki reputasi pengiriman. Gunakan relay terautentikasi pada port 587.

Metode yang didukung adalah layar Email Account pada antarmuka ERPNext. Layar ini menyimpan kata sandi dalam bentuk terenkripsi. Anda juga dapat menuliskan key ke konfigurasi site:

docker compose --project-name erpnext exec backend \
  bench --site erp.example.com set-config mail_server smtp.example.com

docker compose --project-name erpnext exec backend \
  bench --site erp.example.com set-config mail_port 587 --parse

docker compose --project-name erpnext exec backend \
  bench --site erp.example.com set-config use_tls 1 --parse

docker compose --project-name erpnext exec backend \
  bench --site erp.example.com set-config mail_login 'erp@example.com'

docker compose --project-name erpnext exec backend \
  bench --site erp.example.com set-config auto_email_id 'erp@example.com'

--parse menyimpan 587 sebagai angka, bukan string "587". Baca kembali file tersebut dan pastikan kedua nilai itu tidak diapit tanda kutip:

docker compose --project-name erpnext exec backend \
  cat sites/erp.example.com/site_config.json

Atur mail_password melalui layar Email Account, bukan melalui command line, agar nilainya disimpan dalam bentuk terenkripsi dan tidak pernah masuk ke shell history.

Kemudian kirim pesan sungguhan. Buat Sales Invoice, kirimkan melalui email ke alamat yang Anda kontrol, lalu monitor queue saat proses berlangsung:

docker compose --project-name erpnext logs -f queue-short

Email keluar diproses sebagai background job. Karena itu, pesan yang tidak pernah sampai biasanya muncul sebagai job yang gagal di log tersebut, bukan sebagai error di browser. Publikasikan juga record SPF (sender policy framework) dan DKIM (domainkeys identified mail) untuk domain pengirim, lalu tambahkan kebijakan DMARC. Tanpa record tersebut, faktur yang secara teknis benar tetap dapat masuk ke folder spam pelanggan. Jika Anda ingin mengelola seluruh jalur pengiriman sendiri, server email Mailcow yang di-host sendiri menyediakan relay yang Anda kontrol pada server terpisah dari ERP.

Cadangan yang benar-benar dapat dipulihkan

Dump database saja bukan cadangan ERPNext. Lampiran dan file privat berada di direktori sites, bukan di MariaDB. Jika hanya database yang dipulihkan, setiap purchase order yang diunggah akan kembali sebagai tautan yang rusak.

docker compose --project-name erpnext exec backend \
  bench --site erp.example.com backup --with-files

Perintah tersebut menulis empat file ke dalam sites/erp.example.com/private/backups pada volume sites:

  • dump -database.sql.gz
  • arsip file publik -files.tar
  • arsip file privat -private-files.tar
  • salinan konfigurasi site -site_config_backup.json

File keempat sering dibuang, padahal file inilah yang paling bermasalah jika hilang. File tersebut berisi encryption_key, yaitu kunci yang digunakan Frappe untuk mengenkripsi password yang tersimpan: kredensial akun email, kunci payment gateway, dan semua secret integrasi. Jika database dipulihkan tanpa kunci yang sesuai, site tetap dimuat secara normal, tetapi pengiriman email gagal dengan:

frappe.exceptions.ValidationError: Encryption key is invalid! Please check site_config.json

Simpan keempat file tersebut secara bersamaan.

Selanjutnya, salin file-file tersebut keluar dari server. Cadangan di dalam volume tidak akan bertahan jika server rusak, dan bench juga akan menghapusnya: secara default, bench menghapus cadangan yang lebih lama dari 24 jam dari direktori tersebut.

docker compose --project-name erpnext cp \
  backend:/home/frappe/frappe-bench/sites/erp.example.com/private/backups \
  ~/erpnext-backups

Jalankan perintah tersebut melalui cron, lalu kirim direktori itu ke lokasi yang tidak Anda administrasikan. cadangan restic terenkripsi ke penyimpanan di luar lokasi adalah alat yang tepat karena restic mengenkripsi data sebelum diunggah, dan restic check membuktikan bahwa repository masih dapat dibaca. Cadangan ERP merupakan salinan seluruh ledger Anda, sehingga cadangan tersebut harus dienkripsi saat disimpan pada perangkat keras yang bukan server ini.

Uji pemulihan sebelum Anda membutuhkannya

Cadangan yang belum diuji hanya merupakan perkiraan. Uji cadangan tersebut pada situs kedua di server yang sama, jangan pernah pada situs produksi.

docker compose --project-name erpnext exec backend \
  bench new-site --mariadb-user-host-login-scope=% \
  --db-root-password '<your DB_PASSWORD>' \
  --admin-password '<a strong admin password>' \
  restore-test.example.com

docker compose --project-name erpnext exec backend \
  bench --site restore-test.example.com --force restore \
  sites/erp.example.com/private/backups/<stamp>-erp.example.com-database.sql.gz \
  --with-public-files sites/erp.example.com/private/backups/<stamp>-erp.example.com-files.tar \
  --with-private-files sites/erp.example.com/private/backups/<stamp>-erp.example.com-private-files.tar \
  --db-root-password '<your DB_PASSWORD>'

Salin kunci enkripsi dari konfigurasi yang dicadangkan ke situs hasil pemulihan. Jika tidak, integrasinya tetap tidak berfungsi:

docker compose --project-name erpnext exec backend \
  bench --site restore-test.example.com set-config encryption_key '<value from site_config_backup.json>'

Sekarang periksa pemulihan seperti yang dilakukan akuntan. Buka laporan Accounts Receivable dan bandingkan saldo akhir dengan situs produksi. Buka faktur pembelian terbaru dan unduh lampirannya. Situs yang hanya dapat menampilkan halaman login belum membuktikan apa pun.

Hapus situs pengujian setelah selesai:

docker compose --project-name erpnext exec backend \
  bench drop-site restore-test.example.com

Mengapa version pinning lebih penting untuk ERPNext

Pada situs statis, image tag yang tidak dipatok berarti restart yang tidak terduga. Pada ERPNext, ini berarti migrasi skema. bench migrate menulis ulang tabel database dan dapat menulis ulang data dokumen, serta tidak menyediakan pembatalan. Rollback dilakukan dengan memulihkan dari backup, bukan dengan docker compose down.

Karena itu, patok tag tersebut. ERPNEXT_VERSION=v16.32.1 adalah rilis yang dipatok dalam pwd.yml milik repository pada Agustus 2026. Jangan menggunakan angka tersebut terus-menerus tanpa memeriksanya. Rilis saat ini tercantum pada halaman rilis frappe/erpnext, sedangkan image tag yang tersedia tercantum di Docker Hub. Baca catatan untuk versi yang akan Anda gunakan sebelum melakukan pemindahan.

Proses upgrade dimulai dengan backup dan maintenance mode.

docker compose --project-name erpnext exec backend \
  bench --site erp.example.com backup --with-files

docker compose --project-name erpnext exec backend \
  bench --site erp.example.com set-maintenance-mode on

Edit ERPNEXT_VERSION di ~/gitops/erpnext.env, lalu render, pull, dan migrate.

docker compose --project-name erpnext \
  --env-file ~/gitops/erpnext.env \
  -f compose.yaml \
  -f overrides/compose.mariadb.yaml \
  -f overrides/compose.redis.yaml \
  -f overrides/compose.https.yaml \
  config > ~/gitops/erpnext.yaml

docker compose --project-name erpnext -f ~/gitops/erpnext.yaml pull
docker compose --project-name erpnext -f ~/gitops/erpnext.yaml up -d

docker compose --project-name erpnext exec backend \
  bench --site erp.example.com migrate

docker compose --project-name erpnext exec backend \
  bench --site erp.example.com set-maintenance-mode off

Maintenance mode penting karena migrate mengubah skema saat berjalan. Jika pengguna mengirimkan dokumen ke tabel yang baru dimigrasikan sebagian, Anda dapat terpaksa memperbaiki record secara manual.

Pindahkan satu major version setiap kali, dengan backup di antara setiap langkah. Kode migrasi dalam suatu rilis ditulis untuk melakukan upgrade dari rilis sebelumnya. Karena itu, melewati major version akan menjalankan migrasi dalam kombinasi yang belum diuji siapa pun.

Repository tersebut juga menyediakan overrides/compose.migrator.yaml, yang menambahkan container untuk menjalankan bench --site all migrate setiap kali start. Ini praktis. Namun, docker compose up dengan tag yang berubah juga berarti database production Anda dimigrasikan tanpa ada yang memantaunya. Pada sistem bisnis, jalankan migrate sebagai keputusan yang Anda buat pada pagi itu.

Memperkuat keamanan server yang menyimpan data pelanggan

Ubah kata sandi Administrator saat login pertama. File Compose evaluasi menggunakan admin sebagai kata sandi tersebut, dan kebiasaan ini dapat terbawa ke lingkungan produksi.

Ubah DB_PASSWORD dari nilai 123 di example.env. Nilai tersebut akan muncul dalam ~/gitops/erpnext.yaml yang dirender dalam teks biasa, jadi chmod 600 file tersebut dan jangan menyimpannya di repositori git mana pun. Untuk keamanan yang lebih baik, overrides/compose.mariadb-secrets.yaml membaca kata sandi dari file Docker secret, bukan dari variabel lingkungan. menangani file env dan secret di Docker Compose membahas berbagai pertimbangannya.

Publikasikan hanya yang diperlukan. Dengan override HTTPS, hanya port 80 dan 443 yang diekspos. Jangan menambahkan pemetaan ports ke service db agar klien database lebih mudah terhubung: tindakan tersebut mengekspos MariaDB ke Internet publik. Gunakan docker compose --project-name erpnext exec backend bench mariadb sebagai gantinya. Di host, izinkan 22, 80, dan 443, tolak port lainnya, lalu periksa juga firewall jaringan terpisah milik provider.

Aktifkan autentikasi dua faktor di System Settings untuk setiap akun yang memiliki peran System Manager. Peran tersebut dapat membaca setiap dokumen dan mengekspor setiap tabel, jadi perlakukan sebagai akun administrator, bukan sekadar akun untuk kemudahan. Jika Anda menjalankan beberapa aplikasi self-hosted, Authentik sebagai penyedia single sign-on self-hosted lebih baik daripada menambahkan satu kata sandi lagi untuk setiap aplikasi.

Lakukan patch pada host dan reboot untuk pembaruan kernel. Sebelum mengandalkan stack untuk berjalan kembali, periksa file yang dirender guna memastikan adanya kebijakan restart pada setiap service, karena stack tanpa kebijakan tersebut akan tetap berhenti setelah reboot. membuat stack Docker Compose berjalan kembali setelah reboot membahas konfigurasi systemd.

Ketika ERPNext mulai tidak nyaman dijalankan pada satu VPS

Satu VPS dapat menjalankan kebutuhan perusahaan kecil dalam waktu lama. Berikut tanda-tanda bahwa kapasitasnya mulai tidak memadai:

  • Pekerjaan latar belakang menumpuk, sehingga email dan proses impor tiba beberapa menit atau beberapa jam terlambat.
  • docker inspect melaporkan container dengan "OOMKilled": true atau exit code 137.
  • Laporan yang sebelumnya selesai dalam dua detik kini memerlukan tiga puluh detik, dan MariaDB menjadi proses yang menggunakan CPU.
  • Pencadangan berlangsung sangat lama sehingga satu proses bertumpang tindih dengan jadwal berikutnya.

Mulailah dengan menyediakan resource khusus untuk MariaDB, karena database dan worker Python menggunakan memori yang sama, sementara buffer pool membutuhkan lebih banyak memori. Meningkatkan kapasitas application server biasanya memberikan hasil yang lebih kecil dari perkiraan. menjalankan database di Docker atau pada host membahas keputusan tersebut, sedangkan menetapkan batas memori di Docker Compose mencegah satu container menghabiskan resource container lain selama Anda melakukan perubahan.

Setelah itu, tambahkan queue worker, bukan kapasitas web. Pekerjaan ERPNext yang lambat berjalan di latar belakang, seperti pembuatan laporan dan proses impor massal. Menambah container worker biayanya lebih rendah daripada menggunakan server yang lebih besar, dan langkah ini mengatasi masalah yang benar-benar dikeluhkan pengguna.

FAQ

Berapa banyak RAM yang dibutuhkan ERPNext pada VPS?

Panduan yang diterbitkan menetapkan minimal 4 GB dengan 2 vCPU, dan tingkat tersebut hanya untuk evaluasi. Untuk perusahaan yang menggunakannya setiap hari, siapkan 8 GB dan 4 vCPU dengan SSD sebesar 100 GB. Jika kurang dari itu, out-of-memory killer pada kernel akan menghentikan container saat beban meningkat. docker inspect melaporkannya sebagai "OOMKilled": true dengan exit code 137. Angka ini adalah titik awal, bukan hasil pengukuran. Karena itu, pantau penggunaan memori Anda sendiri selama bulan pertama.

Apakah saya dapat menjalankan pwd.yml di production?

Tidak. README proyek menjelaskan bahwa file tersebut hanya ditujukan untuk evaluasi jangka pendek dan menyatakan bahwa Anda tidak dapat menginstal custom app ke dalamnya. Gunakan compose.yaml bersama override MariaDB, Redis, dan HTTPS. Render semuanya menjadi satu file dengan docker compose config, lalu jalankan file tersebut.

Mengapa site ERPNext saya tidak dapat diakses segera setelah dibuat?

Secara default, frontend menentukan site yang akan dilayani berdasarkan header HTTP Host. Karena itu, nama site harus sama dengan domain pada browser. Site yang dibuat sebagai erpnext tidak akan dilayani pada erp.example.com. Buat site menggunakan domain sebagai namanya, atau tetapkan FRAPPE_SITE_NAME_HEADER dalam file env ke nama site, render ulang file compose, lalu restart stack.

Apa saja yang harus ada dalam backup ERPNext?

Ada empat file yang harus disimpan bersama: dump -database.sql.gz, arsip -files.tar dan -private-files.tar, serta salinan konfigurasi -site_config_backup.json. Menjalankan bench --site erp.example.com backup --with-files akan menghasilkan keempatnya. Salinan konfigurasi tersebut berisi encryption_key. Tanpa file itu, password integrasi yang tersimpan tidak dapat didekripsi saat pemulihan, dan masalahnya muncul sebagai Encryption key is invalid! Please check site_config.json.

Bagaimana cara upgrade ERPNext tanpa merusak data?

Buat backup dengan --with-files, aktifkan maintenance mode, ubah ERPNEXT_VERSION dalam file env, render ulang file compose, lakukan pull, jalankan stack, kemudian jalankan bench --site erp.example.com migrate dan nonaktifkan maintenance mode. Pindah satu major version setiap kali dan baca release notes terlebih dahulu, karena migrate menulis ulang schema dan data dokumen tanpa opsi undo. Untuk rollback, pulihkan backup yang dibuat pada awal proses.