Skip to content

Unleash feature flags

Template

Unleash feature flags

This pattern composes Compute, Network, and Block Storage into a self-hosted feature-flags and experimentation platform you run on infrastructure you control.

What this template does#

Provisions a single instance running Unleash, an open-source feature-flags platform (a self-hosted alternative to LaunchDarkly or Flagsmith). Your team rolls out flags, gradual releases, and A/B experiments on infrastructure you own:

  • Compute instance that runs Unleash in Docker alongside a bundled PostgreSQL (4 vCPU and 4 GiB RAM)
  • Private network, subnet, router, port, and security group; a floating IP for public access
  • A block volume mounted at /var/lib/docker, so the feature-flags data lives on a volume you can grow rather than on the boot disk
  • cloud-init installs Docker Engine and starts both containers automatically; no manual configuration step blocks first login

The PostgreSQL password is generated on first boot and written to /opt/unleash/.env; no credential ships with this template.

The simplest ops-tools template in this library#

Unlike Infisical or Plane, Unleash has no encryption key to back up and no auth-callback URL that blocks first boot: UNLEASH_URL only affects links in outgoing emails and integrations. The app is reachable immediately after boot with a default local admin login (admin / unleash4all) that you change on first access.

Parameters#

ParameterDescriptionDefault
key_nameSSH keypair name (must already exist)No default
flavor_nameInstance size (Unleash plus PostgreSQL runs on 4 vCPU / 4 GiB)s1a.medium
image_nameOperating system imageUbuntu-24.04
app_nameDisplay name prefix for resourcesunleash
volume_sizeBlock volume size in GiB, mounted at /var/lib/docker15
external_networkExternal network for floating IP allocationPublicStatic
private_cidrCIDR for the private subnet10.52.0.0/24
app_allowed_cidrCIDR allowed to reach Unleash on port 424210.52.0.0/24

Finish setup after apply#

cloud-init starts PostgreSQL and Unleash together; no held-back service waits on manual configuration:

  1. Open the app at app_url (or tunnel over SSH to port 4242) and log in with the default admin credentials.
  2. Change the admin password immediately.
  3. For production use, point a domain's DNS A record at the floating IP, put a reverse proxy (Caddy or Nginx) in front for HTTPS on 443, and edit /opt/unleash/.env to set UNLEASH_URL to your public HTTPS address.

Access and security#

Unleash listens on port 4242 over plain HTTP. The security group restricts 4242 to app_allowed_cidr, which defaults to the private network only. Ports 80 and 443 stay open for a reverse proxy you add for production use; they carry no traffic until you add one.

When to use this pattern#

Roll out feature flags, gradual releases, and experiments for a team on a host you operate. The bundled PostgreSQL suits a single-team deployment; to run it separately, point DATABASE_HOST and the related DATABASE_* variables at a self-managed PostgreSQL instance.

Estimated cost#

Monthly cost estimate

Pricing calculator ↗

Sized as a custom package on shared vCPU.

Starting template$31.60/mo

Monthly total for the required template above. Use the configurator below to add optional pieces and see the total update.

What each resource is for

Unleash feature-flags host

s1a.medium · 4 shared vCPU, 4 GiB RAM, 0.5 Gbps

Runs Unleash's app container alongside a bundled PostgreSQL, with the database data on an attached volume.

Unleash plus its bundled PostgreSQL runs on 4 vCPU and 4 GiB RAM. Size up for many concurrent SDK connections or a large flag inventory.

$33.00/mo

Compute shown per role at custom-package rates ($29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM). The headline above is the billed total: the cheaper of a named plan and the custom package, plus add-ons.

Included in baseline

s1a.medium

4 shared vCPU, 4 GiB RAM, 0.5 Gbps

$33.00

Compute + RAM rate basis

4 vCPU + 4 GiB RAM at $29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM (regular). Totals apply the flat −$5/mo package promotion.

—

Block storage (45 GiB)

45 GiB at $0.08/GiB/mo

$3.60

Public IP (included)

1 included with the custom package

$0.00

Package promotional discount

Flat −$5.00/mo on the custom package (same promotion as named plans).

$-5.00

Included at no charge

These line items are zero on Quake AI. Many other providers meter them separately.

Data transfer (inbound and outbound)

Unlimited data transfer on every plan; Quake AI does not meter per-GB egress.

