Complete Ubuntu Production Server Setup Guide 2025

Master the art of setting up a secure, production-ready Ubuntu server from scratch. This comprehensive guide covers everything from basic security configuration to advanced hardening techniques, SSL certificates, Nginx setup, and ongoing maintenance.

Est. Time: 2 hours
Skill Level: Beginner to Intermediate
Ubuntu 20.04/22.04 LTS
Updated: June 2025

Prerequisites and Requirements

Before beginning this Ubuntu server setup tutorial, ensure you have the following requirements met:

  • Fresh Ubuntu Server: Ubuntu 20.04 LTS or 22.04 LTS (recommended for production)
  • Server Access: Root or sudo administrative privileges
  • Domain Name: A domain pointing to your server's public IP address
  • SSH Access: Secure shell access to your server
  • Basic Linux Knowledge: Familiarity with command line operations
Important: This guide is designed for production environments. Always test configurations in a development environment first.

Phase 1: Initial Server Security Setup

Step 1: Update System Packages

Start by updating your Ubuntu server to ensure all packages are current and security patches are applied:

# Update package lists and upgrade system
sudo apt update && sudo apt upgrade -y

# Install essential security packages
sudo apt install -y curl wget vim ufw fail2ban unattended-upgrades

Step 2: Create Non-Root User Account

Creating a dedicated user account instead of using root enhances server security:

# Create new user (replace 'yourusername' with your desired username)
sudo adduser yourusername

# Add user to sudo group for administrative privileges
sudo usermod -aG sudo yourusername

# Test sudo access
su - yourusername
sudo whoami  # Should return 'root'

Step 3: Configure SSH Security

Secure your SSH configuration to prevent unauthorized access:

# Backup original SSH configuration
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

# Edit SSH configuration file
sudo vim /etc/ssh/sshd_config

Critical SSH Security Configuration:

Port 2222
PermitRootLogin no
AllowUsers yourusername
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
MaxSessions 2
LoginGraceTime 60
X11Forwarding no

Step 4: Setup SSH Key Authentication

Implement key-based authentication for enhanced security:

# Generate SSH key pair on your local machine
ssh-keygen -t rsa -b 4096 -C "your-email@example.com"

# Copy public key to server
ssh-copy-id -p 2222 yourusername@your-server-ip

# Or manually create and configure:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
vim ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Step 5: Test SSH Configuration

Verify your SSH configuration before applying changes:

# Test SSH configuration syntax
sudo sshd -t

# Restart SSH service to apply changes
sudo systemctl restart sshd
Warning: Always test SSH configuration in a separate terminal session before closing your current connection to avoid lockout.

Phase 2: Firewall Configuration (UFW)

Step 6: Configure UFW Firewall

Set up Ubuntu's Uncomplicated Firewall (UFW) to control network traffic:

# Allow SSH first (use your custom port)
sudo ufw allow 2222/tcp

# Allow HTTP and HTTPS traffic
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Set default firewall policies
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Enable UFW firewall
sudo ufw enable

# Check firewall status and rules
sudo ufw status verbose

Expected UFW Status Output:

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
2222/tcp                   ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere

Phase 3: Install and Configure Nginx

Step 7: Install Nginx Web Server

Install and configure Nginx for serving web content:

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

Step 8: Configure Nginx Basic Security

Add security headers to your Nginx configuration:

sudo vim /etc/nginx/nginx.conf

Add these security headers to the http block:

server_tokens off;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;

Step 9: Create Initial Server Block

Configure a server block for your domain:

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

Basic server block configuration:

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    root /var/www/yourdomain.com;
    index index.html index.htm index.nginx-debian.html;
    location / {
        try_files $uri $uri/ =404;
    }
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
}

Create test HTML content:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Server Setup Complete</title>
</head>
<body>
    <h1>Your Ubuntu Server is Working!</h1>
    <p>Secure server setup in progress...</p>
</body>
</html>

Create web directory and enable site:

sudo mkdir -p /var/www/yourdomain.com
sudo vim /var/www/serversetup.pages.dev/index.html
sudo chown -R www-data:www-data /var/www/yourdomain.com
sudo chmod -R 755 /var/www/yourdomain.com
sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

Phase 4: SSL Certificate Setup with Let's Encrypt

Step 10: Install Certbot for SSL Certificates

Install Certbot to obtain free SSL certificates from Let's Encrypt:

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

Step 11: Verify SSL Configuration

Test SSL certificate installation and auto-renewal:

sudo certbot renew --dry-run
sudo certbot certificates
sudo nginx -t
sudo systemctl reload nginx
SSL Best Practice: Let's Encrypt certificates auto-renew every 90 days. The renewal process is automatically configured during installation.

Phase 5: Advanced Security Hardening

Step 12: Configure Fail2Ban Intrusion Prevention

Set up Fail2Ban to protect against brute force attacks:

sudo vim /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3

