Complete Server Setup: The Ultimate Reference Guide

From first boot to complete production environment. OS, users, firewall, Nginx, PHP, MySQL, SSL, monitoring — everything in one guide.
From Empty Server to Full Production Environment
This guide takes you from a brand new Linux server to a secured production environment ready to serve traffic. Every step is explained with actual commands. The guide assumes you are using Ubuntu 24.04 LTS on a VPS.
Expected execution time: 45-60 minutes for those with basic experience, and 2-3 hours for beginners.
Phase 1: Securing Access
Update the System Immediately
The first command you run on any new server:
apt update && apt upgrade -y
Create a Non-Root User
Never work directly with root privileges. Create a regular user:
adduser deploy
usermod -aG sudo deploy
Set Up SSH Keys
On your local machine, generate a key if one does not exist:
ssh-keygen -t ed25519 -C "your-email@example.com"
Copy the key to the server:
ssh-copy-id deploy@server-ip
Disable Password Login
Edit /etc/ssh/sshd_config:
PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
Restart SSH:
sudo systemctl restart sshd
Warning: Confirm your SSH key works before disabling password authentication. Otherwise you will lock yourself out of the server.
Phase 2: Firewall
Configure UFW
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Verify
sudo ufw status verbose
You should see only ports 22, 80, and 443 open. Any other port you need (such as 3306 for MySQL) should not be exposed publicly but kept local only.
Phase 3: Installing Core Software
Nginx
sudo apt install nginx -y
sudo systemctl enable nginx
PHP 8.4 (For Laravel Applications)
sudo add-apt-repository ppa:ondrej/php -y
sudo apt install php8.4-fpm php8.4-mysql php8.4-mbstring php8.4-xml php8.4-curl php8.4-zip php8.4-gd php8.4-intl php8.4-redis -y
MySQL 8
sudo apt install mysql-server -y
sudo mysql_secure_installation
Answer "yes" to all security questions: remove anonymous users, disable remote root login, remove test database.
Node.js 22 LTS (If Needed)
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install nodejs -y
Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
Phase 4: Site Configuration
Directory Structure
sudo mkdir -p /var/www/myapp
sudo chown deploy:www-data /var/www/myapp
sudo chmod 750 /var/www/myapp
Nginx Configuration
Create a config file at /etc/nginx/sites-available/myapp:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/myapp/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
}
Enable the site:
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Phase 5: Free SSL
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com
Certbot automatically modifies the Nginx configuration and adds automatic renewal. Free Let's Encrypt certificates are available on all CLOUD servers (cloud.net.sa).
Phase 6: Backups
Daily Database Backup
Create a script at /usr/local/bin/backup-db.sh:
#!/bin/bash
DATE=$(date +%Y-%m-%d)
mysqldump -u root --all-databases | gzip > /backups/db-$DATE.gz
find /backups -name "db-*.gz" -mtime +30 -delete
Make it executable and schedule it:
chmod +x /usr/local/bin/backup-db.sh
echo "0 2 * * * root /usr/local/bin/backup-db.sh" >> /etc/crontab
File Backups
Use rsync to copy application files to an external location or storage service.
Phase 7: Monitoring
Basic Monitoring at Minimal Cost
- htop:
sudo apt install htop -y— real-time resource monitoring - ncdu:
sudo apt install ncdu -y— disk usage analysis - fail2ban:
sudo apt install fail2ban -y— protection against brute-force attacks
Configure Fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Edit /etc/fail2ban/jail.local and ensure:
[sshd]
enabled = true
maxretry = 3
bantime = 3600
Phase 8: Automatic Security Updates
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades
This ensures security updates are installed automatically without your intervention.
Post-Setup Checklist
| Item | Status |
|---|---|
| System update | Required |
| Non-root user | Required |
| SSH keys only (no password) | Required |
| UFW firewall | Required |
| Nginx + PHP + MySQL | As needed |
| SSL certificate | Required |
| Daily backup | Required |
| Fail2ban | Required |
| Automatic security updates | Required |
| Resource monitoring | Recommended |
This guide covers 90% of what you need to set up a secure production server. On CLOUD servers (cloud.net.sa), you can start with the Growth plan (2 vCPU, 4GB RAM, competitive pricing — pricing and plans) and execute these steps within one hour. Activation is instant after payment, with very low latency from Riyadh.
A properly configured server from the start saves you hours of troubleshooting later. Invest the time now in correct setup.
Get Started
Want to try it yourself? Choose the right hosting plan or build your custom server with the specs you need.
