Open-source project
debops/debops avatar
debops/debops

DebOps in practice: roles, inventory, and a Dockerfile that disagrees with the quick start

DebOps - Your Debian-based data center in a box

1,426 stars377 forksJinjaLicense varies

At a glance

What is it?
DebOps packages general-purpose Ansible roles for Debian and Ubuntu hosts and customizes them through inventory. Its own build files tell three different stories about base image, SPDX scope and version numbering.
Who is it for?
DebOps earns its place for teams that already live in Ansible and want opinionated, inventory-driven roles for databases, web servers and virtualization on Debian-family hosts. The parts to verify before adopting it are all in its build files rather than its prose.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Jinja, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Roles are shared, inventory holds the differences

The project supplies general-purpose Ansible roles for Debian and Ubuntu hosts, plus a default set of playbooks that applies those roles in a controlled way through Ansible inventory groups. The customization story is the part worth understanding before anything else: options are set in inventory rather than in the role code, so the same roles and playbooks can be shared between environments that need different configuration. A service can be managed on one host or spread across many. The stated coverage includes SQL and NoSQL databases, web servers, programming languages, and specialized applications useful in a data center or a cluster. Virtualization is part of the same offer, with KVM/libvirt, Docker and LXC named as the technologies it can deploy. The recorded primary language for the repository is Jinja, which follows from roles being templates rather than scripts.

The quick start names Buster while the Dockerfile builds on trixie

The quick start tells you to start a container acting as an Ansible Controller with DebOps support, described as based on Debian Buster. The Dockerfile in the repository says something different, in two stages from the same slim base:

code
FROM debian:trixie-slim AS builder

A builder stage installs the packaging toolchain, Sphinx, pandoc and make, then runs `make man wheel-quiet` and copies `lib/docker/docker-entrypoint` into place. A second, identical-base stage installs the runtime set, including iproute2, iputils-ping, vim, openssh-client, procps, sudo, tree, sshpass, make, git and man-db, followed by a pip install step. Buster and trixie are far apart in Debian's lifecycle, so anyone sizing Python and Ansible versions from the quick start text is sizing them from the wrong release. The container is also only one of three routes in.

Three install routes, two artifact formats

The container route and the Vagrant route both clone the source and run from the `src/controller` subdirectory, and both end with the same command:

code
docker run -it --rm debops/debops
cd src/controller ; debops run common --diff

Vagrant does the same work on a local VM after `vagrant up && vagrant ssh`. The other two routes install artifacts instead of cloning. The Python package carries the roles and playbooks plus helper scripts, and the documented install is:

code
pipx install --user debops[ansible]

The Ansible Galaxy route installs a collection instead:

code
ansible-galaxy collection install debops.debops

Those two produce different layouts on disk, and the `debops project init` and `debops run` helpers that the quick start assumes come from the Python package rather than from a bare collection.

Password authentication is disabled and the image installs sshpass

Ansible reaches hosts over SSH, and DebOps enforces SSH security by disabling password authentication, which is why SSH keys are strongly recommended. The behavior is not hardcoded into a role you cannot touch: it is described as changeable through inventory variables, consistent with the project's inventory-driven design. The second warning is operational. During initial deployments you may find that the firewall created by DebOps has blocked you from the hosts, so out-of-band console access is advisable for login and troubleshooting. The runtime image carries `sshpass` in its package list, which sits oddly beside a policy of disabled password logins: the tool is there for hosts that still require one, and the project is candid that securing the server is part of your side of the arrangement.

make check refuses to run on a dirty working tree

The Makefile is a thin dispatcher over the test suite, and two of its entries change how you work. The sanity target declares a dependency before it does anything:

code
SPHINXFLAGS ?= -n -W

check: fail-if-git-dirty

So `make check` is gated on a clean tree rather than on passing tests, and the documentation build runs Sphinx in nitpicky mode with warnings promoted to errors. Every other name is an alias with a comment, which makes the file readable as an index: spdx for copyright and license checks, versions for upstream versions, docker for an image build, spell, docs, man, links, pep8, shell, syntax for playbook syntax, and collection for building with ansible-galaxy. The clean-git target is worth reading before running, since it calls `git clean -X -d -f` and removes every ignored file in the tree.

