Mastodon ships Ruby 4.0.7 in its image while the docs ask for 3.3, and three lines stay alive
GitHub describes it as Your self-hosted, globally interconnected microblogging community. The repository metadata lists Ruby as its primary language. The metadata lists the AGPL-3.0 license. This article stays within the project description and details documented in the GitHub repository README.
At a glance
- What is it?
- mastodon/mastodon is the AGPL-3.0 ActivityPub server written in Ruby on Rails, and the gap between what its documentation promises and what its build files actually do is where most self-hosting surprises live. Requirements list Ruby 3.3+ and Node 22+, the Dockerfile defaults to Ruby 4.0.7 and Node 24, the compose file starts Postgres with trust authentication and no search backend, and three release lines were patched on the same day.
- Who is it for?
- Mastodon is a serious piece of infrastructure for anyone who needs a server they control, and the federation claim holds because the network speaks ActivityPub rather than a proprietary protocol. The costs are operational rather than conceptual: five runtime dependencies with stated minimums, a compose file written for production that starts an unauthenticated database, a search backend that ships commented out, and a frontend test command that never touches the Ruby suite.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The Dockerfile defaults to Ruby 4.0.7 and Node 24 while the requirements say 3.3 and 22
The requirements list and the build arguments disagree, and the disagreement is larger than a version bump. The documented minimums are Ruby 3.3+, PostgreSQL 14+, Redis 7.0+, Node.js 22+, and FFmpeg 5.1+. The Dockerfile declares `ARG RUBY_VERSION="4.0.7"` and `ARG NODE_MAJOR_VERSION="24"`, on a trixie base pulled from docker.io, with a comment above the Node argument that suggests changing it to 22. The package.json agrees with the docs on the floor, declaring engines node >=22, and pins the package manager to [email protected]. So the artefact you get from a default build is not the oldest thing the project claims to support. That gap has a direct consequence: an operator who provisions to the documented floor is running a combination the maintainers do not ship, and a gem that resolves on 4.0.7 is not evidence that it resolves on 3.3. If your policy is to run the oldest supported version, you are now the compatibility test.
docker-compose.yml is written for production and starts Postgres with trust authentication
The compose file says so twice in its own header: it is designed for production server deployment, not local development work, and for a containerized development environment you should read the development documentation instead. What it starts is a db service on `postgres:14-alpine` with `shm_size: 256mb`, a healthcheck running pg_isready against the postgres user, a bind mount at ./postgres14, and one environment setting that deserves attention:
POSTGRES_HOST_AUTH_METHOD=trustTrust means the database accepts connections without a password. Along with redis on `redis:7-alpine` and a healthcheck of redis-cli ping, the file is a competent production skeleton, and both images line up with the stated minimums. The consequence is that the file is not safe to run unchanged on a host anything can reach, and the bind mounts mean the data directories sit on the host filesystem where a backup script will find them whether you meant it or not. Treat the file as a starting point to harden, not a finished deployment.
The Elasticsearch service in the compose file is commented out, so nothing starts a search backend
Below the two active services there is a third, es, and every line of it is commented. The block specifies an Elasticsearch image, sets ES_JAVA_OPTS with matching -Xms512m and -Xmx512m and a note that both must be the same size, disables several xpack features, sets xpack.security.enabled to false, requests unlimited memlock, names the cluster es-mastodon, sets discovery.type to single-node, and joins both an internal and an external network. As shipped, the compose file therefore starts a database and a cache and nothing else. If your deployment needs a search backend, this commented block is the only documentation of the settings the project expects, and it is a starting point that will run Elasticsearch with security switched off if you uncomment it verbatim. The heap note is the part worth heeding, since a mismatched minimum and maximum heap is a common way to lose an index.
Three release lines were patched on the same day, so the newest tag is not the only live one
The three most recent releases are v4.7.2, v4.6.8, and v4.5.18, and all three are dated 2026-09-15, minutes apart. That is the signature of a project maintaining parallel branches rather than a single moving line, and it changes how an operator should read a version number. Taking the highest tag tells you which line was cut last, not which line you should be on, and a 4.5 install is neither dead nor equivalent to a 4.7 install. The corollary is that security and bug fixes arrive per line on separate schedules, so an instance left on an older branch accumulates a growing gap that no badge on your dashboard will show you. Pick a line when you install, write down which one it is, and check its release page before assuming you are current. The main branch is where development happens, and the last push to it is dated 2026-09-29, well after those releases.
yarn test never runs the Ruby suite, and the storybook tests are a separate command
The frontend test script is one line and it is narrower than the name suggests:
"test": "yarn lint && yarn run typecheck && yarn test:js run"That is eslint plus stylelint through the lint script, then tsc with --noEmit, then vitest against the legacy-tests project. The storybook suite lives in its own command, vitest --project=storybook, and the browser tests the project advertises through Chromatic and BrowserStack are run by those services rather than by this script. Nothing here touches RSpec, so a green yarn test says nothing at all about the Rails application that serves the REST API. Two more scripts are worth knowing about. postversion is `git push --tags`, so a version bump pushes tags to the origin with no review step in between. And lint:js begins with `cd $INIT_CWD`, a variable set by the package manager rather than by your shell, so eslint runs in the wrong directory in a runner that does not export it.
The frontend package is private, so there is nothing to install from npm
The package.json is named @mastodon/mastodon and marked private, with workspaces for the root and for streaming, so the frontend is built from a clone rather than consumed as a dependency. The streaming side is a second workspace started on its own with node ./streaming/index.js, which is why the tech stack lists Node.js as the power behind the streaming API while Ruby on Rails serves the REST API and the web pages. PostgreSQL is the main database, Redis and Sidekiq handle caching and queueing, and React with Redux covers the dynamic parts of the interface. The tooling reflects the same split: an rspec config and a simplecov setup for Ruby, rubocop and haml-lint configs alongside the JavaScript lint and format chain, an annotaterb config for model documentation, and Storybook config for components. Two build systems, two test suites, and a translation pipeline through Crowdin that extracts strings into app/javascript/mastodon/locales/en.json.
A silent video is delivered as an animated image and a normal video loops without a stop control
Media handling has two documented behaviours that surprise people uploading their own content. Videos with no audio track are treated like animated GIFs, and normal videos loop continuously. Neither is a bug so much as a transfer of a web convention to a server that has no reason to know better, but both change what a user experiences. A silent clip arrives as animated image content rather than as a video file, which is what determines whether clients autoplay it, how a CDN treats it, and whether your storage grows at video or image rates. A video with sound loops forever in the timeline with nothing in the interface to stop it, so a post that plays the same few seconds endlessly is the expected result rather than a rendering fault. FFmpeg 5.1 or newer is a hard requirement for this processing, which is why it appears in the requirements list next to the database and the runtimes.
Deployment is offered through seven shapes, and the Helm chart lives somewhere else
The repository ships configuration for Docker and docker-compose, and states that configurations for other environments such as Heroku and Scalingo are included as well, with Helm charts handled by the separate mastodon/chart repository. The tree backs that up with a Dockerfile, a docker-compose.yml, a Procfile, a Procfile.dev, a Vagrantfile, a .foreman directory, .buildpacks, an Aptfile, an app.json for one-click deploy tools, a config.ru, and a chart directory, plus a .devcontainer and an official container image. Six runtime pieces have to move together on an upgrade: Ruby, PostgreSQL, Redis, Node, FFmpeg, and the Mastodon release itself, with Sidekiq workers and the streaming process restarting alongside the web process. Consequence for anyone planning an upgrade is that each of these shapes has its own update story, and choosing one means choosing who handles the database migration. A standalone installation guide sits in the main documentation, and FEDERATION.md at the root covers the federation side.
Editorial conclusion
Mastodon is a serious piece of infrastructure for anyone who needs a server they control, and the federation claim holds because the network speaks ActivityPub rather than a proprietary protocol. The costs are operational rather than conceptual: five runtime dependencies with stated minimums, a compose file written for production that starts an unauthenticated database, a search backend that ships commented out, and a frontend test command that never touches the Ruby suite. Before you commit, pick your release line deliberately rather than taking the newest tag, since 4.5, 4.6, and 4.7 were all patched on 2026-09-15 and they will not age at the same rate. Then decide which Ruby you are actually running: the official image builds on 4.0.7 while the documented floor is 3.3, so code that works in the container is not evidence that your floor is real. And if you deploy the shipped compose file, harden the database before the host is reachable.
Frequently asked questions
What is a Mastodon?
In this repository, Mastodon is a free, open-source social network server based on ActivityPub, described as a self-hosted, globally interconnected microblogging community. Servers are interoperable as a federated network, so a user on one server can communicate with users on another, including software that is not Mastodon.
What is Mastodon used for?
It publishes links, pictures, text, and video to a real-time chronological timeline, with media attachments, and it provides safety and moderation tools including private posts, locked accounts, phrase filtering, muting, blocking, and a reporting and moderation system. It also acts as an OAuth2 provider so third party apps can use the REST and Streaming APIs.
how to install mastodon on ubuntu
The page gives no distribution specific steps. It states requirements of Ruby 3.3+, PostgreSQL 14+, Redis 7.0+, Node.js 22+, and FFmpeg 5.1+, includes deployment configurations for Docker and docker-compose plus Heroku and Scalingo, points Helm users at the mastodon/chart repository, and links a standalone installation guide in the main documentation.
how to use hashtags on mastodon
The README does not describe hashtag behaviour. What it describes is a real-time chronological timeline, media attachments where silent videos are treated as animated GIFs and other videos loop continuously, private posts, locked accounts, phrase filtering, muting, blocking, and a reporting and moderation system.
how many use mastodon
The repository publishes no user, instance, or post counts. It is self-hosted software under AGPLv3, and the surrounding links go to the project homepage, a blog, a documentation site, a sponsors page, a Crowdin project for translations, and an app directory.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mastodon-mastodon)