Skip to main content

Overview

This guide will walk you through setting up Frontier from scratch and demonstrate its core capabilities. By the end of this tutorial, you’ll have:
  • A running Frontier server with authentication configured
  • An organization with projects and users
  • Role-based access control in action
  • A basic understanding of permission checks
This tutorial assumes you have Docker and Go installed on your system. If you prefer using Kubernetes, check out our deployment guides.

Prerequisites

Before you begin, ensure you have:
  • Docker and Docker Compose installed
  • Go 1.21 or higher (for running examples)
  • PostgreSQL client (optional, for database inspection)
  • A text editor or IDE

Step 1: Start Required Services

Frontier requires PostgreSQL and SpiceDB to run. Let’s start them using Docker Compose.
1

Clone the Frontier repository

git clone https://github.com/raystack/frontier.git
cd frontier
2

Start dependencies with Docker Compose

docker-compose up -d postgres spicedb
This starts:
  • PostgreSQL on port 5432 for storing Frontier data
  • SpiceDB on port 50051 for authorization
Wait about 10 seconds for the services to be ready before proceeding.
3

Verify services are running

docker ps
You should see both postgres and spicedb containers running.

Step 2: Configure Frontier

Create a configuration file with your authentication and server settings.
1

Generate RSA keys for token signing

mkdir -p temp
go run main.go server keygen > temp/rsa
This generates an RSA key pair that Frontier uses to sign JWT tokens.
2

Create configuration file

Create config.yaml in the frontier directory:
config.yaml
version: 1

log:
  level: info
  audit_events: db

app:
  port: 8000
  grpc:
    port: 8001
  metrics_port: 9000

  # WARNING: Only for development - remove in production
  identity_proxy_header: X-Frontier-Email

  authentication:
    session:
      hash_secret_key: "hash-secret-should-be-32-chars--"
      block_secret_key: "block-secret-should-be-32-chars-"
      same_site: "lax"
      secure: false
      validity: "720h"
    
    token:
      rsa_path: ./temp/rsa
      iss: "http://localhost.frontier"
      validity: "1h"
      claims:
        add_org_ids: true
        add_user_email: true
    
    callback_urls: ["http://localhost:8000/v1beta1/auth/callback"]
    authorized_redirect_urls: ["http://localhost:3000"]
  
  admin:
    users: ["[email protected]"]

db:
  driver: postgres
  url: postgres://frontier:@localhost:5432/frontier?sslmode=disable
  max_query_timeout: 500ms

spicedb:
  host: localhost
  port: 50051
  pre_shared_key: frontier
  consistency: "best_effort"
The identity_proxy_header allows you to bypass authentication during development by passing a user email in the header. Remove this in production!

Step 3: Initialize and Start Frontier

1

Run database migrations

go run main.go server migrate
This creates all necessary tables in PostgreSQL.
2

Start the Frontier server

go run main.go server start
You should see output indicating the server started:
INFO  server started  port=8000
INFO  grpc server started  port=8001
INFO  metrics server started  port=9000
3

Verify the server is running

Open a new terminal and check the health endpoint:
curl http://localhost:8000/v1beta1/ping
Expected response:
{"message":"pong"}

Step 4: Create Your First Organization

Now let’s use Frontier to create an organization structure.
1

Create a user

curl -X POST http://localhost:8000/v1beta1/users \
  -H "Content-Type: application/json" \
  -H "X-Frontier-Email: [email protected]" \
  -d '{
    "name": "Admin User",
    "email": "[email protected]",
    "metadata": {
      "department": "Engineering"
    }
  }'
Save the returned id - you’ll need it later.
2

Create an organization

curl -X POST http://localhost:8000/v1beta1/organizations \
  -H "Content-Type: application/json" \
  -H "X-Frontier-Email: [email protected]" \
  -d '{
    "name": "Acme Corp",
    "title": "Acme Corporation",
    "metadata": {
      "industry": "Technology"
    }
  }'
Save the organization id from the response.
3

Create a project under the organization

