
Open-source authentication and authorization for your applications.
Bring your own database and stay in control of user data.
Documentation · OAuth 2.0 / OIDC · v1 → v2 migration · Contributing · Discord
Authorizer is an open-source authentication and authorization server you can self-host. Connect any supported database (13+ backends including Postgres, MySQL, SQLite, SQL Server, YugaByte, MariaDB, Cassandra, ScyllaDB, MongoDB, ArangoDB, DynamoDB, and Couchbase) and run OAuth2/OIDC, social login, MFA, magic links, RBAC, webhooks, and email templates from one place.
v2 note: Authorizer v2 uses CLI arguments for all configuration. The server does not read from
.envor OS environment variables. Pass config when starting the binary (e.g../authorizer --client-id=... --client-secret=...). See MIGRATION.md.
Prerequisites: Go ≥ 1.24 (see go.mod).
git clone https://github.com/authorizerdev/authorizer.git
cd authorizer
make dev
make dev runs the server with SQLite and development defaults (RS256 keys, sample client credentials). Open the URL printed in the logs (default port 8080) and sign in with --admin-secret (admin in dev).
For production builds, tests, and Docker, see Getting Started below.
Deploy production ready Authorizer instance using one click deployment options available below
| Infra provider | One-click link | Additional information |
|---|---|---|
| Railway.app | docs | |
| Heroku | docs | |
| Render | docs | |
| Koyeb | docs | |
| RepoCloud | ![]() |
docs |
| Alibaba Cloud | docs |
This guide helps you practice using Authorizer to evaluate it before you use it in a production environment. It includes instructions for installing the Authorizer server in local or standalone mode.
go.mod)git clone https://github.com/authorizerdev/authorizer.git (or your fork URL)cd authorizermake dev — SQLite, RS256 dev keys, sample OAuth client (see Quick start)make build (or go build -o build/authorizer .); optionally make build-app and make build-dashboardmake dev:
bash
./build/authorizer \
--database-type=sqlite \
--database-url=test.db \
--jwt-type=HS256 \
--jwt-secret=test \
--admin-secret=admin \
--client-id=123456 \
--client-secret=secretv2: The server does not read from
.env. All configuration must be passed as CLI arguments. See MIGRATION.md for the full mapping of env vars to flags.
The default image runs as non-root (UID 65532). Writable mounts (SQLite under /authorizer/data, etc.) are usually root-owned, so pick one of:
sh
docker run -p 8080:8080 -u root \
-v authorizer_data:/authorizer/data \
quay.io/authorizer/authorizer \
--database-type=sqlite \
--database-url=/authorizer/data/data.db \
--client-id=123456 \
--client-secret=secret \
--admin-secret=admin \
--jwt-type=HS256 \
--jwt-secret=test
65532 (good for production-style bind mounts):sh
mkdir -p ./data && sudo chown -R 65532:65532 ./data
docker run -p 8080:8080 \
-v "$(pwd)/data:/authorizer/data" \
quay.io/authorizer/authorizer \
--database-type=sqlite \
--database-url=/authorizer/data/data.db \
...
-u at run time):sh
docker build --target final-root -t authorizer:root .
docker run -p 8080:8080 -v authorizer_data:/authorizer/data authorizer:root \
--database-type=sqlite --database-url=/authorizer/data/data.db ...
-p 8080:8080 to expose it.authorizer_data persists the SQLite DB; use a named volume or a host path (e.g. -v $(pwd)/data:/authorizer/data).ENTRYPOINT ["./authorizer"] so args after the image name go to the binary). See MIGRATION.md for the full list of flags.Inside a container, localhost / 127.0.0.1 is the container itself, not your machine. Use a host alias instead:
host.docker.internal in --database-url or --database-host (built in).sh
docker run -p 8080:8080 quay.io/authorizer/authorizer \
--database-type=postgres \
--database-url="postgres://user:pass@host.docker.internal:5432/dbname?sslmode=disable" \
...
sh
docker run -p 8080:8080 --add-host=host.docker.internal:host-gateway \
quay.io/authorizer/authorizer \
--database-type=postgres \
--database-url="postgres://user:pass@host.docker.internal:5432/dbname?sslmode=disable" \
...
172.17.0.1) if your DB listens on 0.0.0.0, or run with --network host so the container shares the host network (then localhost works; port mapping -p is not used the same way).Ensure the database accepts non-localhost connections (e.g. listen_addresses in Postgres, bind address in MySQL) and that your OS firewall allows the Docker subnet.
Extending the image with env-based config (e.g. Railway): If you FROM quay.io/authorizer/authorizer and use a shell-form CMD so that env vars are expanded at runtime, you must override ENTRYPOINT in your Dockerfile or the binary will receive /bin/sh and -c as arguments and fail. Use:
FROM quay.io/authorizer/authorizer:2.0.0-rc.1
# v2 uses CLI arguments only. Railway (etc.) inject env vars; shell form CMD expands them at runtime.
# Override ENTRYPOINT so CMD is run by a shell; otherwise the base ENTRYPOINT would receive /bin/sh -c "..." as args.
ENTRYPOINT ["/bin/sh", "-c"]
CMD ./authorizer \
--database-type="$${DATABASE_TYPE:-postgres}" \
--database-url="$${DATABASE_URL}" \
--client-id="$${CLIENT_ID}" \
--client-secret="$${CLIENT_SECRET}" \
--admin-secret="$${ADMIN_SECRET}" \
...
Use $$ in the Dockerfile so Docker does not expand $VAR at build time.
Deploy / Try Authorizer using binaries. With each Authorizer Release, binaries are baked with required deployment files and bundled. You can download a specific version for the following operating systems:
Note: For Windows, we recommend running Authorizer via Docker.
sh
tar -zxf authorizer-VERSION-OS-ARCH.tar.gz
cd authorizer-VERSION-OS-ARCHsh
./authorizer \
--database-type=sqlite \
--database-url=test.db \
--jwt-type=HS256 \
--jwt-secret=test \
--admin-secret=admin \
--client-id=123456 \
--client-secret=secretv2: The binary is named
authorizer(notserver). Configuration is passed via CLI arguments;.envis not read. On macOS you may need:xattr -d com.apple.quarantine authorizer
--admin-secret you configured at startupv2: Environment variables are not configurable from the dashboard. All configuration is set at startup via CLI arguments. See MIGRATION.md for the full list of flags.
Note: One can alway
$ claude mcp add authorizer \
-- python -m otcore.mcp_server <graph>