Skip to content

Developer guide

Developer guide

You can go from an empty folder to a first flag evaluation by copying commands from one page.

This page is a runbook. Run the sections in order. Each section ends with a check that you can run, and a link to the chapter page that explains the topic in depth. The page uses the same two files as the video series, so each chapter picks up where this page ends.

Prerequisites

  • Docker with Compose v2 (docker compose version works).
  • openssl, to generate a secret.
  • curl and jq, for the checks.
  • Node 20 or newer, only for the OpenFeature example in section 7.
  • Free ports 3000 (UI), 8080 (backend), 8081 (edge server) and 5433 (PostgreSQL).

The images come from Docker Hub: forgeopslabs/flux-gate-backend, forgeopslabs/flux-gate-ui and forgeopslabs/flux-gate-edge, tag v2.0.1. You do not need a source checkout.

1. Get the files

Create an empty folder and download the two demo files into it:

bash
mkdir fluxgate && cd fluxgate
curl -fsSLO https://flux.forgeopslabs.com/downloads/docker-compose.demo.yml
curl -fsSLO https://flux.forgeopslabs.com/downloads/config.demo.toml

Check that both files are there:

bash
ls

The output lists config.demo.toml and docker-compose.demo.yml.

Learn more: Install and first boot describes what the two files contain.

2. Create the encryption key

FluxGate encrypts the secrets it stores with one key. Generate it once and keep it in a .env file next to the compose file:

bash
echo "FLUXGATE_ENCRYPTION_KEY=$(openssl rand -base64 32)" > .env

Check that the file holds one line:

bash
wc -l .env

Learn more: Install and first boot.

3. Start FluxGate

bash
docker compose -f docker-compose.demo.yml up -d

Compose starts PostgreSQL, the backend and the UI. The backend runs its database migrations at startup. Check the containers, then ask the backend for its API documentation page. Type the trailing slash:

bash
docker compose -f docker-compose.demo.yml ps
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080/docs/

All three services show Up, and the curl command prints 200. If the curl command fails to connect, wait a few seconds and run it again.

Learn more: Install and first boot has the expected ps output and fixes for common start problems.

4. Create the first admin

  1. Open http://localhost:3000. On a fresh database FluxGate redirects you to /create-admin.
  2. Fill Username with admin, then Password, Confirm Password, First Name, Last Name and Email. Click Create Admin.
  3. On Sign in to FluxGate, sign in with the new credentials.

You land on System Overview at /. Check it from the terminal: the backend now refuses unauthenticated calls.

bash
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080/api/v1/teams

The command prints 401.

Learn more: Install and first boot.

5. Create a team, an environment, and a flag

FluxGate needs two people to deploy a stage: one who requests the deployment and a different one who approves it. Nobody approves their own request. The shortest path is therefore: you (admin) request, and a second user, sam, approves. The steps below take one flag, express-checkout, from nothing to a deployed Development stage.

