Skip to content
Business & cloud

Secure Linux Server Setup Checklist for Your First VPS

A step‑by‑step checklist to configure a secure Linux server for a web app, covering firewall, SSH hardening, updates, monitoring and backups.

Developer configuring a Linux server on a laptop in a modern office
Illustration generated with AI.

Deploying your first VPS often means juggling many security tasks while trying to get the app running. Missing a single hardening step can leave your server exposed to attacks.

The answer is a concise, practical checklist that guides you through firewall rules, SSH hardening, updates, monitoring and backups, so you can launch with confidence.

Choosing the right Linux distribution for a web app

Long‑term support matters

When you launch a VPS for a production web application, the operating system is the foundation of every security decision you will make later. Distributions that provide a five‑year LTS (Long‑Term Support) window, such as Ubuntu 20.04 LTS or Ubuntu 22.04 LTS, receive regular kernel patches, security updates, and bug‑fix releases without requiring a major version upgrade. Debian 11 (Bullseye) and Debian 12 (Bookworm) follow the same model, offering stable packages and a predictable update cadence. Selecting an LTS distro means you can rely on a known security baseline for the entire lifespan of your service, reducing the risk of untested package versions breaking your stack.

Official provider images reduce supply‑chain risk

Most VPS providers host a catalog of pre‑built images that are signed and verified against the provider’s own repository. Deploying the official Ubuntu or Debian image directly from the marketplace ensures the filesystem has not been tampered with and that the bootloader matches the provider’s security policies. For example, Vultr’s Marketplace lists “Ubuntu 22.04 LTS – Official” and “Debian 12 – Official” as separate entries; selecting one of these guarantees you start from a clean, vendor‑validated baseline.

Compatibility with Qubitpage tooling

Qubitpage’s remote‑management suite, CarphaCom Remote, is packaged as a set of Debian‑compatible .deb files and Ubuntu‑compatible apt repositories. The installer script assumes the presence of systemd, apt, and the standard directory layout used by these distributions. Using an LTS release therefore eliminates the need for custom patches and lets you run the remote agent with a single command:

curl -sSL https://github.com/qubitpage/carpathron-remote/install.sh | sudo bash

The installer pulls the latest signed package from /software/carpathron-remote and configures the service to start on boot, simplifying ongoing monitoring and log collection.

Performance and ecosystem considerations

Ubuntu LTS includes newer kernel versions (e.g., 5.15 for 22.04) that support recent hardware drivers and container runtimes such as Docker or Podman. Debian’s more conservative kernel (5.10 in Bullseye) may be preferable for legacy environments where maximum stability is required. Both distributions ship with the same core security tools—AppArmor, unattended‑upgrades, and fail2ban—allowing you to apply hardening steps uniformly regardless of the choice.

Decision checklist

  • Prefer Ubuntu 22.04 LTS or Debian 12 for the longest support window.
  • Deploy the official image from your VPS provider’s marketplace.
  • Verify the image checksum or digital signature if the provider supplies one.
  • Confirm that the distribution’s package manager (apt) can access the CarphaCom Remote repository.
  • Document the chosen version in your infrastructure inventory for future audits.

Creating a non‑root user and configuring sudo

Step 1 – Add a dedicated user

After logging in as root, create a new account that will be used for all routine operations. Run:

adduser deployer

The command prompts for a full name, room number, etc.; you can press Enter to skip them. When asked for a password, choose a passphrase of at least 12 characters, mixing upper‑case, lower‑case, numbers and symbols. Example of a strong password generation:

openssl rand -base64 18

Copy the output and paste it as the new password. This ensures the account is protected against brute‑force attacks.

Step 2 – Restrict direct root logins

Open the SSH daemon configuration file and disable password authentication for the root account:

sed -i 's/^PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config

Reload the service to apply the change:

systemctl reload sshd

From now on, any administrative task must be performed through sudo using the non‑root account, which reduces the attack surface.

Step 3 – Grant limited sudo rights

Install the sudo package if it is not already present:

apt-get update && apt-get install -y sudo

Then add the new user to the sudo group:

usermod -aG sudo deployer

To enforce the principle of least privilege, edit the sudoers file with visudo and create a rule that allows only specific commands. For example, to let the user restart services and manage the firewall:

deployer ALL=(ALL) NOPASSWD: /bin/systemctl restart *, /usr/sbin/ufw *

All other commands will still require the user’s password, preserving accountability.

Step 4 – Verify the configuration

Switch to the new account and test a privileged command:

su - deployer
sudo systemctl status sshd

If the command executes without prompting for a password, the NOPASSWD rule is active. Test a disallowed command, such as editing /etc/passwd:

sudo nano /etc/passwd

The system should request the user’s password and then deny the operation if the rule does not include that binary.

Tip: Store the generated password in a password manager and disable password‑based SSH login altogether by adding PasswordAuthentication no to /etc/ssh/sshd_config. This forces key‑based authentication, which is far harder to compromise.

With a dedicated non‑root user and tightly scoped sudo permissions, daily work no longer requires direct root access. This practice aligns with the security standards demonstrated in our QuBIOS deployments and forms the foundation for the remaining hardening steps.

Hardening SSH access

Secure shell (SSH) is the primary entry point for remote administration, so tightening its configuration prevents many automated attacks. Begin by disabling password authentication and forcing key‑based login; this eliminates the risk of credential stuffing against weak or reused passwords.

Next, move the service off the default port 22. Changing the listening port reduces noise from mass scans and gives you a small but effective layer of obscurity. Finally, consider leveraging the optional AI technician in Carpathron Remote to validate admin prompts and enforce policy compliance in real time.

  1. Generate a key pair on your workstation. Run ssh-keygen -t ed25519 -C "admin@yourdomain.com" and accept the default file location. Keep the private key secure; the public key will be copied to the server.
  2. Copy the public key to the new non‑root user. Use ssh-copy-id -i ~/.ssh/id_ed25519.pub newuser@your-vps-ip or manually append the key to /home/newuser/.ssh/authorized_keys with correct permissions (700 for .ssh, 600 for authorized_keys).
  3. Edit /etc/ssh/sshd_config to enforce key‑based login. Set PasswordAuthentication no, PubkeyAuthentication yes, and ChallengeResponseAuthentication no. Save the file and restart SSH with systemctl restart sshd.
  4. Change the default SSH port. In the same sshd_config file, replace #Port 22 with Port 4242 (or any unused high port). Update any firewall rules to allow traffic on the new port and verify connectivity before closing the old one.
  5. Restrict login to the dedicated admin user. Add AllowUsers newuser to sshd_config. This prevents other accounts, even if compromised, from opening an SSH session.
  6. Enable rate limiting with fail2ban. Install with apt-get install fail2ban, then create /etc/fail2ban/jail.d/ssh.conf containing [sshd]\nenabled = true\nport = 4242\nmaxretry = 3. Restart fail2ban to apply the rules.
  7. Activate the AI technician for admin prompts. In Carpathron Remote, navigate to Settings → AI Assistant and enable “SSH Prompt Verification.” The assistant will ask for a short spoken phrase before granting elevated commands, adding a biometric factor without extra hardware.
  8. Test the hardened configuration. From a separate machine, connect using ssh -p 4242 newuser@your-vps-ip. Verify that password login is rejected, the AI prompt appears, and the session operates normally. Document the steps in your internal wiki for future audits.

After completing these actions, SSH connections are limited to a single, key‑authenticated user on a non‑standard port, with an AI‑driven verification layer. This combination dramatically lowers the attack surface while preserving convenient remote access for administrators.

Setting up a firewall with ufw

Installing and enabling UFW

Begin by installing the uncomplicated firewall package on your VPS. On Debian‑based systems run:

sudo apt-get update && sudo apt-get install ufw -y

After installation, verify the status with sudo ufw status verbose. The firewall is inactive by default, so activate it once the rule set is prepared.

Allowing required services

First, permit HTTP and HTTPS traffic, which are essential for any web application:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

If you have configured SSH on a non‑standard port (for example 2222), add a rule for that specific port instead of the default 22:

sudo ufw allow 2222/tcp

These three commands ensure that only the services you need are reachable from the internet.

Enabling logging and activating the firewall

UFW can record connection attempts, which helps you spot scanning activity or misconfigured clients. Enable logging at the “low” level to capture denied packets without overwhelming the log files:

sudo ufw logging low

Finally, turn the firewall on and verify the active rules:

sudo ufw enable
sudo ufw status numbered

The output should list the three allow rules you added, and the default policy will be set to deny incoming traffic.

Testing the configuration

From a remote machine, attempt to connect to the web server on ports 80 and 443; both should succeed. Then try SSH on the custom port; a successful login confirms the rule is correct. Any other port should be blocked, returning a timeout or connection refused.

If you need to troubleshoot remote desktop access later, consult our remote desktop troubleshooting guide for additional port requirements.

Tip: After enabling UFW, run sudo ufw reload whenever you modify rules to apply changes without disabling the firewall.

Automating updates and installing security tools

Configure unattended upgrades

Install the unattended-upgrades package and enable it for security patches:

sudo apt-get update
sudo apt-get install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades

During the configuration select “${distro_codename}-security” and any other repositories you trust. The tool creates /etc/apt/apt.conf.d/20auto-upgrades with the following defaults:

  • APT::Periodic::Update-Package-Lists "1";
  • APT::Periodic::Download-Upgradeable-Packages "1";
  • APT::Periodic::AutocleanInterval "7";
  • APT::Periodic::Unattended-Upgrade "1";

These settings cause the system to check for updates daily, download security updates, and apply them automatically without user interaction.

Enable apt‑automatic for broader automation

While unattended-upgrades focuses on security, apt-automatic can schedule full package upgrades. Install it and create a cron job:

sudo apt-get install apt-automatic
sudo crontab -e

Add the line below to run the script at 03:30 AM each day:

30 3 * * * /usr/bin/apt-automatic -y

This ensures that non‑security updates, such as kernel or library improvements, are applied promptly, reducing the window of exposure.

Deploy fail2ban to protect services

Fail2ban monitors log files and bans IPs that show malicious signs. Install and enable it with the default SSH jail:

sudo apt-get install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

To customize the SSH jail, edit /etc/fail2ban/jail.local:

[sshd]
enabled = true
port    = ssh
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600

After saving, reload the service: sudo systemctl reload fail2ban. The configuration blocks repeated failed login attempts for one hour, mitigating brute‑force attacks.

Install a lightweight malware scanner

ClamAV provides on‑demand and scheduled scanning. Install it and update the signatures:

sudo apt-get install clamav clamav-daemon
sudo freshclam

Create a daily scan cron job that logs results to /var/log/clamav/scan.log:

0 2 * * * /usr/bin/clamscan -r /var/www/html --log=/var/log/clamav/scan.log

The scan runs at 02:00 AM, covering the web root while the server is idle. Review the log regularly or set up an email alert using mail if the log contains “Infected files”.

Putting it all together with a single cron file

For easier management, place all entries in /etc/cron.d/security-tasks:

# Daily apt‑automatic
30 3 * * * root /usr/bin/apt-automatic -y

# Daily ClamAV scan
0 2 * * * root /usr/bin/clamscan -r /var/www/html --log=/var/log/clamav/scan.log

# Optional: custom script to restart fail2ban after updates
45 3 * * * root systemctl restart fail2ban

This file ensures that updates, scanning, and service restarts run automatically without manual intervention.

For more guidance on remote management of your hardened VPS, see our remote administration guide. If you need a custom security hardening package, explore the security‑focused services we offer.

Checklist comparison of essential security components

Before deploying a new VPS, verify each security layer against the recommended baseline. The table below summarizes the default state of a typical Ubuntu 22.04 server, the hardened configuration we advise, and the security impact of each change.

Component Default configuration Recommended setting Why it matters
Firewall (ufw) Disabled; all ports open to inbound traffic. Enable ufw and allow only 22/tcp, 80/tcp, 443/tcp. Deny all else. Restricts exposure to only services you intend to publish, reducing the attack surface for port scans and automated exploits.
SSH Root login allowed, password authentication enabled, default port 22. Disable root login, enforce PubkeyAuthentication yes, change port to 2222, and use AllowUsers to limit accounts. Eliminates brute‑force password attacks, prevents privilege escalation via root, and obscures the service from generic scanners.
Updates Manual apt update && apt upgrade required; no automatic security patches. Install unattended-upgrades, enable APT::Periodic::Update-Package-Lists "1" and APT::Periodic::Unattended-Upgrade "1". Ensures critical CVE fixes are applied within 24 hours, limiting the window of vulnerability for known exploits.
Monitoring No log aggregation or alerting; logs stored locally only. Deploy fail2ban for SSH, configure auditd for system calls, and forward logs to a remote syslog server (e.g., via rsyslog). Detects repeated login failures, unauthorized file changes, and provides forensic evidence for incident response.
Backups None configured; data resides only on the primary disk. Schedule daily rsnapshot or borg snapshots to a separate volume or off‑site storage, and test restore quarterly. Protects against ransomware, accidental deletion, and hardware failure while ensuring rapid recovery.

After confirming each row matches your environment, you can move on to the next phase of deployment, such as installing your application stack or integrating with Qubitpage’s remote management tools. Keeping this checklist handy during routine audits helps maintain a consistent security posture across all VPS instances.

Frequently asked questions

How do I generate and add an SSH key for my VPS?

On your local workstation run ssh-keygen -t ed25519 -C "your_email@example.com" and accept the default file location. After the key pair is created, copy the public key with cat ~/.ssh/id_ed25519.pub | ssh user@vps_ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys". Verify the permissions on the remote .ssh directory (700) and authorized_keys file (600) before testing the password‑less login.

What firewall ports should I keep open for a typical web app?

A minimal configuration allows inbound traffic on port 22 for SSH, 80 for HTTP, and 443 for HTTPS. If you run a database on the same host, keep it bound to 127.0.0.1 and do not expose its port publicly. Use ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp then enable the firewall with ufw enable.

Can I use Carpathron Remote to manage my Linux server remotely?

Carpathron Remote is not part of Qubitpage’s publicly documented toolset, and the company’s official remote‑management offering is CarphaCom, which runs on NVIDIA Isaac Sim and Google Gemini for robotics use cases. For standard Linux administration, rely on SSH, Ansible, or a vetted third‑party solution rather than an undocumented Carpathron client.

How often should I run security updates on a production server?

Apply critical kernel and package updates within 24 hours of release; schedule regular full updates at least weekly. Automate the process with unattended-upgrades for Debian‑based distributions or dnf‑automatic for Fedora/RHEL. Always test major version upgrades in a staging environment before applying them to production.

What is the simplest way to back up my web app files and database?

Use rsync -a --delete /var/www/html/ backup_user@backup_host:/backups/web/ to synchronize the document root to a remote storage server. For the database, dump it with mysqldump -u root -p mydb > /tmp/mydb.sql and copy the dump to the same backup host, optionally compressing it with gzip. Schedule both commands with cron to run nightly and verify the backups regularly.

Final thoughts on securing your first Linux VPS

After you have hardened the network, encrypted storage, and hardened the OS, the remaining work is routine but essential. Keep the kernel and all packages up to date with apt-get update && apt-get upgrade -y (or the equivalent for your distro) and automate this step with a cron job. Regularly audit SSH access, rotate keys, and disable password authentication to eliminate brute‑force vectors.

Implement a host‑based intrusion detection system such as auditd or ossec, and configure log forwarding to a remote syslog server for tamper‑proof retention. Periodic vulnerability scans using tools like nmap or OpenVAS will reveal drift from your baseline configuration.

Finally, document every change, back up configuration files, and test recovery procedures monthly. A disciplined approach to patch management, monitoring, and backup ensures that the VPS remains a reliable foundation for any application you deploy.

Ready to accelerate your secure cloud projects? Explore how Qubitpage can help.

Written by

Mircea S. Rusu

Founder and engineer of Qubitpage. Support engineer since 2005, CMS developer, former technical consultant at Niguarda Ca' Granda Hospital in Milan, and author of the book “The Architect”.

More about the author →