Virtual Private Servers (VPSs) provide an economical and flexible infrastructure platform for small and medium-sized businesses, engineering organizations, software companies and eCommerce businesses.
A single VPS may host:
-
WordPress
-
Joomla
-
Magento/Open Source
-
Nginx
-
Apache
-
PHP-FPM
-
MariaDB/MySQL
-
Redis
-
Docker
-
Docker Compose
-
APIs
-
development tools
-
monitoring systems
-
business applications
This concentration of services also creates a concentrated security risk.
A vulnerable plugin, stolen administrator credential, exposed Docker port, compromised PHP application or misconfigured firewall can potentially provide an attacker with access to valuable business systems.
This paper presents a defense-in-depth security architecture using multiple independent security controls:
Defense-in-Depth VPS Security
Cloud Firewall, UFW, Docker Hardening, Malware Detection and Rootkit Hunting
A Production Engineering Tutorial for WordPress, Joomla, Magento and Docker-Based Web Applications
Executive Summary
Virtual Private Servers (VPSs) provide an economical and flexible infrastructure platform for small and medium-sized businesses, engineering organizations, software companies and eCommerce businesses.
A single VPS may host:
-
WordPress
-
Joomla
-
Magento/Open Source
-
Nginx
-
Apache
-
PHP-FPM
-
MariaDB/MySQL
-
Redis
-
Docker
-
Docker Compose
-
APIs
-
development tools
-
monitoring systems
-
business applications
This concentration of services also creates a concentrated security risk.
A vulnerable plugin, stolen administrator credential, exposed Docker port, compromised PHP application or misconfigured firewall can potentially provide an attacker with access to valuable business systems.
This paper presents a defense-in-depth security architecture using multiple independent security controls:
Internet | v Cloud Firewall | v Ubuntu VPS | +-- UFW / nftables | +-- SSH Hardening | +-- Fail2ban | +-- Nginx / Apache | +-- WAF | +-- Docker Isolation | +-- WordPress / Joomla / Magento | +-- MariaDB | +-- Redis | +-- ClamAV | +-- Rootkit Hunting | +-- File Integrity | +-- Monitoring | +-- Backup | +-- Incident Response
The reference implementation in this tutorial uses a Contabo VPS running Ubuntu LTS as an example. The same principles can be applied to other VPS providers.
The fundamental engineering principle is:
Do not depend on a single security control. Build multiple layers so that the failure or misconfiguration of one layer does not automatically result in compromise.
1. Introduction
Modern web infrastructure is a software-defined system rather than simply a server.
A typical eCommerce or CMS deployment may contain:
INTERNET | v +----------------+ | DNS / CDN / WAF| +----------------+ | v +----------------+ | Cloud Firewall | +----------------+ | v +----------------+ | Ubuntu VPS | | | | UFW | | SSH | | Docker | +----------------+ | v +----------------+ | Nginx / Apache | +----------------+ | +----------+----------+ | | | v v v WordPress Joomla Magento | | | +----------+----------+ | Private Network | +-------+-------+ | | v v MariaDB Redis
Every component represents an attack surface.
Security therefore has to be designed at multiple levels:
-
Network
-
Host
-
Identity
-
Container
-
Web server
-
Application
-
Database
-
File system
-
Monitoring
-
Recovery
2. Research Objective
This paper develops a practical security methodology for production VPS environments.
The objectives are to demonstrate:
-
why cloud firewalls and host firewalls should be combined;
-
how to harden an Ubuntu VPS;
-
how to secure SSH;
-
how to handle Docker firewall behavior;
-
how to prevent accidental exposure of databases and internal services;
-
how to secure WordPress, Joomla and Magento;
-
how to use ClamAV;
-
how to perform rootkit hunting;
-
how to establish file-integrity baselines;
-
how to automate security checks;
-
how to investigate a compromised website;
-
how to recover from compromise;
-
how SMEs can operationalize VPS security.
3. Defense-in-Depth Model
The recommended security architecture is:
INTERNET | v +------------------+ | CDN / WAF / DNS | +------------------+ | v +------------------+ | CLOUD FIREWALL | | External Layer | +------------------+ | v +------------------+ | CONTABO VPS | | Ubuntu LTS | +------------------+ | v +------------------+ | UFW / nftables | | Host Layer | +------------------+ | +--------+--------+ | | v v SSH NGINX | v WAF | v Docker | +-----------------+----------------+ | | | v v v WordPress Joomla Magento | | | +-----------------+----------------+ | Private Network | +-----------+-----------+ | | v v MariaDB Redis Security Operations: ClamAV | Rootkit Hunting | AIDE Lynis | Fail2ban | Logging Monitoring | Backup | Incident Response
4. Why Use Both a Cloud Firewall and UFW?
A cloud firewall and UFW operate at different architectural boundaries.
Cloud firewall
The provider firewall operates outside the VPS.
It can reject traffic before it reaches the operating system.
UFW
UFW provides host-level firewall administration.
The two layers therefore provide defense in depth.
Internet | v Cloud Firewall | v VPS Network Interface | v UFW | v Application
If a cloud firewall rule is accidentally changed, UFW remains available as another control.
If an application unexpectedly opens a service, the provider firewall can provide an additional perimeter control.
5. Firewall Design Principle
Use:
DEFAULT DENY
for inbound traffic.
Then explicitly permit required services.
For a typical production web server:
TCP 80 HTTP TCP 443 HTTPS TCP 22 SSH, preferably restricted
Do not expose internal services unless there is a documented requirement.
Examples include:
3306 MariaDB 6379 Redis 9000 PHP-FPM 9200 Elasticsearch 11211 Memcached 8080 Development application 3000 Development application 5000 Development API 8000 Development service
6. Contabo VPS Reference Use Case
The example environment is:
Provider: Contabo Operating System: Ubuntu LTS Application Platform: Docker / Docker Compose Web Server: Nginx Applications: WordPress Joomla Magento Database: MariaDB Cache: Redis Security: Cloud Firewall UFW Fail2ban ClamAV Rootkit Hunter chkrootkit Lynis AIDE
This is a reference architecture rather than a requirement that all components be installed on every server.
7. Initial VPS Discovery
Connect to the VPS:
ssh administrator@YOUR_SERVER_IP>If root access was initially provided:ssh root@YOUR_SERVER_IP>Immediately identify the operating system:hostnamectl uname -a cat /etc/os-release
8. Create an Administrative Account
usermod -aG sudo administrator
ssh administrator@YOUR_SERVER_IP>Then:sudo whoami
Do not disable root SSH access until the administrative account has been tested successfully.
9. Update Ubuntu
sudo apt update sudo apt upgrade -y
sudo apt autoremove -y sudo apt autoclean
ssh administrator@YOUR_SERVER_IP>10. Install Administration Toolssudo apt install -y \ curl \ wget \ git \ vim \ nano \ htop \ iotop \ ncdu \ tree \ unzip \ zip \ rsync \ jq \ net-tools \ dnsutils \ lsof \ ca-certificates \ gnupg
11. SSH Key Authentication
On the administrator's workstation:
ssh-copy-id administrator@YOUR_SERVER_IP>Test:ssh administrator@YOUR_SERVER_IP>The key-based connection must work before disabling password authentication.
12. SSH Hardening
sudo nano /etc/ssh/sshd_config.d/99-hardening.conf
Keep the existing SSH session open.
Open a second terminal and test:
ssh administrator@YOUR_SERVER_IP>Only after successful testing should the original session be closed.
Configure the provider-level firewall to allow only required public services. A typical policy: Do not expose database or container-development ports simply because applications use them internally. Before enabling UFW: TCP: UDP: Alternative: Save the baseline: This is an important security-management step. Check: Set defaults: Allow SSH: Allow HTTP: Allow HTTPS: Check: Enable: Verify: Never enable UFW before permitting the SSH access path. Correct sequence: For a custom SSH port: The port must correspond to the actual SSH configuration. Always maintain provider console/recovery access. If the administrator has a fixed trusted IP: Then: Verify: This can dramatically reduce automated SSH attack traffic. Enable: Check: Or: Follow: Because modern Linux systems use netfilter technologies and applications such as Docker may manipulate firewall rules, inspect the underlying rules. Inspect Docker-specific chains later: Inspect nftables: The goal is not to manipulate every rule manually. The goal is to understand which system owns and controls each rule. Remove potentially conflicting packages: Install prerequisites: Create the keyring directory: Then install Docker Engine and Compose using the current official Docker repository procedure appropriate for the Ubuntu release. Verify: Compose: Log out: Reconnect:13. Contabo Cloud Firewall
14. Discover Existing Listening Services
15. Install UFW
sudo apt install -y ufw
16. Avoiding SSH Lockout
17. Restrict SSH to an Administration IP
18. UFW Logging
19. Inspect nftables and iptables
20. Install Docker
21. Add the Administrator to Docker
sudo usermod -aG docker administrator
administrator@YOUR_SERVER_IP>Test:docker ps
Docker changes the networking model.
docker ps --format "table {{.Names}}\t{{.Ports}}"
Inspect an individual container:
23. The Docker/UFW Security Problem
Docker manages network filtering and port publishing.
docker run -p 127.0.0.1:8080:80 nginx
The second configuration binds the service only to localhost.
24. Docker Published-Port Audit
docker ps --format "table {{.Names}}\t{{.Ports}}"
0.0.0.0:3306 0.0.0.0:6379 0.0.0.0:8080 0.0.0.0:9200
25. Secure Docker Compose Design
A production architecture should expose only the reverse proxy.
This is a conceptual example and must be adapted to the application.
27. Docker Firewall Inspection
sudo iptables -L DOCKER-USER -n -v
sudo iptables -L FORWARD -n -v
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban
sudo fail2ban-client status sshd
sudo nano /etc/fail2ban/jail.local
[DEFAULT] bantime = 1h findtime = 10m maxretry = 5 [sshd] enabled = true
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
sudo apt update sudo apt install -y clamav clamav-daemon
sudo systemctl status clamav-freshclam
sudo clamscan -r --infected /var/www/
sudo clamscan \ -r \ --infected \ --log=/var/log/clamav/web-scan.log \ /var/www/
32. Scan Docker Application Data
Identify the host path used for persistent application data.
Then scan the appropriate mounted directory:
sudo clamscan -r --infected /PATH/TO/DATA
sudo nano /usr/local/sbin/web-malware-scan.sh
sudo chmod 750 /usr/local/sbin/web-malware-scan.sh
sudo /usr/local/sbin/web-malware-scan.sh
sudo nano /etc/cron.d/web-malware-scan
0 2 * * * root /usr/local/sbin/web-malware-scan.sh
cat /etc/cron.d/web-malware-scan
After establishing a known-good baseline:
sudo less /var/log/rkhunter.log
Rootkit Hunter warnings require investigation.
A warning is not automatically proof of a rootkit.
sudo apt install -y chkrootkit
sudo chkrootkit | tee ~/chkrootkit-report.txt
Use multiple sources of evidence:
sudo lynis audit system --quick
Lynis recommendations should be reviewed by an administrator rather than applied blindly.
The baseline should be created when the system is known to be clean.
ps aux --sort=-%cpu | head -20
ps aux --sort=-%mem | head -20
Investigate unknown processes.
sudo ss -tnp state established
Unexpected outbound connections should be investigated.
41. User and Privilege Hunting
Users with interactive shells:
awk -F: '$7 !~ /(nologin|false)$/ {print $1,$7}' /etc/passwd
sudo journalctl -u ssh --since "24 hours ago"
sudo journalctl -u ssh | grep -Ei "failed|invalid"
sudo journalctl -u ssh | grep -Ei "accepted"
sudo find /etc/cron* -type f -ls
Unknown cron entries should be investigated.
44. Systemd Persistence Hunting
systemctl list-unit-files --state=enabled
systemctl --type=service --state=running
Find recently modified PHP files:
sudo find /var/www \ -type f \ -name "*.php" \ -mtime -7 \ -ls
sudo find /var/www \ -type f \ -path "*/uploads/*" \ -name "*.php" \ -print
sudo grep -RniE \ 'eval\(|base64_decode\(|shell_exec\(|passthru\(|system\(' \ /var/www
These searches generate investigation leads.
They do not prove that a file is malicious.
46. Recently Modified Website Files
sudo find /var/www \ -type f \ -mtime -1 \ -ls
sudo find /var/www \ -type f \ -mtime -7 \ -ls
sudo find /var/www \ -type f \ -mtime -14 \ -ls
This is particularly useful after a reported website compromise.
sudo find /var/www \ -type f \ -perm -0002 \ -ls
sudo find /var/www \ -type d \ -perm -0002 \ -ls
48. Executable Files in Web Roots
sudo find /var/www \ -type f \ -perm /111 \ -ls
Unexpected executable files should be investigated.
sudo find /var/www \ -type f \ -name ".*" \ -ls
Remember that legitimate files such as:
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
Search common attack indicators:
sudo grep -Ei \ "wp-admin|xmlrpc|\.env|phpmyadmin|/shell|cmd=" \ /var/log/nginx/access.log
The search patterns should be adapted to the actual application.
51. WordPress Security Use Case
WordPress should be treated as both an application and an infrastructure workload.
wp-admin/ wp-includes/ wp-content/
wp-content/uploads/ wp-content/plugins/ wp-content/themes/
sudo find /var/www \ -type f \ -name "*.php" \ -mtime -14 \ -ls
sudo find /var/www \ -path "*/uploads/*" \ -name "*.php" \ -print
configuration.php administrator/ components/ plugins/ modules/ templates/ media/ images/ cache/ tmp/
sudo find /var/www \ -type f \ -mtime -14 \ -ls
sudo find /var/www \ -type f \ -name "*.php" \ -mtime -14 \ -ls
Magento combines many components:
PHP Composer MariaDB Redis Nginx Cron Admin APIs Extensions Themes Media Cache
app/ pub/ vendor/ generated/ var/ bin/
pub/media/ app/code/ app/design/
sudo find /path/to/magento \ -type f \ -name "*.php" \ -mtime -14 \ -ls
Production architecture should normally be:
Internet | v Nginx | v Application | v Private Docker Network | +---- MariaDB | +---- Redis
Internet | +---- 3306 ---> MariaDB | +---- 6379 ---> Redis
If installed directly on Ubuntu:
sudo mysql_secure_installation
SELECT User, Host FROM mysql.user;
The exact hardening procedure depends on the MariaDB version and deployment architecture.
sudo systemctl status redis-server
Redis should generally be restricted to:
A production backup system should not depend exclusively on the same VPS.
PRODUCTION VPS | +------------+------------+ | | v v Local Backup Remote Backup | v Off-site Copy
Protect secrets appropriately.
mysqldump \ -u root \ -p \ --single-transaction \ --all-databases \ > /backup/all-databases.sql
gzip /backup/all-databases.sql
sudo nano /usr/local/sbin/backup-web.sh
sudo chmod 750 /usr/local/sbin/backup-web.sh
sudo /usr/local/sbin/backup-web.sh
sudo nano /usr/local/sbin/vps-security-audit.sh
sudo chmod 750 /usr/local/sbin/vps-security-audit.sh
sudo /usr/local/sbin/vps-security-audit.sh
61. Schedule the Security Audit
sudo nano /etc/cron.d/vps-security-audit
30 1 * * * root /usr/local/sbin/vps-security-audit.sh
cat /etc/cron.d/vps-security-audit
sudo mkdir -p /root/security-baseline
sudo ss -tulpn \ > /root/security-baseline/ports.txt
sudo ufw status verbose \ > /root/security-baseline/ufw.txt
systemctl list-unit-files --state=enabled \ > /root/security-baseline/services.txt
systemctl list-timers --all \ > /root/security-baseline/timers.txt
docker ps -a \ > /root/security-baseline/docker.txt
This creates a reference against which future changes can be compared.
63. HTProtect and CMS Security
Infrastructure hardening should be combined with application-specific security.
The operational model should be:
HTProtect should not be treated as a replacement for:
Instead, it should form another layer in the application-security stack.
64. Joomla Compromise Investigation
When SEO spam, redirects or suspicious content appear:
sudo find /var/www \ -type f \ -mtime -14 \ -ls
sudo clamscan -r --infected /var/www/
sudo rkhunter --check sudo chkrootkit
systemctl list-timers --all systemctl list-unit-files --state=enabled sudo crontab -l
Then investigate the initial entry point.
65. Incident Response Procedure
Do not immediately delete suspicious files.
sudo ss -tunap \ > /root/incident-network.txt
ps auxf \ > /root/incident-processes.txt
systemctl list-unit-files --state=enabled \ > /root/incident-services.txt
systemctl list-timers --all \ > /root/incident-timers.txt
The decision to rebuild should depend on the nature and scope of the compromise.
From an authorized external system:
The expected public exposure should match the documented architecture.
Internal services should normally appear:
Do not scan systems without authorization.
Create a documented port inventory:
Every additional listener must have a business or technical reason.
SSH UFW Nginx Apache Docker PHP MariaDB Redis CMS Cron systemd Filesystem CPU Memory Disk Network
sudo journalctl --since "24 hours ago"
sudo du -xhd1 /var/www | sort -h
Unexpected disk growth may indicate:
docker logs --tail 100 CONTAINER
Remove unused objects only after confirming they are not required.
74. Application Security Testing
Security testing should include:
The infrastructure firewall cannot protect against every application-layer vulnerability.
75. Security Layers by Attack Type
|
Attack |
Primary Controls |
|---|---|
|
Port scanning |
Cloud firewall + UFW |
|
SSH brute force |
SSH keys + source restriction + Fail2ban |
|
Web attack |
WAF + web server + application security |
|
Malicious upload |
Application controls + ClamAV |
|
Web shell |
File integrity + malware scanning + rootkit hunting |
|
Docker exposure |
Cloud firewall + Docker network controls |
|
Database exposure |
Private network + firewall |
|
Credential theft |
SSH keys + credential management |
|
Persistence |
rkhunter + chkrootkit + AIDE + system inspection |
|
Data loss |
Backups |
|
Deep compromise |
Incident response + rebuild |
76. Production Deployment Lifecycle
A secure deployment should follow:
Security is therefore an ongoing engineering activity.
77. Contabo Production Checklist
Cloud Firewall UFW SSH Keys TLS Updates Backups
Fail2ban Docker isolation ClamAV Rootkit hunting Lynis File permissions
WAF Centralized logging AIDE Vulnerability management Automated backups Incident response
Level 4 — Engineering Security
Small and medium-sized businesses frequently have limited IT staff.
The security architecture should therefore prioritize:
Simple Automated Documented Repeatable Recoverable Measurable
This provides a substantial security foundation without requiring a large enterprise security team.
80. Strategic Role of KeenComputer
KeenComputer can serve as the infrastructure and digital-transformation partner.
81. Strategic Role of IAS-Research
IAS-Research can provide the engineering and research layer.
The role is especially relevant where the VPS is part of a larger engineering or industrial system.
82. Strategic Role of KeenDirect
KeenDirect can focus on the eCommerce platform layer.
VPS security is not simply an IT expense.
A compromised website can cause:
Security controls therefore contribute directly to business resilience.
84. Recommended Operating Model
A mature VPS security program should operate continuously.
85. Final Engineering Conclusions
The Contabo VPS example demonstrates that modern VPS security cannot be reduced to installing UFW.
A production security architecture should combine:
The most important engineering principle is:
Security should be layered, continuously monitored, tested and recoverable.
The cloud firewall protects the perimeter.
Docker isolation protects internal application boundaries.
The web server and WAF protect the HTTP layer.
WordPress, Joomla and Magento hardening protects the application.
ClamAV provides malware scanning.
Rootkit Hunter and chkrootkit provide additional persistence/rootkit investigation capabilities.
AIDE provides file-integrity monitoring.
Fail2ban provides automated response to repeated authentication abuse.
Incident response provides the process for handling failure.
hostnamectl uname -a cat /etc/os-release nproc free -h df -h lsblk ip addr ip route
sudo apt update sudo apt upgrade -y sudo apt autoremove -y sudo apt autoclean
sudo ss -tulpn sudo ss -lntup sudo ss -tunap sudo lsof -i -P -n
sudo systemctl status fail2ban sudo fail2ban-client status sudo fail2ban-client status sshd
sudo freshclam sudo clamscan -r --infected /var/www/
sudo rkhunter --update sudo rkhunter --propupd sudo rkhunter --check
sudo lynis audit system sudo lynis audit system --quick
sudo aideinit sudo aide --check
ps auxf ps aux --sort=-%cpu | head -20 ps aux --sort=-%mem | head -20 htop
cut -d: -f1 /etc/passwd getent group sudo last sudo lastb
sudo crontab -l sudo cat /etc/crontab sudo find /etc/cron* -type f -ls
sudo tail -f /var/log/nginx/access.log sudo tail -f /var/log/nginx/error.log
df -h sudo du -xhd1 / | sort -h sudo du -xhd1 /var/www | sort -h
The operating principle is simple:
Prevent → Harden → Isolate → Monitor → Detect → Investigate → Recover → Improve.
-
Docker Engine documentation — networking, packet filtering and firewall behavior.
-
OWASP — Web Application Security, attack-surface analysis and secure application design.
-
Rootkit Hunter documentation — rootkit and persistence detection.