Updating Mastodon under FreeBSD 12.0-RELEASE

After recently upgrading my server from FreeBSD 11.2 to 12.0 (and rebuilding my entire installed ports tree), I noticed that trying to run my usual rebuild process for Mastodon to get it to pick up the new library changes kept dieing on a Ruby gem ‘bcrypt’.

Looks like this has been noted on the Gem’s GitHub:

https://github.com/codahale/bcrypt-ruby/pull/166

https://github.com/codahale/bcrypt-ruby/issues/175

Thankfully, it looks like the FreeBSD port version has already been patched: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=212304

So, here’s my hacky way of trying to get this working for now (on top of my existing hack to get uws to compile!).  Started with these great instructions for a funky port + local hybrid: https://blog.gegeweb.org/installer-mastodon-sous-freebsd-sans-le-port.html

cd /usr/ports/security/rubygem-bcrypt && sudo make
sudo mkdir ~mastodon/gem-overrides
sudo cp -rv /usr/ports/security/rubygem-bcrypt/work/bcrypt-3.1.12 ~mastodon/gem-overrides
sudo chown -R mastodon:mastodon ~mastodon/gem-overrides

Then, as the mastodon user, you need to edit the Gemfile, and near the top add the line:

gem 'bcrypt', :path => "~/gem-overrides/bcrypt-3.1.12"

Trying to run the normal complicated bundle command throws an error about the lockfile not matching, so I just ran a plain ‘bundle install’ like it said, before trying again:

bundle install
bundle install -j$(getconf NPROCESSORS_ONLN) --force --deployment --without development test
yarn install --pure-lockfile
RAILS_ENV=production bundle exec rails assets:precompile

I got a compile error here complaining about ‘bcrypt_ext’.  According to https://stackoverflow.com/questions/3900180/no-such-file-to-load-bcrypt-ext-via-devise it sounds like it doesn’t build native extensions (??), so I tried all this, no idea how much of it actually ended up being necessary:

cd ~/vendor/bundle/ruby/2.4/gems/bcrypt-3.1.12/ext/mri
cp ~/gem-overrides/bcrypt-3.1.12/ext/mri/*.c .
cp ~/gem-overrides/bcrypt-3.1.12/ext/mri/*.h .
ruby extconf.rb
make
make install

cp ~/vendor/bundle/ruby/2.4/gems/bcrypt-3.1.12/ext/mri/bcrypt_ext.so ~/vendor/bundle/ruby/2.4/extensions/amd64-freebsd-12/2.4/bcrypt-3.1.1

Still had issues, noticed by comparing with another ‘with native extensions’ gem (‘pg’) that it was calling from a different folder, looking for it in the same folder as its ‘bcrypt.rb’ in ‘lib’, so:

cp ~mastodon/gem-overrides/bcrypt-3.1.12/ext/mri/bcrypt_ext.so ~mastodon/gem-overrides/bcrypt-3.1.12/lib/
cd ~mastodon
RAILS_ENV=production bundle exec rails assets:precompile

Finally, progress!  At this point, uws will fail to compile (this is normal even on FreeBSD 11), so we need to rebuild it.  The normal install process seems to clean up after itself a bit too much when it fails, so we have to do this by hand to make sure it leaves its source behind:

npm rebuild uws
cd node_modules/uws/build

Then fire up your editor of choice on ‘uws.target.mk’ and delete both lines that read:

-fno-exceptions \

Then we manually compile (via gmake, not make!) and copy the resulting binary where it’s needed:

gmake
cp Release/uws.node ..

Oh, hey, UWS still doesn’t work, throwing an SSL error, because we’re still on Node 8.  Well, time to try Node 10… (remember to leave the bundled OpenSSL option on, I guess?  Also reconfigure www/npm and www/yarn to use www/node10 instead of www/node8)… and run through all this again until it works.  Apparently Mastodon’s package.json explicitly asks for ‘between 8 and 11’, i.e. not 11, so hopefully 10 + bundled SSL works.

(I tried going all the way to Node 11 and editing package.json to allow it.  Errors.  Errors everywhere.  Don’t do that, stick to 10.)

Looks like ‘node-zopfli’ hasn’t been updated in years (and thus doesn’t compile on newer versions of Node?), but someone made a ‘zopfli-node’ last week that maybe does?

So, change the line in package.json from node-zopfli 2.0.2 and re-run the things:

"zopfli-node": "^2.0.3"

…can we have an alternative that doesn’t suck from a SysAdmin / Ops standpoint?  Please? :/  I get that libraries are great, and all, but this is obscene.