eigenbase — Ansible Workstation Provisioning
eigenbase is the provisioning layer of the Eigenstack — a self-hosted, privacy-first infrastructure stack built in Germany. It configures a full DevOps workstation in under 5 minutes from a clean Ubuntu 24.04 install. One command. No manual steps.
Repository: github.com/serg-markovich/eigenbase
Problem
Every time I set up a new machine, I spent hours reinstalling tools,
hunting down configs, and debugging things that worked last time.
Nothing was recorded. Nothing was reproducible.
A single mv ~/projects ~/work could silently break three services.
The real problem wasn't missing tools — it was missing declarations.
Solution
A declarative Ansible playbook where the state of the machine lives in git, not in memory. Running it on a fresh machine or an existing one produces the same result. If CI passes, the playbook is correct. Not "probably correct" — verifiably correct on a clean environment.
Stack
| Tool | Role |
|---|---|
| Ansible | Provisioning engine |
| ansible-lint | Idempotency and code quality enforcement |
| GitHub Actions | CI — lint + syntax-check on every push |
| community.general | UFW firewall, extended OS modules |
Helm via get_url |
Kubernetes package manager — no curl piping |
| Kind | Local Kubernetes cluster for dev |
Architecture
eigenbase/
├── roles/
│ ├── base/ ← packages, locale, timezone
│ ├── docker/ ← Docker CE + Compose
│ ├── kubernetes/ ← kubectl, Helm, k9s
│ ├── monitoring/ ← node_exporter
│ ├── ollama/ ← local LLM runtime
│ ├── security/ ← UFW, SSH hardening
│ └── eigenstack_dev/ ← Kind cluster for local dev
├── site.yml
├── requirements.yml ← explicit collection dependencies
└── Makefile ← install, lint, syntax, run
What I built and why it matters
Replaced curl | bash with get_url + unarchive
Most Helm and Ollama install guides use curl | bash.
It works once. It's not idempotent, not auditable,
and Ansible can't track what it did.
Switching to get_url + unarchive means Ansible owns
the binary lifecycle — install, update, verify.
Declared collection dependencies explicitly
community.general.ufw worked on my machine.
CI had never heard of it. Adding requirements.yml
and installing collections before lint runs
removed the last implicit dependency on my local environment.
Set up CI before expanding roles
Lint and syntax-check went in at v0.1.0,
before the role count grew. It caught two real bugs
during the same session: a misplaced mode parameter
and a missing collection. Both silent in local runs.
Both caught immediately on a clean CI runner.
Honest limitations
- Currently single-host —
inventory/localhost.ymlonly - No secrets management yet —
.envin.gitignore, Ansible Vault or SOPS planned for next iteration - Molecule tests scaffolded but not written
eigenbase is part of a larger project: Eigenstack — Sovereign Self-Hosted Cloud (Germany) This role provisions the machine. The next layer runs services on it.