Overview
Authwall is an authentication proxy — it sits between clients and an internal app,
handling sign-in (email/password, magic links, and OAuth) and forwarding
authenticated requests with an X-Auth-User header.
client → authwall → your appsequenceDiagram
participant client
participant authwall
participant your_app
client ->> authwall: request
authwall ->> your_app: request (X-Auth-User)
your_app -->> authwall: response
authwall -->> client: responseQuick start
Authwall runs with zero configuration: by default it uses SQLite and open
registration. Each recipe below is a complete docker run command — pick the
one that matches how you want users to sign in. More setups — seeded users,
personal access tokens, WebSockets — are in Recipes.
Open registration (username + password only)
docker run --rm -p 3000:3000 \
-e AUTHWALL_UPSTREAM_URL=http://internal:8080 \
vbarbarosh/authwallBehavior:
- sign-in: username + password
- registration: open
- email features: disabled
- storage: SQLite (ephemeral unless volume mounted)
Open registration (username/email + password + magic link)
docker run --rm -p 3000:3000 \
-e AUTHWALL_UPSTREAM_URL=http://internal:8080 \
-e AUTHWALL_RESEND_KEY=re_xxx \
-e AUTHWALL_RESEND_FROM="Authwall <noreply@myapp.test>" \
vbarbarosh/authwallBehavior:
- sign-in: username/email + password
- magic link: enabled
- email confirmation: enabled
- registration: open
Google OAuth only
Create a Google OAuth client and add this authorized redirect URI:
https://myapp.test/auth/google/callbackThen run:
docker run --rm -p 3000:3000 \
-e AUTHWALL_PUBLIC_URL=https://myapp.test \
-e AUTHWALL_UPSTREAM_URL=http://internal:8080 \
-e AUTHWALL_GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com \
-e AUTHWALL_GOOGLE_CLIENT_SECRET=GOCSPX_xxx \
-e AUTHWALL_GOOGLE_REDIRECT_URL=https://myapp.test/auth/google/callback \
vbarbarosh/authwallBehavior:
- sign-in: Google OAuth
- registration: open for Google accounts
- email identity: added only when Google reports a verified email
- email features: disabled unless a mailer is configured
Google OAuth with an email allowlist
Same Google OAuth client as above, plus AUTHWALL_ALLOWED_EMAILS to limit
sign-in to named addresses:
docker run --rm -p 3000:3000 \
-e AUTHWALL_PUBLIC_URL=https://myapp.test \
-e AUTHWALL_UPSTREAM_URL=http://internal:8080 \
-e AUTHWALL_GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com \
-e AUTHWALL_GOOGLE_CLIENT_SECRET=GOCSPX_xxx \
-e AUTHWALL_GOOGLE_REDIRECT_URL=https://myapp.test/auth/google/callback \
-e AUTHWALL_ALLOWED_EMAILS=alice@example.com,bob@example.com \
vbarbarosh/authwallBehavior:
- sign-in: Google OAuth
- registration: open for listed Google accounts
- allowed users: only verified Google emails listed in
AUTHWALL_ALLOWED_EMAILS - everyone else: rejected
Notes
- If no mailer is configured, email-based flows are disabled automatically
- First user is created via sign-up (no bootstrap user required)
- Data is stored inside the container unless a volume is mounted
Philosophy
- Zero-config start —
docker runworks with no required variables. - Env-driven configuration — everything is set through
AUTHWALL_*environment variables; see the configuration reference. - Fail loudly — anything you request explicitly (a mailer, a flow, a provider) must be fully configured, or Authwall refuses to start instead of silently falling back.
- Sensible defaults for local development — SQLite, open registration, no
mailer required; rarely-needed knobs live in
config/settings.yaml.
Secret management
AUTHWALL_SECRET is optional.
Startup order is:
- Use
AUTHWALL_SECRETwhen it is set. - Otherwise, load
/app/data/secret.keyif it already exists. - Otherwise, generate a new random secret, write it to
/app/data/secret.key, and use that value.
Why this default exists:
- Authwall derives its session secret from one root secret, so that root value must stay stable across restarts.
- Requiring an env var for every local or single-host deployment makes first boot harder and encourages weak placeholder values.
- Persisting the generated secret in the data directory keeps restarts deterministic as long as the data volume is preserved.
- An explicit
AUTHWALL_SECRETstill takes precedence, which is the better fit when secrets are managed by the runtime or an external secret store.
If you rotate either AUTHWALL_SECRET or data/secret.key, existing sessions and CSRF tokens become invalid by design.
Related projects
- Auth0 – hosted identity platform
- WorkOS – enterprise SSO and user management
- Supabase Auth – open-source auth with many integrations
- Netlify GoTrue – JWT-based API for managing users and issuing tokens
- Firebase Auth – simple, multi-platform sign-in
- Amazon Cognito – AWS authentication and access control
- Authentik – open-source identity provider
- Keycloak – open-source identity and access management
- Authelia – open-source authentication portal with MFA and SSO
- Zitadel – open-source identity infrastructure
- Ory – composable open-source IAM
- Tinyauth – tiny OIDC server for self-hosted applications
- Logto – modern auth infrastructure for developers
- Clerk – authentication and complete user management
- OAuth2 Proxy – reverse proxy that authenticates via OAuth providers
- Kanidm – simple, secure identity management platform
- lldap – light LDAP implementation
- Rauthy – OIDC single sign-on and IAM
- Casdoor – authentication and authorization platform
- PocketBase – open-source backend in one file