docs: add CI deployment and internal-TLS guidance, cross-reference from generic

Add two new guidance documents alongside generic.md:

- deployment-gitea-actions.md: CI-driven deployment via a Gitea Actions
  workflow as an alternative to deploy.sh + manifest.yml (§7), with the
  workflow as the source of infra truth and a scoped gitea_ci runner user.
- internal-tls.md: provisioning and renewing per-service internal TLS
  certs (<service>.internal) for mesh-only nginx vhosts, extending the
  PKI conventions in §11.

Cross-reference both from generic.md and list them in readme.md. Also
add a "never suppress errors" rule to the deploy-script conventions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-14 15:43:18 +03:00
parent 83652460ed
commit 200c41b4f1
4 changed files with 365 additions and 0 deletions

View File

@@ -279,6 +279,14 @@ Config file templates use a simple `{{VAR_NAME}}` syntax. `deploy.sh` substitute
## 7. Deployment Script (`script/deploy.sh`)
> **Alternative: CI-driven deployment.** When a project should redeploy from a Gitea
> Actions workflow instead of an operator running `deploy.sh`, see
> **`deployment-gitea-actions.md`**. In that model the workflow itself is the source of
> infra truth (no `manifest.yml`), the runner SSHes in as a dedicated `gitea_ci` user
> with a scoped sudoers drop-in, and one-time host prep lives in
> `script/infra-setup.sh`. The `asset/` layout (§6) and the on-host conventions
> (§8§11) are otherwise identical. The two models coexist; pick per project.
A bash script with a stable CLI:
```
@@ -311,6 +319,7 @@ A bash script with a stable CLI:
- Quiet on success, loud on failure.
- Supports `--dry-run` to print what would happen.
- Never writes secrets to disk on the build host outside of the rendered template being rsynced.
- **Never suppress errors.** Do not use `2>/dev/null`, `|| true`, or any pattern that hides error output or swallows exit codes. If a command might fail legitimately (e.g. stopping a service that isn't installed yet on first deploy), handle the failure explicitly with a visible message (e.g. `cmd || info "service was not running"`). If a command shouldn't fail, let it fail loudly — `set -euo pipefail` will catch it. This rule applies to all shell scripts in the project, not just `deploy.sh`.
---
@@ -520,6 +529,12 @@ The service unit itself needs an `ExecReload=` that causes the daemon to re-read
Ship these `.path` and cert-reload `.service` units from `asset/systemd/` the same way as the main unit.
**Per-service internal certs.** The paths above are the host *identity* cert. A service
fronted by its own mesh name (e.g. an nginx vhost at `<service>.internal`, distinct from
the host FQDN) needs its own cert — minted via the `lair` provisioner and renewed by a
templated `step@<name>` unit. That pattern is documented separately in
**`internal-tls.md`**.
### Ingress
- Per-site nginx reverse proxy terminates all WAN inbound 443.
- Public DNS via Cloudflare, **unproxied by default** (CF's mTLS origin-pull has been unreliable). Revisit if/when that changes.