AWS, GCP, and Azure meter outbound transfer per GB. DigitalOcean and Hetzner include an allowance on compute plans, then charge overage.

Learn more
$0.00

Private networking

Private networks, subnets, Neutron routers, and security groups are included with the plan.

VPC objects are usually free to create elsewhere, but NAT gateways bill hourly plus per-GB processed. Quake AI uses router SNAT with no separate NAT line item.

$0.00

Control-plane API requests

OpenStack API calls for provisioning and management are included.

Some managed services on other clouds meter API calls or charge for premium control-plane features.

$0.00

Pricing data last validated: . For current rates, check quake.ai/pricing.

Template source#

7 files. Download the zip or expand to copy any file.Download unleash-feature-flags.zip
Show source (7 files)
main.tfHCL
data "openstack_images_image_v2" "os" {
  name        = var.image_name
  most_recent = true
}

data "openstack_networking_network_v2" "external" {
  name = var.external_network
}

resource "openstack_networking_network_v2" "private" {
  name           = "${var.app_name}-net"
  admin_state_up = true
}

resource "openstack_networking_subnet_v2" "private" {
  name            = "${var.app_name}-subnet"
  network_id      = openstack_networking_network_v2.private.id
  cidr            = var.private_cidr
  ip_version      = 4
  dns_nameservers = ["1.1.1.1", "8.8.8.8"]
}

resource "openstack_networking_router_v2" "main" {
  name                = "${var.app_name}-router"
  external_network_id = data.openstack_networking_network_v2.external.id
}

resource "openstack_networking_router_interface_v2" "private" {
  router_id = openstack_networking_router_v2.main.id
  subnet_id = openstack_networking_subnet_v2.private.id
}

resource "openstack_networking_secgroup_v2" "unleash" {
  name        = "${var.app_name}-sg"
  description = "SSH and HTTP/HTTPS for a reverse proxy; app port 4242 restricted"
}

resource "openstack_networking_secgroup_rule_v2" "ssh" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 22
  port_range_max    = 22
  remote_ip_prefix  = "0.0.0.0/0"
  security_group_id = openstack_networking_secgroup_v2.unleash.id
}

# 80 and 443 carry Unleash when it is served over a domain with automatic TLS
# through a reverse proxy (Caddy or Nginx). Recommended for production use;
# nothing blocks first boot or first login without a domain.
resource "openstack_networking_secgroup_rule_v2" "http" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 80
  port_range_max    = 80
  remote_ip_prefix  = "0.0.0.0/0"
  security_group_id = openstack_networking_secgroup_v2.unleash.id
}

resource "openstack_networking_secgroup_rule_v2" "https" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 443
  port_range_max    = 443
  remote_ip_prefix  = "0.0.0.0/0"
  security_group_id = openstack_networking_secgroup_v2.unleash.id
}

# Raw app HTTP on 4242 is restricted to app_allowed_cidr (the private network
# by default). Use it for setup over an SSH tunnel or a scoped workstation IP;
# put a reverse proxy on 443 in front for routine access.
resource "openstack_networking_secgroup_rule_v2" "app" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 4242
  port_range_max    = 4242
  remote_ip_prefix  = var.app_allowed_cidr
  security_group_id = openstack_networking_secgroup_v2.unleash.id
}

resource "openstack_networking_port_v2" "unleash" {
  name               = "${var.app_name}-port"
  network_id         = openstack_networking_network_v2.private.id
  security_group_ids = [openstack_networking_secgroup_v2.unleash.id]

  fixed_ip {
    subnet_id = openstack_networking_subnet_v2.private.id
  }

  depends_on = [openstack_networking_router_interface_v2.private]
}

resource "openstack_blockstorage_volume_v3" "data" {
  name = "${var.app_name}-data"
  size = var.volume_size
}

resource "openstack_compute_instance_v2" "unleash" {
  name        = var.app_name
  flavor_name = var.flavor_name
  key_pair    = var.key_name

  user_data = templatefile("${path.module}/cloud-init/unleash.yaml.tftpl", {
    app_name = var.app_name
  })

  block_device {
    uuid                  = data.openstack_images_image_v2.os.id
    source_type           = "image"
    destination_type      = "volume"
    volume_size           = 30
    boot_index            = 0
    delete_on_termination = true
  }

  network {
    port = openstack_networking_port_v2.unleash.id
  }
}

