|
| 1 | +#!/bin/bash |
| 2 | +# |
| 3 | +# Manage the full local Open Inwoner stack: the main app plus every |
| 4 | +# satellite service it talks to (Keycloak for OIDC, Open Zaak, the |
| 5 | +# Objects/Objecttypes APIs, the Haal Centraal BRP mock, Open Klant, and Open |
| 6 | +# Afval), plus the observability stack (Grafana/Loki/Prometheus/otel-collector). |
| 7 | +# |
| 8 | +# Usage: |
| 9 | +# bin/stack.sh up # bring everything up: network, then satellites |
| 10 | +# # (waited on until healthy), then the app |
| 11 | +# bin/stack.sh up --logs # ...then follow the main app's logs |
| 12 | +# bin/stack.sh down # stop and remove containers, keep volumes/data |
| 13 | +# bin/stack.sh down -v # ...and remove volumes too (wipes all data) |
| 14 | +# bin/stack.sh urls # print the service URLs shown at the end of `up` |
| 15 | +# bin/stack.sh logs [args] # forwarded to `docker compose logs` |
| 16 | +# bin/stack.sh <cmd> [args] # anything else forwarded to `docker compose`, |
| 17 | +# # e.g. `bin/stack.sh ps`, `bin/stack.sh exec web bash` |
| 18 | +# |
| 19 | +# Run from anywhere; this always operates from the repository root. |
| 20 | +# |
| 21 | +# web-init's setup_configuration run needs Keycloak (OIDC discovery) and the |
| 22 | +# ZGW/Open Klant services reachable, which is why `up` waits for those before |
| 23 | +# starting the app. See docs/installation/docker-compose.rst for the full |
| 24 | +# explanation and how to bring stacks up individually. |
| 25 | + |
| 26 | +set -e |
| 27 | + |
| 28 | +SCRIPT=$(readlink -f "$0") |
| 29 | +REPO_ROOT=$(dirname "$(dirname "$SCRIPT")") |
| 30 | +cd "$REPO_ROOT" |
| 31 | + |
| 32 | +# docker-compose.dev.yml pulls in docker-compose.yml (the main app stack) and |
| 33 | +# docker/docker-compose.keycloak.yml (OIDC) via `include:`, which resolves |
| 34 | +# each file's relative paths against its own directory -- required for |
| 35 | +# Keycloak's realm fixture mount to resolve correctly. The remaining |
| 36 | +# satellite files use paths relative to the repository root instead, which |
| 37 | +# works fine alongside `include:` since they're passed as plain `-f` files. |
| 38 | +# See docker-compose.dev.yml's header comment for the full reasoning. |
| 39 | +COMPOSE=( |
| 40 | + docker compose |
| 41 | + -f docker-compose.dev.yml |
| 42 | + -f docker/docker-compose.open-zaak.yml |
| 43 | + -f docker/docker-compose.objects-apis.yml |
| 44 | + -f docker/docker-compose.hc-brp-mock.yml |
| 45 | + -f docker/docker-compose.openklant.yml |
| 46 | + -f docker/docker-compose.openafval.yml |
| 47 | + -f docker/docker-compose.observability.yml |
| 48 | +) |
| 49 | + |
| 50 | +print_urls() { |
| 51 | + cat <<'EOF' |
| 52 | + Open Inwoner http://localhost:8000/ (behind nginx: http://localhost:9000/) |
| 53 | + Open Inwoner admin http://localhost:8000/admin/ (click "Login with OIDC", Keycloak admin / admin) |
| 54 | + Mailpit (sent emails) http://localhost:8025/ |
| 55 | + Keycloak admin http://localhost:8080/ (admin / admin) |
| 56 | + Open Zaak admin http://localhost:8002/admin/ (admin / admin) |
| 57 | + Objecttypes API admin http://localhost:8003/admin/ (admin / admin) |
| 58 | + Objects API admin http://localhost:8004/admin/ (admin / admin) |
| 59 | + Open Klant admin http://localhost:8338/admin/ (admin / admin) |
| 60 | + Open Afval admin http://localhost:8339/admin/ |
| 61 | + Haal Centraal BRP mock http://localhost:5010/ |
| 62 | + Grafana (observability) http://localhost:3000/ |
| 63 | + Prometheus http://localhost:9090/ |
| 64 | + Loki http://localhost:3100/ready |
| 65 | +
|
| 66 | + DigiD login http://localhost:8000/digid-oidc/authenticate/ |
| 67 | + eHerkenning login http://localhost:8000/eherkenning-oidc/authenticate/ |
| 68 | + eIDAS login http://localhost:8000/eidas-oidc/authenticate/ |
| 69 | + (any Keycloak test user works -- see docker/keycloak/README.md for the |
| 70 | + full list, including DigiD machtigen and eHerkenning bewindvoering/vestiging) |
| 71 | +EOF |
| 72 | +} |
| 73 | + |
| 74 | +cmd=${1:-} |
| 75 | +[ $# -gt 0 ] && shift |
| 76 | + |
| 77 | +case "$cmd" in |
| 78 | + up) |
| 79 | + echo "==> Ensuring the shared open-inwoner-dev network exists" |
| 80 | + bin/ensure_dev_network.sh |
| 81 | + |
| 82 | + echo |
| 83 | + echo "==> Starting satellite services (Keycloak, Open Zaak, Objects APIs, Haal Centraal BRP mock, Open Klant, Open Afval)" |
| 84 | + echo " web-init needs all of these reachable, so they come up -- and are waited on -- first." |
| 85 | + "${COMPOSE[@]}" up -d --wait \ |
| 86 | + keycloak \ |
| 87 | + openzaak-web openzaak-celery \ |
| 88 | + objecttypes-web objects-web objects-celery \ |
| 89 | + personen-mock \ |
| 90 | + openklant-seed \ |
| 91 | + openafval-seed |
| 92 | + |
| 93 | + echo |
| 94 | + echo "==> Starting the main app stack (web-init will now configure it against the services above)" |
| 95 | + # OTEL_SDK_DISABLED defaults to true in docker-compose.yml's shared |
| 96 | + # x-app-env (so plain `docker compose up` stays opt-in, per |
| 97 | + # docs/installation/docker-compose.rst) -- overridden here since this |
| 98 | + # script also brings up the observability stack itself, and running |
| 99 | + # Grafana/Loki/Prometheus with nothing feeding them defeats the point. |
| 100 | + OTEL_SDK_DISABLED=false "${COMPOSE[@]}" up -d |
| 101 | + |
| 102 | + echo |
| 103 | + echo "==> Stack is up." |
| 104 | + echo |
| 105 | + print_urls |
| 106 | + echo |
| 107 | + echo "Bring it all down again with:" |
| 108 | + echo " bin/stack.sh down" |
| 109 | + |
| 110 | + if [ "$1" = "--logs" ]; then |
| 111 | + "${COMPOSE[@]}" logs -f web web-init |
| 112 | + fi |
| 113 | + ;; |
| 114 | + |
| 115 | + urls) |
| 116 | + print_urls |
| 117 | + ;; |
| 118 | + |
| 119 | + down) |
| 120 | + echo "==> Stopping and removing containers" |
| 121 | + "${COMPOSE[@]}" down --remove-orphans "$@" |
| 122 | + echo |
| 123 | + echo "The shared open-inwoner-dev network is left in place (it's external to" |
| 124 | + echo "every compose file here). Remove it yourself if you need to, with:" |
| 125 | + echo " docker network rm open-inwoner-dev" |
| 126 | + ;; |
| 127 | + |
| 128 | + reset-config) |
| 129 | + # web-init is a one-shot container, not a running service, so its |
| 130 | + # marker (see bin/setup_configuration.sh) can't be removed with |
| 131 | + # `exec` -- use a throwaway container against the same volume instead. |
| 132 | + echo "==> Clearing the setup_configuration marker" |
| 133 | + "${COMPOSE[@]}" run --rm --entrypoint sh web-init -c \ |
| 134 | + "rm -f /var/lib/open-inwoner/setup-configuration/.completed" |
| 135 | + |
| 136 | + echo |
| 137 | + echo "==> Re-running web-init" |
| 138 | + "${COMPOSE[@]}" up -d web-init |
| 139 | + ;; |
| 140 | + |
| 141 | + ""|-h|--help) |
| 142 | + cat <<'EOF' |
| 143 | +Usage: bin/stack.sh <command> [args] |
| 144 | +
|
| 145 | +Commands: |
| 146 | + up [--logs] Bring up the full stack: network, then satellites |
| 147 | + (waited on until healthy), then the app. |
| 148 | + down [args] Stop and remove containers. Forwarded to |
| 149 | + `docker compose down` (e.g. `bin/stack.sh down -v` to |
| 150 | + also remove volumes). |
| 151 | + reset-config Force setup_configuration to run again on next `up` |
| 152 | + (e.g. after editing docker/setup_configuration/data.yaml), |
| 153 | + instead of being skipped as already-completed. |
| 154 | + urls Print the service URLs shown at the end of `up`, without |
| 155 | + bringing anything up or down. |
| 156 | + <anything else> Forwarded to `docker compose` as-is, e.g.: |
| 157 | + bin/stack.sh ps |
| 158 | + bin/stack.sh logs -f openklant-web |
| 159 | + bin/stack.sh exec web bash |
| 160 | +EOF |
| 161 | + ;; |
| 162 | + |
| 163 | + *) |
| 164 | + "${COMPOSE[@]}" "$cmd" "$@" |
| 165 | + ;; |
| 166 | +esac |
0 commit comments