Database
Deploy the platform's shared PostgreSQL server on the DevOps server host, and seed Vault with access credentials for the downstream databases that connect to it.
Ansible hosts group: database
Variables
| Option | Type | Description | Default |
|---|---|---|---|
ds_db_downstream_databases | list | Downstream database names to generate a Vault access credential for | ["devops-server-scm"] |
Everything else is fixed: the Docker network (devops-server-database), the container name
(devops-server-postgres), the data directory (/app/devops-server-postgres), the maintenance
user and database (postgres), and the digest-pinned image. The image's container registry layer
URL sits in a comment directly above its pin, so the database engine can be swapped without
touching any other file.
Mutual TLS
The listener requires mutual TLS:
| Boundary | Server presents | Client must present |
|---|---|---|
| Client -> Database | Server certificate | A client certificate signed by the root CA |
The server certificate is signed by the Root CA and is valid for ten years. Host-based
authentication trusts local connections and requires scram-sha-256 plus a verified client
certificate for every remote one.
Downstream database credentials
For each name in ds_db_downstream_databases, the database_downstream_db_credentials tag ensures
a generated access credential exists at
{{ cs_project_code }}/devops-server/hosts/{{ inventory_hostname }}/apps/postgres/generated-<name>-db-credential:
host and port set to the database's current address, a user field set to <name>-user, and a
password. host and port are refreshed on every run. If user and password already have
that shape, they are left exactly as they are; otherwise a fresh 64 character password is
generated.
The vault_downstream_db_credentials module behind this stage is backed by an action plugin, so it
runs on the control node, where the Vault connection is, regardless of which host the play
targets.
Vault configurations
- key:
{{ cs_project_code }}/devops-server/hosts/{{ inventory_hostname }}/apps/postgres/config
{
"maintenance_db": "Maintenance database; read by the SCM service only",
"maintenance_user": "Maintenance login user; read by the SCM service only",
"maintenance_password": "Password set on the database's postgres superuser; ASCII letters and digits only",
"port": "(int) Port the database listens on, published on the host and opened in the firewall"
}
The database service itself reads only maintenance_password and port, and always uses
postgres as its maintenance user and database. The SCM service connects with maintenance_db,
maintenance_user, and maintenance_password to create its own user, database, and schema (see
SCM). The shared Root CA path is listed in
Prerequisites.
Tags
database: Deploy the database and seed the downstream credentials.database_prepare: Install APT dependencies and the PostgreSQL client library, and create the Docker network.database_install: Open the firewall port, issue the server certificate, write the host-based authentication config, start the container (initializing the data directory on the first run), and reset the maintenance user's password. Runsdatabase_preparefirst.database_downstream_db_credentials: Seed Vault with a generated access credential for each downstream database.dangerously_cleanup_database: Destructive. Removes the database container, its Docker network, and its data directory. Never included by the plaindatabasetag.
Deployment
uv sync --all-extras --all-packages --no-progress
uv --offline run --no-sync --no-progress ansible-galaxy install -r requirements.yml
uv --offline run --no-sync --no-progress ansible-playbook playbook.yml --tags database