Skip to main content

Installation Guide

Complete installation instructions for Easy AppServer with detailed configuration options.

System Requirements

Minimum Requirements

  • CPU: 2 cores (4+ cores recommended for production)
  • RAM: 4 GB minimum (8+ GB recommended)
  • Disk Space: 10 GB minimum (includes database storage)
  • Operating Systems: Linux, macOS, Windows (with WSL2)

Required Software

  • Docker 20.10+ and Docker Compose v2.0+
  • Go 1.22+ (for building from source)
  • Git for repository access
  • Make (optional, for convenience commands)

Network Requirements

The platform requires the following ports to be available:

ServicePortsPurpose
AppServer8080, 9090HTTP/GraphQL and gRPC
PostgreSQL5432Database
Redis6379Cache
RabbitMQ5672, 15672Message broker and management UI
Kratos4433, 4434Identity (public and admin)
Hydra4444, 4445OAuth2 (public and admin)
OpenFGA8090, 8091Authorization (HTTP and gRPC)
Oathkeeper4455, 4456Access proxy
Grafana3000Observability dashboard
Prometheus9090Metrics (conflicts with appserver gRPC if both on host)
Loki3100Logs
Tempo3200Traces
OTel Collector4317, 4318Telemetry (gRPC and HTTP)

Installation Methods

This is the recommended method for both development and production environments.

Step 1: Clone the Repository

git clone <repository-url>
cd easy.appserver

Step 2: Run Setup Script

The automated setup script configures everything for you:

./docker/scripts/setup.sh

This script:

  1. Creates docker/.env from docker/.env.example
  2. Starts PostgreSQL container
  3. Runs database migrations for all 6 schemas
  4. Starts all infrastructure services
  5. Initializes OpenFGA with 4 base roles

Step 3: Update Secrets

CRITICAL: Before running in production, update these secrets in docker/.env:

# Must be exactly 32 characters
KRATOS_SECRETS_COOKIE=<generate-32-char-secret>
KRATOS_SECRETS_CIPHER=<generate-32-char-secret>

# Strong unique secrets
HYDRA_SYSTEM_SECRET=<generate-strong-secret>
HYDRA_PAIRWISE_SALT=<generate-strong-salt>
POSTGRES_PASSWORD=<generate-strong-password>

Generate secrets using:

# Generate 32-character secret
openssl rand -base64 32 | head -c 32

# Generate strong random secret
openssl rand -base64 48

Step 4: Start All Services

# Start infrastructure
make docker-up

# Or manually
docker-compose -f docker/docker-compose.yml up -d

Step 5: Start the AppServer

# Using Makefile (recommended - uses legacy CLI)
make run

# Or manually with v2 (no subcommands)
export APPSERVER_DB_HOST=localhost
export APPSERVER_DB_PORT=5432
export APPSERVER_DB_USER=appserver
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
export APPSERVER_SETTINGS_ENCRYPTION_KEY=changeme-32-char-encryption-key

go run cmd/appserver-v2/main.go

Method 2: Standalone Binary

Run the AppServer as a standalone binary while still using Docker for infrastructure.

Step 1: Build the Binary

# Build the appserver binary
go build -o appserver cmd/appserver-v2/main.go

# Or for production with optimizations
CGO_ENABLED=0 go build -ldflags="-s -w" -o appserver cmd/appserver-v2/main.go

Step 2: Start Infrastructure

make docker-up

Step 3: Create Configuration File

Create a config.yml file:

server:
http_port: 8080
grpc_port: 9090
graphql_playground_enabled: false
grpc_reflection_enabled: false

database:
host: localhost
port: 5432
database: appserver
username: partner
password: changeme-in-production

cache:
redis_url: redis://localhost:6379
local_cache_ttl: 300

eventbus:
enabled: true
url: amqp://guest:guest@localhost:5672/
max_retries: 3

auth_services:
kratos_public_url: "http://localhost:4433"
kratos_admin_url: "http://localhost:4434"
openfga_api_url: "http://localhost:8090"

Step 4: Run the Binary

# Run with config file
./appserver serve -c config.yml

# Or with environment variables
export APPSERVER_DB_PASSWORD=changeme-in-production
./appserver serve

Method 3: From Source

Build and run directly from source code.

Step 1: Install Dependencies

# Install Go dependencies
go mod download

# Verify build works
go build ./cmd/appserver-v2

Step 2: Start Infrastructure

make docker-up

Step 3: Run from Source

# Run with default configuration (v2 - no subcommands)
go run cmd/appserver-v2/main.go

# Or use legacy CLI with serve subcommand
go run cmd/app/main.go serve

# Or run in development mode (uses legacy CLI)
make run-dev

Configuration

Environment Variables

The AppServer can be configured via environment variables or a YAML config file.

Database Configuration

VariableDefaultDescription
APPSERVER_DB_HOSTlocalhostPostgreSQL host
APPSERVER_DB_PORT5432PostgreSQL port
APPSERVER_DB_USERappserverDatabase username
APPSERVER_DB_PASSWORD-Database password (required)
APPSERVER_DB_NAMEappserverDatabase name
APPSERVER_DB_SSLMODEdisableSSL mode (disable, require, verify-ca, verify-full)

