Stick is a small, self-hosted coordination service for shared operational resources. Users claim a stick with a reason, release it when finished, and can subscribe to release notifications.
- Uses OIDC for login.
- Supports different storage backends:
- SQLite (default)
- PostgreSQL
- MongoDB
- Supports multiple notification modes:
- Webhooks
- Microsoft Teams
Clone the repository:
git clone https://github.com/alxtr/the-stick.git
cd the-stickCopy the example environment file:
cp .env.example .envEdit .env and set the OIDC values, a random session secret, and the public URL. HTTPS is required for non-local deployments.
Register <public-url>/auth/callback as the OIDC client's redirect URI.
openssl rand -hex 32 # use the result for STICK_AUTH_SESSION_SECRET
docker compose up -d --buildStick is available at STICK_SERVER_PUBLIC_URL. The Compose file binds it to loopback, so put it behind a TLS reverse proxy for remote access.
Create and edit the application configuration. Keep this file private because it contains credentials:
cp example.config.yaml config.yaml
# edit config.yaml and set a random session_secret
kubectl create namespace stick
kubectl -n stick create secret generic stick-config --from-file=config.yaml=./config.yamlEdit example.kubernetes.yaml with your image name and apply it:
kubectl apply -f example.kubernetes.yamlThis creates a single-replica Deployment, Service, and persistent volume claim.
Expose the Service through an Ingress or Gateway, use its HTTPS URL as STICK_SERVER_PUBLIC_URL, and register <public-url>/auth/callback with the OIDC provider.
If the application is mounted under a path, include that path in the probe URLs as well.
Go 1.27 or newer is required.
make buildThis creates ./stickd. To run the binary, copy and edit example.config.yaml, then run:
cp example.config.yaml config.yaml
# edit config.yaml
install -d -m 0700 local-data
STICK_DATABASE="$PWD/local-data/stick.db" ./stickd -config config.yaml- Configuration can be provided in YAML, environment variables, Azure App Configuration, or a combination of providers.
- Non-empty
STICK_*variables override values from earlier providers.
See .env.example and example.config.yaml for the available settings.
Stick can also load configuration from Azure App Configuration. Select it with
the bootstrap setting below; environment remains last so ordinary STICK_*
overrides retain precedence:
STICK_CONFIG_PROVIDERS=azure-app-config,environment
STICK_AZURE_APPCONFIG_ENDPOINT=https://stick-prod.azconfig.io
STICK_AZURE_APPCONFIG_LABEL=production
STICK_AZURE_APPCONFIG_KEY_PREFIX=stick/
STICK_AZURE_APPCONFIG_SEPARATOR=/When Azure is the only structured source, omit -config; when combining it
with a file, use STICK_CONFIG_PROVIDERS=yaml,azure-app-config,environment.
Use slash-separated keys such as stick/database,
stick/server/public_url, and stick/auth/oidc/issuer. Notification lists
should be stored as JSON values with the application/json content type.
The hierarchy separator is configurable (supported values include /, .,
: and __) and defaults to /.
Empty labels select unlabeled settings. Azure App Configuration Key Vault
references are resolved automatically when the identity can read the referenced
secrets.
Authentication uses Azure's default credential chain. In production, prefer a managed identity or workload identity and grant it the App Configuration Data Reader role (and Key Vault Secrets User when Key Vault references are used). No Azure credentials are stored in the Stick configuration.
The provider loads a snapshot during startup. Configuration changes require a Stick restart.
If you use MongoDB, it must be deployed as a replica set because Stick uses multi-document transactions.
make test
make check
make imageThe compose.idp.yaml override also starts Keycloak for local OIDC development.
Set IDP_ADMIN_PASSWORD in .env, configure Keycloak as your OIDC provider, and run it with:
docker compose -f compose.yaml -f compose.idp.yaml up -d --build