Switch Language
Toggle Theme

Ubuntu Server Initialization: User Management, SSH Hardening, and fail2ban Security Setup

Introduction

At 3 AM, I stared at the “Permission denied” error in my terminal, cold sweat running down my back.

I was locked out of my server. All because I casually changed an SSH configuration without leaving myself a backup plan.

That was three years ago when I bought my first VPS. Looking back now, my approach was a textbook example of what NOT to do: logging in directly as root, setting my birthday as the password, using the default SSH port 22, and firewall? Never heard of it. The result? My server got hammered within two weeks, with brute force attack traces all over the logs.

Let’s be honest—many beginners’ first instinct after buying a VPS is to start installing software and deploying projects immediately. User management? SSH hardening? Too much hassle, let’s deal with that later. But those “later” tasks are exactly what determine how long your server survives.

This article does one thing: walk you through configuring a fresh Ubuntu server (22.04 or 24.04) from scratch into a secure, production-ready state. User permissions, SSH hardening, fail2ban auto-banning—we’ll cover everything. At each step, I’ll explain why we’re doing it, not just give you a pile of commands to copy-paste.

About 10 minutes to complete this entire flow. After that, your server’s security level will exceed 80% of the exposed machines on the internet.

1. Pre-Initialization Preparation

Before we start, let’s get our tools ready. You’ll need to generate an SSH key pair locally.

Why keys instead of passwords? Simply put, passwords can be brute-forced; keys essentially cannot. A 256-bit Ed25519 key would take longer to crack than the age of the universe.

Key Generation

These days, I recommend Ed25519 over the older RSA—it’s more secure and produces shorter keys. The generation command is straightforward:

# macOS / Linux
ssh-keygen -t ed25519 -C "your_email@example.com"

# Windows (PowerShell, requires OpenSSH client)
ssh-keygen -t ed25519 -C "your_email@example.com"

After running it, you’ll be asked where to store the key and whether to set a passphrase. Press Enter to use the default path. Whether to add a passphrase is up to you—it’s more secure if you do, but you’ll need to enter it every time you connect.

After generation, you’ll have two files locally:

  • ~/.ssh/id_ed25519 — Private key, NEVER share this
  • ~/.ssh/id_ed25519.pub — Public key, this will be uploaded to the server

For terminal tools, macOS’s built-in Terminal works fine. Windows users might prefer Windows Terminal or MobaXterm. Not the focus here, so I won’t elaborate.

2. User and Permission Management

First, log into your server as root (this is the last time you’ll log in directly as root—we’ll disable it afterward):

ssh root@your_server_ip

Why Not Use root?

In short: the consequences are too severe.

Root has too much power—delete one wrong file, change one wrong configuration, and your entire system is toast. Worse, many attack scripts specifically target the root account for brute force attacks. Exposing root in SSH login is like handing hackers a giant target.

Use a regular account for daily operations, and sudo when you need elevated privileges. This is a fundamental Linux security principle.

Create a Deployment User

I like to use the name deploy, meaning “for deployment purposes.” You can use any name you prefer:

# Create user (will prompt for password and some info)
adduser deploy

# Grant sudo privileges
usermod -aG sudo deploy

Ubuntu will ask you to set a password and fill in user information. Set a memorable password; for the other fields, just press Enter to skip.

Upload Public Key to New User

Now upload your local public key to this new account. Run this on your local machine:

# macOS / Linux
ssh-copy-id deploy@your_server_ip

# Windows (PowerShell)
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh deploy@your_server_ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Then test if you can log in as deploy:

ssh deploy@your_server_ip

Logged in successfully? Great. From now on, operate as deploy—don’t switch back to root. Need root privileges? Just add sudo.

Multi-User Scenario

If your server needs to be shared by a team, you can create separate accounts for each person. For example:

# Create account for colleague John
adduser john
usermod -aG sudo john

# Have them upload their public key (they run this locally)
ssh-copy-id john@your_server_ip

Everyone uses their own account—operation logs are traceable, and it’s easier to troubleshoot when issues arise.

3. SSH Security Hardening

This is the most critical part of initialization, and also where “locking yourself out” disasters most commonly occur.

Warning: Before changing SSH configuration, always keep your current connection open while testing in a separate terminal window. This way, if something goes wrong, you can fix it from the other window.

Edit SSH Configuration File

sudo nano /etc/ssh/sshd_config

Line-by-Line Explanation of Core Parameters

1. Port

Port 22    # Default value, should be changed

Port 22 is the primary target for internet-wide scans. Changing to a high port (like 22222 or 54321) avoids most indiscriminate scanning.

Port 54321

Note: If you’re using a cloud provider (Alibaba Cloud, Tencent Cloud, AWS, etc.), remember to open the new port in your security group/firewall after changing, or you won’t be able to connect.

2. PermitRootLogin

PermitRootLogin no    # Must change

Why? I mentioned it earlier—root is hackers’ number one target. Disable it, and your attack surface shrinks significantly.

3. PasswordAuthentication

PasswordAuthentication no    # Key-based login only

This is critical for preventing brute force attacks. As long as your private key doesn’t leak, even if someone knows the password, they can’t get in.

4. Other Security Parameters

MaxAuthTries 3              # Maximum 3 password attempts
ClientAliveInterval 300     # Disconnect after 5 minutes of inactivity
ClientAliveCountMax 2       # Maximum 2 unresponsive checks

These parameters prevent idle connections from hogging resources and limit brute force attempts.

Three-Step Configuration Verification

Don’t rush to restart after changing configuration—verify first:

Step 1: Test Configuration Syntax

sudo sshd -t

No output is good news—syntax is fine.

Step 2: Test Connection in New Window

Keep your current window open. Open another terminal window and connect with the new port and deploy account:

ssh -p 54321 deploy@your_server_ip

Can connect? Configuration is working, and you haven’t locked yourself out.

Step 3: Restart Service After Confirmation

sudo systemctl restart sshd
# or
sudo systemctl restart ssh

After restarting, test once more in a new window. Confirm you can log in normally—only then is this step truly complete.

Pro Tip

If you find yourself locked out after changing configuration, don’t panic. Go to your cloud provider’s console, use VNC login, revert the configuration, and restart the service. That’s why I keep emphasizing—maintain one connection before changing SSH configuration.

4. fail2ban Auto-Banning

The SSH configuration we discussed mainly prevents brute force attacks. But what if someone keeps trying passwords relentlessly? That’s where fail2ban comes in.

What is fail2ban? A tool that automatically monitors logs and bans suspicious IPs. Someone fails password attempts a few times in a row? Automatically banned for a period. Simple, brutal, and effective.

Installation and Startup

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

Configure SSH Jail

fail2ban uses the concept of “jails” to manage monitoring rules for different services. SSH has a default sshd jail.

Create a local configuration file (don’t modify the default configuration directly—upgrades will overwrite it):

sudo nano /etc/fail2ban/jail.local

Add the following content:

[sshd]
enabled = true
port = 54321          # Change to your SSH port
maxretry = 3          # Ban after 3 failures
findtime = 600        # Within 10 minutes
bantime = 3600        # Ban for 1 hour

Parameter Explanation:

  • maxretry: Maximum allowed failures. Default is 5; I changed it to 3 for stricter security.
  • findtime: Time window in seconds. 600 seconds = within 10 minutes, 3 failures trigger action.
  • bantime: Ban duration in seconds. 3600 = 1 hour. You can set it to 86400 (one day) or longer.

Restart the service after changes:

sudo systemctl restart fail2ban

Check Ban Status

# Check all jail statuses
sudo fail2ban-client status

# Check sshd jail details
sudo fail2ban-client status sshd

You’ll see a list of currently banned IPs.

Unban IP

If you accidentally ban yourself (e.g., entering wrong password too many times during debugging), unban like this:

sudo fail2ban-client set sshd unbanip your_ip

Advanced: Custom Rules

fail2ban can protect more than just SSH—it can also protect Nginx, Apache, MySQL, and other services. Configuration is similar: create corresponding jails. This topic runs deep, so I’ll just mention it here.

5. Version Differences Quick Reference

Ubuntu 22.04 and 24.04 have largely identical initialization processes, but some details differ.

Core Differences Comparison

ItemUbuntu 22.04 LTSUbuntu 24.04 LTS
Kernel Version5.156.8
OpenSSH Version8.99.6
Default Python3.103.12
systemd Version249255
Support CycleUntil April 2027Until April 2029

Practical Impact

Good news: The initialization process in this article works identically on both versions. SSH configuration paths, fail2ban installation methods, and user management commands haven’t changed.

Points to note:

  1. OpenSSH 9.x (24.04) has stricter default configurations, with some older encryption algorithms disabled. If you’re using an older SSH client to connect to 24.04, you might encounter issues—just upgrade the client.

  2. Cloud provider images: Some cloud providers’ 22.04 images come pre-installed with monitoring or management scripts that might conflict with your configuration. I recommend using official clean images or checking existing services before initialization.

  3. Upgrade issues: If you have a running 22.04 server, make a snapshot before upgrading to 24.04. While do-release-upgrade succeeds most of the time, it’s better to be safe with security configurations.

Which to Choose?

  • New projects: Go with 24.04. Longer support cycle, newer software versions.
  • Legacy projects: If you depend on specific versions (like Python 3.10), use 22.04.
  • Stability priority: 22.04 is mature; most pitfalls have been discovered.
  • Trying new things: 24.04 has new features like better hardware support and performance optimizations.

Summary

After all that, let’s review the core points of this initialization process:

Security Trio:

  • Create regular user, disable root login
  • Change SSH port, disable password login, allow key-based only
  • fail2ban auto-bans suspicious IPs

Operational Principles:

  • Keep one connection open before changing configurations
  • Verify each step, don’t rush to restart
  • Private key must NEVER leak

Verification Checklist:

  • Can SSH login with deploy account through new port
  • root account cannot login
  • Password login disabled
  • fail2ban service running normally

This configuration is just the first step in server security. Next, you’ll need to configure firewall (UFW), install Docker, deploy applications… topics for another day.

If you run into issues following this tutorial, feel free to leave a comment. That 3 AM lockout disaster three years ago—I genuinely don’t want you to experience it.

Ubuntu Server Initialization Security Configuration

Configure a secure Ubuntu server from scratch, including user management, SSH hardening, and fail2ban banning

⏱️ Estimated time: 10 min

  1. 1

    Step1: Generate SSH Key

    Generate an Ed25519 key pair on your local machine:

    • Command: ssh-keygen -t ed25519 -C "email@example.com"
    • Private key stored in ~/.ssh/id_ed25519 (never share)
    • Public key stored in ~/.ssh/id_ed25519.pub (to be uploaded)
  2. 2

    Step2: Create Regular User

    After logging into the server, create a deployment user:

    • Create user: adduser deploy
    • Grant sudo privileges: usermod -aG sudo deploy
    • Set a memorable password
  3. 3

    Step3: Upload Public Key and Test Login

    Run on your local machine:

    • ssh-copy-id deploy@server_ip
    • Test login: ssh deploy@server_ip
    • Confirm you can login as deploy normally, then use this account for subsequent operations
  4. 4

    Step4: Modify SSH Configuration

    Edit /etc/ssh/sshd_config:

    • Port 54321 (change to high port)
    • PermitRootLogin no (disable root login)
    • PasswordAuthentication no (disable password login)
    • MaxAuthTries 3
    • ClientAliveInterval 300

    Note: Keep one connection open before modifying!
  5. 5

    Step5: Verify and Restart SSH

    Three-step verification:

    • Test syntax: sudo sshd -t
    • Test in new window: ssh -p 54321 deploy@server_ip
    • Restart after confirmation: sudo systemctl restart sshd
  6. 6

    Step6: Install and Configure fail2ban

    Auto-ban brute force IPs:

    • Install: sudo apt install fail2ban -y
    • Configure /etc/fail2ban/jail.local
    • Set maxretry=3, bantime=3600
    • Restart service: sudo systemctl restart fail2ban

FAQ

What SSH port should I use?
I recommend using a high port between 1024-65535, such as 22222 or 54321. Avoid common ports (80, 443, 3306, etc.) to reduce scanning probability. Remember to open the new port in your cloud provider's security group after changing.
What if I can't connect after changing SSH configuration?
Don't panic. Go to your cloud provider's console, use VNC login, revert the configuration, and restart the sshd service. That's why I emphasize keeping one connection open while testing in a new window before changing configuration.
Can fail2ban ban my own IP?
Yes. If you enter wrong passwords too many times, your own IP will be banned. Unban command: sudo fail2ban-client set sshd unbanip your_ip. I recommend adding your IP to the whitelist (ignoreip) during configuration.
What's the difference between Ubuntu 22.04 and 24.04 initialization?
The process in this article works identically on both versions. The main difference is that 24.04 has a higher OpenSSH version (9.6) with stricter default configuration, and some older encryption algorithms are disabled. If you're using an older SSH client, you may need to upgrade.
How much more secure is key-based login compared to password login?
By orders of magnitude. A 256-bit Ed25519 key would take longer to crack than the age of the universe. Password login is vulnerable to dictionary attacks and brute force, especially weak passwords which are essentially defenseless.
Can I change the SSH port back to 22?
Technically yes, but I don't recommend it. Port 22 is the primary target for internet-wide scans. Changing to a high port avoids most automated scanning scripts. Combined with fail2ban and key-based login, it's much more secure.

10 min read · Published on: Mar 27, 2026 · Modified on: Mar 27, 2026

Comments

Sign in with GitHub to leave a comment

Related Posts