resource "openstack_compute_volume_attach_v2" "data" {
  instance_id = openstack_compute_instance_v2.unleash.id
  volume_id   = openstack_blockstorage_volume_v3.data.id
}

resource "openstack_networking_floatingip_v2" "unleash" {
  pool = var.external_network
}

resource "openstack_networking_floatingip_associate_v2" "unleash" {
  floating_ip = openstack_networking_floatingip_v2.unleash.address
  port_id     = openstack_networking_port_v2.unleash.id
}
variables.tfHCL
variable "key_name" {
  description = "SSH keypair name (must already exist in your project)"
  type        = string
}

variable "flavor_name" {
  description = "Instance size. Unleash plus its bundled PostgreSQL runs comfortably on 4 vCPU and 4 GiB RAM (s1a.medium). Size up for many concurrent SDK connections or a large flag inventory."
  type        = string
  default     = "s1a.medium"
}

variable "image_name" {
  description = "Operating system image. Ubuntu 24.04 is the recommended base."
  type        = string
  default     = "Ubuntu-24.04"
}

variable "app_name" {
  description = "Display name prefix for compute and network resources"
  type        = string
  default     = "unleash"
}

variable "volume_size" {
  description = "Block volume size in GiB, mounted at /var/lib/docker so the feature-flags data (the PostgreSQL database) lives on a volume you can grow rather than on the boot disk."
  type        = number
  default     = 15
}

variable "external_network" {
  description = "Shared external network for router gateway and floating IPs; defaults to PublicStatic (persisted FIP / production pattern). Override with PublicEphemeral for ephemeral demos."
  type        = string
  default     = "PublicStatic"
}

variable "private_cidr" {
  description = "CIDR for the private tenant network the instance lives in"
  type        = string
  default     = "10.52.0.0/24"
}

variable "app_allowed_cidr" {
  description = "CIDR allowed to reach Unleash on port 4242. Defaults to the private network only, so the app is not exposed to the public internet on its raw port. Put a reverse proxy on 443 in front for HTTPS once you point a domain at the instance. To reach port 4242 directly from your workstation during setup, set this to YOUR_IP/32."
  type        = string
  default     = "10.52.0.0/24"
}
outputs.tfHCL
output "instance_id" {
  description = "ID of the compute instance running Unleash"
  value       = openstack_compute_instance_v2.unleash.id
}

output "floating_ip" {
  description = "Public floating IP address of the Unleash host"
  value       = openstack_networking_floatingip_v2.unleash.address
}

output "private_ip" {
  description = "Private IP address of the instance"
  value       = openstack_compute_instance_v2.unleash.access_ip_v4
}

output "app_url" {
  description = "Unleash app URL on port 4242. Reachable from app_allowed_cidr (the private network by default). Both Unleash and its bundled PostgreSQL start automatically on first boot; log in with the default admin credentials and change the password immediately. Put a reverse proxy in front and use HTTPS on 443 for production use, then set UNLEASH_URL in /opt/unleash/.env."
  value       = "http://${openstack_networking_floatingip_v2.unleash.address}:4242"
}
versions.tfHCL
terraform {
  required_version = ">= 1.6.0"

  required_providers {
    openstack = {
      source  = "terraform-provider-openstack/openstack"
      version = "~> 2.0"
    }
  }
}

provider "openstack" {}
terraform.tfvars.exampleHCL
# Required: SSH keypair must already exist in your project
key_name = "YOUR_KEY_NAME"

# Recommended: restrict the app port (4242) to your workstation IP for setup.
# Leave unset to keep 4242 reachable only from the private network and tunnel
# over SSH. For production use, put a reverse proxy in front on 443.
# app_allowed_cidr = "203.0.113.10/32"

# flavor_name = "s1a.medium"
# image_name = "Ubuntu-24.04"
# app_name = "unleash"
# volume_size = 15
# external_network = "PublicStatic"
# private_cidr = "10.52.0.0/24"
cloud-init/unleash.yaml.tftpl
#cloud-config
package_update: true
packages:
  - ca-certificates
  - curl
write_files:
  - path: /opt/unleash/docker-compose.yml
    permissions: "0644"
    content: |
      # Unleash feature-flags platform for ${app_name}. The app listens on
      # port 4242. Unlike some of the other self-hosted ops tools in this
      # library, Unleash has no auth-callback URL that blocks first boot and
      # no encryption key to back up: both postgres and unleash start
      # automatically on first boot. No credential ships with this template:
      # the PostgreSQL password is generated on first boot. Log in with the
      # default admin credentials (admin / unleash4all) and change the
      # password immediately.
      services:
        unleash:
          image: unleashorg/unleash-server:latest
          restart: unless-stopped
          ports:
            - "4242:4242"
          env_file:
            - /opt/unleash/.env
          depends_on:
            - postgres
        postgres:
          image: postgres:16-alpine
          restart: unless-stopped
          env_file:
            - /opt/unleash/.env
          volumes:
            - unleash_pg:/var/lib/postgresql/data
      volumes:
        unleash_pg:
runcmd:
  - |
    set -e
    # The data volume attaches as /dev/sdb on this platform (not /dev/vdb).
    # Mount it at /var/lib/docker before Docker is installed so the
    # PostgreSQL data lives on the resizable volume rather than the boot disk.
    DEV=/dev/sdb
    for i in $(seq 1 30); do [ -b "$DEV" ] && break; sleep 5; done
    if ! blkid "$DEV" >/dev/null 2>&1; then mkfs.ext4 -F -L unleashdata "$DEV"; fi
    mkdir -p /var/lib/docker
    mount "$DEV" /var/lib/docker
    grep -q "$DEV" /etc/fstab || echo "$DEV /var/lib/docker ext4 defaults,nofail 0 2" >> /etc/fstab
    # Install Docker Engine plus the compose plugin from Docker's convenience
    # script.
    curl -fsSL https://get.docker.com | sh
    # Generate the bundled database password on first boot. It never leaves
    # this instance.
    PGPASS=$(openssl rand -hex 24)
    umask 077
    {
      echo "DATABASE_HOST=postgres"
      echo "DATABASE_PORT=5432"
      echo "DATABASE_NAME=unleash"
      echo "DATABASE_USERNAME=unleash"
      echo "DATABASE_PASSWORD=$PGPASS"
      echo "DATABASE_SSL=false"
      echo "POSTGRES_USER=unleash"
      echo "POSTGRES_PASSWORD=$PGPASS"
      echo "POSTGRES_DB=unleash"
      echo "PORT=4242"
      # UNLEASH_URL only affects links in outgoing emails and integrations;
      # it does not block first boot or first login. Update it to your public
      # HTTPS address once you point a domain at this instance.
      echo "UNLEASH_URL=http://localhost:4242"
    } > /opt/unleash/.env
    chmod 600 /opt/unleash/.env
    # Bring up both services. Unlike the Infisical/Plane/Appsmith pattern,
    # nothing here waits on manual configuration: Unleash is reachable right
    # after boot on port 4242.
    cd /opt/unleash
    docker compose up -d
README.mdMarkdown
# Unleash feature flags

