7.1 KiB
nbops-ansible
nbops
Infrastructure as Code for notBoris' Homelab
nbops is the central operations repository for my hosted infrastructure, containing everything required to provision, configure, and maintain my virtual machines and services. The goal is to treat my infrastructure as code for reproducibility and automation from source control, while having minimal manual intervention.
About
nbops-ansible contains the configuration management layer of the nbops platform.
Every virtual machine begins life as a standardised Debian 13 GenericCloud template, provisioned by Proxmox and bootstrapped with Cloud-Init. Once the operating system has completed its initial configuration, the host runs ansible-pull against this repository to configure itself according to its assigned role.
A freshly created virtual machine should require little more than a hostname, network configuration and SSH key before automatically configuring itself into a production-ready host.
Design Philosophy
This repository follows a layered approach where each component has a clearly defined responsibility.
flowchart TD
A[GitHub: nbops-ansible] --> B[Proxmox VE]
B --> C[Debian 13 GenericCloud Template]
C --> D[Clone VM]
D --> E[Cloud-Init Bootstrap]
E --> F[ansible-pull]
F --> G[Apply Base Roles]
G --> H[Apply Service Roles]
H --> I[Docker Compose]
I --> J[Running Services]
Layer Responsibilities
flowchart LR
P[Proxmox VE<br/>VM lifecycle<br/>storage<br/>networking]
D[Debian 13<br/>GenericCloud<br/>minimal OS]
C[Cloud-Init<br/>identity<br/>network<br/>bootstrap]
A[Ansible<br/>desired state<br/>roles<br/>configuration]
DC[Docker Compose<br/>service runtime]
S[Applications<br/>actual workloads]
P --> D --> C --> A --> DC --> S
Repository Structure
. ├── inventories/ │ ├── production/ │ └── development/ │ ├── playbooks/ │ ├── roles/ │ ├── base/ │ ├── docker/ │ ├── ssh/ │ ├── ufw/ │ ├── mtls/ │ ├── monitoring/ │ ├── traefik/ │ ├── authentik/ │ ├── immich/ │ ├── gitea/ │ ├── arr/ │ ├── ocis/ │ └── pterodactyl/ │ ├── group_vars/ ├── host_vars/ ├── templates/ ├── files/ ├── scripts/ └── docs/
As the infrastructure grows, additional functionality should be implemented as new roles rather than modifying existing ones wherever practical.
Configuration Workflow
Cloud-Init is intentionally lightweight.
Its responsibility is limited to preparing the operating system by configuring:
- Hostname
- Networking
- DNS
- Users
- SSH
- Docker
- Firewall
- Internal CA trust
- Base packages
Once complete, Cloud-Init hands over to Ansible.
Ansible is responsible for configuring and maintaining the desired state of every machine for the remainder of its lifecycle.
Roles
The repository is built around reusable Ansible roles; every server receives a common baseline before additional service-specific roles are applied.
Core Roles
- base
- docker
- ssh
- ufw
- mtls
- monitoring
- updates
Service Roles
- traefik
- authentik
- gitea
- Pelican
- etc..
This approach allows new services to inherit the same security, logging and operating system configuration while remaining independent from one another.
Operating System Standard
Unless otherwise required, every virtual machine deployed by nbops follows the same baseline.
- Debian 13 (Trixie)
- GenericCloud image
- UEFI (OVMF)
- Q35 machine type
- VirtIO networking
- VirtIO SCSI storage
- QEMU Guest Agent
- Docker Engine
- Docker Compose Plugin
- Chrony
- UFW
- SSH key authentication only
Standardising the operating system significantly reduces maintenance overhead and configuration drift across the environment.
Infrastructure Principles
The following principles guide every decision made within this repository.
- Everything should be reproducible.
- Everything should be version controlled.
- Manual configuration should be avoided.
- Infrastructure should be disposable rather than unique.
- Security should be built into the baseline.
- Applications should remain isolated from the operating system wherever possible.
- Configuration should be modular and reusable.
Future Goals
Planned work includes:
- Automated Debian template creation
- Cloud-Init template generation
- Automated certificate management
- Secret management
- Monitoring and alerting
- Backup automation
- Configuration validation
- Disaster recovery testing
- Multi-node infrastructure support
Contributing
This repository is primarily maintained for my own homelab, but the techniques and playbooks may be useful to others building similar self-hosted environments.
Suggestions, improvements and ideas are always welcome.
License
Unless otherwise stated, all code within this repository is released under the MIT License.
nbops-ansible
Ansible repository for a reproducible Proxmox-based Infrastructure as Code
platform using Debian 13 GenericCloud, Cloud-Init, Docker Engine, Docker Compose,
and ansible-pull.
Model
Proxmox
-> Debian 13 GenericCloud template
-> clone
-> Cloud-Init
-> ansible-pull
-> base roles
-> service roles
-> Docker Compose
Cloud-Init handles Day 0 bootstrap only. Ansible owns Day 1 onward state.
Layout
inventories/: production and development inventoriesplaybooks/: site and pull entrypointsroles/: reusable core and application rolesgroup_vars/: shared defaultshost_vars/: per-VM overridestemplates/: Cloud-Init and shared templatesscripts/: local helper scriptsdocs/: operational notes
Roles
Core roles:
basesshufwupdatesdockermtlsmonitoring
Application roles:
traefikauthentikimmichgiteaocispterodactylarr
Enable roles per host with nbops_roles.
nbops_roles:
- base
- ssh
- ufw
- updates
- docker
- mtls
- monitoring
- traefik
VM Topology
Every VM is expected to run Docker. Put docker in nbops_roles for each VM.
The edge VM normally runs traefik and authentik, with Traefik publishing
ports 80 and 443. Downstream VMs can run their own internal Traefik and set
nbops_service_routing_mode: traefik so applications register with Traefik
instead of exposing individual host ports.
See host_vars/edge.yml.example, host_vars/downstream.yml.example, and
docs/topology.md. The full Docker service list is in docs/service-catalog.md.
Bootstrap
Render templates/cloud-init-user-data.yml.j2 with host variables and pass it to
Proxmox as user-data. The template installs baseline packages, Docker from
Docker's official Debian repository, configures UFW and SSH, creates /srv and
PKI directories, and executes ansible-pull.
Secrets
Secrets are intentionally excluded. Do not commit passwords, API keys,
certificates, private keys, or generated .env files. Use Ansible Vault, SOPS,
Vault, or Smallstep-backed issuance when introducing real secret material.
Validation
ansible-galaxy collection install -r requirements.yml
scripts/check.sh