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>
77 lines
3.8 KiB
Markdown
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`.)
|