Skip to content
Back to Blog
Security10 min read

Prevent Data Breach: 10 Server Controls [Solved 2026]

Defense-in-depth controls for hosting environments: encryption, access logging, MFA, vulnerability scanning, and incident response plans that protect your server and application layers.

Written by Abdul AbrorTechnical Hosting Support Engineer
Prevent Data Breach: 10 Server Controls [Solved 2026]
On this page

A single misconfigured directive or a missed patch can expose your entire database to the internet. I've seen it happen—root access obtained through an outdated plugin, customer records scraped because SSL was only half-deployed, backups sitting in cleartext on the same partition as production. Defense-in-depth means layering controls so that when one fails, three others still hold.

This article walks through ten practical controls you can implement on your hosting stack today. Each one addresses a different attack surface.

Encrypt data at rest

If an attacker gets physical access to your disks or snapshots, encryption at rest is your last line. Modern Linux distributions ship with LUKS for full-disk encryption and dm-crypt for per-volume setups.

For existing production servers, encrypting the root partition requires downtime and a full reinstall. Most teams start with dedicated encrypted volumes for sensitive data:

cryptsetup luksFormat /dev/sdb1
cryptsetup luksOpen /dev/sdb1 encrypted_data
mkfs.ext4 /dev/mapper/encrypted_data
mount /dev/mapper/encrypted_data /var/lib/mysql

Store the unlock key in a hardware security module or a separate KMS service, never on the same disk. Database engines like PostgreSQL and MySQL also offer tablespace-level encryption if full-disk encryption isn't an option.

For application-level encryption, encrypt sensitive columns (credit card numbers, social security numbers) before writing them. Keep encryption keys out of your application config files; use environment variables or a secrets manager.

Enforce encryption in transit

Every connection between client and server, and between your internal services, should be encrypted. That means TLS everywhere.

Web traffic

Deploy valid certificates on all public endpoints. Let's Encrypt makes this free and automatable:

certbot --nginx -d example.com -d www.example.com

Force HTTPS with a 301 redirect and set the Strict-Transport-Security header:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Disable old TLS versions. TLS 1.0 and 1.1 are broken; enforce TLS 1.2 as the minimum, TLS 1.3 where supported.

Database and backend connections

MySQL, PostgreSQL, Redis, and Memcached all support TLS. On MySQL:

[mysqld]
require_secure_transport=ON
ssl-ca=/etc/mysql/ca-cert.pem
ssl-cert=/etc/mysql/server-cert.pem
ssl-key=/etc/mysql/server-key.pem

Test it:

mysql -u root -p -h 127.0.0.1 --ssl-mode=REQUIRED

For internal service-to-service calls (API gateways, microservices), mutual TLS adds bidirectional verification.

Require multi-factor authentication

Passwords leak. Credential stuffing attacks are cheap and effective. MFA makes stolen passwords worthless.

Enforce MFA for every administrative interface: - SSH (use libpam-google-authenticator or hardware keys) - cPanel/WHM (enable two-factor in Tweak Settings) - Cloud consoles (AWS, DigitalOcean, Cloudflare) - Git repositories - VPN access

For SSH, add this to /etc/ssh/sshd_config:

ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

Then configure PAM:

google-authenticator

Add auth required pam_google_authenticator.so to /etc/pam.d/sshd.

Hardware tokens (YubiKey, Titan) are better than TOTP apps because phishing-resistant. For user-facing applications, support WebAuthn.

Implement least-privilege access control

Every account, every process, every database user should have the minimum permissions needed to do its job. Nothing more.

Operating system accounts

Never run application processes as root. Create dedicated service accounts:

useradd -r -s /bin/false -d /var/www/app appuser
chown -R appuser:appuser /var/www/app

Use sudo with fine-grained rules in /etc/sudoers.d/ instead of giving users full root.

Database permissions

Your application doesn't need GRANT ALL. It needs SELECT, INSERT, UPDATE, DELETE on its own schema:

CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;

Read-only reporting users get SELECT only.

File permissions

Sensitive config files should be 0600 or 0640, owned by the service user:

chmod 600 /var/www/app/.env
chown appuser:appuser /var/www/app/.env

Never chmod 777 anything in production.

Enable comprehensive access logging

You can't investigate what you didn't record. Logs are your evidence chain.

What to log

  • Authentication attempts (successful and failed)
  • Privilege escalation (sudo, su)
  • File access to sensitive directories
  • Database queries (especially DDL changes)
  • API requests with user IDs and IP addresses
  • Configuration changes

Where to send logs

Local logs get deleted by attackers. Ship them off-host in real time to a SIEM or a logging service (Splunk, ELK stack, Papertrail).

For syslog forwarding:

echo "*.* @@logs.example.com:514" >> /etc/rsyslog.conf
systemctl restart rsyslog

For application logs, use structured JSON and include request IDs so you can trace a single user's journey.

Retain logs for at least ninety days. A year is better for compliance and forensic investigations.

Automate vulnerability scanning

Manual audits happen once a quarter if you're lucky. Automated scanners run daily.

Operating system packages

Use unattended-upgrades on Debian/Ubuntu to apply security patches automatically:

apt install unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades

On RHEL/CentOS, yum-cron does the same.

For manual checks:

apt list --upgradable
yum updateinfo list security

Application dependencies

