Infra as code incus

Created
Updated
Author Nicolas Dorriere Reading 2 min

In this post, I want to document a small but important part of my homelab workflow: how I deploy and update AdGuard Home on an Incus-based host using a GitOps approach.

The goal is simple: the desired version lives in Git, the automation pipeline reacts to changes, an immutable artifact is built, and OpenTofu applies the expected state through the Incus API. Instead of manually logging into the host and changing a running container, the update process is described, triggered, and reproduced from version-controlled configuration.

The diagram below shows the overall flow. Everything runs on the same physical Incus machine, but responsibilities are split across dedicated LXC containers: one for management, one for automation, and one for the AdGuard Home service itself. The Incus daemon acts as the control plane that manages those containers, while persistent volumes keep the service data separate from the replaceable application container.

WORKSTATION: macOS
Bump AGH v0.107.54 → v0.107.55

Git Push / Version Control
Same Physical Machine — Immutable Host / Incus OS
LXC: Management
  • Forgejo
  • GitOps Source of Truth
  • OpenTofu State Backend

Webhook Trigger
LXC: Automation
  • Laminar Job : adguard.run

    imperative  bash — build AGH  v0.107.55  image/artifact

    declarative  opentofu — apply desired state

Incus API over HTTPS :8443
Incus Daemon
  • API / control plane
  • Profiles
  • Storage
  • Networks
  • Lifecycle management
→ manages →
LXC: AdGuard Home
  • Active version: v0.107.55
  • Configuration and data mounted from persistent volumes
  • Beszel metrics enabled

uses
Persistent Volumes
  • AdGuard Home configuration
  • Work directory
  • Runtime data

Another important aspect of this setup is that it relies entirely on lightweight, open-source software.


All fit well in a small homelab environment because they do not require heavy orchestration layers or large memory footprints.

The automation part is intentionally kept simple too: Laminar does not hide the workflow behind complex abstractions, it just runs straightforward Bash scripts. That makes the deployment pipeline easy to read, easy to debug, and easy to reproduce.

 

.tf incus

https://library.tf/providers/lxc/incus/latest

https://github.com/lxc/terraform-provider-incus

Close
Fullscreen image