The package version is manufactured at build time by git describe

setup.py does not carry a version string. It shells out during the build, retrieves the project version from `git describe`, and writes it into `__version__.py` and a VERSION file, which the file comments say is needed for correct installation of the Python package. It also reads the long description from disk with a plain `README = open('README.md').read()`, and keeps a small compatibility shim that defines a `unicode` class when the name is missing on Python 3. A separate helper walks directories for package data, and its docstring records a real packaging failure: a glob pattern matching a directory can make setuptools try to install that directory as a file. Meanwhile pyproject.toml holds no build table at all, only codespell configuration.

SPDX headers disagree about or-later, and the license field is empty

Each file declares its own license, and the declarations do not match. pyproject.toml carries `SPDX-License-Identifier: GPL-3.0-only`, while setup.py, the Dockerfile and the Makefile carry `SPDX-License-Identifier: GPL-3.0-or-later`. The repository also has a LICENSES/ directory and a REUSE status badge wired into the overview, so the project takes the question seriously enough to have tooling for it. The license recorded for the repository itself is empty, and the overview links to GPL v2 by URL rather than naming a license for the project. Three files therefore give three answers, and picking one is a decision for the maintainers, not something a reader should infer. If compliance depends on the exact scope, that question is worth asking before the roles touch a production host.

Three tags in one afternoon, plus two CI systems

Three releases went out on the same day: v3.3.2, v3.2.8 and v3.1.9, all on 2026-09-28, which is the shape of parallel maintenance branches rather than a single line. The last push was 2026-10-01, the default branch is master, and the repository is not archived. It shows 1,426 stars and 426 open issues. Both CI systems are wired in, with a GitHub Actions badge for a Continuous Integration workflow and a GitLab CI pipeline badge pointing at gitlab.com/debops/debops, and the overview carries a CII Best Practices badge as well. Packaging extends past pip and Galaxy: PKGBUILD at the root brings Arch Linux into scope, and the top level also holds MANIFEST.in, setup.cfg, requirements.yml, requirements-integration.txt, a CODEOWNERS file and .pre-commit-config.yaml.

Editorial conclusion

DebOps earns its place for teams that already live in Ansible and want opinionated, inventory-driven roles for databases, web servers and virtualization on Debian-family hosts. The parts to verify before adopting it are all in its build files rather than its prose. Check which base image you actually get, since the quick start text and the Dockerfile name different Debian releases. Check the SPDX scope, because the recorded license field is empty and the headers disagree on or-later. Check how your version is produced, because the package version comes out of git describe at build time. And keep out-of-band console access, because the first deployment can lock you out with its own firewall. The distribution model itself is unfussy: a fork, a pull request, and a preference for signed commits.

Frequently asked questions

What does DebOps manage on a host?

General-purpose Ansible roles for Debian and Ubuntu hosts, applied by a default set of playbooks through Ansible inventory groups. Coverage includes SQL and NoSQL databases, web servers, programming languages, and virtualization with KVM/libvirt, Docker or LXC, on one host or spread across many.

How do you install DebOps?

Three documented routes. The Python package installs with pipx install --user debops[ansible], the Ansible collection installs with ansible-galaxy collection install debops.debops, and the container or Vagrant route clones the repository and runs debops run common --diff from the src/controller subdirectory.

Why do DebOps managed hosts need SSH keys?

DebOps enforces SSH security by disabling password authentication, so keys are strongly recommended, and the behavior can be changed through inventory variables. The overview also advises keeping out-of-band console access, because the DebOps firewall can block you from the hosts during an initial deployment.

Which license does DebOps use?

The recorded license field for the repository is empty, and the files disagree on scope: pyproject.toml carries GPL-3.0-only while setup.py, the Dockerfile and the Makefile carry GPL-3.0-or-later. The repository also has a LICENSES/ directory and a REUSE status badge.

What do the debops run and debops project init commands do?

debops project init creates a project directory, debops run site runs the full playbook against every host in the inventory, and debops run common -l <hostname> targets a single host. Hosts are declared in the ansible/inventory/hosts file inside the project directory.

Official sources

  1. debops/debops on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/debops-debops.svg)](https://hysenlabs.com/projects/debops-debops)