Getting started
First server setup
Provision a fresh Ubuntu box over SSH without locking yourself out.
You have a fresh Ubuntu box and an SSH login. Before it runs an agent, it needs five things. The order below is not cosmetic: each phase assumes the one before it worked, and two of the steps will lock you out of the machine permanently if you run them early.
Every command runs as root or under sudo.
Get in safely
Update first. A fresh image is rarely current, and you do not want to spend an afternoon debugging a bug that was fixed upstream months ago.
apt update && apt full-upgrade -y
Create a non-root user. Your shell, the daemon, and anything the agent runs
all belong to a normal account with sudo. Substitute your own name for alex.
adduser alex
usermod -aG sudo alex
Install your SSH key — this one runs on your laptop, not on the server. It
appends your public key to the new user’s authorized_keys.
ssh-copy-id alex@<server-ip>
Now prove key login works, in a second terminal. Leave your current session open and connect from a new window:
ssh alex@<server-ip> 'id && sudo -n true && echo SUDO-OK'
This is the gate for everything below. The next phase turns off password login. With a working session still open you can undo any mistake; without one, a bad SSH config means reinstalling the machine. If this command does not print your user and
SUDO-OK, stop and fix it.
Shut the door
Turn off password authentication. Write a drop-in rather than editing
sshd_config directly — cloud images ship /etc/ssh/sshd_config.d/50-cloud-init.conf,
and a setting there beats one you added to the main file. sshd -t validates
the config, so a typo fails before the restart makes it real:
cat >/etc/ssh/sshd_config.d/99-hardening.conf <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF
sshd -t && systemctl restart ssh
Bring up the firewall — allow before enable.
ufw allow OpenSSH
ufw enable
ufw status verbose
Order is the entire point.
ufw enablestarts denying inbound traffic immediately. Run it beforeufw allow OpenSSHand it drops your own session mid-command, with no way back in.
Install fail2ban. It bans addresses that hammer SSH, and its default sshd jail is active the moment it installs:
apt install -y fail2ban
systemctl status fail2ban --no-pager
Moving SSH off port 22 is optional and mostly reduces log noise rather than
adding real security. If you do it, note that Ubuntu 24.10 and later start sshd
through socket activation: a Port line in sshd_config is silently ignored,
because the port now lives in ssh.socket.
systemctl edit ssh.socket
# [Socket]
# ListenStream=
# ListenStream=2222
systemctl daemon-reload && systemctl restart ssh.socket
ufw allow 2222/tcp
The empty ListenStream= line is required. It clears the inherited port 22
instead of adding a second listener alongside it.
Survive unattended
Automatic security updates are the highest-value thing you can leave running on a machine you will stop thinking about. Answer Yes at the prompt.
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
Add swap if the box has less than 4 GB of RAM. Check with free -h. Without
it, the first large build or an agent loading a big context gets killed by the
OOM killer, and the failure reads as a mysterious crash rather than an
out-of-memory condition.
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
Name it and set the clock. The hostname is what you will read in logs, prompts, and the machine list; a wrong timezone turns every timestamp into a small subtraction problem.
hostnamectl set-hostname box-1
timedatectl set-timezone Europe/Moscow
Put it on the console
Install the daemon. The script picks the binary for your architecture, verifies
its SHA-256 against the published checksums, installs it to
/usr/local/bin/farcrewd, and hands off to the setup wizard. It needs systemd,
curl, and sha256sum, all of which a stock Ubuntu already has.
curl -fsSL https://get.farcrew.app/install.sh | sudo sh
The wizard stops and asks for a pair code. Open the console, choose Add machine, and type the code it shows into the waiting prompt.
Pair codes expire after 15 minutes, so generate one when the prompt is already waiting rather than before you start. The alphabet is
A–Zand2–7: there is no zero and no one in a code, so anOis always the letter.
If the daemon is already installed and no wizard is waiting, pair from the shell instead. The same applies to a fully unattended install, where you pass the code straight to the installer:
farcrewd pair <CODE>
# or, unattended from scratch:
curl -fsSL https://get.farcrew.app/install.sh | sudo sh -s -- <CODE>
The machine appears in the console within a few seconds. If it does not, the journal says why:
systemctl is-active farcrewd
journalctl -u farcrewd -n 30 --no-pager
One thing on your laptop
Add a host entry to ~/.ssh/config on your own machine so you never type the IP
again. ServerAliveInterval keeps NAT from quietly dropping an idle session.
Host box1
HostName <server-ip>
User alex
Port 22
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 30
Then it is just ssh box1.