JavaScript projects leak vulnerabilities through npm packages. Run npm audit in CI/CD pipelines and block merges on high-severity findings. For Python, use safety:

safety check --json

For containerized apps, scan images with Trivy or Clair before pushing to production registries.

External scanning

Point a web vulnerability scanner at your staging environment weekly. Options include OWASP ZAP, Nikto, or commercial tools. Look for SQL injection, XSS, exposed admin panels, and default credentials.

Harden SSH access

SSH is the front door to your server. Lock it down.

Disable password authentication

Use key pairs only:

PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes

Disable root login

PermitRootLogin no

Force users to log in with personal accounts and sudo up.

Change the default port

Port 22 gets hammered by bots. Moving to a high port cuts noise:

Port 2222

Update your firewall rules and inform your team.

Restrict access by IP

If your admins connect from known networks, whitelist them:

ufw allow from 203.0.113.0/24 to any port 2222

For dynamic IPs, use a VPN as a jump host.

Deploy a web application firewall

A WAF sits in front of your web server and filters malicious requests before they reach your application. ModSecurity with the OWASP Core Rule Set is the open-source standard:

apt install libapache2-mod-security2
cd /etc/modsecurity
cp modsecurity.conf-recommended modsecurity.conf
sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' modsecurity.conf

Download the OWASP CRS:

git clone https://github.com/coreruleset/coreruleset.git /etc/modsecurity/crs
cp /etc/modsecurity/crs/crs-setup.conf.example /etc/modsecurity/crs/crs-setup.conf

Configure Apache to load it:

IncludeOptional /etc/modsecurity/crs/*.conf

For Nginx, compile with the ModSecurity module or use the standalone proxy.

Cloud-based WAFs like Cloudflare or Sucuri are easier to deploy and handle DDoS mitigation as well.

Maintain offline encrypted backups

Backups are your last resort. If ransomware encrypts your production data, backups are the only way back.

The 3-2-1 rule

Three copies of your data, on two different media types, with one copy offsite. For hosting environments:

  • Primary: live production server
  • Secondary: encrypted snapshot on the same provider but different region
  • Offsite: encrypted archive in a different cloud or on tape

Encryption and immutability

Encrypt backups before they leave the server:

tar czf - /var/www | gpg --encrypt --recipient [email protected] > backup.tar.gz.gpg

Store them in append-only or immutable buckets (S3 Object Lock, Wasabi immutability) so attackers can't delete them.

Test restores

Backups you've never restored are Schrödinger's backups. Test full restores quarterly and document the process.

Write and drill an incident response plan

When a breach happens, you'll be under pressure. An incident response plan tells you what to do before panic sets in.

Detection

Define what constitutes an incident: - Unauthorized root login - Unexpected database exports - Sudden spike in outbound traffic - File integrity changes in /etc or web roots

Containment

Have runbooks ready: 1. Isolate the compromised server (firewall rules or disconnect) 2. Snapshot disks for forensics before making changes 3. Revoke credentials and rotate secrets 4. Check other servers for indicators of lateral movement

Communication

Who needs to know, and when? Customers, legal, compliance teams, law enforcement. Draft template emails.

Recovery

Rebuild from known-good images, not from potentially compromised snapshots. Apply the lessons learned before bringing systems back online.

Drills

Run tabletop exercises twice a year. Simulate a breach and walk through your plan. Time how long each step takes.

Enforce least-privilege network segmentation

Not every server needs to talk to every other server. Segment your network so a breach in one zone doesn't cascade.

Put web servers in a DMZ. Database servers in a private subnet with no internet access. Use firewall rules or security groups to allow only necessary flows:

# Web server can reach database on port 3306
ufw allow from 10.0.1.10 to any port 3306

# Nothing else
ufw default deny incoming

Jump boxes (bastion hosts) mediate SSH access to internal networks. Require MFA on the jump box and log every session.

For containerized applications, use network policies in Kubernetes to isolate pods.

What to check first

Start with encryption in transit—it's the easiest win and protects data on the wire. Add MFA to SSH and admin panels the same day. Then work through logging, patch management, and backups.

No single control will prevent every breach. The goal is to make your infrastructure expensive enough to attack that adversaries move on to softer targets. Layer these ten controls and you'll close the doors that most attackers walk through.

FAQ

How often should I rotate encryption keys? For data-at-rest encryption, rotate keys annually or after a suspected compromise. For TLS certificates, Let's Encrypt renews every ninety days automatically.

Do I need a WAF if I'm already patching regularly? Yes. Patching fixes known vulnerabilities, but a WAF blocks zero-day exploits and malformed requests before they reach your application logic.

Can I use the same SSH key on multiple servers? You can, but it increases blast radius. If that key leaks, an attacker owns every server. Generate unique keys per server or per admin.

Where should I store MFA backup codes? In a password manager or printed and locked in a safe. Never in plaintext on the same server you're protecting.

How do I know if my backups are encrypted correctly? Try restoring one without the decryption key. If it fails, the encryption works. If it succeeds, fix your backup script.

Start with the gaps you can close today

You don't have to implement everything at once. Pick the three controls your environment lacks most—usually MFA, logging, and patch automation—and deploy them this week. Document what you did and schedule the next three. Six months from now you'll have a hardened stack that can survive the attacks most hosting environments can't.