Date 24 August; the demo environment is lab1 (zone lab1, lab1.makerfloss.eu outside / lab1.internal inside). Adds the upstream 'developing TAPPaaS modules' topology from tappaas.org ahead of our own repo picture, which now carries forgejo.makerfloss.eu and highlights that this site tracks main, not stable. Drops the manager-verbs slide; the demo slides carry the verbs where they are actually used, with network/environment/module status commands. Cockpit now logs in via identity:identity rather than a local PAM password, and identity hand-out uses 'authentik-manager user-recovery-link' so no password is ever read aloud. NOTE: podman.json in Community does not yet declare identity:identity — the module needs that change before the session.
316 lines
9 KiB
Markdown
316 lines
9 KiB
Markdown
---
|
|
marp: true
|
|
theme: gaia
|
|
class: invert
|
|
paginate: true
|
|
title: How to implement a TAPPaaS module
|
|
description: Live build of a Podman module — OrangeMaker, 24 August
|
|
---
|
|
|
|
<style>
|
|
section { font-size: 26px; }
|
|
h1 { font-size: 1.5em; }
|
|
h2 { font-size: 1.15em; }
|
|
pre { font-size: 0.7em; line-height: 1.35; }
|
|
table { font-size: 0.78em; }
|
|
th, td { padding: 0.2em 0.55em; }
|
|
/* Unfinished content, loud on purpose: an unfinished deck should never be
|
|
presented by accident. Written in the markdown as `TODO: ...`. */
|
|
code.todo { color: #ff8a80; font-weight: 600; }
|
|
/* Mermaid renders at its natural size, which is far too small on a projector. */
|
|
div.mermaid { display: flex; justify-content: center; width: 100%; }
|
|
div.mermaid svg { width: 100% !important; height: auto !important; max-height: 500px; }
|
|
section.diagram h2 { margin-bottom: 0.1em; }
|
|
</style>
|
|
|
|
<!-- _paginate: false -->
|
|
|
|
# Getting a module onto TAPPaaS
|
|
|
|
Live build of a **Podman** container host
|
|
|
|
OrangeMaker · 24 August
|
|
|
|
<!--
|
|
Slides are the map; the terminal is the territory. Everything here has a live
|
|
counterpart — keep the deck moving and spend the time in the shell.
|
|
-->
|
|
|
|
---
|
|
|
|
## The plan
|
|
|
|
1. **What TAPPaaS is** — a few diagrams, ten minutes, no deeper
|
|
2. **What a module actually is** — a json contract and three scripts
|
|
3. **Build one live** — the `lab1` environment, then `podman` into it
|
|
4. **Prove it works** — tests, then the web console
|
|
5. **You get a login** — your own identity on this system
|
|
|
|
You leave with: a mental model, a module you watched get built, and an account.
|
|
|
|
---
|
|
|
|
<!-- _class: invert diagram -->
|
|
|
|
## The shape of a TAPPaaS site
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
sat["satellite VPS<br/>public IP · ingress<br/>off-site backup"]
|
|
subgraph z0["mgmt · zone mgmt"]
|
|
cicd["tappaas-cicd"]
|
|
net["network"]
|
|
clu["cluster"]
|
|
bak["backup"]
|
|
idp["identity"]
|
|
end
|
|
subgraph z1["default · zone srv"]
|
|
nc["nextcloud"]
|
|
ha["home-assistant"]
|
|
end
|
|
subgraph z2["lab1 · zone lab1"]
|
|
pod["podman — today"]
|
|
end
|
|
sat --> net
|
|
cicd --> nc
|
|
cicd --> pod
|
|
```
|
|
|
|
---
|
|
|
|
## The words we will use
|
|
|
|
| Word | Meaning |
|
|
| --- | --- |
|
|
| **Module** | The smallest deployable unit — its own VM, its own json contract. Foundation *and* apps are modules. |
|
|
| **Environment** | A tenant. `mgmt` and one named after the site always exist; add more freely. Today we add `lab1`. |
|
|
| **Zone** | A VLAN with a firewall policy. Modules land in their environment's zone. |
|
|
| **Mothership** | `tappaas-cicd` — where the managers run and where you type. |
|
|
| **Satellite** | Optional VPS, for sites with no usable public IP. |
|
|
|
|
Everything is a module. There is one model to learn, not eight.
|
|
|
|
---
|
|
|
|
<!-- _class: invert diagram -->
|
|
|
|
## Developing modules: dev instance, private branch
|
|
|
|
```mermaid
|
|
flowchart RL
|
|
subgraph Development["Development repository"]
|
|
dev_main["main"]
|
|
end
|
|
subgraph Upstream["Upstream repository"]
|
|
up_main["main"]
|
|
up_stable["stable"]
|
|
up_main -->|merge| up_stable
|
|
end
|
|
subgraph InstanceDev["TAPPaaS instance · dev"]
|
|
localDev["clone of Upstream"]
|
|
localDev_dev["clone of Development"]
|
|
end
|
|
subgraph InstanceProd["TAPPaaS instance · prod"]
|
|
localProd["clone of Upstream"]
|
|
end
|
|
localProd -->|pull| up_stable
|
|
localDev -->|pull| up_main
|
|
localDev_dev -->|push| dev_main
|
|
dev_main -->|PR| up_main
|
|
```
|
|
|
|
---
|
|
|
|
<!-- _class: invert diagram -->
|
|
|
|
## Our setup tonight
|
|
|
|
```mermaid
|
|
flowchart RL
|
|
subgraph t["TAPPaaS · codeberg"]
|
|
stable["stable"]
|
|
main["main"]
|
|
end
|
|
subgraph c["Community · codeberg"]
|
|
cm["main"]
|
|
end
|
|
subgraph f["forgejo.makerfloss.eu"]
|
|
fm["main"]
|
|
end
|
|
subgraph inst["Our TAPPaaS · tappaas-cicd"]
|
|
lt["clone of TAPPaaS"]
|
|
lc["clone of Community"]
|
|
lf["clone of MakerFLOSS"]
|
|
end
|
|
lt -->|pull| main
|
|
lc -->|pull| cm
|
|
lf -->|pull| fm
|
|
classDef tracked stroke:#ff8a80,stroke-width:3px
|
|
class main tracked
|
|
```
|
|
|
|
We track **`main`**, not `stable` — this is a lab, we want the new things.
|
|
|
|
---
|
|
|
|
## A module is a contract and three scripts
|
|
|
|
```text
|
|
podman/
|
|
├── podman.json # the contract — what it is, needs, provides
|
|
├── install.sh # put the software in the VM (once)
|
|
├── update.sh # keep it patched (on schedule)
|
|
├── test.sh # prove it still works (gates updates)
|
|
├── README.md # what it is
|
|
└── INSTALL.md # what automation cannot do for you
|
|
```
|
|
|
|
That is the whole surface. Everything else is the platform's job.
|
|
|
|
---
|
|
|
|
## The contract, for real
|
|
|
|
```json
|
|
{
|
|
"description": "Podman container host — Debian 13 VM with rootless Podman + Cockpit",
|
|
"vmname": "podman", "vmid": 812,
|
|
"dependsOn": ["cluster:vm", "templates:debian", "backup:vm",
|
|
"network:proxy", "identity:identity"],
|
|
"config": {
|
|
"cluster:vm": { "cores": 2, "memory": "2048", "diskSize": "20G",
|
|
"image": "debian-13-generic-amd64.qcow2" },
|
|
"network:proxy": { "proxyPort": 9090, "proxyUpstreamTls": true,
|
|
"proxyUpstreamHttp1": true, "proxyAllowedZones": ["mgmt"] }
|
|
}
|
|
}
|
|
```
|
|
|
|
`dependsOn` is the whole trick: five services, declared — not scripted.
|
|
|
|
---
|
|
|
|
## The three scripts, honestly
|
|
|
|
| Script | Called | Does |
|
|
| --- | --- | --- |
|
|
| `install.sh` | once, at add | For podman: `exec update.sh` — install *is* update here |
|
|
| `update.sh` | every schedule | apt: `podman`, `podman-compose`, `cockpit`, `cockpit-podman`; enable the rootless socket |
|
|
| `test.sh` | on demand + before every update merge | VM reachable · podman present · plugin present · console answers on `:9090` |
|
|
|
|
If `test.sh` is honest, unattended updates are safe. That is the entire deal.
|
|
|
|
---
|
|
|
|
## What you did not have to write
|
|
|
|
- A VM — `cluster:vm` built it from the Debian 13 cloud image
|
|
- OS prep — `templates:debian` did apt + guest agent
|
|
- A VLAN, an interface, DHCP, firewall rules — the zone came with the environment
|
|
- `https://podman.lab1.makerfloss.eu` with a real certificate — `network:proxy`
|
|
- A login — `identity:identity`, so it is your TAPPaaS account, not a local one
|
|
- Nightly backup to PBS, scheduled updates, health reporting
|
|
|
|
A few lines of json bought all of it.
|
|
|
|
---
|
|
|
|
## Demo 1 — an environment of our own
|
|
|
|
```bash
|
|
network-manager zone add lab1 --from-zone srv
|
|
network-manager show lab1 # vlan tag, subnet, access-to
|
|
network-manager reconcile # dry-run: drift on all 4 planes
|
|
network-manager reconcile --apply # converge OPNsense, Proxmox, switch, AP
|
|
|
|
environment-manager add lab1 --display "MakerFLOSS lab" \
|
|
--zone lab1 --domain lab1.makerfloss.eu
|
|
environment-manager list
|
|
environment-manager show lab1
|
|
```
|
|
|
|
A tenant with its own VLAN, firewall posture and DNS names —
|
|
`lab1.makerfloss.eu` outside, `lab1.internal` inside.
|
|
|
|
<!-- Show zones.json before/after, and the OPNsense interface appearing. -->
|
|
|
|
---
|
|
|
|
## Demo 2 — install the module
|
|
|
|
```bash
|
|
module-manager module add podman --environment lab1
|
|
|
|
module-manager module list # what is deployed
|
|
module-manager module show podman # the resolved config, cascade applied
|
|
```
|
|
|
|
Watch the order: dependencies resolve first, then the VM, then the network, then
|
|
`install.sh`. Install order is **computed** from every module's `dependsOn` — nobody
|
|
maintains a list.
|
|
|
|
<!-- Expect a few minutes. Good moment for questions. -->
|
|
|
|
---
|
|
|
|
## Demo 3 — prove it, then look at it
|
|
|
|
```bash
|
|
module-manager module test podman
|
|
```
|
|
|
|
Then open **`https://podman.lab1.makerfloss.eu`** — Cockpit, with the Podman page.
|
|
|
|
- Reachable from the `mgmt` zone only. Not from the internet, by declaration.
|
|
- You log in with your **TAPPaaS identity** — that is what the `identity:identity`
|
|
dependency buys; no per-VM Linux passwords to hand out.
|
|
|
|
---
|
|
|
|
## Where this module lives
|
|
|
|
```text
|
|
Community/src/larsrossen/containers/podman/
|
|
```
|
|
|
|
Three homes for a module, all first-class:
|
|
|
|
| Home | For |
|
|
| --- | --- |
|
|
| **TAPPaaS** repo, by pull request | modules the whole project should carry |
|
|
| **Community** repo | yours, shared, no gatekeeping — today's podman |
|
|
| **Private** repo — e.g. `forgejo.makerfloss.eu` | yours, not shared |
|
|
|
|
Adding a repository is one `site-manager repository add`.
|
|
|
|
---
|
|
|
|
## Your turn — identity on this TAPPaaS
|
|
|
|
```bash
|
|
people-manager user add <you> --email <you>@example.org \
|
|
--roles user --groups <group>
|
|
people-manager reconcile # preview
|
|
people-manager reconcile --apply # push to Authentik
|
|
|
|
authentik-manager user-recovery-link <you> # one-time URL: set your own password
|
|
```
|
|
|
|
One login per person, roles via groups. Nobody types a password into a chat window.
|
|
|
|
`TODO: which group do participants land in?`
|
|
|
|
<!-- Do these live, one per participant, while the podman VM builds. -->
|
|
|
|
---
|
|
|
|
## Take it further
|
|
|
|
- **Develop a module** — tappaas.org/generated/develop-a-module
|
|
- **Every json field** — tappaas.org/generated/schemas
|
|
- **Zones and the access model** — tappaas.org/generated/zones
|
|
- **Repository topology** — tappaas.org/generated/design/cicd-git
|
|
- **This deck** — slides.makerfloss.eu/tappaas/how-to/new-module
|
|
|
|
Pick an app you want on a sovereign box. Open an issue first — someone may already
|
|
be packaging it.
|