Episode 4: Vaultwarden single sign-on via Forgejo

- compose: SSO_ENABLED, SSO_AUTHORITY and the two client credentials, with the
  undocumented redirect path written down where people will look for it
- .env.example: was referenced by the README since episode 1 but never actually
  committed, so a fresh clone could not follow the quickstart
- README: the four steps, plus the debugging notes that cost the most time
  (no SSO line at startup, 404 on routes without query parameters, HEAD on the
  discovery endpoint, and the three-step member join)
- HARDENING: never copy db.sqlite3 alone while the container runs. WAL mode
  keeps recent writes in a side file, so that backup silently misses data
This commit is contained in:
Maximilian Grimm 2026-08-26 21:54:23 +02:00
parent 0341ae777d
commit d5398caece
4 changed files with 130 additions and 1 deletions

View file

@ -140,6 +140,55 @@ command (`examples/deploy-hello-ops.sh`). Read the CI section of
[HARDENING.md](HARDENING.md) before you wire the deploy step — there are two
comfortable ways to hand your whole server to anyone who can push a branch.
## One login for the vault (Episode 4)
Your Forgejo already knows your team. Let it log them into the password
manager too, so offboarding is one switch instead of a checklist.
```bash
# 1. Create the OAuth2 app in Forgejo
# Site Administration -> Applications -> OAuth2 Application
# Name: Vaultwarden
# Redirect URI: https://vault.<DOMAIN>/identity/connect/oidc-signin
# Confidential client: yes
#
# That redirect path is not documented anywhere in the UI, and a wrong one
# only fails AFTER the Forgejo login. Copy it character for character.
# 2. Put the client id and secret in .env
VAULTWARDEN_SSO_CLIENT_ID=...
VAULTWARDEN_SSO_CLIENT_SECRET=...
# 3. Restart just that container
docker compose up -d vaultwarden
# 4. Log in: https://vault.<DOMAIN>
# Type your work mail, hit "Use single sign-on", authorize once in Forgejo.
```
Vaultwarden will then ask you to set a master password. That is not a bug.
Forgejo proved *who you are*; nothing so far produced the key that *decrypts
your vault*. Your master password never leaves your browser, and the server
stores blobs it cannot read. Two different jobs, two different mechanisms.
Debugging notes, all of them learned the hard way:
- Vaultwarden logs nothing about SSO at startup. It builds the OIDC client on
the first login attempt, not before. Watch `docker compose logs -f
vaultwarden` *while* you log in instead: you will see a `prevalidate` call
and then the `oidc-signin` callback coming back with a code.
- `/identity/connect/authorize` and the callback both answer `404` when called
without query parameters. That is route matching, not a wrong path.
- `curl -I` on Forgejo's `/.well-known/openid-configuration` returns 404 because
there is no HEAD route. Use `curl -s` and it is a normal 200.
- Turn on `SSO_SIGNUPS_MATCH_EMAIL` **before** anyone logs in, or you get
duplicate accounts instead of linked ones.
Then make it a team vault: create an organization, add collections, invite
people. Note that joining is three steps, not two: you invite, they log in,
and then an owner has to **confirm** them. Until that confirmation, a member
sees no shared items at all.
## Hardening
Before you put real company data on this box, read **[HARDENING.md](HARDENING.md)**.