Running A Bun Service On A Cheap VPS
Today, I spun up a Bun service on a Hetzner VPS. It was pretty straightforward, but I thought I'd share my notes.
Config
Spinning up a new VPS on Hetzner was simple. I took Hetzner's example config and tweaked it to include automatic updates:
#cloud-config users: - name: {YOUR_USER_NAME} groups: users, admin sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash ssh_authorized_keys: - {YOUR_PUBLIC_SSH_KEY} packages: - fail2ban - ufw - unattended-upgrades - apt-listchanges package_update: true package_upgrade: true runcmd: - printf "[sshd]\nenabled = true\nbanaction = iptables-multiport" > /etc/fail2ban/jail.local - systemctl enable fail2ban - ufw allow ssh - ufw allow http - ufw allow https - ufw enable - sed -i -e '/^\(#\|\)PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config - sed -i -e '/^\(#\|\)PasswordAuthentication/s/^.*$/PasswordAuthentication no/' /etc/ssh/sshd_config - sed -i -e '/^\(#\|\)KbdInteractiveAuthentication/s/^.*$/KbdInteractiveAuthentication no/' /etc/ssh/sshd_config - sed -i -e '/^\(#\|\)ChallengeResponseAuthentication/s/^.*$/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config - sed -i -e '/^\(#\|\)MaxAuthTries/s/^.*$/MaxAuthTries 2/' /etc/ssh/sshd_config - sed -i -e '/^\(#\|\)AllowTcpForwarding/s/^.*$/AllowTcpForwarding no/' /etc/ssh/sshd_config - sed -i -e '/^\(#\|\)X11Forwarding/s/^.*$/X11Forwarding no/' /etc/ssh/sshd_config - sed -i -e '/^\(#\|\)AllowAgentForwarding/s/^.*$/AllowAgentForwarding no/' /etc/ssh/sshd_config - sed -i -e '/^\(#\|\)AuthorizedKeysFile/s/^.*$/AuthorizedKeysFile .ssh\/authorized_keys/' /etc/ssh/sshd_config - sed -i '$a AllowUsers {YOUR_USER_NAME}' /etc/ssh/sshd_config - systemctl enable unattended-upgrades - reboot
Verifying the SSH signature
My VPS was ready in a few seconds. (It was ready so fast, I thought maybe something hadn't worked.) When I first SSHed into the box, I was given a message like this:
The authenticity of host '...' can't be established. ED25519 key fingerprint is SHA256:....
To verify the key, I ran:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Installing Caddy
Once in, it was time to install Caddy:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install caddy
I hit https://{IP_ADDRESS}
and saw a default Caddy page. Nice! It told me to do the following:
Point your domain's A/AAAA DNS records at this machine. Upload your site's files to /var/www/html. Edit your Caddyfile at /etc/caddy/Caddyfile: Replace :80 with your domain name Change the site root to /var/www/html Reload the configuration: systemctl reload caddy Visit your site!
I love the way Caddy presented that. This is the way dev-tooling should be. Anyway, I'm ignoring all of that advice, since I'm going to instead proxy a Bun service.
Hello, Bun!
I pointed a test domain at my IP address, installed Bun, then created a little hello-world script:
// /home/{YOUR_USER_NAME}/hello-world/hi.ts const port = 3000; Bun.serve({ fetch(req) { return new Response("Hello, world!"); }, }); console.log('Listening on', port);
Next, I ran my server manually:
bun hi.ts
And, I modified /etc/caddy/Caddyfile
to look like this:
{DOMAIN_NAME} { reverse_proxy :3000 }
Hey, presto! Everything worked. I can now see Hello, world!
over HTTPS from any browser on the planet. Neato.
Systemd
I want my Bun service to run automatically when the server restarts, or after a crash. To do that, I created a systemd service like so:
# /etc/systemd/system/hello-world.service [Unit] Description=Hello world web service After=network.target [Service] Type=simple User={YOUR_USER_NAME} WorkingDirectory=/home/{YOUR_USER_NAME}/hello-world ExecStart=/home/{YOUR_USER_NAME}/.bun/bin/bun run hi.ts Restart=always [Install] WantedBy=multi-user.target
I enabled and started it:
sudo systemctl enable hello-world sudo systemctl start hello-world
Checking the status of everything
Lastly, I created a cheatsheet of the stuff I might want to hop in and check later:
# Review statuses, logs, etc # View unattended-upgrades logs here: # # /var/log/unattended-upgrades/ # sudo unattended-upgrades --dry-run --debug sudo fail2ban-client status ssh sudo ufw status sudo systemctl status hello-world sudo systemctl status caddy sudo journalctl -u caddy -f
That's all, folks
And that's it. A working Bun service running on a cheap Hetzner VPS, served over https.
Happy hacking.