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:

ProtocolPortPurpose
TCP22SSH
TCP80HTTP (for Let's Encrypt challenges)
TCP443HTTPS

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 80 and 443. Everything else (databases, internal services) talks only within Docker's internal network — never publicly exposed.

Next up

Chapter 3: Install Caddy (Reverse Proxy)

Continue →
    Self-Hosting dotCMS on a VPS · Ch. 2/8 — Securing Your VPS | dotCMS Dev Site