Docker Deployment
Deploy Licenz on your own infrastructure using Docker Compose for a production-ready setup.
Prerequisites
Before deploying Licenz, ensure you have the following installed:
| Requirement | Minimum Version | Notes |
|---|---|---|
| Docker | 20.10+ | Docker Engine or Docker Desktop |
| Docker Compose | 2.0+ | V2 syntax required |
| Memory | 2 GB | 4 GB recommended for production |
| Disk Space | 10 GB | SSD recommended for database |
| CPU | 2 cores | 4 cores recommended |
Quick Start
Get Licenz running in minutes with these steps:
1. Clone the Repository
# Clone the Licenz self-hosted repository
git clone https://github.com/licenz/licenz-self-hosted.git
cd licenz-self-hosted 2. Configure Environment
# Copy the example environment file
cp .env.example .env
# Generate a secure JWT secret
JWT_SECRET=$(openssl rand -base64 64 | tr -d '\n')
echo "JWT_SECRET=$JWT_SECRET" >> .env
# Edit .env with your configuration
nano .env 3. Start Services
# Start all services
docker compose -f docker-compose.prod.yml up -d
# Check service status
docker compose ps
# View logs
docker compose logs -f api 4. Verify Installation
# Check API health
curl http://localhost:8080/health
# Expected response:
# {\"status\":\"healthy\",\"version\":\"1.0.0\"} Docker Compose Configuration
The production Docker Compose file includes all required services:
version: "3.9"
services:
api:
image: licenz-saas-api:${VERSION:-latest}
container_name: licenz-api
restart: unless-stopped
ports:
- "${API_PORT:-8080}:8080"
environment:
- DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
- JWT_SECRET=${JWT_SECRET}
- REDIS_URL=redis://redis:6379
- RUST_LOG=licenz_saas_api=info,tower_http=info
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
web:
image: licenz-saas-web:${VERSION:-latest}
container_name: licenz-web
restart: unless-stopped
ports:
- "${WEB_PORT:-3000}:80"
depends_on:
- api
postgres:
image: postgres:16-alpine
container_name: licenz-postgres
restart: unless-stopped
environment:
- POSTGRES_USER=${POSTGRES_SUPERUSER:-postgres}
- POSTGRES_PASSWORD=${POSTGRES_SUPERUSER_PASSWORD}
- POSTGRES_DB=postgres
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: licenz-redis
restart: unless-stopped
command: redis-server --appendonly yes --maxmemory 128mb
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
redis_data: Environment Variables
Create a .env file with the following configuration:
# Required - Generate with: openssl rand -base64 64
JWT_SECRET=your-secure-jwt-secret-here
# PostgreSQL
POSTGRES_SUPERUSER=postgres
POSTGRES_SUPERUSER_PASSWORD=secure-password-here
POSTGRES_USER=licenz
POSTGRES_PASSWORD=licenz-password-here
POSTGRES_DB=licenz
# Ports
API_PORT=8080
WEB_PORT=3000
# Logging
RUST_LOG=licenz_saas_api=info,tower_http=info
# Version
VERSION=latest Security Warning
Never use default passwords in production. Always generate strong, unique passwords for JWT_SECRET and database credentials.
Service Architecture
The Licenz stack consists of the following services:
| Service | Port | Description |
|---|---|---|
| api | 8080 | Rust backend API server |
| web | 3000 | React frontend dashboard |
| graxon | 9000 (internal) | Rules engine for license policies |
| postgres | 5432 (internal) | PostgreSQL 16 database |
| redis | 6379 (internal) | Caching and rate limiting |
Reverse Proxy Setup
For production, use a reverse proxy like Nginx with SSL termination:
server {
listen 80;
server_name licenz.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name licenz.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/licenz.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/licenz.yourdomain.com/privkey.pem;
# API routes
location /api/ {
proxy_pass http://localhost:8080/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Web frontend
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
} SSL with Let's Encrypt
# Install Certbot
sudo apt install certbot python3-certbot-nginx
# Obtain certificate
sudo certbot --nginx -d licenz.yourdomain.com
# Auto-renewal is configured automatically Resource Limits
The default resource limits are configured for moderate workloads:
| Service | Memory Limit | Memory Reserved |
|---|---|---|
| api | 512 MB | 128 MB |
| web | 128 MB | 32 MB |
| graxon | 256 MB | 64 MB |
| postgres | 512 MB | 128 MB |
| redis | 256 MB | 64 MB |
Health Checks
All services include health checks for automated monitoring:
# Check all service health
docker compose ps
# API health endpoint
curl http://localhost:8080/health
# Redis health
docker exec licenz-redis redis-cli ping
# PostgreSQL health
docker exec licenz-postgres pg_isready -U postgres Updating Licenz
To update to a new version:
# Pull latest images
docker compose -f docker-compose.prod.yml pull
# Restart with new images
docker compose -f docker-compose.prod.yml up -d
# Verify update
docker compose ps
curl http://localhost:8080/health Backup Before Updating
Always create a database backup before updating. See the Backup and Restore guide.
Troubleshooting
Services Not Starting
# Check logs for errors
docker compose logs api
docker compose logs postgres
# Verify environment variables
docker compose config
# Restart all services
docker compose down && docker compose up -d Database Connection Issues
# Check PostgreSQL is running
docker exec licenz-postgres pg_isready
# Verify database exists
docker exec licenz-postgres psql -U postgres -c "\l"
# Check connection from API container
docker exec licenz-api curl postgres:5432