Proxmox-GitOps implements a self-contained GitOps environment for provisioning and orchestrating Linux Containers (LXC) on Proxmox VE.
Encapsulating infrastructure within an extensible monorepository - recursively resolved from Git submodules at runtime - it provides a comprehensive Infrastructure-as-Code (IaC) abstraction for an entire, automated container-based infrastructure.
The architecture is based on a multi-stage pipeline capable of recursively deploying and configuring itself as a self-managed control plane.
Initial bootstrapping is performed via a local Docker environment, with subsequent deployments targeting Proxmox VE.
Proxmox-GitOps standardizes stateless infrastructure and automates container-based deployment on Proxmox VE.
| Concept | Approach | Reasoning |
|---|---|---|
| Desired State | Monorepository as Single Source of Truth represents the entire infrastructure state. | Deterministic bootstrap from code over version history. |
| Self-Containment | The composite monorepository is pushed to a local container, triggering a pipeline that provisions onto Proxmox. | Fully automated infrastructure deployment mirroring local development. |
| Dynamic Configuration | Imperative logic (e.g. config/recipes/repo.rb) used for dynamic, cross-layer state management. |
Declarative approach intractable for dynamic cross-layer changes (e.g. submodule remote rewriting). |
| Monorepository | Centralizes infrastructure as a single code artifact, utilizing submodules for modular composition. | Provides modular container base; dynamically resolved for container-specific workflow control. |
-
Decoupled Architecture: Containers operate independently, allowing for runtime replacement and detached operation.
-
Headless container configuration: By convention, Ansible is used for provisioning (
community.proxmoxupstream); Cinc (Chef) handles modular, recursive desired state complexity. -
Integrated Baseline: The
baserole standardizes container configuration defaults. Proxmox-GitOps leverages this baseline and built-in infrastructure libraries to deploy itself, establishing a reproducible operational pattern to reuse for containerlibs.
-
Complexity vs. Autonomy: Self-containment increases complexity to achieve automated bootstrap and reproducible behavior.
-
Git as State Engine: Uses Git as a state engine rather than for versioning in volatile, stateless contexts. Monorepository representation, however, encapsulates the entire infrastructure as a self-contained asset suited for version control.
-
API Token Restriction vs. Automation: With Proxmox 9, stricter privilege separation prevents privileged containers from mounting shares via API token; automation capabilities, however, are mainly within the root user context. As a consequence, root user-based API access takes precedence over token-based authentication.
- Docker
- Proxmox VE 8.4-9.1
- See Wiki for recommendations
-
Set Proxmox VE host and default account credentials in
local/config.json. -
Adjust environment configuration in
globals.json. -
Ensure container configuration in
container.env. -
Run
./local/run.shfor local Docker environment. -
Accept the Pull Request at
http://localhost:8080/main/configto deploy on Proxmox VE.
-
Global environment variables can be set in
globals.json. -
container.stage.envis sourced for forked-repository deployments. -
.localfiles can be used to structure versioning; e.g.globals.local.json,container.local.envor10-assistant.local.caddy
- run
release: creates and configures a container. - run
main: configures an existing container. - run
snapshot: creates a snapshot leveragingUtils.snapshot. - run
rollback: rolls back configuration changes.
git clone --recurse-submodules, e.g., for Version-Controlled Mirroring.
-
local/share/can be used for persistence. -
Backup, Update and Rollback: See Self-Containment, which mirrors the system's architecture, implying lifecycle operations emerge from the principle itself.
Reusable container definitions are stored in the libs folder.
Copy an example container (like libs/broker or libs/proxy) as a template, or create a new container lib from scratch and follow these steps:
- Add
container.envto your container's root directory (e.g../libs/apache):
IP=192.168.178.42
ID=42
CORES=2
MEMORY=2048
SWAP=512
DISK=local-lvm:8
BOOT=yes- Add your cookbook to the container definition root:
# libs/apache/recipes/default.rb
package 'apache2'
file '/var/www/html/index.html' do
content "<h1>Hello from #{Env.get(node, 'login')}</h1>"
mode '0644'
owner Default.user(self) # see base/roles/base/tasks/main.yml
group Default.group(self) # each container is configured identically
end
Common.application(self, 'apache2') # provided by convention-
Add to Monorepository and redeploy.
-
Container
libscan be tested locally by running./local/run.sh [container]:
- Optionally, use
Env.get()andEnv.set()to access environment variables, initially set by globals.