Deploy your own alpstack¶
alpstack is the config behind a small, self-hosted openDesk platform — Talos, Cilium, Longhorn, ArgoCD, Galera/Postgres, Keycloak, Synapse, Nextcloud, OpenProject, mail, monitoring, NetBird and Vaultwarden — sized for a family or a small organisation. This guide is for a different operator who wants to stand up the same stack on their own hardware, their own domain and their own cloud.
This is a reference architecture, not a turnkey product
alpstack is published so you can replicate it by reading and adapting — not
(yet) as a parameterised product you helm install with a values file. A
moderately experienced Kubernetes operator can get to a working stack from these
docs; someone who has never run a cluster cannot. The couplings you'll need to
replace are catalogued in What you must change,
and the honest expectation is "possible without consulting us", not "trivially
easy". If real adopters appear, the project may grow toward a
values-driven chart family — see the roadmap.
What you get¶
A single GitOps-reconciled cluster running:
- openDesk — the BMI's sovereign-workplace suite: Univention identity (Keycloak), Nextcloud (files), OpenProject, Collabora (office), Element/Synapse (chat), XWiki, and groupware mail (Open-Xchange + Postfix/Dovecot).
- A production-grade substrate replacing openDesk's demo backing services: Galera (MariaDB), Percona PostgreSQL, Valkey, Memcached and Garage (S3) — all with off-site S3 backups.
- Platform services — Cilium (CNI + kube-proxy replacement + host firewall), Longhorn (storage), cert-manager, Sealed Secrets, VictoriaMetrics/Logs monitoring, and Gateway-API ingress.
- Remote access — NetBird (WireGuard mesh) and Vaultwarden.
See Architecture for how the four repos and three ArgoCD instances fit together.
What you'll need¶
| Requirement | Notes |
|---|---|
| Hosts | 3 control-plane + N worker nodes (bare metal or VMs) that can boot Talos Linux. Ours run 3 CP + 6 workers; smaller works. |
| A DNS domain | You control the zone. Many public sub-domains (id., portal., matrix., smtp.…) and an internal wildcard (*.apps.int.<domain>) are published under it. |
| An edge firewall | Something that DNATs a fixed set of NodePorts to the workers (we use an OPNsense HA pair with CARP). See the NodePort contract. |
| S3-compatible object storage | For Longhorn, Postgres/MariaDB and Garage off-site backups. We use Exoscale SOS; any S3 endpoint works. |
| A secrets vault | Somewhere you keep master passwords and private keys (we use Psono). Not the cluster — the cluster only ever holds sealed secrets. |
| An OIDC IdP | openDesk ships Keycloak, which becomes your IdP — you don't need an external one. |
| Ops skills | Comfortable with kubectl, helm, talosctl, ArgoCD and DNS. |
How this guide is organized¶
Read these pages in order the first time:
| Page | What it gives you |
|---|---|
| What you must change | The complete inventory of hardcoded couplings, per repo, with file references. |
| Configuration values | The global.* values that redirect the stack to your domain, cluster and cloud. |
| Secrets | Every secret the stack expects, and how to seal your own set against your controller. |
| (this page, below) | The bootstrap walkthrough. |
| License & contributing | How alpstack is licensed and how to track upstream. |
Getting started — the bootstrap walkthrough¶
The stack builds bottom-up in four layers. Each layer is one repo with its own
bootstrap/README.md; this walkthrough is the map, and the per-repo READMEs carry
the exact commands.
Fork first
Fork all four repos into your own Git host, then work on your forks. Tracking our
updates later is a git merge upstream/main (see Track upstream).
0 · Prepare¶
- Pick your identifiers now and keep them in one place — you'll reuse them
everywhere: cluster name, base domain, internal domain
(
apps.int.<domain>), S3 endpoint/region, and your Git owner. The full list is Configuration values. - Provision your secrets vault and generate a master password — most of openDesk's secrets derive from it (see Secrets).
1 · Layer 1 — Talos (the OS + empty cluster)¶
Repo: talos-cluster. Talos is reusable out of the box; only a handful of
talosctl gen config inputs are yours.
- Build (or reuse) a Talos image-factory schematic with the documented system extensions.
talosctl gen config <your-cluster-name> https://<api-endpoint>:6443with the repo's--config-patch @patch-*.yamlset. Edit the patches' embedded site values first — node subnet, nameserver/NTP, per-CP metrics IPs, the Dex OIDC issuer URL, and the API-server's embedded CA cert. These are itemised in What you must change → Talos.- Apply configs,
talosctl bootstrap, fetch the kubeconfig.
You now have an empty, encrypted, CNI-less cluster. Cilium arrives in Layer 2.
2 · Layer 2 — Platform (platform-argocd)¶
Repo: platform-argocd. This installs the platform ArgoCD, then Cilium,
Longhorn, cert-manager (your <cluster>-ca / <cluster>-issuer), Sealed Secrets,
monitoring and Gateway-API ingress via the app-of-apps pattern.
- Set your
values/global.yaml(source-repo URL, cluster name, base/internal domains, S3 backup target). - Bootstrap Sealed Secrets and seal your own platform secrets (Longhorn S3 creds, ArgoCD repo credentials, etc.) before the first sync — the committed sealed values are ours and are useless in your cluster.
- Bootstrap the platform ArgoCD and seed the app-of-apps (
bootstrap/README.md), then watch it reconcile.
3 · Layer 3 — Addons (addons-argocd)¶
Repo: addons-argocd. NetBird (remote access) and Vaultwarden, plus the mail-mesh
routing that publishes IMAP/SMTP over NetBird.
- Seal the addon secrets (NetBird PAT, Vaultwarden SSO + backup age key).
- The NetBird mail-routing uses manually pinned ClusterIPs, hand-rolled EndpointSlices and a server-generated Network UUID — none of which port across clusters. What you must change → Addons walks through re-pinning them for your cluster.
4 · Layer 4 — openDesk (opendesk-argocd)¶
Repo: opendesk-argocd. The production backing services (Galera, Percona PG,
Valkey, Garage) plus a helmfile pipeline that renders the upstream openDesk charts
and feeds them to ArgoCD as manifests.
- Set the openDesk domain/host map, Garage buckets, and the three backing-store bucket names (Configuration values).
- Run the
generate-*script to render openDesk with your master password → sealed secrets, then sync in the documented order (the 13 databases + 13 DB users and the Keycloak realm are created by the upstream render — treat them as a set, not individual edits).
openDesk is consumed upstream, not forked
We render the upstream openDesk deployment
via its own helmfile and override only what we must. You do the same — don't fork
their repo. The couplings that live inside that render (DB/user names, Matrix
server_name, the realm) are flagged "entwined — upstream render" throughout
these docs.
Customise what you need¶
Not every layer is mandatory. The optional pieces:
- NetBird / Vaultwarden (whole
addons-argocdrepo) — skip if you don't need a mesh VPN or a password manager. openDesk itself doesn't depend on them. - Mail-over-NetBird — our family reads mail only over the mesh; a normal setup can expose IMAP/SMTP through the edge firewall instead and drop the pinned-ClusterIP plumbing entirely.
- coturn / TURN — needed only for Element calls; disable if you don't use them.
- imapsync — a one-shot migration tool for importing existing mailboxes; delete after cutover.
Operate it¶
Once running, the day-to-day is the same as ours — see Operations and the Runbooks (node maintenance, storage, upgrades). Monitoring and a daily/weekly digest email come with the platform layer.
Track upstream¶
At reference-architecture tier the update model is fork + manual merge — the same way we consume openDesk:
git remote add upstream https://codeberg.org/alpstack/<repo>.git
git fetch upstream
git merge upstream/main # resolve conflicts against your customisations
Your changes cluster in a few predictable places (values/global.yaml, your sealed
secrets, the clusters/<name>/ overlay), so merges mostly touch chart structure, not
your values. Renovate-style auto-tracking of chart bumps only becomes available if the
project moves to a published-chart model.
Roadmap¶
This guide documents the setup well enough to replicate it. A fully parameterised,
helm install-able version — with versioned chart releases you'd track via Renovate —
isn't a goal today; it would only make sense if external adopters actually appear and
ask for it. Everything here (the customization surface, the values schema, the secrets
inventory, the license) is the groundwork that would build on.
Next: What you must change →