Universal Logout
This folder contains an Ansible role to deploy and configure the Universal Logout Service.
Description
This role sets up the universal logout proxy service, a Dockerized Python Flask container that coordinates logout requests across multiple OIDC-integrated applications. It also configures the necessary NGINX proxy snippets and environment variables to enable unified logout flows.
It solves the common challenge of logging a user out from all connected apps with a single action, especially in environments where apps live on multiple subdomains and use OIDC authentication.
Overview
- Deploys the universal logout service container based on the official universal-logout GitHub repository.
- Configures the logout domains dynamically based on application inventory and features using custom Ansible filters.
- Provides an NGINX
/logoutproxy configuration snippet that handles CORS and forwards logout requests to the logout service. - Supplies a user-friendly logout conductor UI that requests logout on all configured domains and shows live status.
- Designed to be used as the Front Channel Logout URL for Keycloak or other OpenID Connect providers, enabling a seamless, service-spanning logout experience.
Cosmos
The diagram places Universal Logout 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_net_tor["svc-net-tor 🐳🐝"]
dep_web_app_matomo["web-app-matomo 🐳🐝"]
dep_web_app_prometheus["web-app-prometheus 🐳🐝"]
dep_web_svc_css["web-svc-css 💻"]
end
subgraph role [web-svc-logout 🐳🐝]
svc_logout["logout"]
svc_matomo["matomo"]
svc_css["css"]
svc_javascript["javascript"]
svc_prometheus["prometheus"]
svc_tor["tor"]
end
subgraph dependents [Dependents]
dpt_web_app_akaunting["web-app-akaunting 🐳🐝"]
dpt_web_app_baserow["web-app-baserow 🐳🐝"]
dpt_web_app_bigbluebutton["web-app-bigbluebutton 🐳🐝"]
dpt_web_app_bluesky["web-app-bluesky 🐳🐝"]
dpt_web_app_bookwyrm["web-app-bookwyrm 🐳🐝"]
dpt_web_app_checkmk["web-app-checkmk 🐳🐝"]
dpt_web_app_confluence["web-app-confluence 🐳🐝"]
dpt_web_app_dashboard["web-app-dashboard 🐳🐝"]
dpt_web_app_decidim["web-app-decidim 🐳🐝"]
dpt_web_app_discourse["web-app-discourse 🐳🐝"]
dpt_web_app_erpnext["web-app-erpnext 🐳🐝"]
dpt_web_app_espocrm["web-app-espocrm 🐳🐝"]
dpt_more["..."]
end
dep_svc_net_tor -. "0..1" .-> svc_tor
dep_web_app_matomo -. "0..1" .-> svc_matomo
dep_web_app_prometheus -. "0..1" .-> svc_prometheus
dep_web_svc_css -. "0..1" .-> svc_css
svc_logout -- "1:1" --> dpt_more
svc_logout -. "0..1" .-> dpt_web_app_akaunting
svc_logout -. "0..1" .-> dpt_web_app_baserow
svc_logout -. "0..1" .-> dpt_web_app_bigbluebutton
svc_logout -. "0..1" .-> dpt_web_app_bluesky
svc_logout -. "0..1" .-> dpt_web_app_bookwyrm
svc_logout -. "0..1" .-> dpt_web_app_checkmk
svc_logout -. "0..1" .-> dpt_web_app_confluence
svc_logout -. "0..1" .-> dpt_web_app_dashboard
svc_logout -. "0..1" .-> dpt_web_app_decidim
svc_logout -. "0..1" .-> dpt_web_app_discourse
svc_logout -. "0..1" .-> dpt_web_app_erpnext
svc_logout -. "0..1" .-> dpt_web_app_espocrm
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
- Automatic discovery of logout domains from applications with the
features.logoutflag enabled. - Centralized logout proxy that clears cookies and sessions across all configured subdomains.
- Status page with live feedback on logout progress for each domain.
- Built-in support for Docker Compose deployment and integration with the Infinito.Nexus ecosystem.
- Includes security-conscious headers (CORS, CSP) for smooth cross-domain logout operations.
Quick Setup
Development
Clone, set up the workstation, and deploy Universal Logout onto the local stack:
git clone https://github.com/infinito-nexus/core.git
cd core
make onboard
make compose-deploy mode=reinstall apps=web-svc-logout full_cycle=false
Production
Run the published image to provision the inventory and deploy Universal Logout to a managed server (the mounted volume persists the inventory):
APP=web-svc-logout
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'
Further Resources
This role is licensed under the Infinito.Nexus Community License (Non-Commercial).
Persona contract opt-outs
meta/services.yml declares no sso service, so this role is never registered as a Keycloak client. Its only HTTP surface is the anonymous logout conductor and the /logout endpoints proxied by templates/logout-proxy.conf.j2 — there is no login form, no account and no session to end.
templates/playwright.env.j2 therefore declares PERSONA_BIBER_BLOCKED=true and PERSONA_ADMINISTRATOR_BLOCKED=true. The service's real coverage is per consumer: files/playwright/playwright.spec.js parameterises the injected logout JS over roles_with_service('logout').
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).