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.
Clone the Frontier repository
git clone https://github.com/raystack/frontier.git
cd frontier
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.
Verify services are running
You should see both postgres and spicedb containers running.
Create a configuration file with your authentication and server settings.
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.
Create configuration file
Create config.yaml in the frontier directory: 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
Run database migrations
go run main.go server migrate
This creates all necessary tables in PostgreSQL.
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
Verify the server is running
Open a new terminal and check the health endpoint: curl http://localhost:8000/v1beta1/ping
Expected response:
Step 4: Create Your First Organization
Now let’s use Frontier to create an organization structure.
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.
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.
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"
}
}'
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
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
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"
}
}'
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.
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:
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:
Step 7: Explore the Admin Portal (Optional)
Frontier includes an admin portal for managing your deployment visually.
Navigate to the admin portal directory
Install dependencies and start
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
Server won't start - port already in use
Check if another process is using port 8000: Either stop that process or change the port in config.yaml.
Database connection failed
Ensure PostgreSQL is running: docker ps | grep postgres
Check the connection string in your config matches the container settings.
SpiceDB connection refused
Verify SpiceDB is accessible: curl http://localhost:50051
The pre_shared_key in config.yaml must match the SpiceDB configuration.
Permission check always returns false
Make sure you:
Created the role with the correct permissions
Assigned the role to the user for the specific organization
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.