Single compute instance running [Unleash](https://www.getunleash.io), a self-hosted feature-flags and experimentation platform (a self-hosted alternative to LaunchDarkly or Flagsmith) on infrastructure you control. After apply, both Unleash and its bundled PostgreSQL start automatically: log in with the default admin credentials, change the password, and create your first flag.


**Network class:** production — `external_network` defaults to `PublicStatic` for persisted floating IPs and multi-tier stacks; override with `PublicEphemeral` for ephemeral demos.

The instance provisions a private network, a floating IP, and a block volume mounted at `/var/lib/docker` so the feature-flags data lives on a resizable volume. cloud-init installs Docker Engine and brings up both containers with no manual steps required before first login.

## Where this fits

Unleash centralizes feature flags, gradual rollouts, and A/B experiment toggles for a team, with projects, environments, and strategy-based targeting, on infrastructure you own rather than on a third-party SaaS.

## The simplest ops-tools template in this library

Unlike [Infisical](/resources/iac-templates/infisical-secrets) or [Plane](/resources/iac-templates/plane-project-management), Unleash has no encryption key that must be backed up and no auth-callback URL that blocks first boot: `UNLEASH_URL` only affects links in outgoing emails and integrations. cloud-init brings up the full stack automatically, and the app ships with a default local admin login you change after first login.

## Prerequisites

- OpenTofu >= 1.6.0 or Terraform >= 1.6.0
- Quake AI account with OpenStack credentials
- An existing SSH keypair in your project (the value of `key_name` must match that keypair)

## Resource baseline

Unleash plus its bundled PostgreSQL runs on 4 vCPU and 4 GiB RAM. The default `s1a.medium` flavor leaves headroom for both containers. Size up for many concurrent SDK connections or a large flag inventory.

## Usage

1. Clone or copy this template directory
2. Copy `terraform.tfvars.example` to `terraform.tfvars` and fill in your values
3. Source your OpenStack credentials: `source openrc.sh`
4. Initialize: `tofu init`
5. Preview: `tofu plan`
6. Apply: `tofu apply`

After apply, cloud-init installs Docker, generates the PostgreSQL password into `/opt/unleash/.env`, and starts both `postgres` and `unleash`. No credential ships with this template: the database password is generated on first boot.

## Change the default admin password

Unleash ships with a default local admin login (`admin` / `unleash4all`). Log in immediately after first boot and change the password before you invite anyone else or connect a production SDK client.

## Access and security

Unleash listens on port 4242 over plain HTTP. The security group restricts 4242 to `app_allowed_cidr`, which defaults to the private network only. For production use, point a domain's DNS A record at `floating_ip`, add a reverse proxy (Caddy or Nginx) in front for HTTPS on 443, and update `UNLEASH_URL` in `/opt/unleash/.env` to the public address. Ports 80 and 443 stay open for that reverse proxy; they carry no traffic until you add one.

## Datastores

This template bundles PostgreSQL as a container on the same instance, which suits a single-team feature-flags deployment. To run it as a separate service, point `DATABASE_HOST` and the related `DATABASE_*` variables in `/opt/unleash/.env` at a [self-managed PostgreSQL](/resources/iac-templates/self-managed-postgres) instance and remove the bundled service from the compose file.

## Variables

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `key_name` | string | yes | n/a | SSH keypair name (must already exist in your project) |
| `flavor_name` | string | no | `s1a.medium` | Instance size (Unleash plus PostgreSQL runs on 4 vCPU / 4 GiB) |
| `image_name` | string | no | `Ubuntu-24.04` | Operating system image |
| `app_name` | string | no | `unleash` | Display name prefix for resources |
| `volume_size` | number | no | `15` | Block volume size in GiB, mounted at `/var/lib/docker` |
| `external_network` | string | no | `PublicStatic` | Persisted FIP / production default; override with `PublicEphemeral` for demos |
| `private_cidr` | string | no | `10.52.0.0/24` | CIDR for the private subnet |
| `app_allowed_cidr` | string | no | `10.52.0.0/24` | CIDR allowed to reach Unleash on port 4242 |

## Outputs

| Name | Description |
| --- | --- |
| `floating_ip` | Public floating IP assigned to the instance |
| `private_ip` | Private IP address of the instance |
| `app_url` | Unleash app URL on port 4242 |
| `instance_id` | Compute instance ID |

## Scope

This is a single-VM Unleash host that you operate, not a managed feature-flags cloud. It is CPU-only and runs in one region, and it bundles PostgreSQL as a container on the same host. You operate the instance, Docker, Unleash, the database, and the data volume yourself: back them up, patch them, and watch resource use as SDK connections grow. For a larger team, move PostgreSQL onto its own instance and size the app host up.

## Documentation

See also: [self-managed PostgreSQL](/resources/iac-templates/self-managed-postgres), [Infisical secrets management](/resources/iac-templates/infisical-secrets)
Resources, parameters, and variables
Provisions
Parameterized by
Variables
  • key_namerequired
  • flavor_name="s1a.medium"
  • image_name="Ubuntu-24.04"
  • app_name="unleash"
  • volume_size=15
  • external_network="PublicStatic"
  • private_cidr="10.52.0.0/24"
  • app_allowed_cidr="10.52.0.0/24"

Customize this pattern#

See also#

Usage Guidelines

The sample code, software libraries, command line tools, proofs of concept, templates, and other related technology on this page (including any of the foregoing that is provided by Quake AI personnel) is provided to you as Quake AI Content under the Quake AI Customer Agreement, or the relevant written agreement between you and Quake AI (whichever applies). Do not use this Quake AI Content in your production accounts, or on production or other critical data. You are responsible for testing, securing, and optimizing the Quake AI Content (such as sample code) as appropriate for production grade use based on your specific quality control practices and standards. Deploying Quake AI Content may incur Quake AI charges for creating or using Quake AI chargeable resources, such as running Compute instances or storing data in Object Storage. Your use is also subject to the Acceptable Use Policy.

For the full policy, see Usage Guidelines.

Was this page helpful?