Skip to main content

Local Development Stack

Complete guide to setting up and running the Easy AppServer development environment with all dependencies.

Overview

The local development stack includes:

Core Services:

  • PostgreSQL - Shared database
  • Redis - Cache & session store
  • RabbitMQ - Message broker & event bus
  • Kratos - Identity and user management
  • Hydra - OAuth2/OIDC provider
  • OpenFGA - Fine-grained authorization
  • Oathkeeper - Identity & access proxy
  • AppServer - Central orchestration platform

Observability Stack:

  • OpenTelemetry Collector - Telemetry aggregation
  • Prometheus - Metrics storage
  • Loki - Log aggregation
  • Tempo - Distributed tracing
  • Grafana - Unified visualization

Prerequisites

  • Docker & Docker Compose: For running infrastructure
  • Go 1.21+: For running AppServer
  • Node.js 18+: For running Shell and documentation
  • Make: For using makefiles (optional)

Quick Start

1. Clone and Navigate

git clone <repository-url>
cd easy.appserver

2. Run Setup Script

./docker/scripts/setup.sh

This automated script will:

  1. Create .env file from .env.example
  2. Start PostgreSQL
  3. Run database migrations
  4. Start all core services (Kratos, Hydra, OpenFGA, Oathkeeper, etc.)
  5. Initialize OpenFGA with base roles: easy, admin, advertiser, publisher

3. Update Secrets

IMPORTANT: Before running in production or sharing environments, update these values in docker/.env:

# Must be exactly 32 characters
KRATOS_SECRETS_COOKIE=changeme-32-char-secret-cookie-key
KRATOS_SECRETS_CIPHER=changeme-32-char-secret-cipher-k

# Strong secrets
HYDRA_SYSTEM_SECRET=changeme-change-this-system-secret-key
HYDRA_PAIRWISE_SALT=changeme-pairwise-salt-key
POSTGRES_PASSWORD=changeme-in-production

4. Start AppServer

# Set environment variables
export APPSERVER_DB_HOST=localhost
export APPSERVER_DB_PORT=5432
export APPSERVER_DB_USER=partner
export APPSERVER_DB_PASSWORD=changeme-in-production
export APPSERVER_DB_NAME=appserver
export APPSERVER_KRATOS_PUBLIC_URL=http://localhost:4433
export APPSERVER_OPENFGA_API_URL=http://localhost:8090

# Run appserver
go run cmd/appserver-v2/main.go serve

Or using Makefile:

make docker-up    # Start all infrastructure
make run # Run appserver

Service URLs

Core Services

ServiceURLPurpose
Kratos Publichttp://localhost:4433User-facing identity APIs
Kratos Adminhttp://localhost:4434Admin identity management
Hydra Publichttp://localhost:4444OAuth2 authorization server
Hydra Adminhttp://localhost:4445OAuth2 admin APIs
OpenFGA APIhttp://localhost:8090Authorization API
OpenFGA gRPChttp://localhost:8091Authorization gRPC
OpenFGA Playgroundhttp://localhost:8090/playgroundAuthorization testing UI
Oathkeeper Proxyhttp://localhost:4455Access control proxy
Oathkeeper APIhttp://localhost:4456Proxy configuration
PostgreSQLlocalhost:5432Database
Redislocalhost:6379Cache
RabbitMQlocalhost:5672Message broker
RabbitMQ Managementhttp://localhost:15672Queue management UI
AppServer HTTPhttp://localhost:8080Main HTTP API
AppServer GraphQLhttp://localhost:8080/graphqlGraphQL API
AppServer gRPClocalhost:9090gRPC API
Documentationhttp://localhost:3030Docusaurus docs

Observability Services

ServiceURLCredentials
Grafanahttp://localhost:3000admin/admin
Prometheushttp://localhost:9090-
Lokihttp://localhost:3100-
Tempohttp://localhost:3200-
OTel Collector (gRPC)localhost:4317-
OTel Collector (HTTP)http://localhost:4318-
OTel Collector Metricshttp://localhost:8888-

Architecture

