Getting Started
This guide gets you to a working FerrisKey instance with your first authenticated user. You will start the Docker stack, create a realm, register a client, create a user, and request tokens.
Prerequisites
- Docker and Docker Compose installed
- A terminal and a web browser
- Ports
3333(API) and5555(UI) available
Deploy FerrisKey
Start the stack
Clone the repository and start all services:
git clone https://github.com/ferriskey/ferriskey.git
cd ferriskey
docker compose --profile registry up -dThis starts PostgreSQL, the FerrisKey API server, database migrations, and the admin console.
Verify the deployment
Wait a few seconds for migrations to complete, then check that all services are healthy:
docker compose --profile registry psThe API is available at http://localhost:3333 and the UI at http://localhost:5555.
Log in to the admin console
Open http://localhost:5555 in your browser and sign in with the default credentials:
- Username:
admin - Password:
admin
You’ll land in the master realm, the built-in realm that manages all other realms.
Change default credentials
The default admin credentials are for local development only. Change them immediately in any non-local environment by setting the ADMIN_USERNAME, ADMIN_PASSWORD, and ADMIN_EMAIL environment variables.
Deploy Without Cloning the Repository
The quickstart above clones the repository, but you don’t need the source code to run FerrisKey. The API, web app, and database migrations all ship as published images on ghcr.io/ferriskey. To deploy on a server, save the following as docker-compose.yml and start it directly — no checkout required:
services:
db:
image: postgres:18.2
environment:
POSTGRES_DB: ferriskey
POSTGRES_USER: ferriskey
POSTGRES_PASSWORD: ferriskey
volumes:
- pgdata:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -d ferriskey"]
interval: 10s
timeout: 10s
retries: 5
start_period: 30s
db-migrations:
image: ghcr.io/ferriskey/ferriskey-api
entrypoint: ["sqlx"]
command: ["migrate", "run", "--source", "/usr/local/src/ferriskey/migrations"]
environment:
DATABASE_URL: postgresql://ferriskey:ferriskey@db/ferriskey
restart: "no"
depends_on:
db:
condition: service_healthy
api:
image: ghcr.io/ferriskey/ferriskey-api
environment:
ALLOWED_ORIGINS: http://localhost:5555
WEBAPP_URL: http://localhost:5555
DATABASE_HOST: db
DATABASE_NAME: ferriskey
DATABASE_USER: ferriskey
DATABASE_PASSWORD: ferriskey
ports:
- 3333:3333
depends_on:
db-migrations:
condition: service_completed_successfully
webapp:
image: ghcr.io/ferriskey/ferriskey-webapp
environment:
API_URL: http://localhost:3333
ports:
- 5555:80
volumes:
pgdata:
name: ferriskey_pgdata
Then start the stack:
docker compose up -d
The migration files are baked into the ferriskey-api image (under /usr/local/src/ferriskey/migrations), so the db-migrations service applies the schema without any checked-out source. These are the same images the repository’s registry profile uses, extracted into a self-contained file you can drop onto any host or convert to a Docker Swarm stack.
Pin a version for production
The images above track the latest tag. For reproducible deployments, pin an explicit tag — for example ghcr.io/ferriskey/ferriskey-api:vX.Y.Z — on both the api and db-migrations services so they always run the same binary and schema.
Upgrading FerrisKey
Schema changes ship inside the API image, so upgrading a running stack is “pull, migrate, restart”:
Pull the new images
docker compose pull Apply new migrations
The db-migrations service runs sqlx migrate run, which only applies migrations that have not run yet — so it is safe to run on every upgrade:
docker compose up -d db-migrations Restart the application
Once migrations complete, recreate the API and web app on the new images:
docker compose up -d api webapp Keep api and migrations on the same tag
Always pull the api and db-migrations services from the same image tag. Running a newer API against an older schema — or an older API against a newer schema — can fail at startup.
Create Your First Realm
A realm is an isolated tenant. Users, clients, roles, and credentials all live inside a realm.
Create a realm
In the admin console, navigate to Realms and click Create Realm. Give it a name like my-app and save.
Switch to the new realm
Use the realm selector in the sidebar to switch to my-app. All subsequent operations happen within this realm.
Register a Client
A client represents an application that uses FerrisKey for authentication.
Create a client
Navigate to Clients and click Create Client. Use these values:
- Client ID:
my-frontend - Client Type:
Public(for a single-page application) - Redirect URIs:
http://localhost:3000/*
Save the client.
Enable direct access grants
If you want to test authentication directly via the API (password grant), enable Direct Access Grants on the client settings page.
Create a User
Create a user
Navigate to Users and click Create User. Fill in:
- Username:
alice - Email:
alice@example.com - First Name:
Alice - Last Name:
Smith
Save the user.
Set a password
On the user’s Credentials tab, set a password. Uncheck Temporary if you don’t want to force a password change on first login.
Authenticate
With direct access grants enabled, you can request tokens directly from the API:
curl -X POST http://localhost:3333/realms/my-app/protocol/openid-connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=password" \
-d "client_id=my-frontend" \
-d "username=alice" \
-d "password=your-password"
The response contains an access_token, refresh_token, and optionally an id_token. That means the user authenticated successfully.
Connect a Real Application
The password grant above is useful for a quick API test. For real applications, use browser-based SSO with the OpenID Connect authorization code flow.
If you want to connect a dashboard, internal service, or self-hosted tool, follow the application SSO guide next. It shows which dashboard screens to use, what values to copy, and how to debug common setup mistakes.