ERPNext is powerful – but in production, your biggest risk is rarely ERPNext itself.
The biggest risk is a Linux server with:
- weak SSH settings
- open ports
- no brute-force protection
- wrong file ownership
- missing TLS/HTTPS
- outdated packages
This guide is a practical hardening checklist for real ERPNext deployments.
Before You Start (Important)
You need:
- a server running Ubuntu/Debian
- ERPNext installed (or you’re about to install)
- SSH access to the server
Golden rule: Do not lock yourself out.
When changing SSH settings, keep one terminal session open while testing a second session.
1) Create a Normal Admin User (Stop Using Root)
Commands
adduser karani What it does (detailed)
- Creates a new Linux user called
karani - Creates a home directory:
/home/karani - Creates a primary group also called
karani - Prompts you to set a password (even if you later disable password login, it’s still fine)
Why it matters
roothas unlimited control of the entire machine.- If attackers guess or steal root access, you lose everything instantly.
- A normal user reduces risk and forces you to use
sudo(which is logged).
Give the user admin rights (sudo)
usermod -aG sudo karani Explanation
usermodmodifies an existing user-aG sudomeans: “append (-a) this user to the group list (-G), adding them to thesudogroup”- On Ubuntu/Debian, users in
sudogroup can run administrative commands.
Verify
groups karani You should see sudo listed.
2) Harden SSH (The #1 Real Attack Target)
SSH is the first thing bots attack on the internet.
Open SSH configuration
sudo nano /etc/ssh/sshd_config sudoruns as adminnanois the editor/etc/ssh/sshd_configis the main SSH server config file
Block direct root login
In the file, find or add:
PermitRootLogin no Meaning:
No one can log into the server directly as root, even if they know the password/key.
Why:
Bots always try “root” first.
Disable password login (keys only)
PasswordAuthentication no Meaning:
SSH will reject passwords and only accept SSH keys.
Why:
This kills brute-force attacks completely.
Restart SSH so changes apply
sudo systemctl restart ssh Explanation:
systemctlcontrols Linux servicesrestart sshreloads the SSH service with the new config
Test safely (before closing your current session)
Open a new terminal and try:
ssh karani@yourserverip If it works, you’re safe.
3) Set Up SSH Keys (So Passwords Are Useless)
On your laptop (client machine)
ssh-keygen What it does:
- Generates a key pair:
- private key (keep secret):
~/.ssh/id_ed25519(or id_rsa) - public key (shareable):
~/.ssh/id_ed25519.pub
- private key (keep secret):
- You can press Enter through prompts.
- Add a passphrase if you want extra security.
Copy your public key to the server
ssh-copy-id karani@yourserverip What it does:
- Logs into the server once
- Adds your public key into:
/home/karani/.ssh/authorized_keys
- After this, your laptop can login without typing the password.
Why this matters:
Even if someone knows your user password, they still can’t SSH in.
4) Firewall the Server with UFW (Only Allow What You Need)
UFW = Uncomplicated Firewall.
Allow SSH first (so you don’t lock yourself out)
sudo ufw allow OpenSSH Explanation:
- Adds a firewall rule allowing SSH traffic (port 22) using the preset
OpenSSH.
Allow web traffic (ERPNext needs this)
sudo ufw allow 80 sudo ufw allow 443 Explanation:
80= HTTP (used for initial web access + Let’s Encrypt validation)443= HTTPS (secure ERPNext traffic)
Enable the firewall
sudo ufw enable Meaning:
- Turns UFW on.
- Anything not explicitly allowed becomes blocked.
Check status
sudo ufw status verbose You should only see: OpenSSH, 80, 443.
Why this matters:
Open ports = open doors.
Most servers get breached because unnecessary ports are exposed.
5) Install Fail2Ban (Auto-ban Attackers)
Fail2Ban watches log files and bans IPs that behave like attackers.
Install
sudo apt install fail2ban -y Explanation:
apt installdownloads and installs the package-yautomatically confirms “yes”
Enable on boot
sudo systemctl enable fail2ban Meaning:
- Fail2Ban will start automatically after reboot.
Start now
sudo systemctl start fail2ban Meaning:
- Starts it immediately.
Check status
sudo systemctl status fail2ban If it says “active (running)”, it’s working.
Why this matters:
Bots try thousands of logins daily. Fail2Ban blocks them automatically.
6) Enable HTTPS with Certbot (Production Must Have SSL)
ERPNext handles logins, invoices, customer data. HTTPS is not optional.
Install Certbot and Nginx plugin
sudo apt install certbot python3-certbot-nginx -y Explanation:
certbotgets and renews SSL certificatespython3-certbot-nginxlets certbot automatically modify Nginx config
Issue SSL certificate and configure Nginx
sudo certbot --nginx What happens:
- It asks for your domain(s)
- It validates domain ownership
- It updates Nginx config to enable HTTPS
- It can redirect HTTP → HTTPS automatically
Test renewal
sudo certbot renew --dry-run Meaning:
- Simulates renewal to confirm auto-renew will work.
Why this matters:
Without HTTPS, passwords and sessions can be intercepted on networks.
7) Lock ERPNext Files & Folder Ownership (Prevent Silent Breakage)
ERPNext runs as a Linux user (often frappe).
If files are owned incorrectly, ERPNext fails with:
- permission denied
- broken uploads
- failed PDFs
- worker crashes
Go to bench
cd ~/frappe-bench Fix ownership (critical folders)
sudo chown -R frappe:frappe sites logs config Detailed explanation:
chownchanges ownership-Rmeans recursive (everything inside too)frappe:frappesets:- owner = frappe
- group = frappe
sitescontains site configs + assetslogsmust be writable by ERPNext workersconfigcontains common bench settings
Why this matters:
If logs becomes owned by root, ERPNext can’t write logs → workers fail.
Set safe permissions
sudo chmod -R 750 sites logs Explanation:
chmodchanges permissions750means:- owner: 7 (rwx)
- group: 5 (r-x)
- others: 0 (—)
- This blocks “everyone else” from accessing ERPNext internals.
8) Protect Your Database (MariaDB/Postgres)
Rule: Never expose DB ports publicly.
Check open ports
sudo ss -lntp If you see MariaDB on 0.0.0.0:3306 or Postgres on 0.0.0.0:5432, that’s risky.
Best practice:
- Bind DB to localhost only:
127.0.0.1 - Use strong passwords
- Remove remote root access
- Only allow ERPNext server to connect locally
Why this matters:
Databases are where invoices, customers, and money live.
9) Keep the Server Updated (Patch Security Holes)
sudo apt update && sudo apt upgrade -y Explanation:
apt updaterefreshes package listsapt upgradeinstalls available updates-yconfirms automatically
Why this matters:
Hackers often use known vulnerabilities in outdated packages.
10) Bonus Hardening Ideas (Next-Level)
If you want to go further:
- enable automatic security updates
- restrict SSH to a known IP (if you have static IP)
- separate ERPNext + DB server for larger deployments
- monitor logs and disk space
- daily automated backups
Final Words
Linux security is not complicated.
It is discipline.
And disciplined servers do not get hacked.
Contact & Links
Upeosoft (ERPNext & SaaS Consulting)
https://upeosoft.com
Code With Karani (Tutorials & Mentorship)
https://codewithkarani.com
Upeo Academy
https://upeo.academy
consult@upeosoft.com
+254725307131