┌─────────────────────────────────────────────────────────────┐
│ Docker Network │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ AppServer │───▶│ Oathkeeper │───▶│ Kratos │ │
│ │ (Go/gRPC) │ │ (Proxy) │ │ (Identity) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ │ │ │ │
│ │ ▼ ▼ │
│ │ ┌──────────────┐ ┌──────────────┐ │
│ └───────────▶│ Hydra │ │ OpenFGA │ │
│ │ (OAuth2) │ │ (AuthZ) │ │
│ └──────────────┘ └──────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ PostgreSQL │ │
│ │ (kratos, hydra, openfga, │ │
│ │ appserver, shell, partner) │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

Database Setup

The setup script creates the following schemas in PostgreSQL:

Databases:

  • partner - Main database

Schemas:

  • kratos - Ory Kratos identity data
  • hydra - Ory Hydra OAuth2 data
  • openfga - OpenFGA authorization data
  • appserver - AppServer application data
  • shell - Shell frontend data
  • partner - Legacy partner data

Migrations:

  • Automatically run during setup
  • Located in relevant service directories
  • Use Goose for AppServer migrations

OpenFGA Roles

The setup script creates 4 base roles:

Built-in Roles

easy - God mode (full platform access):

  • Internal employees
  • Full access to all resources
  • Can perform any action

admin - Platform administrator:

  • Manage applications
  • Manage users
  • Configure settings

advertiser - Advertiser role:

  • Manage own campaigns
  • View reports
  • Limited platform access

publisher - Publisher role:

  • Manage own properties
  • View analytics
  • Limited platform access

Assign User to Role

curl -X POST 'http://localhost:8090/stores/${STORE_ID}/write' \
-H 'Content-Type: application/json' \
-d '{
"writes": {
"tuple_keys": [
{
"user": "user:<USER_ID>",
"relation": "assignee",
"object": "role:easy"
}
]
}
}'

Replace <USER_ID> with the actual Kratos identity ID.

Grant Role Permission

# Grant 'advertiser' role viewer access to an app
curl -X POST 'http://localhost:8090/stores/${STORE_ID}/write' \
-H 'Content-Type: application/json' \
-d '{
"writes": {
"tuple_keys": [
{
"user": "role:advertiser#assignee",
"relation": "viewer",
"object": "app:<APP_ID>"
}
]
}
}'

Management Commands

View Logs

# All services
docker-compose -f docker/docker-compose.yml logs -f

# Specific service
docker-compose -f docker/docker-compose.yml logs -f kratos

# Or use makefile
make docker-logs

Stop Services

# Stop all services
docker-compose -f docker/docker-compose.yml down

# Stop and remove volumes (clean slate)
docker-compose -f docker/docker-compose.yml down -v

# Or use makefile
make docker-down

Restart Service

# Restart specific service
docker-compose -f docker/docker-compose.yml restart kratos

# Rebuild and restart
docker-compose -f docker/docker-compose.yml up -d --build kratos

Database Access

# Connect to PostgreSQL
docker exec -it easy-appserver-postgres psql -U partner -d partner

# Run query
docker exec -it easy-appserver-postgres psql -U partner -d partner -c "SELECT * FROM appserver.apps"

# Run migrations
make migrate-up
make migrate-down

RabbitMQ Management

# Access management UI
open http://localhost:15672

# Default credentials: guest/guest

# List queues via CLI
docker exec -it easy-appserver-rabbitmq rabbitmqctl list_queues

# List exchanges
docker exec -it easy-appserver-rabbitmq rabbitmqctl list_exchanges

Environment Variables

AppServer Configuration

Key environment variables (see docker/.env.example for full list):

Server:

APPSERVER_HTTP_PORT=8080
APPSERVER_GRPC_PORT=9090
APPSERVER_ENV=development

Database:

APPSERVER_DB_HOST=postgres
APPSERVER_DB_PORT=5432
APPSERVER_DB_NAME=appserver
APPSERVER_DB_USER=partner
APPSERVER_DB_PASSWORD=changeme-in-production
APPSERVER_DB_SSLMODE=disable

Cache:

APPSERVER_REDIS_URL=redis://redis:6379
APPSERVER_CACHE_TTL=300 # 5 minutes

Event Bus:

APPSERVER_EVENTBUS_ENABLED=true
APPSERVER_RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672/
APPSERVER_RABBITMQ_MAX_RETRIES=5
APPSERVER_RABBITMQ_PREFETCH_COUNT=10

