The files copied to /srv/stacks/<stack>/ verbatim: compose files, vhosts, Prometheus configuration, the webapp image source. Payloads are data, never templated and never linted as Ansible content. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
54 lines
2.9 KiB
Markdown
54 lines
2.9 KiB
Markdown
# server/ — the payloads
|
|
|
|
Everything under this directory is **data**. These files are copied to the hosts
|
|
verbatim: no templating, no variable substitution by Ansible, no generation.
|
|
|
|
```
|
|
server/<host>/<stack>/ a stack that runs on exactly one host
|
|
server/shared/<stack>/ a payload used by more than one host or instance
|
|
server/shared/components/ single files that belong to another stack's directory
|
|
```
|
|
|
|
The directory names under `server/` must match the inventory host names, because
|
|
the role resolves a payload as `server/{{ inventory_hostname }}/{{ stack_name }}`
|
|
unless a playbook overrides `stack_src`.
|
|
|
|
`server/` is excluded from `ansible-lint` and `yamllint`. A compose file is not
|
|
Ansible content, and most of these come from upstream projects that format them
|
|
their own way — linting them produces noise and pressure to reformat files you
|
|
want to be able to diff against upstream.
|
|
|
|
## The examples
|
|
|
|
All six are fictional. `example.com` is reserved by RFC 2606 and can never
|
|
resolve to a real service. Replace them with your own; the framework around them
|
|
is the reusable part.
|
|
|
|
| Payload | Used by | Notes |
|
|
| --- | --- | --- |
|
|
| `edge/reverse-proxy/` | `reverse-proxy.yml` | nginx-proxy + acme-companion. Owns `proxy-net`. Its `proxy-data/` subdirectories are bind mounts holding plain config files. |
|
|
| `app/static-site/` | `static-site.yml` | One container, one network, no state. The simplest thing that works. |
|
|
| `app/webapp/` | `webapp.yml`, `webapp-staging.yml` | Postgres plus an app built from `app/Dockerfile`. A second compose file holds maintenance-only services. Every credential comes from `.env`. |
|
|
| `shared/metrics/` | `metrics.yml` | Prometheus and Grafana, identical on both hosts, so it lives here rather than being duplicated per host. |
|
|
| `shared/components/banner.html` | `banner.yml` | A single file that belongs to the reverse proxy's directory on every host. |
|
|
|
|
## Conventions worth copying
|
|
|
|
**Take secrets from `.env`, and require them.** Every credential in these
|
|
payloads is written as `${VAR:?message}`. Compose then refuses to start and names
|
|
the missing variable, instead of expanding it to an empty string and starting the
|
|
service with no password. Ship a `.env.example` listing the names with no values;
|
|
the role never syncs `.env` itself.
|
|
|
|
**Pin image tags.** `nginx:1.27-alpine`, not `nginx:latest`. A `latest` tag means
|
|
a plain deploy will not pick up a new build (Compose keeps the image it has) and
|
|
an update run picks up whatever was published this morning. Both are surprises.
|
|
|
|
**Declare shared networks external.** A network two stacks need is created by the
|
|
playbook through `stack_networks`, not by whichever compose file happened to run
|
|
first. That is what lets every playbook stand on its own.
|
|
|
|
**Do not put host paths in the compose file.** Use `${PWD}` if a sibling
|
|
container needs one — the role exports it as the stack's directory on the host,
|
|
which is the only value that is correct from inside a deploy.
|