Shared Caddy on :443 and easydeploy-net for running multiple Easy Deploy kits on one VPS.
Each product kit can use proxy.mode: integrate to emit a Caddy fragment; this engine assembles them and runs a single easydeploy_caddy container.
Kits stay independent: you can still clone opencloud-easy-deploy (or Kanidm, or Matrix) and run bash wizard.sh on its own. The engine is the one-VPS path that clones those repos as siblings and runs their wizards for you.
Kanidm is the organisation identity source. Users, groups, and authentication live there. Applications do not keep their own account databases for normal login.
EasyDeploy
│
▼
Kanidm
users / groups
authentication
OIDC / LDAP
│
┌─────────┼─────────┐
│ │ │
OIDC OIDC LDAP
│ │ │
OpenCloud Matrix Stalwart
See docs/integrated-vps.md and kanidm-easy-deploy/docs/identity.md.
git clone --recurse-submodules https://github.com/opencomp-eu/easydeploy-engine.git
cd easydeploy-engine
bash wizard.shThe wizard can:
- Clone Kanidm, OpenCloud, Matrix, and/or Stalwart next to this repo (if they are not already there), or update existing checkouts to
engine.kit_branch, withgit clone --recurse-submodules --branch <branch>. - Run each kit’s
wizard.sh(domains, admin user, …). - Switch those kits to
proxy.mode: integrate. - Apply Kanidm then apps, wire OpenCloud and Matrix OIDC plus Stalwart LDAP, and start shared Caddy.
The clone branch defaults to feature/engine (where the engine-aware kit changes live today). After those land on main, set engine.kit_branch: main in engine.yaml, pass --branch main, or answer main in the wizard.
Re-run a kit apply.sh, then engine apply.sh, whenever a fragment or domain changes. Re-run bash wizard.sh to add a service. For version bumps, bash update.sh.
Power users can skip the wizard: write engine.yaml, put each service’s deploy.yaml in kits/, and run bash apply.sh.
Same model as a kit: desired state in YAML, apply.sh converges.
git clone --recurse-submodules https://github.com/opencomp-eu/easydeploy-engine.git
cd easydeploy-engine
cp engine.yaml.example engine.yaml
# enable kanidm + opencloud + matrix + stalwart in engine.yaml
# One-time: clone kits so you can copy examples (or let the first apply.sh clone them)
bash apply.sh --ensure-dependencies # fails until deploy YAML exists — that's ok
cp ../kanidm-easy-deploy/deploy.yaml.example kits/kanidm.yaml
cp ../opencloud-easy-deploy/deploy.yaml.example kits/opencloud.yaml
cp ../matrix-easy-deploy/deploy.yaml.example kits/matrix.yaml
cp ../stalwart-easy-deploy/deploy.yaml.example kits/stalwart.yaml
# edit domains, users, auth in kits/*.yaml (do not commit secrets)
bash apply.shapply.sh then:
- Clones missing sibling kits on
engine.kit_branch(--sync-kitsalso updates existing clones). - Copies
kits/<name>.yaml→<kit>/deploy.yamlwhen that file exists (override withservices.<name>.deploy). - Sets
proxy.mode: integrateon each kit. - Writes identity sidecars, applies Kanidm then apps, starts shared Caddy.
Later changes: edit kits/opencloud.yaml (or engine.yaml) and run bash apply.sh again.
Updates: bash update.sh pulls the engine and enabled kit repos, merges new tag / tools_tag pins from each kit’s deploy.yaml.example into your operator YAML (kits/*.yaml or kit deploy.yaml), then runs the full apply (pull images, recreate containers). Use --skip-tags to keep your current image pins, or --skip-git when not using git checkouts.
--skip-kits only reloads Caddy / identity sidecars without touching kit stacks.
If kits/<name>.yaml is absent, the kit’s own deploy.yaml is used — so you can still keep config in each repo.
A kit the engine can clone and run looks like this (Kanidm, OpenCloud, Matrix, and Stalwart already do):
| File | Role |
|---|---|
wizard.sh |
Interactive setup; writes deploy.yaml |
apply.sh |
Converge config and start that kit’s stack |
update.sh |
Pull git repos, sync image tags, then apply everything |
deploy.yaml |
Operator config (created by the wizard) |
wizard.sh also accepts --from-engine (used by this wizard): set proxy.mode: integrate and write deploy.yaml without applying — the engine applies in order.
Checkout layout (siblings of this repo), cloned on engine.kit_branch (default feature/engine):
../kanidm-easy-deploy←https://github.com/opencomp-eu/kanidm-easy-deploy.git../opencloud-easy-deploy←https://github.com/opencomp-eu/opencloud-easy-deploy.git../matrix-easy-deploy←https://github.com/opencomp-eu/matrix-easy-deploy.git../stalwart-easy-deploy←https://github.com/opencomp-eu/stalwart-easy-deploy.git
See engine.yaml.example. Each enabled service needs:
path— root of the kit checkoutfragment— relative path to the Caddy snippet (written by that kit’s apply)
When Kanidm and an app kit are enabled, apply.sh writes integration sidecars so you do not have to paste OIDC/LDAP config by hand:
- Kanidm OAuth2 client →
.kanidm-easy-deploy/integration/oidc-clients.d/<id>.yaml - OpenCloud IdP settings →
.opencloud-easy-deploy/integration/oidc-provider.yaml - Matrix MAS upstream →
.matrix-easy-deploy/integration/oidc-provider.yaml - Stalwart directory →
.stalwart-easy-deploy/integration/identity-provider.yaml
When Stalwart/Bulwark is enabled, apply also writes embed sidecars so OpenCloud and Element can load inside Bulwark's inline iframe. Those use bulwark.domain from the Stalwart kit (or identity.consumers.stalwart.webmail / embed.frame_ancestors in engine.yaml). Each kit can add more origins in embed.frame_ancestors or set embed.managed: false.
Then re-apply Kanidm, then the app kit (the engine wizard does this order for you).
Kanidm OIDC issuers are per client: https://idm.example.com/oauth2/openid/opencloud and https://idm.example.com/oauth2/openid/matrix. Stalwart/Bulwark uses /oauth2/openid/stalwart-webui for webmail SSO; IMAP/SMTP clients use a Stalwart app password.
Same VPS: kit wizards ask “Use Kanidm on this VPS?” when they find ../kanidm-easy-deploy/deploy.yaml (the engine wizard auto-accepts).
Split VPS: leave the app off this engine; set auth.oidc (OpenCloud) or features.sso (Matrix) or identity (Stalwart) on the other host. On the Kanidm host you can still register a remote client with:
identity:
consumers:
opencloud:
domain: cloud.other-vps.example
matrix:
domain: matrix.other-vps.example
stalwart:
hostname: mail.other-vps.example
mail_domain: other-vps.exampleOpt out: identity.wire: false, or auth.oidc.managed: false / auth.oidc.provider: keycloak on OpenCloud, or features.sso.managed: false / a non-Kanidm features.sso.providers list on Matrix, or identity.managed: false on Stalwart.
- Network name must be
easydeploy-net. - Warns if known standalone Caddy containers still exist.
uv sync --dev
uv run pytestSee also docs/integrated-vps.md and each kit’s integration docs.