Feature Flags
    Open Source

    Deploy Unleash Feature Flag Server

    Self-hosted LaunchDarkly alternative with first-party SDKs for Node, Python, Go, Ruby, Java, .NET, PHP, Rust, and browser environments.

    At a Glance

    ProjectUnleash 6.x
    LicenseApache 2.0
    Recommended PlanRamNode Cloud VPS 2 vCPU / 4 GB
    OSUbuntu 24.04 LTS
    StackNode 20 + PostgreSQL 16
    1

    System Prep

    Base packages
    sudo apt update && sudo apt upgrade -y
    sudo apt install -y curl wget gnupg ca-certificates ufw nginx certbot \
      python3-certbot-nginx postgresql postgresql-contrib build-essential
    2

    PostgreSQL Database

    Create role + DB
    sudo -u postgres psql <<EOF
    CREATE USER unleash WITH ENCRYPTED PASSWORD '<strong-database-password>';
    CREATE DATABASE unleash OWNER unleash;
    GRANT ALL PRIVILEGES ON DATABASE unleash TO unleash;
    ALTER DATABASE unleash SET timezone TO 'UTC';
    EOF
    
    PGPASSWORD='<strong-database-password>' psql -h 127.0.0.1 -U unleash -d unleash -c "SELECT version();"
    3

    Install Node.js 20 LTS

    From NodeSource
    curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
    sudo apt install -y nodejs
    node --version && npm --version
    4

    Install Unleash

    Service user + install
    sudo useradd --system --shell /bin/bash --home-dir /opt/unleash --create-home unleash
    sudo mkdir -p /opt/unleash /var/log/unleash
    sudo chown -R unleash:unleash /opt/unleash /var/log/unleash
    
    sudo -u unleash bash <<'EOF'
    cd /opt/unleash
    npm init -y
    npm install unleash-server@latest
    EOF
    /opt/unleash/server.js
    const unleash = require('unleash-server');
    
    unleash.start({
      db: {
        host: process.env.DATABASE_HOST,
        port: process.env.DATABASE_PORT,
        database: process.env.DATABASE_NAME,
        user: process.env.DATABASE_USERNAME,
        password: process.env.DATABASE_PASSWORD,
        ssl: false,
      },
      server: {
        port: process.env.HTTP_PORT || 4242,
        host: process.env.HTTP_HOST || '127.0.0.1',
      },
      authentication: { type: process.env.AUTH_TYPE || 'open-source', createAdminUser: true },
      secureHeaders: true,
      enableOAS: true,
    }).then(i => console.log('Unleash listening on', i.app.get('host'), i.app.get('port')))
      .catch(err => { console.error(err); process.exit(1); });
    5

    Environment + systemd

    /etc/unleash/unleash.env
    DATABASE_HOST=127.0.0.1
    DATABASE_PORT=5432
    DATABASE_NAME=unleash
    DATABASE_USERNAME=unleash
    DATABASE_PASSWORD=<strong-database-password>
    HTTP_HOST=127.0.0.1
    HTTP_PORT=4242
    UNLEASH_URL=https://unleash.example.com
    AUTH_TYPE=open-source
    LOG_LEVEL=info
    NODE_ENV=production
    Lock the env file
    sudo mkdir -p /etc/unleash
    sudo chmod 0640 /etc/unleash/unleash.env
    sudo chown root:unleash /etc/unleash/unleash.env
    /etc/systemd/system/unleash.service
    [Unit]
    Description=Unleash Feature Flag Server
    After=network-online.target postgresql.service
    Wants=network-online.target
    Requires=postgresql.service
    
    [Service]
    Type=simple
    User=unleash
    Group=unleash
    WorkingDirectory=/opt/unleash
    EnvironmentFile=/etc/unleash/unleash.env
    ExecStart=/usr/bin/node /opt/unleash/server.js
    Restart=on-failure
    RestartSec=10
    StandardOutput=append:/var/log/unleash/unleash.log
    StandardError=append:/var/log/unleash/unleash-error.log
    
    NoNewPrivileges=true
    PrivateTmp=true
    ProtectSystem=strict
    ProtectHome=true
    ReadWritePaths=/opt/unleash /var/log/unleash
    
    [Install]
    WantedBy=multi-user.target
    Enable
    sudo systemctl daemon-reload
    sudo systemctl enable --now unleash
    sudo tail -f /var/log/unleash/unleash.log
    # Capture the auto-generated admin password from the first-start log
    6

    Nginx + TLS + Login Rate Limiting

    UFW
    sudo ufw default deny incoming && sudo ufw default allow outgoing
    sudo ufw allow OpenSSH
    sudo ufw allow 80/tcp && sudo ufw allow 443/tcp
    sudo ufw enable
    In /etc/nginx/nginx.conf http {}
    limit_req_zone $binary_remote_addr zone=login_limit:10m rate=10r/m;
    /etc/nginx/sites-available/unleash
    upstream unleash_backend { server 127.0.0.1:4242; keepalive 32; }
    
    server {
      listen 80;
      server_name unleash.example.com;
      return 301 https://$host$request_uri;
    }
    server {
      listen 443 ssl http2;
      server_name unleash.example.com;
      add_header X-Frame-Options "SAMEORIGIN" always;
      add_header X-Content-Type-Options "nosniff" always;
      proxy_read_timeout 90s;
      client_max_body_size 50m;
    
      location / {
        proxy_pass http://unleash_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      }
      location = /auth/simple/login {
        limit_req zone=login_limit burst=5 nodelay;
        proxy_pass http://unleash_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      }
    }
    Enable + cert
    sudo ln -s /etc/nginx/sites-available/unleash /etc/nginx/sites-enabled/
    sudo nginx -t && sudo systemctl reload nginx
    sudo certbot --nginx -d unleash.example.com --redirect --agree-tos -m admin@example.com
    7

    Backups

    /usr/local/bin/backup-unleash.sh
    #!/bin/bash
    set -euo pipefail
    TS=$(date +%Y%m%d-%H%M%S)
    DEST="/var/backups/unleash"
    RETENTION_DAYS=14
    mkdir -p "${DEST}"
    
    PGPASSWORD='<strong-database-password>' pg_dump -h 127.0.0.1 -U unleash \
      -F custom -f "${DEST}/unleash-${TS}.dump" unleash
    
    tar -czf "${DEST}/unleash-config-${TS}.tar.gz" /etc/unleash /etc/nginx/sites-available/unleash
    
    find "${DEST}" -name 'unleash-*.dump' -mtime +${RETENTION_DAYS} -delete
    find "${DEST}" -name 'unleash-config-*.tar.gz' -mtime +${RETENTION_DAYS} -delete
    Schedule
    sudo chmod 0750 /usr/local/bin/backup-unleash.sh
    echo '0 2 * * * root /usr/local/bin/backup-unleash.sh' | sudo tee /etc/cron.d/unleash-backup
    8

    Monitoring (Prometheus)

    Add to env file
    echo "PROMETHEUS_API=true" | sudo tee -a /etc/unleash/unleash.env
    sudo systemctl restart unleash
    Scrape
    scrape_configs:
      - job_name: unleash
        metrics_path: /internal-backstage/prometheus
        static_configs:
          - targets: ['127.0.0.1:4242']