Files
SRCmail/VNCMAIL-SETUP.md
T
Bernd RodlerandClaude Opus 4.8 a3d551b640 feat(deploy): k8s manifests for microk8s (vncmail.sandbox.vnc.de)
Bulwark is stateful (local /app/data) — Vercel serverless (read-only fs)
crashes it. Deploy as a container with 4 persistent volumes on microk8s,
alongside bulwark.sandbox.vnc.de. Adds deploy/k8s/ (namespace, pvc, deployment,
service, ingress, secret template, runbook) + rewrites setup doc off Vercel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 17:09:54 +02:00

77 lines
3.8 KiB
Markdown

# VNCmail+ — setup & deploy runbook
VNCmail+ is VNC's fork of [Bulwark](https://github.com/bulwarkmail/webmail), a
Next.js (App Router) JMAP webmail client for **Stalwart**. Stalwart is the source
of truth; VNCmail+ is the UI. It deploys as a **container on Kubernetes
(microk8s)** at `vncmail.sandbox.vnc.de` — see **[deploy/k8s/](deploy/k8s/README.md)**.
> **License:** AGPL-3.0. Serving a modified VNCmail+ to users over the network
> obligates VNC to offer those users the corresponding source. Keeping this fork
> public (with a "Source" link in the imprint/UI) satisfies that. Loop in legal
> before a public/customer-facing launch if a closed fork is ever desired.
## Architecture — why a container, not Vercel
- Bulwark is a **stateful, long-lived server**: it persists settings-sync, admin
config/state, and telemetry to a **local data directory** (`/app/data/*`).
- **Vercel serverless was tried and dropped** — its filesystem is read-only
except `/tmp`, so Bulwark's `mkdir ./data` crashes (`ENOENT /var/task/data`).
You cannot point its data dirs at a remote host either (they're POSIX paths,
not URLs). Bulwark's native model is a container + persistent volumes.
- So VNCmail+ runs as a Docker image (`ghcr.io/brvncde-dotcom/vncmail-plus-*`)
with **4 persistent volumes**, exactly like the existing `bulwark.sandbox.vnc.de`.
- JMAP calls go through **server-side `/api/*` routes** (`proxy.ts`) → server-to-
server to Stalwart, **no browser CORS**. Config is **runtime-read**.
## Branches (dev-first)
| Branch | Role |
|--------|------|
| `main` | **Production** — CI builds `…/vncmail-plus-beta`. Only updated by an explicit promote. |
| `dev` | Integration + QA — CI builds `…/vncmail-plus-dev` on push. Default working branch. |
| `vnc/*`| Feature branches for UI work (branch off `dev`, PR into `dev`). |
All VNC customization lives under `vnc/` (see `vnc/VNC-CHANGES.md`).
## Deploy (Kubernetes / microk8s)
Full runbook: **[deploy/k8s/README.md](deploy/k8s/README.md)**. In short:
1. CI builds the image on push to `dev`/`main``ghcr.io/brvncde-dotcom/vncmail-plus-dev` (`.github/workflows/docker-publish.yml`).
2. `kubectl apply` the manifests in `deploy/k8s/` (namespace, 4 PVCs, deployment, service, ingress) + a `secret.yaml` (from `secret.example.yaml`) + a `ghcr-pull` image-pull secret.
3. Point `vncmail.sandbox.vnc.de` DNS at the ingress; cert-manager issues TLS.
Runs alongside the existing `bulwark.sandbox.vnc.de`. Match your cluster's
StorageClass / IngressClass / cert issuer to bulwark's (see the runbook).
## Deploy workflow (dev-first — ALWAYS)
Same flow as every other VNC/SRC repo:
1. Work on `dev` (or `vnc/*` → PR into `dev`). Push to `dev` → CI builds the `-dev` image → `kubectl -n vncmail rollout restart deploy/vncmail-plus` to pull it. QA at `vncmail.sandbox.vnc.de`.
2. **Promote to production only on explicit go-live** — merge `dev``main`:
```bash
git log dev..main # MUST be empty — main must have nothing dev lacks (else prod would revert)
git checkout main && git merge --ff-only dev
git push origin main # CI builds the production image
git checkout dev
```
Then roll the production deployment to the new image (pin its digest — see deploy/k8s/README.md).
Never push straight to `main`. Never let a dev→main merge silently revert prod.
## Syncing upstream (Bulwark releases)
Bring upstream into `dev` (NOT main), integrate + QA on the dev image, then promote as above:
```bash
git fetch upstream
git checkout dev && git merge upstream/main # resolve conflicts via vnc/VNC-CHANGES.md; QA on preview
```
## Auth
Basic auth via Stalwart is the default — users sign in with their
`@sandbox.vnc.de` address + password; VNCmail+ authenticates them over JMAP. No
extra config. (SSO via vncdirectory/OIDC is a later option — see
`vnc/vercel.env.template`.)