VPS Setup

Overview

Baseline hardening procedure for a fresh VPS prior to installing cluster tooling (k3s, Helm, ArgoCD). Establishes a non-root administrative user with SSH key authentication and a restrictive firewall policy.

Scope

  • Provider: Greencloud
  • OS: Ubuntu 22.04/24.04
  • Spec: 8GB RAM / 4vCPU / 88GB SSD
  • Result: nova user with sudo privileges, SSH key-based login, UFW firewall active

Prerequisites

  • Root SSH access to the VPS
  • Local SSH keypair (public key present in /root/.ssh/authorized_keys on the VPS)

Procedure

1. System update

apt update && apt upgrade -y

2. Create administrative user

adduser nova
usermod -aG sudo nova
passwd nova

The password is a fallback credential only; SSH key authentication is the primary access method (Step 3).

3. Provision SSH key access

Cloud images do not propagate the root user's authorized_keys to newly created users. Copy explicitly:

mkdir -p /home/nova/.ssh
cp /root/.ssh/authorized_keys /home/nova/.ssh/authorized_keys
chown -R nova:nova /home/nova/.ssh
chmod 700 /home/nova/.ssh
chmod 600 /home/nova/.ssh/authorized_keys

4. Firewall configuration (UFW)

apt install ufw -y
ufw allow OpenSSH
ufw allow 80/tcp      # HTTP ingress
ufw allow 443/tcp     # HTTPS ingress
ufw allow from <ADMIN_PUBLIC_IP> to any port 6443 proto tcp
ufw enable

Only the ports required for SSH and HTTP(S) ingress are public. The k3s API is restricted to the operator's public IP; omit this rule when kubectl runs only on the VPS.

Verification

From a local machine (not a su nova session on the VPS — this does not exercise the SSH auth path):

ssh nova@<VPS_IP>
sudo whoami
# expected: root

sudo ufw status
# expected: 22, 80, 443, 6443 in ALLOW state

Known Issue: Permission denied (publickey)

Symptom: SSH rejects both key and password auth for the new user, even after setting PasswordAuthentication yes in /etc/ssh/sshd_config.

Cause: OpenSSH applies the first matching directive it encounters. sshd_config typically contains Include /etc/ssh/sshd_config.d/*.conf near the top of the file. If a drop-in file in that directory sets PasswordAuthentication no, it takes precedence over any conflicting directive appearing later in the main config file. Cloud-init frequently generates such drop-in files.

Diagnosis:

sudo sshd -T | grep -i passwordauthentication   # effective value, not raw file content
grep -n "^Include" /etc/ssh/sshd_config
grep -rn "PasswordAuthentication" /etc/ssh/sshd_config.d/

Resolution: Provisioning SSH key access (Step 3) resolves this without modifying sshd_config. Editing the drop-in file directly is an alternative but is not recommended, as password authentication is a weaker access control than key-based authentication.