
August 19, 2026
11 min read
By Kokil Thapa | Last reviewed: September 2026
A default Ubuntu VPS is online and reachable within minutes of provisioning. Bots scan it before you finish installing PHP. That is why Ubuntu server security best practices belong on day one, not after a breach. This guide covers the exact hardening stack I apply on production servers running Laravel, WordPress, and custom PHP — whether the box sits in Kathmandu or on AWS. If you need context for local hosting constraints, start with how to secure your website and server in Nepal and treat this page as the technical baseline underneath it.
What Are the Essential Ubuntu Server Security Best Practices for Production?
There is no single setting that makes a server safe. Defense in depth stacks independent controls so one failure does not expose everything. On legal-tech portals and eCommerce stores I maintain, the same five layers appear on every box.
Network filtering comes first. It drops junk traffic before Nginx or Apache sees it. Access control comes second. Compromised credentials bypass most app-level checks. Automated patching closes known CVEs while you ship features. Monitoring and backups let you detect and recover when something slips through.
Priority order matters. Patch a leaky SSH config all you want — an open MySQL port still exposes your database. For a deeper checklist aligned with industry standards, see the CIS benchmarks for server hardening and the companion Ubuntu security hardening guide on this site.
Most teams I work with treat this stack as standard operating procedure. If you want someone to apply and maintain it, Linux system administration in Nepal covers exactly that scope.
How Do You Harden SSH Access on Ubuntu 24.04?
SSH is the front door every bot on the internet tries first. Ubuntu 24.04 LTS ships with sensible defaults, but sensible is not hardened. Securing Ubuntu server SSH access is the highest-ROI step you can take in the first hour after provisioning.
Disable root login and password authentication
Root login gives attackers a known username with full privileges. Password auth enables brute-force attempts at scale. Edit /etc/ssh/sshd_config:
# /etc/ssh/sshd_config — production hardened
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers deploy admin
Protocol 2 Validate before restart. A syntax error locks you out:
sudo sshd -t
sudo systemctl restart sshd Configure key-based authentication correctly
Generate ED25519 keys on your laptop, not the server. ED25519 beats RSA on modern OpenSSH for both speed and key size:
ssh-keygen -t ed25519 -C "deploy@production-2026"
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@your-server-ip Set private key permissions to 600. Never paste keys into chat or email. For teams running multiple servers, centralise access through SSH certificates rather than scattering public keys. The dedicated walkthrough at SSH key auth, fail2ban, and port hardening covers edge cases I hit on real deployments.
Change the default SSH port (optional)
Moving SSH from port 22 to something like 2222 cuts scanner noise. It does not stop a targeted attacker. Update UFW if you do this. Document the port in your runbook. Never treat port obscurity as a substitute for keys and firewall rules.
How Should You Configure UFW Firewall Rules for Web Servers?
UFW wraps iptables with a readable interface. The rule is simple: deny everything inbound, then allow only what the app needs. A typical Laravel or WordPress server on Nginx needs three ports. Nothing else faces the internet.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw limit 22/tcp comment 'SSH rate limit'
sudo ufw enable
sudo ufw status verbose Official reference: the Ubuntu UFW community documentation. For port-specific guidance on Laravel stacks, read UFW firewall rules for web servers.
Never expose MySQL (3306) or Redis (6379) to the public internet. Bind databases to 127.0.0.1. Use an SSH tunnel for remote admin. Opening database ports is one of the fastest ways to lose customer data.
| Port | Service | Action | Why |
|---|---|---|---|
| 22/tcp | SSH | Allow + limit | Admin access; rate limit slows brute force |
| 80/tcp | HTTP | Allow | Let's Encrypt validation and HTTP redirects |
| 443/tcp | HTTPS | Allow | Encrypted traffic; mandatory in production |
| 3306/tcp | MySQL | Block external | Localhost only; tunnel for remote access |
| 6379/tcp | Redis | Block external | Localhost unless running a dedicated cluster |
| 8080/tcp | Dev server | Block in prod | Proxy through Nginx; never expose directly |
How Do You Set Up Fail2Ban to Block Brute-Force Attacks?
Key-only SSH stops most credential attacks. Fail2ban adds a safety net. It watches log files and bans IPs that show repeated failure patterns. I run it on every production box, including sister sites on shared EC2 infrastructure.
sudo apt update
sudo apt install fail2ban -y
sudo nano /etc/fail2ban/jail.local Add this to /etc/fail2ban/jail.local. Never edit jail.conf directly — package updates overwrite it:
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
banaction = ufw
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5 For Laravel apps, add a custom filter matching failed logins in storage/logs/laravel.log. Network-level bans reduce load on PHP-FPM during credential-stuffing waves. Enable and verify:
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo fail2ban-client status sshd At the edge, compare fail2ban vs Cloudflare for DDoS protection when traffic scales beyond a single VPS.
Why Is Automated Security Patching Critical for Ubuntu Servers?
Manual patching fails in practice. Client deadlines, feature work, and on-call fatigue push security updates to next week. Next week becomes next month. Unattended Upgrades installs security patches automatically, usually within hours of release.
sudo apt install unattended-upgrades apt-listchanges -y
sudo dpkg-reconfigure --priority=low unattended-upgrades Configure /etc/apt/apt.conf.d/50unattended-upgrades:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
};
Unattended-Upgrade::Package-Blacklist {
"php8.3-fpm";
"nginx";
};
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";
Unattended-Upgrade::Mail "admin@yourdomain.com"; Blacklist services that restart during business hours. Schedule reboots for off-peak windows — 4 AM Nepal Time works well for domestic eCommerce traffic. Test in staging first. More detail lives in the Ubuntu security updates guide.
What File Permissions Protect Laravel and WordPress Applications?
Wrong permissions are among the most common issues I find during server audits. Overly open directories let an attacker who gains limited access rewrite PHP files or read secrets. Tight ownership and mode bits contain the blast radius.
- Ownership: App files owned by a deploy user; web server group (
www-data), never root - Directories:
755— owner writes, others read and traverse - Files:
644— owner writes, others read only - Laravel writable dirs:
storage/andbootstrap/cache/at775 - Environment file:
.envat600— never world-readable - Upload dirs: No execute bit; validate MIME types in application code
sudo chown -R deploy:www-data /var/www/html/myapp
sudo find /var/www/html/myapp -type d -exec chmod 755 {} \;
sudo find /var/www/html/myapp -type f -exec chmod 644 {} \;
sudo chmod -R 775 /var/www/html/myapp/storage
sudo chmod -R 775 /var/www/html/myapp/bootstrap/cache
sudo chmod 600 /var/www/html/myapp/.env Enforce permissions through deployment scripts, not manual fixes after each release. Deployer 7 handles writable_dirs automatically. Pair this with the CI/CD pipeline setup guide for production servers and Laravel on Ubuntu VPS with Nginx for a full deploy workflow.
When coordinating with Laravel developers in Nepal, bake permission checks into the pipeline. Manual drift between releases is how production .env files end up readable by the web server group.
How Do You Secure an Ubuntu Server from Hackers After Initial Hardening?
The first-hour checklist stops automated scanners. Staying secure means closing gaps attackers probe after the basics. These steps turn a hardened box into a maintainable production system.
Enable TLS everywhere
HTTP sends credentials and session cookies in plain text. Issue free certificates with Certbot and force HTTPS redirects. Follow the Let's Encrypt and Certbot setup guide for the exact Nginx config blocks.
Automate off-site backups
Ransomware and operator error both destroy local snapshots. Push encrypted backups to S3 or another region nightly. The Ubuntu server backup strategies and rsync and cron backup guide cover tested patterns I use on client infrastructure.
Remove unused packages and services
Every installed daemon is a potential CVE. Audit with sudo ss -tulpn and disable anything not required. A web server does not need a mail transfer agent unless it sends mail directly.
Generate strong credentials with a proper tool
Database passwords, API keys, and admin tokens belong in a secrets manager or at minimum a 600-permissioned .env file. Use the password generator for initial entropy, then store values outside git.
Application security still matters. Server hardening does not fix SQL injection or XSS. Read server hardening for Ubuntu web servers and Ubuntu server setup for PHP apps for the full stack picture. Projects like Nepal Gift Card run on exactly this baseline — Laravel app layer on top, hardened OS underneath.
For ongoing monitoring and patch management after launch, support and maintenance services and domain registration and hosting cover the operational side so you can focus on product work.
Key Takeaways
- Disable root SSH and password auth; use ED25519 keys before opening the server to traffic.
- Run UFW with default deny inbound; allow only ports 22, 80, and 443 on web servers.
- Install fail2ban with SSH and web jails to block brute-force IPs automatically.
- Enable unattended security upgrades; blacklist services that restart during peak hours.
- Set Laravel and WordPress file permissions through deploy scripts, not manual chmod after each release.
- Add TLS, off-site backups, and quarterly audits to secure Ubuntu from hackers long term.
People Also Ask
How do I make Ubuntu more secure on a fresh VPS?
Create a sudo user, deploy SSH keys, disable password and root login, enable UFW, install fail2ban, and turn on unattended security upgrades. Do all six before installing your web stack. The full sequence takes under an hour on Ubuntu 24.04 LTS.
What is the difference between securing Ubuntu and securing the application?
Server hardening controls network access, OS patches, and file permissions. Application security covers input validation, authentication, and dependency updates. You need both. A hardened server with a vulnerable Laravel plugin still gets compromised.
Should I change the SSH port to secure Ubuntu server access?
Changing from port 22 reduces scanner noise but does not stop targeted attacks. Key-only auth plus UFW rate limiting on port 22 is the real fix. If you change the port, update firewall rules and document it in your runbook.
How often should I patch an Ubuntu production server?
Security patches should apply within 24 hours of release. Unattended Upgrades handles this automatically. Test kernel reboots in staging first. Schedule automatic reboots for off-peak hours to avoid downtime during business traffic.
Build Ubuntu Server Security Into Every Deployment
Ubuntu server security best practices are not a one-time checkbox. They are standard operating procedure for every server you provision in 2026. Start with SSH and UFW today — thirty minutes eliminates entire attack categories. Add fail2ban and auto-patching this week. Wire permissions into your deploy pipeline next release.
These layers compound. A bot that cannot reach SSH, cannot brute-force a login, and cannot read your .env file simply moves on to the next target. That is the outcome you want.
Need a production audit or hands-on hardening for your stack? Contact us to discuss your server security requirements, or reach out directly about your infrastructure. For reference, the OpenSSH manual documents every directive mentioned above.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