Sign in as admin and work through these steps in order.

  1. Create the team. Open Teams under Settings to reach /settings/teams, then click Create New Team. Enter Checkout as Team Name and Juniper Market checkout squad as Description, and click Create Team. Reload the page. Check that Select team in the header shows Checkout. If it does not, open Select team and choose Checkout.
  2. Create the environment. Click Environments under Build, then Create New Environment. Enter Development as Environment Name, leave Environment Type on Development, and click Create Environment. The toast "Environment created successfully" appears.
  3. Create the approver. Open Users under Settings and click Create New User. Enter sam as Username, choose a Password, add a first name, a last name and an email, and click Create User. On the Assign Teams tab, tick Checkout and click Assign Selected Teams. On the Assign Roles tab, tick Approver and click Assign Selected Roles.
  4. Give yourself the Requester role. In the Users list, click the pencil icon in the admin row, go to the Assign Roles tab, tick Requester, and click Assign Selected Roles. Then open the avatar menu, click Log out, and sign in as admin again. The UI reads your roles when you sign in, so the new role takes effect only after that.
  5. Create the approval policy. Click Approval Policies under Govern and click Create Policy. Enter Release approvals as Policy Name. Leave Scope on All Environments. Open Approver Roles, choose Approver, and click the dialog heading to close the list. Click Create Policy. The toast "Approval policy created successfully" appears.
  6. Create the flag. Click Features under Build, then Create New Feature. Enter express-checkout as Name, and set Feature Type to CONTEXTUAL. In Feature Variants, click Add Variant twice and fill the two rows: Variant Key classic with Value classic, and Variant Key express with Value express.
  7. Add a stage. Scroll to Rollout Templates. The template Simple on/off (system) and the environment Development are already selected. Click Preview, then Apply Template. The toast "Rollout template applied" appears and the stage graph shows one stage, Development. Click Create Feature. FluxGate opens Edit Feature with the toast "Feature created successfully". The flag stays in the lifecycle DRAFT. That is fine: the lifecycle does not block a deployment.
  8. Serve a variant. Click the edge of the Development node in the stage graph (not its name) to select it. In Stage Editor, click Add Criterion and then Expand. Under Variant Selection Mode, choose Specific Variant and pick express under "Select the variant to return:". Click Save Stage Criteria. A criterion without rules matches every request, so this stage now serves express to everyone.
  9. Request the deployment. With Development still selected, open Actions and click Request Deployment. The stage status changes to DEPLOYMENT_REQUESTED.
  10. Approve as sam. Log out and sign in as sam. FluxGate opens Update Your Password on the first sign-in: enter the password you set in step 3, a new password twice, and click Update Password. Sign in again as sam. Click Approvals under Govern. The pending request reads "Stage NOT_DEPLOYED -> DEPLOYMENT_REQUESTED for feature express-checkout". Click Approve. The toast "Approval recorded" appears.
  11. Deploy. Still as sam, open express-checkout from Features, click Edit, select the Development stage, open Actions, and click Deploy. The stage status changes to DEPLOYED.

Check the result in the UI: open Features, click the details button of express-checkout, and open the Stages tab. The Development stage shows DEPLOYED. Section 7 checks it from the command line.

Learn more: Teams, users and roles, Environments and pipelines, Create your first feature, Targeting rules and Approvals and policies. The chapters build the full setup with a checkout-release pipeline (Development, Staging, Production) and the users priya and sam.

6. Create a client and start the edge server

An app never calls the backend to evaluate a flag. It calls the edge server, which keeps a cached copy of your flags. The edge server signs in to the backend as a client, so you create that client first.

  1. Click Clients under Connect, then Create New Client.

  2. Enter checkout-service as Client Name, choose Backend as Client Type, and choose Development as Environment. The environment decides which stage configuration the client sees. Click Create Client.

  3. The page Edit Client opens. It shows API Key and SDK key, both masked. Click the copy button next to API Key and keep the key. The client ID is the ID in the page address (/clients/<client ID>/edit); the Client ID column on /clients has a copy button as well.

  4. Append both values to .env, start the edge server, and check its health:

    bash
    echo EDGE_CLIENT_ID=<checkout-service client ID> >> .env
    echo EDGE_CLIENT_SECRET=<checkout-service API key> >> .env
    docker compose -f docker-compose.demo.yml --profile edge up -d edge
    curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8081/health

The health check prints 200 when the edge server has connected to the backend. A 503 right after the start is normal for about a second: run the check again. If the 503 persists, the two values in .env are wrong. Run docker compose -f docker-compose.demo.yml logs edge and look for invalid client_secret.

Learn more: Clients and edge server also creates a Web client and explains which endpoint accepts which credential.

7. Evaluate a flag

Evaluate express-checkout as a user in Canada on the plus tier. Every request carries a bucketing key (bucketingKey or targetingKey), which FluxGate uses to place a user in a percentage rollout. This guide's flag serves express to everyone, and a rollout split would use the key.

The two OFREP-based tabs authenticate with an SDK key: the client ID, a dot, and the API key. Build it from .env:

bash
export FLUXGATE_SDK_KEY="$(grep ^EDGE_CLIENT_ID= .env | cut -d= -f2-).$(grep ^EDGE_CLIENT_SECRET= .env | cut -d= -f2-)"
bash
curl -s -X POST http://localhost:8081/evaluate \
  -H 'Content-Type: application/json' \
  -d '{"flagKey":"express-checkout","context":{"bucketingKey":"user-1","country":"CA","user_tier":"plus"}}' | jq
