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:
| Service | Ports | Purpose |
|---|---|---|
| AppServer | 8080, 9090 | HTTP/GraphQL and gRPC |
| PostgreSQL | 5432 | Database |
| Redis | 6379 | Cache |
| RabbitMQ | 5672, 15672 | Message broker and management UI |
| Kratos | 4433, 4434 | Identity (public and admin) |
| Hydra | 4444, 4445 | OAuth2 (public and admin) |
| OpenFGA | 8090, 8091 | Authorization (HTTP and gRPC) |
| Oathkeeper | 4455, 4456 | Access proxy |
| Grafana | 3000 | Observability dashboard |
| Prometheus | 9090 | Metrics (conflicts with appserver gRPC if both on host) |
| Loki | 3100 | Logs |
| Tempo | 3200 | Traces |
| OTel Collector | 4317, 4318 | Telemetry (gRPC and HTTP) |
Installation Methods
Method 1: Docker Compose (Recommended)
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:
- Creates
docker/.envfromdocker/.env.example - Starts PostgreSQL container
- Runs database migrations for all 6 schemas
- Starts all infrastructure services
- 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
| Variable | Default | Description |
|---|---|---|
APPSERVER_DB_HOST | localhost | PostgreSQL host |
APPSERVER_DB_PORT | 5432 | PostgreSQL port |
APPSERVER_DB_USER | appserver | Database username |
APPSERVER_DB_PASSWORD | - | Database password (required) |
APPSERVER_DB_NAME | appserver | Database name |
APPSERVER_DB_SSLMODE | disable | SSL mode (disable, require, verify-ca, verify-full) |
Server Configuration
| Variable | Default | Description |
|---|---|---|
APPSERVER_HTTP_PORT | 8080 | HTTP/GraphQL server port |
APPSERVER_GRPC_PORT | 9090 | gRPC server port |
APPSERVER_GRAPHQL_PLAYGROUND_ENABLED | false | Enable GraphQL playground (dev only) |
APPSERVER_GRPC_REFLECTION_ENABLED | false | Enable gRPC reflection (dev only) |
APPSERVER_LOG_LEVEL | info | Log level (debug, info, warn, error) |
Cache Configuration
| Variable | Default | Description |
|---|---|---|
APPSERVER_REDIS_URL | redis://localhost:6379 | Redis connection URL |
APPSERVER_CACHE_TTL | 300 | Local cache TTL in seconds |
Event Bus Configuration
| Variable | Default | Description |
|---|---|---|
APPSERVER_RABBITMQ_ENABLED | false | Enable RabbitMQ event bus |
APPSERVER_RABBITMQ_URL | amqp://guest:guest@localhost:5672/ | RabbitMQ connection URL |
APPSERVER_RABBITMQ_MAX_RETRIES | 5 | Max retry attempts for failed events |
APPSERVER_RABBITMQ_PREFETCH_COUNT | 10 | Consumer prefetch count |
Auth Services Configuration
| Variable | Default | Description |
|---|---|---|
APPSERVER_KRATOS_PUBLIC_URL | http://localhost:4433 | Kratos public API URL |
APPSERVER_KRATOS_ADMIN_URL | http://localhost:4434 | Kratos admin API URL |
APPSERVER_OPENFGA_API_URL | http://localhost:8090 | OpenFGA API URL |
APPSERVER_OPENFGA_STORE_ID | - | OpenFGA store ID (auto-detected if not set) |
APPSERVER_SESSION_COOKIE_NAME | ory_kratos_session | Session cookie name |
Security Configuration
| Variable | Default | Description |
|---|---|---|
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
- Stop the AppServer (keep infrastructure running):
# Stop appserver process (Ctrl+C if running in terminal)
# Or if running as service:
pkill appserver
- Pull Latest Code:
git pull origin master
- Run Migrations:
# Migrations run automatically on appserver startup
# No manual migration commands needed for v2
- 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:
- Stop the AppServer
- Checkout previous version:
git checkout <previous-version-tag>
- 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:
- Check if ports are already in use:
lsof -i :4433,4434,4444,4445,8090,8091,4455,4456,5432,6379,5672
- Verify
.envfile exists:
ls -la docker/.env
- Check Docker logs:
docker-compose -f docker/docker-compose.yml logs -f
- 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:
- Verify PostgreSQL is running:
docker-compose -f docker/docker-compose.yml ps postgres
- Test connection:
docker exec appserver-postgres psql -U partner -d appserver -c "SELECT 1"
- Check credentials in
.env:
grep POSTGRES docker/.env
- Verify network:
docker network inspect appserver-network
OpenFGA Initialization Fails
Issue: OpenFGA roles not created
Solutions:
- Check OpenFGA is running:
curl http://localhost:8090/healthz
- Re-run setup script:
./docker/scripts/setup-openfga-roles.sh
- Verify store ID:
# List stores
curl http://localhost:8090/stores
Port Conflicts
Issue: Port already in use
Solutions:
- Find process using port:
lsof -i :8080
- Kill the process:
kill -9 <PID>
- 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:
- Increase Docker memory limit (Docker Desktop → Settings → Resources)
- Reduce cache sizes in config:
cache:
max_cache_size: 52428800 # 50MB instead of 100MB
- Reduce database connection pool:
database:
max_open_conns: 10 # Reduce from 25
Migration Errors
Issue: Database migrations fail
Solutions:
- Check Docker migration logs:
docker-compose -f docker/docker-compose.yml logs db-migrate
- 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
- Quick Start Guide - Get running in 15 minutes
- Platform Architecture - Understand the system design
- Development Environment - Local development setup