Security:

APPSERVER_GRPC_TLS_ENABLED=false  # Enable in production
APPSERVER_GRPC_REFLECTION_ENABLED=true # Disable in production
APPSERVER_GRAPHQL_PLAYGROUND_ENABLED=true # Disable in production
APPSERVER_SESSION_COOKIE_NAME=ory_kratos_session
APPSERVER_KRATOS_TIMEOUT=5s
APPSERVER_OPENFGA_TIMEOUT=5s
APPSERVER_SIGNATURE_REPLAY_WINDOW=5m
APPSERVER_CLOCK_SKEW_TOLERANCE=30s

Telemetry:

APPSERVER_LOG_LEVEL=debug
APPSERVER_METRICS_ENABLED=true
APPSERVER_TRACING_ENABLED=false

Troubleshooting

Port Conflicts

OpenFGA ports changed:

  • API: 8090 (was 8080, conflicted with AppServer)
  • gRPC: 8091 (was 8081, conflicted with AppServer)

Documentation port changed:

  • Docs: 3030 (was 8888, conflicted with OTel Collector)

Check for conflicts:

# Check if port is in use
lsof -i :8080
netstat -an | grep 8080

# Kill process using port
kill -9 <PID>

Database Connection Issues

# Check PostgreSQL is running
docker ps | grep postgres

# Check logs
docker logs easy-appserver-postgres

# Test connection
docker exec -it easy-appserver-postgres psql -U partner -d partner -c "SELECT 1"

# Restart PostgreSQL
docker-compose -f docker/docker-compose.yml restart postgres

RabbitMQ Connection Issues

# Check RabbitMQ is running
docker ps | grep rabbitmq

# Check logs
docker logs easy-appserver-rabbitmq

# Check node status
docker exec -it easy-appserver-rabbitmq rabbitmqctl status

# Reset RabbitMQ
docker-compose -f docker/docker-compose.yml restart rabbitmq

Kratos/Hydra Issues

# Run migrations manually
docker exec -it easy-appserver-kratos kratos migrate sql -e --yes

docker exec -it easy-appserver-hydra hydra migrate sql -e --yes

# Check Kratos health
curl http://localhost:4434/health/ready

# Check Hydra health
curl http://localhost:4445/health/ready

OpenFGA Issues

# Check OpenFGA logs
docker logs easy-appserver-openfga

# Test API
curl http://localhost:8090/healthz

# Access playground
open http://localhost:8090/playground

Clean Slate

# Stop all services and remove volumes
docker-compose -f docker/docker-compose.yml down -v

# Remove all AppServer data
docker volume ls | grep easy-appserver | awk '{print $2}' | xargs docker volume rm

# Re-run setup
./docker/scripts/setup.sh

Development Workflow

1. Start Infrastructure

make docker-up

2. Run AppServer

# Terminal 1: AppServer
make run

# Or with custom config
go run cmd/appserver-v2/main.go serve --config custom-config.yaml

3. Run Shell (Optional)

# Terminal 2: Shell
cd web/v2/packages/shell
pnpm install
pnpm dev

4. Run Documentation (Optional)

# Terminal 3: Documentation
cd docs
pnpm install
pnpm start

5. Make Changes

  • Edit code
  • AppServer auto-recompiles (with air or manual restart)
  • Shell hot-reloads automatically
  • Documentation hot-reloads automatically

6. Test Changes

# Run tests
make test

# Run integration tests
make test-integration

# Test specific package
go test ./pkg/v2/application/marketplace/...

Useful Commands

Docker

# View running services
docker ps

# View all logs
make docker-logs

# Stop all services
make docker-down

# Restart specific service
docker-compose -f docker/docker-compose.yml restart <service>

Database

# Create migration
make migrate-create NAME=add_new_table

# Run migrations
make migrate-up

# Rollback migration
make migrate-down

# Migration status
make migrate-status

Testing

# Unit tests
make test

# Integration tests
make test-integration

# E2E tests
make test-e2e

# Coverage
make test-coverage

Code Quality

# Lint
make lint

# Format
make fmt

# Type check (for Shell)
cd web/v2/packages/shell && pnpm typecheck

Next Steps