Deploy services independently by changed paths
This commit is contained in:
1 parent
2277a2e9ac
commit
1ba47e4d22
18 files changed
+1462
-894
No files matched your search
@@ -1,60 +1,129 @@
|
||||
---
|
||||
type: guide
|
||||
title: Deployment Flow
|
||||
description: Service-scoped Git deployment for the two homelab hosts.
|
||||
tags:
|
||||
- deployment
|
||||
- operations
|
||||
- git
|
||||
timestamp: 2026-09-03
|
||||
---
|
||||
|
||||
# Deployment Flow
|
||||
|
||||
Git is the single source of truth. A `deploy.sh` script moves committed
|
||||
changes to the target hosts over SSH. One run per target covers both
|
||||
workloads on that host: the podman stack and the LLM service.
|
||||
Git is the single source of truth. `scripts/deploy.sh` pushes the committed
|
||||
`main` branch, pulls it on one target, and applies only the runtime services
|
||||
whose tracked inputs changed. A SearXNG change no longer recreates the
|
||||
inference service; an LLM change no longer restarts unrelated containers.
|
||||
|
||||
## Workflow
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Edit in this repo] --> B[Commit]
|
||||
B --> C[Push to origin]
|
||||
C --> D[deploy.sh: pull on target]
|
||||
D --> E[restart stack]
|
||||
E --> F[health check]
|
||||
A[Edit in this repo] --> B[Run tests]
|
||||
B --> C[Commit main]
|
||||
C --> D[deploy.sh computes plan]
|
||||
D --> E[Push main]
|
||||
E --> F[Target pulls with ff-only]
|
||||
F --> G[deploy-remote.sh dispatches selected services]
|
||||
G --> H[Per-service health check]
|
||||
```
|
||||
|
||||
1. Edit files locally in this repository.
|
||||
2. Commit and push.
|
||||
3. Run `./scripts/deploy.sh <dankclaw|dankserver>`.
|
||||
4. The script pulls the repo on the target and restarts the podman stack
|
||||
and the LLM service.
|
||||
5. It verifies service health after restart (homepage and LLM endpoint).
|
||||
2. Run `./tests/run.sh`, then commit the complete change on `main`.
|
||||
3. Run `./scripts/deploy.sh <target>`.
|
||||
4. The planner maps changed paths to services. Compose YAML is compared by
|
||||
service definition so an edit to one service does not restart its peers.
|
||||
5. The target pulls with `git pull --ff-only origin main` and runs the remote
|
||||
dispatcher with the explicit plan.
|
||||
6. The dispatcher updates only selected Quadlet, compose, homepage, Caddy, or
|
||||
systemd services and records each successful service revision outside Git.
|
||||
|
||||
## Deploy Script
|
||||
## Commands
|
||||
|
||||
```
|
||||
./scripts/deploy.sh dankclaw # pull + restart on Dankclaw
|
||||
./scripts/deploy.sh dankserver # pull + restart on Dankserver
|
||||
```bash
|
||||
./scripts/deploy.sh dankclaw
|
||||
./scripts/deploy.sh dankserver
|
||||
./scripts/deploy.sh dankclaw --service searxng
|
||||
./scripts/deploy.sh dankserver --service frank-default-small
|
||||
./scripts/deploy.sh dankclaw --dry-run
|
||||
```
|
||||
|
||||
SSH uses the existing key pair (`dank@dankclaw`, `dank@dankserver`). No passwords are stored or documented in this repo. If sudo is needed, use the interactive sudo on the target — never commit a password.
|
||||
`--service` is repeatable and is an explicit retry/override. Without it, the
|
||||
planner compares the local `HEAD` to `origin/main`. A documentation-only
|
||||
commit produces an empty plan. The remote state directory can also replay a
|
||||
service whose earlier deployment failed, but it never expands a plan to a
|
||||
service on the other host.
|
||||
|
||||
## Service managers
|
||||
|
||||
| Service family | Runtime manager | Scope behavior |
|
||||
|---|---|---|
|
||||
| Dankclaw compose services | `podman-compose -f dankclaw/compose.yaml up -d --no-deps NAME` | Recreates only `NAME`; Caddy is handled separately because it fronts both hosts. |
|
||||
| SearXNG, Gluetun, Valkey, OpenWebUI, Pi-hole, Gitea | user Quadlet + `systemctl --user` | Installs the selected unit and restarts only the required dependency-coupled units. |
|
||||
| `frank-default-large` | systemd + `systemctl` | Relinks and restarts only the large inference service; waits up to 20 minutes for `/health`. |
|
||||
| `frank-default-small` | systemd + `systemctl` | Relinks and restarts only the small inference service; waits up to 20 minutes for `/health`. |
|
||||
| Dankserver media inventory | host-managed bare containers | Compose is inventory only; the scoped deploy does not create duplicate containers. |
|
||||
|
||||
The shared chat template maps to the inference service on the selected target.
|
||||
The inactive `frank-default-npu` unit is relink-only when explicitly selected;
|
||||
it is not restarted by an unrelated large-model deployment.
|
||||
|
||||
## Caddy safety
|
||||
|
||||
Caddy runs on Dankclaw and fronts both hosts. The dispatcher never stops
|
||||
`gitea-caddy` implicitly. If the legacy `gitea-caddy` container owns ports
|
||||
80/443 while the compose `caddy` container is absent or stopped, a Caddy
|
||||
selection fails closed rather than replacing the live proxy. Resolve port
|
||||
ownership explicitly before retrying. A Caddy reload failure falls back to a
|
||||
restart of **only** the selected `caddy` container.
|
||||
|
||||
Homepage files, generated `deployed.js`, the status checker, and the rendered
|
||||
Caddyfile are updated only when their service is selected. A media-only
|
||||
Dankserver deployment does not touch Dankclaw's proxy or homepage.
|
||||
|
||||
## Per-service state
|
||||
|
||||
The remote runner writes one revision file per successfully completed service
|
||||
to:
|
||||
|
||||
```text
|
||||
${XDG_STATE_HOME:-~/.local/state}/serverAppConfigs/deploy-state/
|
||||
```
|
||||
|
||||
The directory is outside the checkout and is never committed. A failed handler
|
||||
is not marked successful. On the next ordinary deployment, the runner compares
|
||||
the recorded revision with the new checkout and retries only a still-changed
|
||||
service. This prevents a failed Caddy or LLM deployment from being silently
|
||||
forgotten while avoiding a host-wide restart.
|
||||
|
||||
## Targets
|
||||
|
||||
| Target | Host | Stack |
|
||||
|--------|------|-------|
|
||||
| dankclaw | dank@dankclaw (192.168.0.143) | `dankclaw/` |
|
||||
| dankserver | dank@dankserver (192.168.0.235) | `dankserver/` |
|
||||
| Target | Host | Repository checkout |
|
||||
|---|---|---|
|
||||
| dankclaw | `dank@dankclaw` (`192.168.0.143`) | `/home/dank/serverAppConfigs` |
|
||||
| dankserver | `dank@dankserver` (`192.168.0.235`) | `/home/dank/serverAppConfigs` |
|
||||
|
||||
## Health Verification
|
||||
|
||||
The deploy script polls the health endpoint of each service after restart. Service healthchecks are defined in each compose file. A service that fails its healthcheck is reported, not hidden.
|
||||
SSH uses the existing key pair. No password is stored or documented in this
|
||||
repository. If sudo is needed on a headless target, `FRANK_SUDO_PW` is read
|
||||
from the environment and is never written to the repository.
|
||||
|
||||
## Tests
|
||||
|
||||
Run the test suite before pushing:
|
||||
Run the full suite before pushing:
|
||||
|
||||
```
|
||||
```bash
|
||||
./tests/run.sh
|
||||
```
|
||||
|
||||
The suite validates compose YAML, env consistency, Caddyfiles, docs completeness, and script syntax. See [[Testing Policy]].
|
||||
The deployment seams are in `tests/deployment_scoping.bats` and
|
||||
`tests/deployment_flow.bats`. They cover path isolation, compose narrowing,
|
||||
Caddy safety, inference isolation, per-service state, and legacy wrapper
|
||||
routing. See [[Testing Policy]].
|
||||
|
||||
## See Also
|
||||
|
||||
- [[Storage Policy]]
|
||||
- [[Testing Policy]]
|
||||
- [LLM deployment docs](../LLM/deployment.md) — the LLM half of the same flow
|
||||
- [LLM deployment](../LLM/deployment.md)
|
||||
- [[Caddy]]
|
||||
- [[SearXNG]]
|
||||
@@ -11,7 +11,7 @@ This repository tests its configuration at defined seams. The tests run with `ba
|
||||
| Caddyfile validity | `tests/caddyfile.bats` | per-host Caddyfile, `.local` convention, balanced braces, basic auth present |
|
||||
| Docs completeness | `tests/docs_completeness.bats` | every compose service has a docs page; index links every page |
|
||||
| Script syntax | `tests/scripts_syntax.bats` | `bash -n` clean, executable bits, shellcheck when available |
|
||||
| Deployment flow | `tests/deployment_flow.bats` | deploy.sh exists, targets known, SSH reachable (skips offline) |
|
||||
| Deployment flow | `tests/deployment_flow.bats`, `tests/deployment_scoping.bats` | scoped dispatcher exists, targets are known, service plans isolate inference, Caddy ownership is guarded, and SSH reachability is checked (skips offline) |
|
||||
|
||||
## Focused pre-commit testing
|
||||
|
||||
|
||||
Reference in new issue
Block a user