The same six steps every server gets before it runs a single app: access, firewall, users, baseline, backups and monitoring.

Before a new server runs a single app, it gets the same six steps, in the same order. I look after 29 client sites on Linux servers, and this checklist matters more than any single tool. A server set up from memory is how gaps sneak in.

The commands below are simplified examples. Swap in your own names and paths.

1. Access: keys only, no root

In /etc/ssh/sshd_config:

PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes 

Test the config, then reload. Keep your current session open until a new login works:

sudo sshd -t && sudo systemctl reload ssh 

2. Firewall: start from closed

sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow OpenSSH sudo ufw allow 80,443/tcp sudo ufw enable 

Allow SSH before enabling the firewall, or you'll lock yourself out.

3. Users: nothing runs as root

Each service gets its own system user and owns only what it needs to write to:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin my-app sudo chown -R my-app:my-app /var/www/my-app/storage 

If that service is ever compromised, the damage stops at that user.

4. Baseline: write down what normal looks like

Right after setup, record what should be there:

# who can log in cat /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys # what runs on a schedule for u in $(cut -d: -f1 /etc/passwd); do crontab -l -u "$u" 2>/dev/null; done # what is listening ss -tulpn 

Save the output somewhere off the server. Later, anything that isn't on this list is worth a closer look.

5. Backups: off site from day one

A backup on the same server dies with the server. Send it somewhere else:

mysqldump --single-transaction my_app_db | gzip > /var/backups/my-app-$(date +%F).sql.gz rclone copy /var/backups remote:backups/my-app 

Keep database credentials in ~/.my.cnf, not in the script. And restore one into a scratch database now and then. A backup you have never restored is a hope, not a plan.

6. Watching: let problems find you

A watchdog every 5 minutes, uptime and SSL checks, and alerts that land somewhere a human actually looks. Mine go to Discord and email.

*/5 * * * * /opt/monitor/check-sites.sh 

Then, and only then, deploy

None of these steps are advanced. That's exactly why they get skipped when someone is in a hurry, and why they belong on a checklist instead of in your memory.

Lock the doors before you move the furniture in.