Server Configuration

VariableDefaultDescription
APPSERVER_HTTP_PORT8080HTTP/GraphQL server port
APPSERVER_GRPC_PORT9090gRPC server port
APPSERVER_GRAPHQL_PLAYGROUND_ENABLEDfalseEnable GraphQL playground (dev only)
APPSERVER_GRPC_REFLECTION_ENABLEDfalseEnable gRPC reflection (dev only)
APPSERVER_LOG_LEVELinfoLog level (debug, info, warn, error)

Cache Configuration

VariableDefaultDescription
APPSERVER_REDIS_URLredis://localhost:6379Redis connection URL
APPSERVER_CACHE_TTL300Local cache TTL in seconds

Event Bus Configuration

VariableDefaultDescription
APPSERVER_RABBITMQ_ENABLEDfalseEnable RabbitMQ event bus
APPSERVER_RABBITMQ_URLamqp://guest:guest@localhost:5672/RabbitMQ connection URL
APPSERVER_RABBITMQ_MAX_RETRIES5Max retry attempts for failed events
APPSERVER_RABBITMQ_PREFETCH_COUNT10Consumer prefetch count

Auth Services Configuration

VariableDefaultDescription
APPSERVER_KRATOS_PUBLIC_URLhttp://localhost:4433Kratos public API URL
APPSERVER_KRATOS_ADMIN_URLhttp://localhost:4434Kratos admin API URL
APPSERVER_OPENFGA_API_URLhttp://localhost:8090OpenFGA API URL
APPSERVER_OPENFGA_STORE_ID-OpenFGA store ID (auto-detected if not set)
APPSERVER_SESSION_COOKIE_NAMEory_kratos_sessionSession cookie name

Security Configuration

VariableDefaultDescription
APPSERVER_SETTINGS_ENCRYPTION_KEY-Required 32-byte encryption key for sensitive settings

Configuration File

Alternatively, use a YAML configuration file:

# config.yml
server:
http_port: 8080
grpc_port: 9090
graphql_playground_enabled: false
grpc_reflection_enabled: false

database:
host: localhost
port: 5432
database: appserver
username: appserver
password: ${APPSERVER_DB_PASSWORD}
sslmode: disable

cache:
redis_url: redis://localhost:6379
local_cache_ttl: 300

rabbitmq:
enabled: false
url: amqp://guest:guest@localhost:5672/
max_retries: 5
prefetch_count: 10

auth:
session_cookie_name: "ory_kratos_session"
kratos_timeout: 5s
openfga_timeout: 5s

auth_services:
kratos_public_url: "http://localhost:4433"
kratos_admin_url: "http://localhost:4434"
openfga_api_url: "http://localhost:8090"

telemetry:
log_level: "info"
metrics_enabled: true
tracing_enabled: true

Load the config file:

./appserver serve -c config.yml

Initial Setup

Database Migrations

Migrations run automatically via the db-migrate service in Docker Compose. Migrations are embedded in the appserver code and run on startup.

OpenFGA Setup

OpenFGA is initialized automatically by the setup script with 4 base roles:

  • easy - Full platform access (god mode for internal employees)
  • admin - Platform administrator
  • advertiser - Advertiser role
  • publisher - Publisher role

To reinitialize OpenFGA roles:

./docker/scripts/setup-openfga-roles.sh

Assign a User to a Role

Get the OpenFGA store ID from the environment or logs, then:

# Get store ID
export STORE_ID=$(docker exec appserver-openfga \
fga store list --api-url http://localhost:8090 | \
jq -r '.stores[0].id')

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

Replace <kratos-user-id> with the actual Kratos identity ID from the database.

Create First User (via Kratos)

# Create user via Kratos API
curl -X POST http://localhost:4434/admin/identities \
-H 'Content-Type: application/json' \
-d '{
"schema_id": "default",
"traits": {
"email": "admin@example.com",
"name": {
"first": "Admin",
"last": "User"
}
}
}'

Verification

Health Checks

Verify all services are running correctly:

# AppServer health
curl http://localhost:8080/health

# AppServer readiness
curl http://localhost:8080/ready

# Kratos health
curl http://localhost:4433/health/ready

# Hydra health
curl http://localhost:4444/health/ready

# OpenFGA health
curl http://localhost:8090/healthz

# PostgreSQL
docker exec appserver-postgres pg_isready -U partner

Service Connectivity

Test database connection:

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

# List all databases
docker exec -it appserver-postgres psql -U partner -c "\l"

# Check appserver tables
docker exec -it appserver-postgres psql -U partner -d appserver -c "\dt"

Test Redis connection:

# Test Redis
docker exec appserver-redis redis-cli ping

Test RabbitMQ:

# Check RabbitMQ status
docker exec appserver-rabbitmq rabbitmqctl status

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

Check Service Status

# View all running containers
docker-compose -f docker/docker-compose.yml ps

# Check logs
make docker-logs

# Check specific service
docker-compose -f docker/docker-compose.yml logs -f appserver

Upgrading

Backup Before Upgrading

