Self-Hosting dotCMS on a VPS: A Complete Production Guide
Securing Your VPS
Why this matters: A fresh VPS exposed to the internet will receive automated login attempts within minutes. These steps apply regardless of what you're hosting.
1. Update System Packages#
sudo apt-get update sudo apt-get upgrade -y
If prompted about OpenSSH server configuration during the upgrade, select "Install the package maintainer's version".
After upgrading, check if a reboot is required:
ls /var/run/reboot-required
If the file exists:
reboot
Reconnect after the reboot and run sudo apt-get upgrade again to confirm everything is current.
2. Create a Non-Root User#
Running everything as root means any process or compromised service has full system access. Create a dedicated user with limited privileges:
sudo adduser <USERNAME> # Follow prompts — set a strong password
Add the user to the sudo group so it can run privileged commands when needed:
sudo usermod -aG sudo <USERNAME>
Verify the group was added:
groups <USERNAME> # Should include: <USERNAME> sudo
3. Set Up SSH Key Authentication#
SSH keys are the recommended way to authenticate — significantly more secure than passwords.
On your local machine, generate a key pair:
ssh-keygen -t ed25519 -C "your-email@dotcms.info" # When prompted for file location, enter something like: # ~/.ssh/do-cms-key # Leave passphrase blank (or set one for extra security)
This creates two files:
~/.ssh/do-cms-key— your private key (never share this)~/.ssh/do-cms-key.pub— your public key (this goes on the server)
Configure your SSH client for convenience. Add to ~/.ssh/config:
Host cms-vps HostName dotcms.info User <USERNAME> IdentityFile ~/.ssh/do-cms-key
Copy the public key to your VPS. While still logged in as root:
# On the VPS mkdir -p /home/<USERNAME>/.ssh nano /home/<USERNAME>/.ssh/authorized_keys # Paste the contents of your local ~/.ssh/do-cms-key.pub here # Save and exit
Now you can connect with just ssh cms-vps from your local machine.
Test the SSH key login in a new terminal before continuing:
ssh cms-vps # Should log in without a password prompt
Critical: Confirm this works before the next step. If you disable password auth without a working key, you'll be locked out.
4. Disable Password Authentication#
Once SSH key login is confirmed, disable password-based login for everyone:
sudo nano /etc/ssh/sshd_config
Find and change:
PasswordAuthentication no
Check if your system has override config files:
ls /etc/ssh/sshd_config.d/
If any files in that directory set PasswordAuthentication yes, edit them to no as well.
Restart SSH:
sudo systemctl restart ssh
5. Disable Root Login#
sudo nano /etc/ssh/sshd_config
Find and change:
PermitRootLogin no
Restart SSH:
sudo systemctl restart ssh
Verify the lockout is working:
# From your local machine — this should fail: ssh root@dotcms.info # Expected: "Permission denied (publickey)"
# This should still work: ssh cms-vps
6. Configure the Firewall#
Use your cloud provider's firewall to restrict inbound traffic. Allow only:
| Protocol | Port | Purpose |
|---|---|---|
| TCP | 22 | SSH |
| TCP | 80 | HTTP (for Let's Encrypt challenges) |
| TCP | 443 | HTTPS |
DigitalOcean: Networking → Firewalls → Create Firewall → add the rules above → assign to your droplet.
Verify by temporarily removing the SSH rule — your SSH session should hang. Re-add the rule and reconnect to confirm it works.
Principle: Caddy faces the internet on ports
80and443. Everything else (databases, internal services) talks only within Docker's internal network — never publicly exposed.
Next up
Chapter 3: Install Caddy (Reverse Proxy)