For a personal project I’m working on, and for GoToSocial, I’ve wanted to run Mastodon locally to write integration tests against. Forgejo wants this too, to test their federation code. The problem is, you want to do that against a Mastodon instance that runs in “production” mode (i.e RAILS_ENV=production), except without all the TLS and https URL generation turned on. But in production mode, you normally can’t turn this off. This is good, and safe, and sound. But for integration tests it gets in our way.
Disclaimer
Before we go any further, DO NOT DO THIS to a Mastodon production instance. What I’m about to do is only safe on ephemeral Mastodon instances that are not connected to the internet, do not federate, and are only used for integration tests. DO NOT DO THIS to your Mastodon instance. Really. DON’T. With that out of the way…
Time to crime!
What I need to do is override a number of hardcoded settings in Mastodon’s config/environments/production.rb. But I don’t want to sed a bunch of files across the code base. Thankfully, Mastodon is written in Ruby On Rails and it’s very easy to turn that into Ruby Off The Rails. All I need is to use a built-in facility in Rails, the initializers! Mastodon actually comes with a bunch of them, in config/initializers. These run after configuration and gems are loaded. That can be a little too late, but thankfully there’s the before_initialize event I can hook into to help me out!
So here we go:
Rails.application.config.before_initialize do
Rails.application.config.consider_all_requests_local = true
Rails.application.config.action_controller.perform_caching = false
Rails.application.config.cache_store = :null_store
Rails.application.config.action_controller.allow_forgery_protection = false
Rails.application.config.action_mailer.perform_caching = false
Rails.application.config.action_mailer.perform_deliveries = false
Rails.application.config.action_mailer.raise_delivery_errors = false
Rails.application.config.public_file_server.enabled = true
Rails.application.config.force_ssl = false
Rails.application.config.x.use_https = false
mailer_opts = Rails.application.config.action_mailer.default_url_options || {}
Rails.application.config.action_mailer.default_url_options = mailer_opts.merge(
protocol: 'http'
)
end
Drop this file in config/initializers as zz_overrides.rb and you’re done! For the official Mastodon container, you can bind-mount the file in /opt/mastodon/config/initializers. For testcontainers, use the built-in copy file facility.
But. BUT. But Daenney! Why are you setting protocol: http on ActionMailer, that’s a gem to send e-mails! And you disable it earlier with perform_deliveries = false! Also, protocol: http for emails? What are you smoking?
Glad you asked. I do that because Mastodon merges those settings into Rails’ default_url_options. Why do they load the Action Mailer default_url_options in Rails routing helpers? Idk. Ask Eugene. He did it 9 years ago in commit 1dad72bf13f5e2. This landed in Mastodon 0.1.0.
Conclusion
And with that, we’re done. Mastodon is now production unsafe, ready for integration testing!