Always backup your data before upgrading:

# Backup PostgreSQL databases
docker exec appserver-postgres pg_dumpall -U partner > backup-$(date +%Y%m%d).sql

# Backup .env file
cp docker/.env docker/.env.backup

# Export OpenFGA data (if needed)
# ... (OpenFGA export commands)

Upgrade Steps

  1. Stop the AppServer (keep infrastructure running):
# Stop appserver process (Ctrl+C if running in terminal)
# Or if running as service:
pkill appserver
  1. Pull Latest Code:
git pull origin master
  1. Run Migrations:
# Migrations run automatically on appserver startup
# No manual migration commands needed for v2
  1. Rebuild and Restart:
# Rebuild binary
go build -o appserver cmd/appserver-v2/main.go

# Start appserver
./appserver serve

Rollback Strategy

If you encounter issues after upgrading:

  1. Stop the AppServer
  2. Checkout previous version:
git checkout <previous-version-tag>
  1. Restore database from backup (if needed):
docker exec -i appserver-postgres psql -U partner < backup.sql

Uninstallation

Stop All Services

# Stop services (preserve data)
make docker-down

# Or manually
docker-compose -f docker/docker-compose.yml down

Remove All Data

# Stop services and remove volumes
make docker-clean

# Or manually
docker-compose -f docker/docker-compose.yml down -v

# Or use teardown script
./docker/scripts/teardown.sh --volumes

Remove Docker Images

# Remove appserver images
docker images | grep easy-appserver | awk '{print $3}' | xargs docker rmi

# Remove all project-related images
docker-compose -f docker/docker-compose.yml down --rmi all

Clean Up Binary

# Remove built binary
rm -f appserver

# Clean Go build cache
go clean -cache

Troubleshooting

Services Won't Start

Issue: Docker containers fail to start

Solutions:

  1. Check if ports are already in use:
lsof -i :4433,4434,4444,4445,8090,8091,4455,4456,5432,6379,5672
  1. Verify .env file exists:
ls -la docker/.env
  1. Check Docker logs:
docker-compose -f docker/docker-compose.yml logs -f
  1. Restart Docker daemon:
sudo systemctl restart docker  # Linux
# Or restart Docker Desktop on macOS/Windows

Database Connection Errors

Issue: AppServer can't connect to PostgreSQL

Solutions:

  1. Verify PostgreSQL is running:
docker-compose -f docker/docker-compose.yml ps postgres
  1. Test connection:
docker exec appserver-postgres psql -U partner -d appserver -c "SELECT 1"
  1. Check credentials in .env:
grep POSTGRES docker/.env
  1. Verify network:
docker network inspect appserver-network

OpenFGA Initialization Fails

Issue: OpenFGA roles not created

Solutions:

  1. Check OpenFGA is running:
curl http://localhost:8090/healthz
  1. Re-run setup script:
./docker/scripts/setup-openfga-roles.sh
  1. Verify store ID:
# List stores
curl http://localhost:8090/stores

Port Conflicts

Issue: Port already in use

Solutions:

  1. Find process using port:
lsof -i :8080
  1. Kill the process:
kill -9 <PID>
  1. Or change port in configuration:
# config.yml
server:
http_port: 8081 # Use different port

Kratos Secrets Error

Issue: "secrets must be exactly 32 characters"

Solution:

Generate proper 32-character secrets:

# Generate and update in docker/.env
openssl rand -base64 32 | head -c 32

Out of Memory

Issue: Services crash with OOM errors

Solutions:

  1. Increase Docker memory limit (Docker Desktop → Settings → Resources)
  2. Reduce cache sizes in config:
cache:
max_cache_size: 52428800 # 50MB instead of 100MB
  1. Reduce database connection pool:
database:
max_open_conns: 10 # Reduce from 25

Migration Errors

Issue: Database migrations fail

Solutions:

  1. Check Docker migration logs:
docker-compose -f docker/docker-compose.yml logs db-migrate
  1. Reset database (⚠️ destroys data):
docker-compose -f docker/docker-compose.yml down -v
./docker/scripts/setup.sh

Production Considerations

Security Checklist

  • Change all default secrets and passwords
  • Use strong, unique encryption keys (32+ characters)
  • Enable SSL/TLS for all services
  • Configure proper CORS policies
  • Enable rate limiting
  • Use secrets management (AWS Secrets Manager, Vault, etc.)
  • Enable PostgreSQL SSL connections
  • Review and restrict Oathkeeper access rules
  • Use environment-specific configurations
  • Disable GraphQL playground in production
  • Disable gRPC reflection in production

Performance Tuning

  • Increase database connection pool for high traffic
  • Enable Redis persistence for cache resilience
  • Configure RabbitMQ queue limits and TTLs
  • Set appropriate cache TTLs based on usage patterns
  • Enable compression for large responses
  • Use CDN for static asset serving

Monitoring

  • Set up Grafana dashboards for key metrics
  • Configure Prometheus alerting rules
  • Monitor database query performance
  • Track event bus queue depths
  • Set up log aggregation with Loki
  • Enable distributed tracing with Tempo

Additional Resources