New: Offline-first licensing with cryptographic validation. Learn more

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

Next Steps