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) and 5555 (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 -d

This 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 ps

The 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.

What’s Next?