# Deploy Unleash with the unleash-feature-flags template

Source: https://docs.quake.ai/resources/deployments/deploy-unleash-feature-flags-template
Markdown: https://docs.quake.ai/resources/deployments/deploy-unleash-feature-flags-template.md

---

# Deploy Unleash with the unleash-feature-flags template

Stand up [Unleash](https://www.getunleash.io), an open-source feature-flags and experimentation platform, on a single Quake AI instance using the [validated OpenTofu template](/docs/platform/validation#how-infrastructure-templates-are-checked) `unleash-feature-flags`. You apply the template, log in and change the default admin password, create a project and a feature flag, connect a client SDK to read it, and put a domain in front for production use.

Unleash keeps your team's feature flags on infrastructure you own. You run it yourself; this is a self-hosted tool you operate, not a managed multi-tenant service.

<Figure size="md" caption="What you'll build: an Unleash host on a single instance with a bundled PostgreSQL, reached directly on port 4242 or through an optional Caddy reverse proxy">

```d2
direction: right

user: Team member {shape: person}
sdk: App using the SDK
fip: Floating IP
instance: Ubuntu instance {
  caddy: Caddy\nreverse proxy (optional)
  unleash: Unleash\napp
  db: PostgreSQL
  caddy -> unleash: proxies 443 to 4242
  unleash -> db: flags + projects
}

user -> fip: HTTPS or :4242
fip -> instance.caddy
fip -> instance.unleash
sdk -> fip: reads flag state
```

</Figure>

<PricingCompanion
  components={[
    { kind: "template", slug: "unleash-feature-flags", required: true },
  ]}
/>

## Prerequisites

You need:

- OpenTofu 1.6.0 or later (or Terraform 1.6.0 or later) installed locally.
- Your OpenStack credentials sourced into the shell (`source openrc.sh`). See [the OpenStack CLI guide](/docs/tools/openstack-cli).
- An SSH keypair that already exists in your project. Record its name for the `key_name` variable.
- A copy of the `unleash-feature-flags` template directory from [the template reference page](/resources/iac-templates/unleash-feature-flags).
- Node.js installed locally, to run the client SDK example in this walkthrough.

## Step 1: Apply the template

Copy the template's example variables file and set `key_name`:

```bash
cp terraform.tfvars.example terraform.tfvars
```

```hcl
key_name = "YOUR_KEY_NAME"
```

Initialize, preview, and apply:

```bash
tofu init
tofu plan
tofu apply
```

OpenTofu provisions a private network, a router, a security group, a block volume mounted at `/var/lib/docker`, an instance, and a floating IP. On first boot, cloud-init installs Docker Engine, generates the PostgreSQL password into `/opt/unleash/.env`, and starts both `postgres` and `unleash`: no held-back service waits on manual configuration.

Read the outputs and record `floating_ip` and `app_url`:

```bash
tofu output
```



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. This is a required security step, not an optional one.



## Step 2: Log in and change the admin password

1. Open `app_url` from the previous step (`http://YOUR_FLOATING_IP:4242`). The raw app port is restricted to the private network by default; tunnel over SSH if you have not opened `app_allowed_cidr` to your workstation.
2. Sign in with `admin` / `unleash4all`.
3. Go to **Admin settings** > **My profile** > **Change password** and set a new password.

## Step 3: Create a project and a feature flag

1. Select **New project**, name it (for example `checkout-service`), and create it.
2. Inside the project, select **New feature flag**, name it `new-checkout-flow`, and set the flag type to **Release**.
3. In the `development` environment, add a **Standard** strategy with a 50% gradual rollout, then toggle the environment on.

## Step 4: Connect a client SDK

From the Unleash admin UI, go to **Admin settings** > **API access** and generate a client API token scoped to your project and the `development` environment.

Install the Node.js SDK in a small test project:

```bash
npm install unleash-client
```

Initialize the SDK and check the flag:

```javascript
const { initialize, isEnabled } = require("unleash-client");

const unleash = initialize({
  url: "http://YOUR_FLOATING_IP:4242/api/",
  appName: "checkout-service",
  customHeaders: { Authorization: "YOUR_CLIENT_API_TOKEN" },
});

unleash.on("synchronized", () => {
  console.log("new-checkout-flow enabled:", isEnabled("new-checkout-flow"));
});
```

The SDK polls Unleash on an interval and caches flag state locally, so your application keeps working with the last known state if Unleash is briefly unreachable.

## Step 5: Serve Unleash over HTTPS for production use

Unleash has no auth-callback URL that blocks first boot, so this step is recommended for production use rather than required to get started.

1. Create a DNS **A record** for your domain (for example `flags.example.com`) pointing at `YOUR_FLOATING_IP`. Follow [How to point a domain at a Quake AI resource](/docs/network/how-to/point-domain-to-quake-ai). Wait until it resolves:

```bash
dig +short flags.example.com
```

2. SSH to the instance and create `/opt/unleash/Caddyfile`:

```text
flags.example.com {
  reverse_proxy 127.0.0.1:4242
}
```

3. Add Caddy to `/opt/unleash/docker-compose.yml`:

```yaml
services:
  caddy:
    image: caddy:2
    restart: unless-stopped
    network_mode: host
    volumes:
      - /opt/unleash/Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
volumes:
  caddy_data:
```

For background on certificates, see [How to issue and auto-renew a TLS certificate with Let's Encrypt](/docs/network/how-to/lets-encrypt-certificate).

4. Edit `/opt/unleash/.env` and set the public URL, then restart Unleash:

```text
UNLEASH_URL=https://flags.example.com
```

```bash
cd /opt/unleash
sudo docker compose up -d
```

`UNLEASH_URL` affects links in outgoing emails and integrations; it does not gate login or SDK access, so this step is safe to defer until you are ready to serve the app on a stable domain.

## What you built

- **Applied the `unleash-feature-flags` template** to provision a network, security group, data volume, instance, and floating IP, with PostgreSQL and Unleash both started automatically by cloud-init
- **Changed the default admin password** immediately after first login
- **Created a project and a feature flag** with a gradual rollout strategy
- **Connected the Node.js client SDK** to read the flag with a scoped API token
- **Served Unleash over HTTPS** through an optional Caddy reverse proxy for production use

## Scope of this deployment

This template runs a single-VM Unleash host, not a managed feature-flags cloud. The instance 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 snapshot the volume before you resize or rebuild. For a larger team, move PostgreSQL onto its own instance and size the app host up.

## Next steps

- [Unleash feature-flags template](/resources/iac-templates/unleash-feature-flags): the template reference, parameters, and resource map
- [Self-managed PostgreSQL template](/resources/iac-templates/self-managed-postgres): the database to point at when you outgrow the bundled one
- [Infisical secrets management deployment](/resources/deployments/deploy-infisical-secrets-template): a natural pairing for storing the client API token this walkthrough generated
- [Security hardening checklist](/docs/security/hardening-checklist): tighten SSH access and exposure before you connect production traffic

## Clean up

When you no longer need the deployment, destroy everything the template created:

```bash
tofu destroy
```

Then remove the DNS A record you created in step 5, if you added one. Because Unleash and its database both live on the instance and its attached volume, `tofu destroy` removes them along with the infrastructure.
