rand Bringing minimalism and sanity to real life

Deploying Mastodon on FreeBSD

A few days ago I deployed Mastodon in a FreeBSD jail, here's how I did it.

The stuff on the documentation mostly works, except for parts where it doesn't, you basically clone the repository the same way but when you get to the packages do this instead (if you use pkg(8)):

pkg install ImageMagick7-nox11 ffmpeg postgresql-libpqxx postgresql12-client postgresql12-contrib postgresql12-server libpqtypes libxml2 libxslt file git gcc protobuf protobuf-c pkgconf autoconf bison openssl libyaml readline ncurses libffi gdbm redis libidn libidn2 icu shared-mime-info npm yarn

Also, skip the nodejs and yarn part, let pkg(8) install them.

Now, create a user as usual, just don't set the shell to /sbin/nologin otherwise you'll need something like sudo to actually use it. Also, when you configure the ruby stuff, skip the rbenv, it's not gonna work, instead do this:

pkg install ruby ruby27-gems rubygem-bundler rubygem-nio4r rubygem-puma

The puma gem won't install using ruby's package manager at the time of writing, so we install it using pkg(8), also you can safely skip the bundler stuff since pkg(8) installs that as well.

From this point on you can follow the thing, remember that postgresql on FreeBSD exposes the sockets on /tmp by default, so point it there, skip the Nginx part, we'll do that later.

Now the services, There's a port on Freshports but unfortunately it expired years ago and the scripts are broken, so I wrote my own based on them. Note that my mastodon home directory is mounted on /mastodon, replace that with whatever matches your setup.

mastodon_workers, mastodon_web, mastodon_stream

You might notice I've overridden the bind address of puma in the mastodon_web script, I know it's quite ugly this way, but I really don't feel like changing it, if you really want to you can get rid of it and override it in .env.production instead. Unfortunately I haven't found a way to make the nodejs application bind to a UNIX socket without modifying the code, if any of you know how, please let me know.

Finally, the nginx stuff. My web server runs in another jail and I used nullfs mounts to share the directory, set that up as you please. Since mastodon_web is configured to bind to a socket it makes things a little bit easier, but mastodon_stream is accessed over TCP. Here's my nginx config file, adapt it to match your setup.

Additionally, if you want to configure full text search, just know that elasticsearch won't work by default if it does not have a loopback interface, to work around this you can bind it to the jail's internal address, or use vnet(9).

That should be it, if it worked out for you, drop me a message at @rand@s.chars.jp.