Zoom Keyhole
A small FastAPI service that shows who is in a Zoom room on one or more Miro boards. Room configuration (users, rooms, boards, role symbols) is read from a Google Sheet; Miro text widgets are updated to display live participants.
Quick start
Prepare your Miro boards:
Add a text widget per Zoom room, with the room name and the literal text “Meeting ID:”. The service will insert the meeting ID as a clickable link and keep the participant list up to date.
Prepare your Google Sheet:
Create a sheet with tabs named: Users, Rooms, Boards, Role symbols. Populate them according to your conventions. The service periodically reloads these tabs.
Run locally:
Create a .env file (or export the variables in your shell) with the required environment variables listed below. The Makefile will auto-load .env.
Start the service:
make run
# or:
uvicorn src.zoom_keyhole.main:APP --host 0.0.0.0 --port 8000 --loop asyncio --reload
The service exposes its routes under the optional ROOT_PATH (default is set by the Helm chart).
Environment variables
Required:
ZOOM_KEYHOLE_MIRO_API_TOKEN: Miro API token. For multiple tokens, use a semicolon-separated list locally; when set via Helm/values, use colon-separated.
ZOOM_KEYHOLE_ZOOM_CLIENT_ID: Zoom OAuth client ID.
ZOOM_KEYHOLE_ZOOM_CLIENT_SECRET: Zoom OAuth client secret.
ZOOM_KEYHOLE_ZOOM_ACCOUNT_ID: Zoom account ID for server-to-server OAuth.
ZOOM_KEYHOLE_WEBHOOK_SECRET_TOKEN: Secret used to validate Zoom webhook URL challenges and payloads.
ZOOM_KEYHOLE_GSHEET_ID: Google Sheet ID containing configuration.
One of:
GOOGLE_SERVICE_ACCOUNT_KEY_B64: Base64-encoded Google service account JSON (recommended), or
ZOOM_KEYHOLE_GSHEET_KEY: Google Sheets API key (fallback).
Optional (sensible defaults exist):
ROOT_PATH: URL prefix when running behind a reverse proxy (Helm defaults to /ska/zoom-keyhole).
ENABLE_DEBUG_METHODS: Enable debug/admin routes (default: true). Disable in production.
ZOOM_KEYHOLE_FILE_LOGGER: Enable file logging when set to a non-zero value.
Scan/refresh periods (seconds): ZOOM_ROOM_SCAN_PERIOD, MIRO_BOARD_SCAN_PERIOD, MIRO_BOARD_UPDATE_PERIOD, GSHEET_USERS_SCAN_PERIOD, GSHEET_BOARDS_SCAN_PERIOD, GSHEET_ROOMS_SCAN_PERIOD, GSHEET_ROLES_SCAN_PERIOD.
Kubernetes (Helm)
The included chart deploys the service and sets the default ingress path to /ska/zoom-keyhole. Install by providing sensitive values at install time:
helm install zoom ./charts/ska-zoom-keyhole --values values.yaml
Minimal values.yaml example (redacted):
---
env:
ZOOM_KEYHOLE_MIRO_API_TOKEN: "<token or token:token2>"
ZOOM_KEYHOLE_ZOOM_CLIENT_ID: "<client id>"
ZOOM_KEYHOLE_ZOOM_CLIENT_SECRET: "<client secret>"
ZOOM_KEYHOLE_ZOOM_ACCOUNT_ID: "<account id>"
ZOOM_KEYHOLE_WEBHOOK_SECRET_TOKEN: "<webhook secret>"
ZOOM_KEYHOLE_GSHEET_ID: "<sheet id>"
# Choose one auth method for Google Sheets:
GOOGLE_SERVICE_ACCOUNT_KEY_B64: "<base64 service account json>"
# or, as a fallback:
ZOOM_KEYHOLE_GSHEET_KEY: "<api key>"
# Optional
ROOT_PATH: "/ska/zoom-keyhole"
In environments using an ingress controller (e.g. NGINX), the default path is /ska/zoom-keyhole. Adjust ROOT_PATH and ingress settings as needed in the chart values.
Documentation
Full documentation (architecture, configuration, operations) is available on Read the Docs:
https://zoom-keyhole.readthedocs.io/en/latest/
For chart defaults, see charts/ska-zoom-keyhole/values.yaml in this repository.