mother-of-all-self-hosting/mash-playbook: one Ansible playbook for an entire self-hosted stack
๐ Ansible playbook which helps you host various FOSS services as Docker containers on your own server
At a glance
- What is it?
- MASH is an AGPL-3.0 licensed Ansible playbook that installs FOSS services as Docker containers on your own server, absorbing several separate per-service playbooks into one repository with shared Postgres, Traefik and backup handling. The README is unusually direct about its trade-offs, including that upgrades can introduce backward incompatible changes, and that one large playbook does not mean one server.
- Who is it for?
- Adopt MASH if you self-host a set of open source services and you are tired of running a separate Ansible playbook per application, since the shared Postgres, Traefik and backup handling is the part that the per-service playbooks kept duplicating.
- 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 Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- mother-of-all-self-hosting/mash-playbook1,172 โ ยท +34
| Repository | 2026-10-19 | 2026-11-07 |
|---|---|---|
| mother-of-all-self-hosting/mash-playbook | 1.1k | 1.2k |
34 Stars in the last 19 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
A container per service, driven by one playbook
MASH, Mother-of-All-Self-Hosting, is an Ansible playbook that helps you self-host services as Docker containers on your own server.
The stated benefit of containers is predictability. By running services in containers, the project can have a predictable and up-to-date setup across multiple supported distros and CPU architectures, and it allows self-hosting of a large number of services that will continue to grow by adding support for FOSS software.
The service catalogue is the substance of the project. The topic list gives a taste of the range, with AdGuard Home, Authentik, a bind DNS server, Collabora Online, Etherpad, Forgejo, Headscale, Immich, Jellyfin, Jitsi, a Minecraft server, Nextcloud, ntfy, Paperless-ngx, PeerTube, Prometheus and Vaultwarden among them, and the full list lives in `docs/supported-services.md`.
That is a broad surface, and it is worth noticing the shape of it. These are not toy services. Most of them want a database, a reverse proxy in front of them, a backup story and a place for uploads. The interesting engineering in MASH is not the container definitions, it is the shared infrastructure that many applications all assume and that a dozen separate playbooks each had to implement.
The duplication that made a mega playbook make sense
The Why section of the README is the best argument for the project, and it is written as a history of a maintenance problem rather than as a feature list.
The maintainers used to keep separate playbooks for various services, naming the Matrix, Nextcloud, Gitea, GitLab, Vaultwarden and PeerTube playbooks. They re-used Ansible roles for Postgres and Traefik, but were still hard to maintain due to the large duplication of effort.
The reason is spelled out. Most of these playbooks hosted services which require a Postgres database, a Traefik reverse proxy, a backup solution, and so on, and all of them needed to come with documentation. All of those things need to be created and kept up to date in each and every playbook.
The consequence of the split was worse than duplication. Having to use a dedicated Ansible playbook for each and every piece of software means juggling many playbooks and making sure they do not conflict with one another when installing services on the same server. They did interoperate nicely, but still required a bit of manual configuration to achieve that interoperability. Trying out new software was difficult, because each one is a new git repository you need to clone and maintain. And not all pieces of software are large enough to justify having their own dedicated playbook, so they have no home, and so no one uses them.
That last point is the one that generalises. The problem was never that per-service playbooks were bad, it is that some services are too small to deserve one and most services share the same heavy lifting.
The small services finally get a home
The list of reasons the project gives for combining everything is six items, and the last three are the ones that a self-hoster will feel.
You do not need to juggle multiple Ansible playbooks. You can try out various services easily, since a few lines of extra configuration are enough. And small pieces of software can finally find a home, with Miniflux given as the example, powered by the project's own `ansible-role-miniflux`.
The rest are the infrastructure arguments. You can use a single playbook with the quality you know and trust. Shared services, like Postgres, are maintained in one single place. And backups are made easy, because everything lives together, with the same base data path and the same Postgres instance.
That last point is a genuine design choice with a genuine cost, and the project does not hide it. Co-locating everything in one playbook means one data path and one database instance, which makes backups trivial, and it also means the services share a failure domain. The README addresses that directly in the next paragraph, and it is the single most important operational caveat in the document.
One playbook, many servers
Having one large playbook with all services does not necessarily mean you need to host everything on the same server. The README is explicit that you can use as many servers as you see fit, and adds the reasoning. While containers provide some level of isolation, it is still better to not put all your eggs in one basket and create a single point of failure.
So the playbook is the unit of configuration, not the unit of deployment. The same repository, the same roles and the same conventions can target a dozen servers, each running a different subset of the catalogue, and the inventory file is what decides which services go where. The `justfile` shows the shape of that, with an `add-inventory-host` recipe that takes a hostname and a server address and creates the inventory files as needed, and with the inventory path taken from `ANSIBLE_INVENTORY` when it is set and falling back to `inventory/hosts` otherwise.
There is one deliberate exception. The Matrix playbook will remain separate, because it contains a huge number of components and will likely grow even more, and it deserves to stand on its own.
That is a reasonable line to draw. Matrix is not one service, it is a deployment with a dozen moving parts, and folding it into the same repository would have made the shared parts harder to change rather than easier.
Installation is documentation driven, and upgrades can break
The installation path is deliberately thin in the README. To configure and install services on your own server, you follow the README in the `docs/` directory, and installation, upgrades and some maintenance tasks are automated using Ansible, with the project's own Ansible guide at `docs/ansible.md`.
Then there is the paragraph that a careful adopter should read before the first run. This playbook evolves over time, sometimes with backward-incompatible changes, and when updating the playbook you are told to refer to the changelog to catch up with what is new.
That is a candid warning, and it changes how you should treat the repository. The playbook is the interface, not the containers underneath it. Upgrading MASH is not like pulling a newer image, it is like taking a new version of a configuration system that can rewrite your deployment, and the changelog is the migration notes.
The support model is small and reasonable. There is a Matrix room, and to join Matrix the README suggests a public server such as matrix.org or self-hosting Matrix with the related matrix-docker-ansible-deploy playbook, which is a nice touch since that project stayed separate from this one. GitHub issues are the other channel.
The tooling in the tree
The repository layout shows the quality gates, which is a good sign for a project that many people run unattended against their own servers.
There is an `.ansible-lint` configuration, a `.yamllint` configuration, a `.codespellrc`, a `.pre-commit-config.yaml` and an `.editorconfig`. There is an `AGENTS.md` and a `CHANGELOG.md`, plus a `VERSIONS.md` and a `releases.opml` feed, which is the shape a project takes when it wants people to follow along with changes rather than read release notes on a wiki.
The build and task runner is a `justfile` rather than a Makefile, and it is worth reading because it shows how the project actually works. The inventory comes from the environment, with a default of `inventory/hosts`. Development tool versions are managed with mise, with a `mise.toml` in the repository and the data directory pointed at a `var/` subdirectory. The pre-commit tool is installed into that same tree, with `PREK_HOME` pointing inside the checkout, so a contributor's global state is never touched.
The role update recipe is a practical detail with a real consequence. The project uses `agru` for fast Ansible role updates, and the recipe itself prints the alternative: if you do not have that tool, the standard `ansible-galaxy` tool works but is slow and lacks other features. The `roles/` directory holds the external roles pulled from Galaxy, and the rest of the tree, `group_vars/`, `templates/`, `run/`, `bin/`, `docs/` and `examples/`, is the conventional layout for a large Ansible project.
Licensing is handled with the REUSE specification, with a `REUSE.toml` file, a `LICENSES/` directory and separate `.license` files for the files that need them, and the justfile headers carry SPDX copyright and licence identifiers, which is a level of provenance hygiene that most Ansible projects do not reach.
Where MASH is the wrong choice
The first wrong case is a single service. The setup cost of the catalogue is the price of the catalogue, and if you want one file server you would be installing an infrastructure system to get it.
The second is a team that wants reproducible infrastructure as code in the usual sense. Ansible playbooks are imperative, the playbooks grow over time, and the project's own warning that upgrades can include backward incompatible changes says that the configuration is not a stable artefact you can pin. For a team that wants a small, reviewable, declarative description of its infrastructure, a tool that suits that better exists, and this is not one of them.
The third is a deployment that does not want Docker, or a shared hosting environment without root and without container support. The whole design assumes containers, a reverse proxy, a database and a base data path, and swapping those out is not a configuration change.
The fourth is a licensing question. AGPL-3.0 is permissive for running a playbook and restrictive for modifying and redistributing it, and a company that wants to fork the roles and keep the changes internal has to think about that.
On the state of the project, the repository is not archived and the last push was on 2026-10-19, and there are no GitHub releases at all, with versioning tracked through the changelog and the versions file instead. For a project this large and this opinionated, the release history is less informative than the commit history, and the sensible practice is to read the changelog before every upgrade, because that is the migration note the project publishes.
Editorial conclusion
Adopt MASH if you self-host a set of open source services and you are tired of running a separate Ansible playbook per application, since the shared Postgres, Traefik and backup handling is the part that the per-service playbooks kept duplicating. Do not adopt it for a single service, since the setup cost is the price of the catalogue, and do not expect the configuration to be a stable interface, because the project states that the playbook evolves with backward incompatible changes. Verify first that the services you need are in the supported services list, that your server's distribution and CPU architecture are among those the project claims to support, and that you read the changelog before each upgrade, since the playbook is the interface here rather than the containers underneath it.
Frequently asked questions
What does the MASH playbook do?
MASH, Mother-of-All-Self-Hosting, is an Ansible playbook that helps you self-host FOSS services as Docker containers on your own server, across multiple supported distros and CPU architectures, and it supports a large and growing number of services listed in `docs/supported-services.md`.
Why is MASH one big playbook instead of one per service?
Because the per-service playbooks duplicated everything. Most needed a Postgres database, a Traefik reverse proxy, a backup solution and documentation, all of which had to be created and kept up to date in each playbook, and juggling many playbooks meant making sure they did not conflict on the same server. Sharing those services in one place removes the duplication and gives small services, which could not justify their own playbook, a home.
Does MASH force everything onto one server?
No. The README says you do not need to host everything on the same server and can use as many servers as you see fit, while warning that while containers give some isolation, it is better not to put all your eggs in one basket and create a single point of failure. The Matrix playbook stays as a separate project because of its size.
What should I check before upgrading the MASH playbook?
The changelog. The project states that the playbook evolves over time, sometimes with backward-incompatible changes, and tells you to refer to the changelog to catch up with what is new before updating. The repository also carries a VERSIONS.md file and a releases feed.
How is the MASH repository maintained and checked?
The tree carries an `.ansible-lint` configuration, a `.yamllint` configuration, a `.codespellrc`, a `.pre-commit-config.yaml` and an `.editorconfig`, and the tasks are driven by a `justfile` that uses mise for development tool versions and the `agru` tool for fast Ansible role updates, with the standard ansible-galaxy path documented as a slower alternative.
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/mother-of-all-self-hosting-mash-playbook)Star history chart for your README
[](https://hysenlabs.com/projects/mother-of-all-self-hosting-mash-playbook)Was this useful?