Tutorial

Initial VPS Setup: The First 10 Minutes on a New Ubuntu Server

March 18, 2026

Back to Blog

You just purchased a shiny new VPS from DigitalOcean, Hetzner, Vultr, or any cloud provider. Your terminal is staring back at you with a blinking cursor. The next ten minutes are the most critical — they determine whether your server becomes a hardened fortress or an open door for attackers.

Every day, automated bots scan millions of IP addresses looking for freshly provisioned servers with default configurations. Within minutes of your VPS going live, SSH brute-force attempts begin. This guide walks you through the essential first steps to lock down your Ubuntu server, step by step, command by command.

The Clock Is Ticking
According to security research, a new public-facing server receives its first automated attack within 30 seconds to 5 minutes of going online. Do not leave your server in its default state.

Step 1: Log In via SSH for the First Time

Your hosting provider gave you an IP address and root credentials (either a password or an SSH key). Open your terminal and connect:

$ ssh [email protected]
The authenticity of host '203.0.113.50' can't be established.
ED25519 key fingerprint is SHA256:xR4j...
Are you sure you want to continue connecting (yes/no)? yes
[email protected]'s password: ********
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-51-generic x86_64)
root@vps:~#

You are now logged in as root. This is both powerful and dangerous — every command you run has unlimited access to the system. Our first priority is to reduce our exposure by creating a dedicated user account.

Step 2: Change the Root Password

Many providers send the root password in plain text via email. Change it immediately to something strong and unique:

root@vps:~# passwd
New password: ********
Retype new password: ********
passwd: password updated successfully
Password Best Practices
Use a password manager to generate a random 20+ character password. You will rarely need to type this — SSH keys are your primary authentication method.

Step 3: Create a New Sudo User

Running everything as root is a recipe for disaster. A mistyped destructive command could wipe your entire system. Create a regular user with sudo privileges instead:

root@vps:~# adduser deploy
Adding user 'deploy' ...
Adding new group 'deploy' (1001) ...
Adding new user 'deploy' (1001) with group 'deploy' ...
Creating home directory '/home/deploy' ...
New password: ********
Full Name []: Deploy User

root@vps:~# usermod -aG sudo deploy
# No output = success

root@vps:~# id deploy
uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),27(sudo)

Now verify that your new user can actually use sudo. Open a new terminal tab (keep your root session open as a backup) and test:

$ ssh [email protected]
[email protected]'s password: ********
deploy@vps:~$ sudo whoami
[sudo] password for deploy: ********
root
Checkpoint
Your new user has full sudo access. From this point forward, use deploy for daily operations and only switch to root when absolutely necessary.

Step 4: Set Up SSH Key Authentication

Passwords are vulnerable to brute-force attacks. SSH keys are cryptographically secure and effectively impossible to guess. On your local machine (not the server), generate an SSH key pair:

local$ ssh-keygen -t ed25519 -C "deploy@myserver"
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/you/.ssh/id_ed25519): [Enter]
Enter passphrase (empty for no passphrase): ********
Your identification has been saved in /home/you/.ssh/id_ed25519
Your public key has been saved in /home/you/.ssh/id_ed25519.pub

local$ ssh-copy-id [email protected]
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s)
Number of key(s) added: 1

Test that key-based login works before changing any SSH configuration:

local$ ssh [email protected]
Enter passphrase for key '/home/you/.ssh/id_ed25519': ********
deploy@vps:~$ # No password prompt means key auth is working!

Step 5: Disable Password Authentication

Now that SSH keys work, disable password login entirely. This is the single most impactful security change you can make:

deploy@vps:~$ sudo nano /etc/ssh/sshd_config

# Find and change these lines:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2

deploy@vps:~$ sudo systemctl restart sshd
Do Not Lock Yourself Out!
Before restarting SSH, open a second terminal and verify you can still log in with your SSH key. If you lose access, you will need to use your provider's console access to fix the configuration.

Step 6: Configure UFW Firewall

A firewall is your server's front door. By default, Ubuntu does not enable UFW (Uncomplicated Firewall), leaving all ports open. Let us fix that:

deploy@vps:~$ sudo ufw default deny incoming
Default incoming policy changed to 'deny'

deploy@vps:~$ sudo ufw default allow outgoing
Default outgoing policy changed to 'allow'

deploy@vps:~$ sudo ufw allow 22/tcp comment 'SSH'
Rule added

deploy@vps:~$ sudo ufw allow 80/tcp comment 'HTTP'
Rule added

deploy@vps:~$ sudo ufw allow 443/tcp comment 'HTTPS'
Rule added

deploy@vps:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed (y|n)? y
Firewall is active and enabled on system startup

deploy@vps:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)