Replace {org_id} with your organization ID:
curl -X POST http://localhost:8000/v1beta1/organizations/{org_id}/projects \
  -H "Content-Type: application/json" \
  -H "X-Frontier-Email: [email protected]" \
  -d '{
    "name": "mobile-app",
    "title": "Mobile App Project",
    "metadata": {
      "platform": "iOS,Android"
    }
  }'
4

Create a group for team members

curl -X POST http://localhost:8000/v1beta1/organizations/{org_id}/groups \
  -H "Content-Type: application/json" \
  -H "X-Frontier-Email: [email protected]" \
  -d '{
    "name": "engineering-team",
    "title": "Engineering Team",
    "metadata": {
      "department": "Engineering"
    }
  }'

Step 5: Set Up Permissions and Roles

1

List available permissions

curl http://localhost:8000/v1beta1/permissions \
  -H "X-Frontier-Email: [email protected]"
Frontier comes with built-in permissions like:
  • app.organization.update
  • app.project.get
  • app.project.update
  • app.group.create
2

Create a custom role

curl -X POST http://localhost:8000/v1beta1/roles \
  -H "Content-Type: application/json" \
  -H "X-Frontier-Email: [email protected]" \
  -d '{
    "name": "project-manager",
    "title": "Project Manager",
    "permissions": [
      "app.project.get",
      "app.project.update",
      "app.group.create"
    ],
    "metadata": {
      "description": "Can manage projects and groups"
    }
  }'
3

Assign role to user

Replace {org_id} and {user_id} with actual values:
curl -X POST http://localhost:8000/v1beta1/organizations/{org_id}/users/{user_id}/roles \
  -H "Content-Type: application/json" \
  -H "X-Frontier-Email: [email protected]" \
  -d '{
    "role_id": "project-manager"
  }'

Step 6: Check Permissions

Verify that your permission system is working.
1

Check if user can update project

curl -X POST http://localhost:8000/v1beta1/check \
  -H "Content-Type: application/json" \
  -H "X-Frontier-Email: [email protected]" \
  -d '{
    "resource": "app/project:{project_id}",
    "permission": "app.project.update"
  }'
Expected response:
{
  "status": true
}
2

Check a permission the user doesn't have

curl -X POST http://localhost:8000/v1beta1/check \
  -H "Content-Type: application/json" \
  -H "X-Frontier-Email: [email protected]" \
  -d '{
    "resource": "app/organization:{org_id}",
    "permission": "app.organization.delete"
  }'
Expected response:
{
  "status": false
}

Step 7: Explore the Admin Portal (Optional)

Frontier includes an admin portal for managing your deployment visually.
1

Navigate to the admin portal directory

cd web/apps/admin
2

Install dependencies and start

npm install
npm run dev
3

Access the portal

Open your browser to http://localhost:5173/consoleYou can now manage organizations, users, roles, and more through the UI.

Next Steps

Now that you have Frontier running, explore these topics:

Setup OIDC Authentication

Configure Google, GitHub, or Azure AD for single sign-on

Configure Webhooks

Send events to external services when actions occur

Enable Audit Logs

Track all actions for compliance and security

Authorization Examples

Learn advanced permission patterns and policies

Troubleshooting

Check if another process is using port 8000:
lsof -i :8000
Either stop that process or change the port in config.yaml.
Ensure PostgreSQL is running:
docker ps | grep postgres
Check the connection string in your config matches the container settings.
Verify SpiceDB is accessible:
curl http://localhost:50051
The pre_shared_key in config.yaml must match the SpiceDB configuration.
Make sure you:
  1. Created the role with the correct permissions
  2. Assigned the role to the user for the specific organization
  3. Used the correct resource format: app/resource_type:resource_id

Common Issues

Development vs Production: The identity_proxy_header setting bypasses authentication and should NEVER be used in production. Remove it and configure proper OIDC authentication before deploying.
Testing with cURL: All the examples use cURL for simplicity. In production, you’ll use the Frontier SDKs for JavaScript, React, or make direct API calls from your application.

Build docs developers (and LLMs) love