Preparing a VPS¶
Everything on this page is about the machine, not about CITAR. If you already run servers, skip it — DEPLOY.md is the part that is CITAR-specific.
What to rent¶
| CPU | The thing that matters. Games are CPU-bound and single-threaded per game, so cores ≈ concurrent games. One core runs one game |
| RAM | 1 GB is enough: about 95 MB for CITAR plus 2–7 MB per loaded game. Add 2 GB of swap if the machine has none |
| Disk | 2 GB for the program; saved games are a few hundred kilobytes each |
| OS | Any current Linux. Debian and Ubuntu are the best-tested |
| Network | IPv4. IPv6 too if you can, but nothing requires it |
Per-core speed matters less than you would think: a mid-range VPS core is well under twice as slow as a laptop core. The constraint is how many at once, not how fast.
Before CITAR¶
A non-root account with sudo¶
adduser --disabled-password --gecos "" deploy
usermod -aG sudo deploy # wheel on RHEL-family systems
mkdir -p /home/deploy/.ssh && chmod 700 /home/deploy/.ssh
# put your public key in /home/deploy/.ssh/authorized_keys
chmod 600 /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy/.ssh
Keys only, no passwords¶
sudo tee /etc/ssh/sshd_config.d/01-keys-only.conf >/dev/null <<'EOF'
PasswordAuthentication no
AuthenticationMethods publickey
PermitRootLogin prohibit-password
MaxAuthTries 3
LoginGraceTime 30
EOF
sudo sshd -t && sudo systemctl reload ssh
Test a new session before closing the one you have. Locking yourself out of a remote machine is a slow problem to fix.
Two gotchas that cost people afternoons:
- OpenSSH takes the first value it reads. Ubuntu ships
/etc/ssh/sshd_config.d/50-cloud-init.confcontainingPasswordAuthentication yes. A drop-in numbered01-wins; one numbered60-does not, however correct it looks. - cloud-init rewrites it on reboot unless you also set
ssh_pwauth: falsein/etc/cloud/cloud.cfg.d/99-no-pwauth.cfg.
fail2ban¶
If the machine has a public SSH port, it is being brute-forced right now.
sudo apt install fail2ban
sudo tee /etc/fail2ban/jail.d/sshd.local >/dev/null <<'EOF'
[sshd]
enabled = true
backend = systemd
maxretry = 3
bantime = 1h
EOF
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
backend = systemd matters on Ubuntu 24.04 and similar: sshd logs to the journal, and the stock
file-based jail watches /var/log/auth.log, which does not exist — so it matches nothing while
looking perfectly healthy.
A firewall¶
CITAR itself listens on loopback. Only the proxy is exposed.
Swap, if there is none¶
sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile
sudo mkswap /swapfile && sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
With zero swap, one memory spike makes the kernel kill whatever it likes — which on a shared box may be your database rather than CITAR.
Unattended security updates¶
DNS¶
An A record for your domain pointing at the machine's IPv4 address, and AAAA if it has IPv6.
Do this first: certificate issuance checks it, and propagation is the one part you cannot hurry.
If the machine already runs other sites¶
Normal, and fine. CITAR adds a site to the existing nginx rather than replacing anything, and listens on loopback so it does not contend for port 443.
Two things to think about when sharing:
- Memory. Set
MemoryMax=on the CITAR unit so that CITAR is what dies under pressure, not the other site's database. - CPU. A busy game will use a whole core. If something latency-sensitive shares the machine,
cap CITAR with
CPUQuota=and keepdefault_max_concurrent_gameslow.