Deploying Brut app to Hetzner

My previous Brut apps are deployed to Heroku, since that’s what I know and is super easy to use. A dyno + DB + Redis ends up being around $30/month, so for the app I’m working on now, I’m using Hetzner.

I’m running everything on one box and did manual setup, nothing scripted. The opposite of what you are supposed to do :slight_smile:

I was pleasantly surprised how easy it has been - basically apt install stuff and it tends to be set up correctly. certbot just handled the SSL cert and seems set up to update it as needed.

This setup will cost me around $10/month. It’s obviously not a great practice to have all app, DB, and Redis all on one box, but until this app is used my someone other than me, that’s probably fine.

Brut includes support for Docker-based deployments to Heroku, where the generated Dockerfile could probably be used more generally. I opted to not use Docker for this, just to see what it was like. Not wanting an ancient Ruby, I first tried mise, however it required me to somehow know some system packages to install to make things work since it wanted to build Ruby. Doing this as a non-root user I didn’t want to deal with that.

I ended up using rv - it was super fast, did not require installing anything via apt and so far has just worked. To install a few RubyGems I had to install build-essential and libyaml.

rv is still new, and the docs aren’t super clear, but basically:

  • curl -LsSf https://rv.dev/install | sh
  • rv ruby install 3.4.9
  • Add whatever it said to the .bashrc
  • ruby --version just works!

All that took a matter of minutes to achieve.

YOLO’ing it on a VPS still is missing a lot of stuff from Heroku, like log access, metrics, console, deployments, etc. But, since this app is just me, I am just going to script stuff specific to the app and see how far that gets me.

2 Likes

This is quite interesting as I’ve thought about doing something similar as an experiment to get away from more complicated Docker setups.

I’m curious how ancient the Ruby version on Hetzner? I’m curious since my Hetzner server is running Debian stable which currently has 3.3.8 as the system ruby.

Ah, I mean if you use stock Ubuntu and apt install ruby, you do not get the latest ruby. Most docs I’ve seen indicate you have to install it some other way e.g. rvm or mise. Looks like Debian is not as far behind latest. And I guess neither version is technical “ancient”, so I’m being overly hyperbolic :slight_smile:

But, I do like to be on the most recent or close to it.

1 Like

hah, you’re all good! I wasn’t meaning to call you out.

I was more thinking it might be something crazy like Hetzner defaulted to oldstable Debian without backports, so you’d be on something like Ruby 2.7, which absolutely should be considered ancient.

The main reason I’ve considered using system Ruby for hosting is because if you set up unattended upgrades then you’ll always “just get” the latest stable Ruby and its security patches. Which is less important in Ruby land but more interesting when you start thinking about NodeJS where updates are more common.

Yeah, I debated doing the same thing because 3.2 (what Ubuntu has) it’s fine. But, i like to be on latest. My plan is to include updating Ruby (and Node) as part of the normal app update process, e.g. using Gemfile or tool-versions. My dev env is in Docker (using the Ruby base image).

TBH I should probably use Docker for prod, but one step at at time

1 Like

I already feel like I’m creating a crappy version of Heroku as a series of bash scripts. $robot said that for a small app that may never get used much, there was no value in gold plating the deploy and server management. Intellectually, this is a good argument and I can’t really refute it. But I don’t like having to have a note of “this is the incantation of thing I did to fix this thing one time only”.

That said, I went from “I haven’t touched a Linux server in 20 years” to “my app is running over SSL and deploys are mostly scripted” in 4 hours, so I can’t complain :slight_smile:

1 Like