Architecture
Project Loom is an app-agnostic, reconciliation-based platform: a single k3s node (this
instance is arm64)
that provides edge, TLS, delivery, and databases, then lets apps plug in. The same provision + overlay process runs on
the next server. Only hosts and ApplicationSet rows change. Traefik is the sole public edge.
Operators and workloads are reconciled from webb1es/loom by
Argo CD. Each workload lives under workloads/<app> (Penvoice is one example).
Topology
Section titled “Topology”The diagram below shows the platform layer plus a single generic <app>
workload. Add more apps by dropping another workloads/<app> alongside it.
flowchart TB
subgraph ext[Externals]
SPA[App frontend<br/>e.g. Vercel SPA]
Oracle[Oracle Object Storage<br/>Postgres backups]
GHCR[GHCR<br/>container images]
Mail[OCI Email Delivery<br/>SMTP 587]
end
Internet((Internet)) -->|"80 / 443"| Traefik
subgraph node[k3s node]
Traefik[Traefik edge<br/>+ cert-manager TLS]
subgraph platform[platform layer]
subgraph argocd[ns: argocd]
Argo[Argo CD<br/>+ Rollouts]
end
subgraph cm[ns: cert-manager]
CM[cert-manager]
end
subgraph cnpg[ns: cnpg-system]
CNPG[CloudNativePG operator]
end
subgraph kcop[ns: keycloak]
KCop[Keycloak operator]
end
subgraph kci[ns: keycloak-<env>]
KCi[Keycloak instance]
KCpg[(keycloak-pg)]
end
subgraph inf[ns: infisical]
InfSecOp[Infisical Secrets Operator]
InfSrv[Infisical server]
Infpg[(infisical-pg)]
end
end
subgraph app[ns: <app>-<env>]
API[<app> Rollout]
APIpg[(<app>-pg)]
AppSec[(<app>-api-kc<br/>operator-owned)]
end
Traefik --> Argo
Traefik --> KCi
Traefik --> InfSrv
Traefik --> API
API --> APIpg
KCi --> KCpg
InfSrv --> Infpg
InfSecOp -->|reads project| InfSrv
InfSecOp -->|writes| AppSec
AppSec --> API
end
SPA -->|JWT to| API
SPA -->|PKCE login| KCi
GHCR -->|pulls image| API
APIpg -->|WAL + base backup| Oracle
KCpg -->|WAL + base backup| Oracle
Infpg -->|WAL + base backup| Oracle
API -->|SMTP, own credentials| Mail
KCi -->|realm SMTP| Mail
You (the operator, not the software kind) edit secret values through Infisical’s browser UI: the Infisical Secrets
Operator is what turns that into the plain Kubernetes Secret <app>-api-kc each Rollout already reads via envFrom.
See
Secrets.
Apps and Keycloak send email out to OCI Email Delivery on port 587, each with its own credentials. See Email.
80/443 are open to the internet (Traefik). Run kubectl on the node, or locally over Tailscale.
Access.
What runs where, and how
Section titled “What runs where, and how”Two delivery mechanisms: a one-time Helm bootstrap for the platform plumbing, then continuous reconciliation for everything else (the remaining operators + your apps). See Reconciliation & the app-of-apps for the reconcile model.
The platform layer is fixed; the app rows are templated. Each app you onboard adds one reconciled row under
workloads/<app>.
| Component | How | Namespace |
|---|---|---|
| cert-manager | Helm: Provision | cert-manager |
| Argo CD / Rollouts | Helm: Provision | argocd |
| CNPG operator | Reconciled: apps/cnpg-operator | cnpg-system |
| Keycloak operator | Reconciled: apps/keycloak-operator | keycloak |
| Keycloak instance + Postgres (per env) | Reconciled: ApplicationSet | keycloak-<env> |
| Infisical server + secrets operator + Postgres | Reconciled: apps/infisical* | infisical |
<app> + Postgres + Redis (per env) | Reconciled: workloads/<app>/overlays/<env> | <app>-<env> |
The Helm layer is Argo CD + cert-manager (you cannot bootstrap Argo with Argo itself). No metrics stack yet. Once Helm
is
up,
bootstrap/root-app.yaml takes over and reconciles the rest. Every operator and every workloads/<app>.
Pinned versions
Section titled “Pinned versions”Exact chart/operator versions installed during the Helm bootstrap of the platform:
| Chart / operator | Version |
|---|---|
| cert-manager | v1.20.2 |
| argo-cd | 9.5.21 |
| argo-rollouts | 2.41.0 |
| CloudNativePG | 0.28.3 (operator v1.29.1) |
| Keycloak operator | 26.6.3 |
| Infisical (server chart) | 1.10.0 |
| Infisical Secrets Operator | 0.11.8 |
Live endpoints
Section titled “Live endpoints”Platform consoles are fixed; app endpoints follow each app’s own domain.
| URL | What | Served by |
|---|---|---|
loom.webbies.dev | This guide | off-cluster or static host |
control.webbies.dev | Argo CD (apps portal) | Traefik → argocd |
uat.auth.webbies.dev | Keycloak UAT | Traefik → keycloak-staging |
auth.webbies.dev | Keycloak prod | Traefik → keycloak-prod |
vault.webbies.dev | Infisical UI | Traefik → infisical |
api.<domain> | <app> API | Traefik → <app>-<env> |
<domain> | <app> frontend | external (e.g. Vercel) |
Ready to add an app?
Section titled “Ready to add an app?”The recipe (Dockerfile, CI to GHCR, ApplicationSet rows, overlays, optional CNPG, timed canary) is the Onboard an app playbook. A new node is Provision.