all repos — site @ 6c3d6e69f1f4641125508bdbadbef80e7d3dd5e5

source for my site, found at icyphox.sh

pages/blog/honk-fly.md (view raw)

  1---
  2template:
  3slug: honk-fly
  4title: Honkin' on the Fly
  5subtitle: Running honk on fly.io
  6date: 2022-05-25
  7---
  8
  9**Update 2022-08-11**: As with literally every update of mine, I'm no
 10longer running honk on Fly. It's way easier to simply run it on a server
 11myself, behind nginx. Huh -- who knew?
 12
 13For those unaware -- first of all, how? it's literally everywhere --
 14[fly.io](https://fly.io) is the new platform-as-a-service du jour. The
 15idea is to give them a Dockerfile (or a pre-built image, or just generic
 16applications in [a bunch of
 17languages](https://fly.io/docs/getting-started/#language-guides)), and
 18they run it for you on servers across the globe. Firecracker microVMs,
 19WireGuard, and some other neat tech. Understandably, this gets the
 20average Hacker News-type (me), excited. And I'd been meaning to switch
 21my fediverse instance over to
 22[honk](https://humungus.tedunangst.com/r/honk) -- a stateful Go
 23application using sqlite[^1]. And the fly.io folks [really like
 24sqlite](https://fly.io/blog/all-in-on-sqlite-litestream/). The stars
 25have aligned.
 26
 27[^1]: Written by [tedu](https://honk.tedunangst.com/u/tedu). He's a cool
 28      guy who runs and hacks OpenBSD. The honk source is a fun read.
 29
 30I trust that you can figure out the initial setup bits like logging in
 31to the dashboard and giving them your credit card info and praying that
 32they don't run you a bill of $5000 because you somehow blew through
 33their free allowance resources. As I understand it, Fly "auto-scales",
 34so this scenario isn't unlikely -- however, [they do offer some
 35leniency](https://news.ycombinator.com/item?id=31392497). Luckily, the
 36chances of me turning into a fedi-influencer (_fedifluencer_?) overnight
 37are rather slim.
 38
 39## setup
 40
 41They want a Dockerfile, so let's give them one.
 42
 43```dockerfile
 44FROM golang:1.18-alpine AS builder
 45RUN apk add sqlite-dev build-base mercurial
 46
 47WORKDIR /tmp/src
 48RUN hg clone https://humungus.tedunangst.com/r/honk 
 49RUN cd honk && make
 50
 51FROM alpine:latest
 52RUN apk add sqlite sqlite-dev
 53
 54COPY local /tmp/local
 55COPY memes /tmp/memes
 56COPY emus /tmp/emus
 57
 58WORKDIR /opt
 59COPY --from=builder /tmp/src/honk/honk /bin/
 60COPY --from=builder /tmp/src/honk/views views/
 61COPY start /bin
 62
 63ENV HONK_DATA_DIR "/opt/data"
 64ENV HONK_VIEWS_DIR "/opt/"
 65
 66CMD ["/bin/start"]
 67```
 68
 69Not too much going on here -- we pull latest tip, build honk, copy the
 70`local` directory containing our `local.css` (custom styles); the
 71`memes` directory containing, well, memes (PNGs and GIFs); and the
 72`emus` directory containing emoji (used as `:filename:`). These will
 73then be copied into the Fly volume later on by the `start` script. Kinda
 74gross, but whatever.
 75
 76And the `start` script:
 77
 78```sh
 79#!/bin/sh
 80
 81run() {
 82    cp -R /tmp/memes/* "$HONK_DATA_DIR"/memes/
 83    cp -R /tmp/memes/* "$HONK_DATA_DIR"/emus/
 84    cp -R /tmp/local/* "$HONK_DATA_DIR"/views/
 85
 86    honk -datadir "$HONK_DATA_DIR" -viewdir "$HONK_VIEWS_DIR"
 87}
 88
 89# first time setup
 90if [ ! -f "$HONK_DATA_DIR/honk.db" ]; then
 91    honk init <<-EOF
 92    $HONK_USERNAME
 93    $HONK_PASSWORD
 94    $HONK_ADDRESS
 95    $HONK_SERVER_NAME
 96    EOF
 97fi
 98
 99run
100```
101
102This simply copies our stuff from the container into the volume, and
103launches honk. If the honk database doesn't yet exist, we run `honk
104init` and set it up. These environment variables are configured in the
105`fly.toml` file:
106
107```toml
108app = "honk"
109
110kill_signal = "SIGINT"
111kill_timeout = 5
112processes = []
113
114[mounts]
115  source = "honkstore"
116  destination = "/opt/data"
117
118[env]
119  HONK_USERNAME = "icy"
120  HONK_ADDRESS = "0.0.0.0:8080"
121  HONK_SERVER_NAME = "h.icyphox.sh"
122
123[experimental]
124  allowed_public_ports = []
125  auto_rollback = true
126
127[[services]]
128  http_checks = []
129  internal_port = 8080
130  processes = ["app"]
131  protocol = "tcp"
132  script_checks = []
133
134  [services.concurrency]
135    hard_limit = 50
136    soft_limit = 20
137    type = "connections"
138
139  [[services.ports]]
140    force_https = true
141    handlers = ["http"]
142    port = 80
143
144  [[services.ports]]
145    handlers = ["tls", "http"]
146    port = 443
147
148  [[services.tcp_checks]]
149    grace_period = "1s"
150    interval = "15s"
151    restart_limit = 0
152    timeout = "2s"
153```
154
155The `fly.toml` gets generated when you first run `fly launch`. The only
156bits I've added are the `env` and `mounts` sections. Notice that
157`HONK_PASSWORD` is missing, and for good reason -- Fly has support for
158secrets, which can be created quite handily using:
159
160```sh
161$ flyctl secrets set HONK_PASSWORD="$(pw -s honk)"
162```
163
164## deploy
165
166The only thing left to do is to provision our volume for persistence,
167and we're off to the races:
168
169```sh
170$ flyctl volumes create honkstore --region maa
171        ID: vol_1g67340omkm4ydxw
172      Name: honkstore
173       App: honk
174    Region: maa
175      Zone: aed0
176   Size GB: 10
177 Encrypted: true
178Created at: 21 May 22 16:07 UTC
179
180$ flyctl deploy
181```
182
183## post-deploy
184
185I like having pretty usernames. In this case, I want to drop the `h.`
186subdomain and have it look like this: `icy@icyphox.sh`. To do this, we
187simply set the `masqname` key in the database to our desired
188hostname[^2]:
189
190```sh
191$ honk setconfig 'masqname' 'icyphox.sh'
192```
193
194[^2]: Had to setup a custom domain for this: https://fly.io/docs/app-guides/custom-domains-with-fly/
195
196And at `icyphox.sh`, we setup a redirect to `h.icyphox.sh` at the
197`/.well-known/webfinger` path. I did this [via
198Netlify](https://github.com/icyphox/site/commit/4bbc8335481a0466d7c23953b0f6057f97607ed1);
199you can do it however, as long as the query parameters are preserved.
200Read more about webfingers and other thingamabobs
201[here](https://docs.joinmastodon.org/spec/webfinger/).
202
203I did a bunch more like custom CSS, avatars etc. but I'll leave that as
204homework for you
205([honk(8)](https://humungus.tedunangst.com/r/honk/m/honk.8) is mandatory
206reading!).
207
208## thoughts
209
210**On Fly**: I think it's neat. Rough edges? Sure. My [deploy was stuck
211in
212`pending`](https://community.fly.io/t/app-stuck-in-pending-in-maa-region/5280);
213I had to delete it and re-create it for it to start working again. I
214lost my data in the process because volumes are attached to apps.
215Perhaps I should've waited and the problem would've fixed itself. Who
216knows? 
217
218And that's the eternal problem with PaaS -- there's a layer of
219abstraction that you can't ever pierce. You can't truly know what the
220problem was unless they publish a post-mortem (or don't). Anyway, in
221this case I'll just chalk it up to teething issues.
222
223Is it easier than simply building it on a server and running `nohup
224./honk &` and calling it a day[^3]? Not really. It's more fun, I guess.
225
226[^3]: Yes that's actually how I run a bunch of my services, including
227      [forlater.email](https://forlater.email)!
228
229**On honk**: It's refreshing. I liked running Pleroma + Soapbox (I still
230do, haven't killed it yet), but it always felt alien to me. I didn't
231understand the code, didn't enjoy having to upgrade Elixir/Erlang OTP
232whatever, `mix.deps get` blah blah; a single Go binary + sqlite + HTML
233templates speaks to me.
234
235Go follow me at [icy@icyphox.sh](https://h.icyphox.sh/u/icy). It's why I
236even wrote this post. Not that I can see it, honk doesn't have those
237ego-numbers.
238
239You can find all the source code to deploy honk yourself here:
240https://git.icyphox.sh/honk