bash
curl -si -X POST http://localhost:8081/ofrep/v1/evaluate/flags \
  -H "Authorization: Bearer $FLUXGATE_SDK_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"context":{"targetingKey":"user-1","country":"CA","user_tier":"plus"}}'
app.mjs
import { OpenFeature } from '@openfeature/server-sdk';
import { OFREPProvider } from '@openfeature/ofrep-provider';

await OpenFeature.setProviderAndWait(new OFREPProvider({
  baseUrl: 'http://localhost:8081',
  headers: [['Authorization', `Bearer ${process.env.FLUXGATE_SDK_KEY}`]],
}));

const client = OpenFeature.getClient();
const variant = await client.getStringValue('express-checkout', 'classic', {
  targetingKey: 'user-1',
  country: 'CA',
  user_tier: 'plus',
});
console.log(`checkout: ${variant}`);
await OpenFeature.close();

The first call answers as the edge server's own client and takes no credentials. Keep port 8081 private. The OFREP call authenticates the caller by SDK key and evaluates in the environment of the caller's client.

Expected response of /evaluate:

Response
{
  "flagKey": "express-checkout",
  "value": "express",
  "variant": "express",
  "reason": "TARGETING_MATCH"
}

Expected response of the OFREP call. The etag value differs on your stack:

Response
HTTP/1.1 200 OK
content-length: 193
etag: <etag value>
content-type: application/json

{"flags":[{"key":"express-checkout","value":"express","reason":"TARGETING_MATCH","variant":"express"}],"metadata":{"version":"<etag value>"}}

Repeat the OFREP call with the ETag in an If-None-Match header. While the flags and the context are unchanged, the edge server answers 304 Not Modified with no body:

bash
curl -si -X POST http://localhost:8081/ofrep/v1/evaluate/flags \
  -H "Authorization: Bearer $FLUXGATE_SDK_KEY" \
  -H 'If-None-Match: <etag value from the first response>' \
  -H 'Content-Type: application/json' \
  -d '{"context":{"targetingKey":"user-1","country":"CA","user_tier":"plus"}}'
Response
HTTP/1.1 304 Not Modified
etag: <etag value>

To run the OpenFeature example, save the file as app.mjs in a new folder, then run it with Node 20 or newer. The same terminal needs FLUXGATE_SDK_KEY, so run the export command again if you opened a new one:

bash
npm install @openfeature/server-sdk @openfeature/ofrep-provider
node app.mjs
Output
checkout: express

Learn more: Clients and edge server and Edge server API.

8. Optional: AI assistance, Jira, single sign-on

These features need no change to the files you already have. Add the setting to .env and restart only the backend.

bash
echo TYPESAFE_API_KEY=<your TypeSafe API key> >> .env
docker compose -f docker-compose.demo.yml up -d backend

Check the restart. The backend shows Up:

bash
docker compose -f docker-compose.demo.yml ps backend

Then sign in as admin, select the team, and open AI assistance under Settings (/settings/ai). The page lists the four AI switches, such as Approval risk triage. The AI features stay hidden in the UI until the backend has the key and a team switch is on.

9. Before production

The demo stack is built for a laptop. Before you run FluxGate for a team, work through Going to production. In short:

  • Keep FLUXGATE_ENCRYPTION_KEY in a secret store and back it up. Losing it loses every stored secret.
  • Replace the demo database password and back up the database volume.
  • Put the UI and the backend behind HTTPS, and set allowed_origin and public_base_url to the public addresses.
  • Keep port 8081 private. POST /evaluate on the edge server takes no credentials.
  • Create an approval policy and give each person only the roles they need.

Reset or remove

Stop the stack and keep your data. The next up -d brings your data back; add --profile edge to start the edge server too. The edge server sits behind a Compose profile, so down stops it only when you name the profile. Always add --profile edge. The option does nothing if you never started the edge server:

bash
docker compose -f docker-compose.demo.yml --profile edge down

Next

Follow the chapters in order, starting with What is FluxGate.