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.
This system implements stateless infrastructure management on Proxmox VE, ensuring deterministic reproducibility and environmental parity through recursive self-containment.
Concept | Approach | Reasoning |
---|---|---|
Ephemeral State | Git repository represents current desired state, ensuring state purity across deployments. | Deployment consistency and stateless infrastructure over version history. |
Recursive Self-Containment | Control plane seeds itself by pushing its monorepository onto a locally bootstrapped instance, triggering a pipeline that recursively provisions the control plane onto PVE. | Environmental parity for local and PVE, enabling one-click deployment from version-controlled monorepository. Reuse of validated, generic base. |
Dynamic Orchestration | Imperative logic (e.g. config/recipes/repo.rb ) used for dynamic, cross-layer state management. |
Declarative approach intractable for adjusting to dynamic cross-layer changes (e.g. submodule remote rewriting). |
Monorepository | Centralizes infrastructure as single code artifact, using submodules for modular composition. | Consistency and modularity: infrastructure self-contained; dynamically resolved in recursive context. |
-
Loosely coupled: Containers are decoupled from the control plane, enabling runtime replacement and independent operation.
-
Headless container configuration: By convention, Ansible is used for provisioning (
community.proxmox
upstream); Cinc (Chef) handles modular, recursive desired state complexity. -
Integrated Baseline: The
base
role standardizes defaults in container configuration. The control plane leverages this baseline and uses built-in infrastructure libraries to deploy itself recursively, establishing an operational pattern that is reproduced in containerlibs
.
-
Complexity vs. Autonomy: Recursive self-replication increases complexity drastically to achieve integrated deterministic bootstrap and reproducing behavior.
-
Git Convention vs. Infrastructure State: Uses Git as a state engine rather than 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.
git clone --recurse-submodules
, e.g. for Version-Controlled Mirroring
-
Backup: See Self-Containment
- use
local/share/
for persistence or self-reference network share
- use
-
Update: See Self-Containment, and redeploy merged
-
Rollback: See Self-Containment, or push
rollback
torelease
at runtime
Appendix: The self-referential language in this section is intentional. It mirrors the system's recursive architecture, implying lifecycle operations emerge from the principle itself.
- Docker
- Proxmox VE 8.4-9.0
- See Wiki for recommendations
- Set Proxmox and global usage credentials in
local/.config.json
as./local/config.json
- Ensure container configuration in
config.env
and verify storage - Run
./local/run.sh
for local Docker environment - Accept the Pull Request at
localhost:8080/main/config
to deploy on Proxmox VE
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
config.env
to 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.
- Optionally, use
Env.get()
andEnv.set()
to access Gitea environment variables.
-
The container can be tested locally running
./local/run.sh [container]
: