start_interval is the cadence while start_period runs, and only while it runs. Once the window closes the probe falls back to interval, so a service that becomes ready just after it pays a whole tick anyway and the cadence never reached it. Six of the seven flavors were shaped that way, Curl worst: a thirty second window against a one minute interval. Measured across 151 converge waits in four job logs, 63 sit exactly on a tick boundary, 36 in the thirty second step and 27 in the sixty second one. Attributed by application, web-app-seaweedfs is the largest at 1501s over sixteen waits with a median of 57.7s: it probes with curl and fell straight into the gap. web-app-zammad probes with connect, whose window is fifteen minutes, and its 154s median is real boot time with nothing to recover. So the window moves to ten minutes and the steady state interval to two, and the flavor overrides that sat below them go: Curl, Wget and Connect lose interval 1m, Http its twenty second window, Nc its ten. Connect keeps fifteen minutes. Neither number costs anything while a container works. start_period delays nothing, it only stops failures counting, and interval no longer touches convergence at all since that hangs on the window alone; it is steady state load, which drops from 120 probes an hour per service to 30. Forty six role files follow. Twenty seven declarations go that repeat the new default or undercut it, an undercut window being the defect itself. Eight windows longer than ten minutes keep their value and now say why. The literal blocks and the three Dockerfiles this repository builds spell every timing out, because outside the lookup an omission takes docker's value and not the platform's. A fourth lint rule keeps the shape: start_period must outlast one interval, checked against the effective values, so raising interval without the window cannot quietly bring the cliff back. Two faults in the lint surfaced while building it and are fixed here. It compared timings as strings, so 600s and 10m read as different values, and it matched the healthcheck key exactly, so a line carrying a trailing nocheck was skipped whole, which is how the two swarm-init partials went unexamined. One regression, bounded. A container that starts and never turns healthy is neither rejected nor errored, so stack_ready.sh only calls it fatal after three killed tasks, and each cycle now spans the longer window. That reaches twenty minutes rather than six, capped there by swarm_stack_converge_retries at 600 with a two second delay, and it lands only on runs that were failing anyway. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
pgAdmin
Description
pgAdmin is the most popular and feature‑rich open source administration and development platform for PostgreSQL. This deployment provides a secure, containerized pgAdmin instance complete with optional OAuth2 proxy support for enhanced authentication. It is built for both developers and database administrators who want an easy‐to‐use web interface to manage multiple PostgreSQL servers.
Overview
This Docker Compose deployment uses Ansible automation to launch pgAdmin together with necessary network and volume configurations. It enables you to centrally manage your PostgreSQL databases with the following core software features:
-
Intuitive Web UI:
Access a modern, responsive, and highly customizable dashboard to manage your PostgreSQL servers. -
Multi‑Server Management:
Connect to and administer multiple PostgreSQL instances from a single interface. -
Optional OAuth2 Integration:
Secure your pgAdmin access by integrating an external OAuth2 provider. -
Robust Connectivity:
Easily manage database configurations, user accounts, and monitor query activity with built‑in health checks. -
Flexible Configuration:
Adjust settings such as SSL options, port numbers, and server credentials through environment variables and templated configuration files.
Cosmos
The diagram places pgAdmin in the Infinito.Nexus cosmos: the components it deploys (capabilities), the central services it consumes (dependencies), and its outward reach (federation and bridged external networks).
flowchart LR
subgraph deps [Dependencies]
dep_svc_bkp_volume_2_local["svc-bkp-volume-2-local 💻"]
dep_svc_db_postgres["svc-db-postgres 🐳🐝"]
dep_svc_net_tor["svc-net-tor 🐳🐝"]
dep_web_app_dashboard["web-app-dashboard 🐳🐝"]
dep_web_app_keycloak["web-app-keycloak 🐳🐝"]
dep_web_app_mailu["web-app-mailu 🐳🐝"]
dep_web_app_matomo["web-app-matomo 🐳🐝"]
dep_web_app_prometheus["web-app-prometheus 🐳🐝"]
dep_web_svc_css["web-svc-css 💻"]
dep_web_svc_logout["web-svc-logout 🐳🐝"]
end
subgraph role [web-app-pgadmin 🐳🐝]
svc_pgadmin["pgadmin"]
svc_logout["logout"]
svc_dashboard["dashboard"]
svc_matomo["matomo"]
svc_email["email"]
svc_postgres["postgres"]
svc_sso["sso"]
svc_css["css"]
svc_prometheus["prometheus"]
svc_tor["tor"]
svc_container_backup["container_backup"]
end
dep_svc_bkp_volume_2_local -. "0..1" .-> svc_container_backup
dep_svc_db_postgres -. "0..1" .-> svc_postgres
dep_svc_net_tor -. "0..1" .-> svc_tor
dep_web_app_dashboard -. "0..1" .-> svc_dashboard
dep_web_app_keycloak -. "0..1" .-> svc_sso
dep_web_app_mailu -. "0..1" .-> svc_email
dep_web_app_matomo -. "0..1" .-> svc_matomo
dep_web_app_prometheus -. "0..1" .-> svc_prometheus
dep_web_svc_css -. "0..1" .-> svc_css
dep_web_svc_logout -. "0..1" .-> svc_logout
Solid 1:1 edges are fixed relationships; dashed 0..1 edges are conditional (enabled only in matching deployments); red 0..0 edges are turned off in this role. Node markers show the role's deploy modes (💻 host, 🐳 compose, 🐝 swarm); ❌ marks a service that is explicitly turned off, and ⚙️ an Ansible role dependency declared in meta/main.yml.
Features
- Automated provisioning: Configured by Ansible without manual steps.
Quick Setup
Development
Clone, set up the workstation, and deploy pgAdmin onto the local stack:
git clone https://github.com/infinito-nexus/core.git
cd core
make onboard
make compose-deploy mode=reinstall apps=web-app-pgadmin full_cycle=false
Production
Run the published image to provision the inventory and deploy pgAdmin to a managed server (the mounted volume persists the inventory):
APP=web-app-pgadmin
HOST=<your-server>
DOMAIN=<your-domain>
TLS_MODE=self_signed
SSH_PUBLIC_KEY="<your-ssh-public-key>"
docker run --rm -it \
-v "$PWD/inventories:/etc/infinito.nexus/inventories" \
-e APP="$APP" -e HOST="$HOST" -e DOMAIN="$DOMAIN" -e TLS_MODE="$TLS_MODE" -e SSH_PUBLIC_KEY="$SSH_PUBLIC_KEY" \
ghcr.io/infinito-nexus/core/debian bash -c '
INVENTORY=/etc/infinito.nexus/inventories/production
infinito administration inventory provision "$INVENTORY" \
--inventory-file "$INVENTORY/devices.yml" \
--host "$HOST" \
--include "$APP" \
--vars "{\"TLS_MODE\": \"$TLS_MODE\", \"DOMAIN_PRIMARY\": \"$DOMAIN\", \"users\": {\"administrator\": {\"authorized_keys\": [\"$SSH_PUBLIC_KEY\"]}}}" &&
infinito administration deploy dedicated "$INVENTORY/devices.yml" \
--password-file "$INVENTORY/.password" \
--diff -vv'
Other Resources
Persona contract opt-outs
pgAdmin's own login id is the account e-mail PGADMIN_DEFAULT_EMAIL (templates/env.j2, vars/main.yml), not the Keycloak administrator username, so the administrator persona has no in-app credential once it is through the oauth2-proxy. meta/services.yml additionally admits only the web-app-pgadmin administrator RBAC group to that proxy (sso.oauth2.allowed_groups), and biber carries an empty role list, so it is denied before pgAdmin is reached. templates/playwright.env.j2 therefore declares PERSONA_BIBER_BLOCKED=true and PERSONA_ADMINISTRATOR_BLOCKED=true; the guest persona and the baseline assertions run unconditionally.
Credits
Implemented by Kevin Veen-Birkenbach. Part of the Infinito.Nexus Project and maintained by Kevin Veen-Birkenbach. Licensed under the Infinito.Nexus Community License (Non-Commercial).