To Action From
-- ------ ----
22/tcp ALLOW IN Anywhere # SSH
80/tcp ALLOW IN Anywhere # HTTP
443/tcp ALLOW IN Anywhere # HTTPS

Here is what each rule does and why it matters:

PortProtocolPurposeWhy Open
22TCPSSHRemote server access
80TCPHTTPWeb traffic + Let's Encrypt validation
443TCPHTTPSEncrypted web traffic
Custom SSH Port?
If you change your SSH port (e.g., to 2222), make sure to sudo ufw allow 2222/tcp before enabling UFW, or you will lock yourself out immediately.

Step 7: Enable Automatic Security Updates

Unpatched vulnerabilities are one of the top attack vectors. Ubuntu's unattended-upgrades package automatically installs security patches:

deploy@vps:~$ sudo apt update && sudo apt install -y unattended-upgrades
Reading package lists... Done
unattended-upgrades is already the newest version (2.9.1+nmu4ubuntu1).

deploy@vps:~$ sudo dpkg-reconfigure -plow unattended-upgrades
# Select "Yes" to enable automatic updates

deploy@vps:~$ cat /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

For additional control, you can configure what gets updated by editing /etc/apt/apt.conf.d/50unattended-upgrades. The default settings update security packages only, which is the safest option for production servers.

Step 8: Set Timezone and Hostname

Correct time is essential for log analysis, SSL certificates, cron jobs, and debugging. Set your timezone and a meaningful hostname:

deploy@vps:~$ sudo timedatectl set-timezone UTC

deploy@vps:~$ timedatectl
Local time: Mon 2026-03-17 10:30:00 UTC
Universal time: Mon 2026-03-17 10:30:00 UTC
RTC time: Mon 2026-03-17 10:30:00
Time zone: UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active

deploy@vps:~$ sudo hostnamectl set-hostname web1.example.com
deploy@vps:~$ hostname
web1.example.com
Why UTC?
Using UTC on servers eliminates daylight saving time confusion, makes log correlation across multiple servers easier, and is the industry standard for production environments. Your application can convert to local time for users.

Step 9: Create a Swap File

Many VPS instances come with limited RAM and no swap. If your server runs out of memory, the kernel's OOM killer will terminate processes randomly — often killing your database or web server. A swap file provides breathing room:

deploy@vps:~$ sudo fallocate -l 2G /swapfile
deploy@vps:~$ sudo chmod 600 /swapfile
deploy@vps:~$ sudo mkswap /swapfile
Setting up swapspace version 1, size = 2 GiB
deploy@vps:~$ sudo swapon /swapfile

# Make it permanent
deploy@vps:~$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# Optimize swap behavior
deploy@vps:~$ sudo sysctl vm.swappiness=10
deploy@vps:~$ echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf

deploy@vps:~$ free -h
total used free shared buff/cache available
Mem: 1.9Gi 312Mi 1.2Gi 1.0Mi 420Mi 1.4Gi
Swap: 2.0Gi 0B 2.0Gi

The recommended swap size depends on your RAM:

Server RAMRecommended SwapUse Case
1 GB2 GBBudget VPS, WordPress
2 GB2 GBSmall apps, static sites
4 GB2-4 GBMedium web apps
8+ GB2-4 GBSafety net only

Step 10: Install Essential Tools

Install the utilities you will need for day-to-day server management:

deploy@vps:~$ sudo apt update && sudo apt install -y \
curl wget git htop iotop ncdu tree \
fail2ban logwatch net-tools \
build-essential software-properties-common
Reading package lists... Done
Setting up fail2ban (1.1.0-1) ...
Setting up logwatch (7.9-1) ...

Here is what each package provides:

Monitoring

  • htop — interactive process viewer
  • iotop — disk I/O monitor
  • ncdu — disk usage analyzer

Security

  • fail2ban — bans IPs after failed logins
  • logwatch — daily log summary emails
  • ufw — already installed above

Utilities

  • curl / wget — HTTP requests and downloads
  • git — version control
  • tree — directory visualization

Development

  • build-essential — gcc, make, etc.
  • software-properties-common — PPA management
  • net-tools — ifconfig, netstat

Quick Setup for Fail2Ban

Fail2Ban monitors log files for suspicious activity and automatically bans offending IP addresses. The default configuration protects SSH:

deploy@vps:~$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
deploy@vps:~$ sudo nano /etc/fail2ban/jail.local

# Add under [DEFAULT]:
bantime = 3600
findtime = 600
maxretry = 3

deploy@vps:~$ sudo systemctl enable --now fail2ban
Created symlink ... fail2ban.service.

deploy@vps:~$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:

The Complete 10-Minute Checklist

Here is every step in order with approximate time estimates:

SSH Login
30s
Root Password
30s
Sudo User
1m
SSH Keys
2m
Disable Passwords
1m
UFW Firewall
1m
Auto Updates
1m
Timezone
30s
Swap
1m
Tools
2m
10
Steps to Complete
~10m
Total Time Required
3
Ports Left Open
0
Password Auth Remaining

Bonus: Quick Security Audit After Setup

Once everything is configured, run this quick audit to verify your setup:

# Check SSH configuration
deploy@vps:~$ sudo sshd -T | grep -E 'passwordauth|permitroot|pubkey'
passwordauthentication no
permitrootlogin prohibit-password
pubkeyauthentication yes

# Check firewall status
deploy@vps:~$ sudo ufw status numbered
Status: active
To Action From
[ 1] 22/tcp ALLOW IN Anywhere
[ 2] 80/tcp ALLOW IN Anywhere
[ 3] 443/tcp ALLOW IN Anywhere

# Check for listening services
deploy@vps:~$ sudo ss -tulnp
Netid State Recv-Q Send-Q Local Address:Port Process
tcp LISTEN 0 128 0.0.0.0:22 sshd

# Check swap
deploy@vps:~$ swapon --show
NAME TYPE SIZE USED PRIO
/swapfile file 2G 0B -2

# Check automatic updates
deploy@vps:~$ systemctl is-enabled unattended-upgrades
enabled

What About Changing the SSH Port?

Many guides recommend changing the default SSH port from 22 to something like 2222 or 2847. This is "security through obscurity" — it reduces log noise from automated bots but does not stop a determined attacker. Here is a balanced view:

ApproachProsConsVerdict
Keep port 22Simple, standard, no firewall confusionMore bot traffic in logsFine with keys + fail2ban
Change to custom portReduces 99% of automated scansMust remember the port, update scriptsNice to have

If you do change the port, update both UFW and your SSH config:

deploy@vps:~$ sudo ufw allow 2847/tcp comment 'SSH custom'
deploy@vps:~$ sudo sed -i 's/^#Port 22/Port 2847/' /etc/ssh/sshd_config
deploy@vps:~$ sudo systemctl restart sshd
deploy@vps:~$ sudo ufw delete allow 22/tcp
# Test with: ssh -p 2847 [email protected]

Next Steps After the First 10 Minutes

Your server is now reasonably secure for a fresh installation. Depending on your use case, your next steps will be:

For Web Hosting

  • Install Nginx or Apache
  • Install PHP and configure PHP-FPM
  • Install MySQL or PostgreSQL
  • Set up Let's Encrypt SSL
  • Configure virtual hosts

For Application Deployment

  • Install Docker and Docker Compose
  • Set up a reverse proxy
  • Configure CI/CD pipelines
  • Set up monitoring
  • Configure log aggregation

Or Skip Everything: Install Panelica

Everything in this guide — and much, much more — is automated by Panelica. Instead of spending 10 minutes on basic setup (and hours on the follow-up configuration), you can have a production-ready server in about 3 minutes:

root@vps:~# curl -sSL https://get.panelica.com | bash
____ _ _
| _ \ __ _ _ __ ___| (_) ___ __ _
| |_) / _` | '_ \ / _ \ | |/ __/ _` |
| __/ (_| | | | | __/ | | (_| (_| |
|_| \__,_|_| |_|\___|_|_|\___\__,_|

Installing Panelica Server Management Panel...
[1/20] Configuring system...
[2/20] Setting up PostgreSQL 17...
[3/20] Setting up MySQL 8...
...
[20/20] Starting all services...

Panelica installed successfully!
Panel URL: https://203.0.113.50:8443
Username: root
Password: [generated-password]

With Panelica installed, you get out of the box:

20 Managed Services

  • Nginx + Apache (dual-stack)
  • PHP 8.1 through 8.4 with per-user FPM pools
  • MySQL 8 + PostgreSQL 17
  • Redis 7 for caching
  • BIND DNS server
  • Postfix + Dovecot email

5-Layer Security

  • Cgroups v2 resource isolation
  • Namespace isolation (PID + Mount)
  • SSH chroot jails
  • Per-user PHP-FPM with open_basedir
  • Unix permission enforcement (home 700)

Automation

  • Automatic SSL with Let's Encrypt
  • 9-step domain provisioning
  • Backup and restore
  • Fail2Ban + ModSecurity WAF

Management

  • Web-based file manager
  • Multi-user RBAC (Root/Admin/Reseller/User)
  • Docker container management
  • Cloudflare DNS integration
Save Hours, Not Minutes
The initial VPS setup described in this guide is just the beginning. Installing, configuring, and maintaining Nginx, PHP, databases, email, DNS, backups, and security normally takes hours of manual work and ongoing maintenance. Panelica handles all of it through a modern web interface with one-click management.
Share: