CodeKits.shopNew developer offer

Set up an Ubuntu VPS without locking yourself out

Prepare an Ubuntu VPS with a sudo user, tested SSH keys, updates and UFW rules while keeping a working recovery path throughout.

By Jonathan · 4 min read

Published

Diagram showing verify access, then allow ssh, then test again
In this article

The safest first-server setup preserves a working route back in at every step. Create and test the new login before tightening authentication, permit the actual SSH port before enabling the firewall, and keep the provider console available.

These commands target a fresh Ubuntu 24.04 LTS VPS you own. They are a reviewed checklist, not a record of a provisioned test machine. Provider images, cloud-init and socket activation can change defaults, so inspect the current configuration rather than assuming every Ubuntu server is identical.

Establish a recovery path

Before changing anything, locate the provider's browser console or rescue mechanism and confirm you can use it. Record the current SSH hostname and port securely. Keep the first SSH session open until a second independent session succeeds.

Verify the host fingerprint through a trusted provider console or another authenticated channel. Do not blindly accept a changed host key. If the server is newly rebuilt, confirm that event before replacing an old trusted entry.

Local terminal — initial connection
ssh -p 22 [email protected]

Use the provider-supplied initial username if it is not root. Replace the domain and port with your own values; the tutorial's hostname is a placeholder.

Create a named administrator

Server terminal — administrative user
sudo adduser deploy
sudo usermod -aG sudo deploy
sudo install -d -m 0700 -o deploy -g deploy /home/deploy/.ssh

On your workstation, create a passphrase-protected key if you do not already have an appropriate one. Never copy its private half to the server.

Local terminal — key creation
ssh-keygen -t ed25519 -a 64 -f "$HOME/.ssh/demo-vps"

Install the public key into /home/deploy/.ssh/authorized_keys through the existing authenticated session or the provider's supported key workflow. If password login for the new account is temporarily available, ssh-copy-id -i "$HOME/.ssh/demo-vps.pub" [email protected] can do this. Review the exact destination and port.

Set the file owner to deploy and mode to 0600. In a second local terminal, test both authentication and sudo:

Local terminal — independent verification
ssh -i "$HOME/.ssh/demo-vps" -o IdentitiesOnly=yes [email protected]
sudo -v
sudo whoami

Do not close the original session yet. The Ubuntu OpenSSH guide explains configuration snippets and key-based access.

Update before hosting an application

Server terminal — package maintenance
sudo apt update
sudo apt upgrade
sudo apt install ufw
test -f /var/run/reboot-required && cat /var/run/reboot-required

Review package changes and any configuration-file prompts. If a reboot is required, schedule it while the machine is still empty, then verify reconnection and sudo again. A successful package installation is not proof that the new kernel is running.

Allow the real SSH port before enabling UFW

Inspect the effective SSH configuration and listeners. If the provider uses a nonstandard port, substitute it below and check its separate network firewall.

Server terminal — firewall setup
sudo sshd -T
sudo ss -ltnp
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH administration'
sudo ufw status verbose
sudo ufw enable
sudo ufw status numbered

The example deliberately uses a port rule rather than assuming the OpenSSH application profile matches a customized port. Open ports 80 and 443 only when you are ready to serve web traffic. Do not open MySQL or an internal Node port just to make local services communicate.

Open another new SSH connection after enabling UFW. Existing sessions can remain connected even when a rule would block new ones. Ubuntu's firewall documentation covers UFW and application profiles.

Tighten authentication only after the test passes

Use a reviewed snippet under /etc/ssh/sshd_config.d/ to disable password and root login if that matches your access policy. Cloud-init or earlier settings may take precedence, so verify the effective result.

/etc/ssh/sshd_config.d/00-local-access.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no

Run sudo sshd -t before reloading ssh.service, then inspect sudo sshd -T and test a fresh key-based connection. Keep recovery access and the original session until that succeeds. Authentication involving Match blocks needs context-specific validation.

The next step is deploying Next.js behind Nginx, not disabling more settings without understanding them. Next.js development can include a documented server handover and recovery process.