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

> 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.

**debops/debops** — DebOps - Your Debian-based data center in a box

- Repository: https://github.com/debops/debops
- Website: https://debops.org/
- Stars: 1,426 · Forks: 377
- Language: Jinja
- License: not declared
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/debops-debops

## 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:

```
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:

```
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:

```
pipx install --user debops[ansible]
```

The Ansible Galaxy route installs a collection instead:

```
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:

```
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.

## 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.

## FAQ

### 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.

## Sources

- [debops/debops on GitHub](https://github.com/debops/debops)
- [Issues](https://github.com/debops/debops/issues)
- [Project website](https://debops.org/)
- [README](https://github.com/debops/debops/blob/master/README.md)
- [Releases](https://github.com/debops/debops/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/debops-debops