[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600

[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600

[nginx-req-limit]
enabled = true
filter = nginx-req-limit
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 10
findtime = 600
bantime = 3600
sudo systemctl restart fail2ban
sudo systemctl enable fail2ban
sudo fail2ban-client status

Step 13: Configure Automatic Security Updates

Enable automatic security updates to keep your server secure:

sudo vim /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}-security";
    "${distro_id}ESMApps:${distro_codename}-apps-security";
    "${distro_id}ESM:${distro_codename}-infra-security";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
sudo vim /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

Step 14: Setup Log Monitoring with Logwatch

Configure log monitoring for security awareness:

sudo apt install -y logwatch
sudo vim /etc/cron.daily/00logwatch
#!/bin/bash
/usr/sbin/logwatch --output mail --mailto your-email@example.com --detail high
sudo chmod +x /etc/cron.daily/00logwatch

Phase 6: System Verification and Testing

Step 15: Security Verification Checklist

Run comprehensive tests to verify your server configuration:

ssh -p 2222 yourusername@your-server-ip
sudo ufw status verbose
sudo systemctl status nginx
sudo nginx -t
curl -I https://yourdomain.com
curl -L http://yourdomain.com
curl -I https://yourdomain.com
sudo fail2ban-client status sshd
sudo systemctl status nginx ssh fail2ban ufw

Step 16: Create Server Status Monitoring Script

Create a comprehensive server monitoring script:

vim ~/server-status.sh
#!/bin/bash
echo "=== Ubuntu Server Status Check ==="
echo "Date: $(date)"
echo ""
echo "=== System Information ==="
uptime
echo ""
echo "=== Disk Usage ==="
df -h /
echo ""
echo "=== Memory Usage ==="
free -h
echo ""
echo "=== Active Services Status ==="
systemctl is-active nginx ssh fail2ban ufw
echo ""
echo "=== Firewall Status ==="
sudo ufw status
echo ""
echo "=== SSL Certificate Status ==="
sudo certbot certificates
echo ""
echo "=== Recent Failed Login Attempts ==="
sudo tail -10 /var/log/auth.log | grep "Failed password"
echo ""
echo "=== Fail2Ban Status ==="
sudo fail2ban-client status
chmod +x ~/server-status.sh

Phase 7: Backup and Maintenance Setup

Step 17: Setup Configuration Backups

Create automated backups of critical configuration files:

sudo mkdir -p /root/config-backups
sudo vim /root/backup-configs.sh
#!/bin/bash
BACKUP_DIR="/root/config-backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR/$DATE"

# Backup critical configuration files
cp /etc/nginx/sites-available/* "$BACKUP_DIR/$DATE/"
cp /etc/ssh/sshd_config "$BACKUP_DIR/$DATE/"
cp /etc/ufw/user.rules "$BACKUP_DIR/$DATE/"
cp /etc/fail2ban/jail.local "$BACKUP_DIR/$DATE/"
cp /etc/apt/apt.conf.d/50unattended-upgrades "$BACKUP_DIR/$DATE/"

# Create backup summary
echo "Configuration backup completed: $BACKUP_DIR/$DATE" > "$BACKUP_DIR/$DATE/backup-info.txt"
echo "Backup created on: $(date)" >> "$BACKUP_DIR/$DATE/backup-info.txt"
echo "Server: $(hostname)" >> "$BACKUP_DIR/$DATE/backup-info.txt"

echo "Configuration backup completed: $BACKUP_DIR/$DATE"
sudo chmod +x /root/backup-configs.sh
sudo /root/backup-configs.sh

# Schedule weekly backups
sudo crontab -e
# Add this line: 0 2 * * 0 /root/backup-configs.sh

Step 18: Setup System Maintenance Tasks

Configure regular maintenance tasks:

sudo vim /root/maintenance.sh
#!/bin/bash
echo "=== System Maintenance Started: $(date) ==="

# Clean package cache
apt autoremove -y
apt autoclean

# Update package database
apt update

# Check for available updates
apt list --upgradable

# Clean log files older than 30 days
find /var/log -name "*.log" -mtime +30 -delete

# Check disk space
df -h

echo "=== System Maintenance Completed: $(date) ==="
sudo chmod +x /root/maintenance.sh

Emergency Access and Recovery

Important Server Configuration Summary

  • SSH Port: 2222 (or your customized port)
  • SSH User: yourusername (non-root account)
  • Firewall: UFW enabled with SSH (2222), HTTP (80), HTTPS (443)
  • SSL Certificates: Let's Encrypt with auto-renewal
  • Intrusion Prevention: Fail2Ban configured for SSH and Nginx
  • Web Server: Nginx with security headers
  • Updates: Automatic security updates enabled

Emergency Recovery Procedures

If you get locked out of your server, follow these steps:

  1. Console Access: Use your hosting provider's console/VNC access
  2. Reset Firewall: sudo ufw --force reset && sudo ufw allow ssh
  3. Restart SSH: sudo systemctl restart sshd
  4. Check SSH Config: sudo sshd -t
  5. Check Fail2Ban: sudo fail2ban-client unban --all
  6. Restore Backup: Use your configuration backups if needed
Emergency Contacts: Keep your hosting provider's support contact information readily available. Document your server access credentials securely.

Common Troubleshooting Commands

# Check service status
sudo systemctl status nginx ssh fail2ban ufw

# View recent logs
sudo journalctl -u nginx -n 50
sudo journalctl -u ssh -n 50
sudo tail -50 /var/log/auth.log

# Test configurations
sudo nginx -t
sudo sshd -t

# Check network connectivity
ss -tulpn | grep :80
ss -tulpn | grep :443
ss -tulpn | grep :2222