Setting up a Linux server the right way from day one will save you countless hours of troubleshooting later. In this guide, I walk through every step I take when provisioning a fresh Ubuntu server for production — from the first SSH connection to having a fully secured, monitored environment ready to serve real traffic.

Prerequisites

Before you begin, make sure you have the following ready:

  • A fresh Ubuntu 22.04 LTS server (VPS or bare metal)
  • Root SSH access or a user with sudo privileges
  • A local SSH key pair — if you don't have one, generate it with ssh-keygen -t ed25519
  • A domain name pointed to your server's IP (optional but recommended for SSL)

This guide assumes you are connecting as root initially. We will fix that immediately.

Initial Server Setup

The very first thing you should do after logging in is update the system packages and configure a non-root user. Running as root all the time is a bad habit that will eventually cost you.

Creating a New User

Log in as root and run the following commands to create a dedicated admin user:

adduser datadmin
usermod -aG sudo datadmin

Now switch to the new user and verify sudo access:

su - datadmin
sudo whoami   # should print: root

From this point forward, always log in as datadmin (or whatever you named the user) and use sudo when elevated privileges are needed.

Setting Up SSH Key Authentication

Password authentication is convenient but dangerous. Let's disable it and use SSH keys instead.

On your local machine, copy your public key to the server:

ssh-copy-id datadmin@your-server-ip

Now on the server, harden the SSH daemon config:

sudo nano /etc/ssh/sshd_config

Make sure these lines are set:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

Restart SSH to apply changes:

sudo systemctl restart sshd

Important: Before closing your current session, open a new terminal and confirm you can still log in with your key. If you lock yourself out, you'll need console access to fix it.

Configuring the Firewall

Ubuntu comes with ufw (Uncomplicated Firewall) which makes firewall management straightforward. Let's set up a basic ruleset.

Allow only the services you actually need:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

The output should show SSH, HTTP, and HTTPS allowed from anywhere. Everything else is denied by default.

If you're running other services like PostgreSQL or Redis, only expose them on 127.0.0.1 — never on the public interface unless you have a very good reason.

Installing and Configuring Nginx

Nginx is my go-to web server and reverse proxy for production environments. It's fast, battle-tested, and its configuration syntax is clean once you understand it.

Basic Nginx Installation

sudo apt update
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx

Visit your server's IP in a browser — you should see the default Nginx welcome page.

Setting Up Virtual Hosts

Never put your config in the default site. Instead, create a dedicated config file for each domain:

sudo nano /etc/nginx/sites-available/yourdomain.com

Paste in a basic reverse proxy config (assuming your app runs on port 3000):

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Enable the site and reload Nginx:

sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t   # always test before reloading
sudo systemctl reload nginx

Securing Your Server with SSL/TLS

There is absolutely no excuse for running HTTP-only in 2025. Let's Encrypt gives you free, auto-renewing certificates in under two minutes.

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot will automatically modify your Nginx config to redirect HTTP to HTTPS and set up the certificate. It also installs a systemd timer that renews the cert before it expires.

Verify renewal works:

sudo certbot renew --dry-run

After this, your site is accessible via HTTPS with a valid certificate and automatic HTTP → HTTPS redirects.

Setting Up Automatic Updates

Security patches should be applied automatically. Manual updates are fine for major version upgrades, but you shouldn't have to babysit CVE announcements for routine patches.

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

Choose "Yes" when prompted. This enables automatic installation of security updates only (not regular package upgrades, which could break things).

Check the config file to understand what gets updated:

cat /etc/apt/apt.conf.d/50unattended-upgrades

You'll see it's scoped to Ubuntu:22.04 security repos — safe and focused.

Monitoring and Alerts

You can't fix what you can't see. A production server without monitoring is an accident waiting to happen. Here are the two tools I install on every server.

Installing Netdata

Netdata gives you beautiful, real-time metrics with zero configuration. It's the fastest way to get visibility into CPU, RAM, disk I/O, network, and more:

wget -O /tmp/netdata-kickstart.sh https://my-netdata.io/kickstart.sh
sudo sh /tmp/netdata-kickstart.sh --stable-channel

Once installed, Netdata runs on port 19999. Don't expose this publicly — access it via SSH tunnel:

ssh -L 19999:localhost:19999 datadmin@your-server-ip

Then visit http://localhost:19999 in your browser.

Setting Up Email Alerts

Configure Netdata to send you an email when something goes wrong. Edit the alarm notification config:

sudo nano /etc/netdata/health_alarm_notify.conf

Find the EMAIL_SENDER and DEFAULT_RECIPIENT_EMAIL lines and fill in your addresses:

EMAIL_SENDER="[email protected]"
DEFAULT_RECIPIENT_EMAIL="[email protected]"

Test the alert system:

sudo -u netdata /usr/libexec/netdata/plugins.d/alarm-notify.sh test

You should receive a test email within a few seconds.

Final Checklist

Before considering a server production-ready, go through this checklist:

  • ✅ Root login disabled
  • ✅ SSH key authentication only (password auth disabled)
  • ✅ Firewall enabled — only ports 22, 80, 443 open
  • ✅ Nginx installed and configured with virtual hosts
  • ✅ SSL certificate issued and auto-renewal verified
  • ✅ Automatic security updates enabled
  • ✅ Monitoring running (Netdata or equivalent)
  • ✅ Email alerts configured
  • ✅ Backups configured (covered in a separate post)

This setup takes about 30 minutes on a fresh server and will serve you well for years. The key insight is that most server compromises and outages are completely avoidable — they happen because of skipped steps, not advanced attacks. Do the basics right and you're ahead of 80% of the internet.

In the next post, I'll cover automated backups with restic and off-site storage to an S3-compatible bucket. Stay tuned.