Skip to content

Spike: Unified provisioning system #6797

@khvn26

Description

@khvn26

Flagsmith currently has four fragmented ways to provision an instance:

  1. bootstrap management command — creates a superuser + org + project via CLI, controlled by ALLOW_ADMIN_INITIATION_VIA_CLI and a handful of env vars (ADMIN_EMAIL, ORGANISATION_NAME, PROJECT_NAME).
  2. UI onboarding — web form at /api/v1/users/config/init/ for interactive first-time setup.
  3. E2E test seede2e_seed_data.py creates a complex dataset (2 orgs, 5 users, 7 projects, 8 environments, permissions, subscriptions) via direct model creation.
  4. (upcoming) make reset (PR #6459) — flushes the DB and seeds dev data via APIClient calls.

As noted in PR #6459, this fragmentation warrants a unified provisioning system. Inspired by Grafana's provisioning, we want a declarative, file-based system that serves all these use cases and self-hosted IaC scenarios. This will also help us automate the last remaining mile of Private Cloud provisioning (FoF, SSO configurations, user data).

The user-facing spec is defined in the docs PR: docs: Provisioning (#6802).

See the docs here.

The outcome of this spike is either a wontfix, or an epic detailing out the V1 implementation and migration of existing tools.

Use cases

1. Fresh instance bootstrap (self-hosted operators)

Operators deploying Flagsmith via Docker, Kubernetes, or bare metal need a way to initialise the instance without manual UI steps. Today this requires ALLOW_ADMIN_INITIATION_VIA_CLI=true and is limited to a single superuser, one organisation, and one project.

With provisioning, a provisioning/bootstrap.yaml file ships with Flagsmith. The Docker entrypoint runs python manage.py provision instead of bootstrap. The same env vars (ADMIN_EMAIL, ORGANISATION_NAME, PROJECT_NAME) work via ${VAR:default} interpolation, so existing deployments continue to work without changes.

2. Infrastructure as code / repeatable deployments (Kubernetes, Helm etc.)

Self-hosted operators want to check their instance configuration into version control and apply it as part of their deployment pipeline — creating projects, environments, features, segments, and master API keys without manual UI work.

Today, there is no built-in IaC support for Flagsmith's internal entities. The Terraform provider manages flags via API but requires a running instance with auth tokens. Provisioning complements it: provisioning handles instance-level setup, Terraform handles ongoing flag management.

Operators using the Helm chart need to mount YAML files as ConfigMaps or Secrets. On startup, the provisioner reads these and creates everything declared — without manual UI steps or custom init containers.

3. Flagsmith-on-Flagsmith pre-configuration

Setting up Flagsmith on Flagsmith currently requires manually creating a project, environments, and flags, then configuring env vars. Issue #4447 requests automating this.

With provisioning, a dedicated YAML file creates the FoF project with all required flags (e.g. oauth_google, dark_mode). The provisioner outputs the environment API key, which can be used to set FLAGSMITH_ON_FLAGSMITH_API_KEY on the frontend.

4. Local development reset

PR #6459 introduces make reset, which flushes the DB and seeds a rich test dataset. With provisioning, make reset runs provision --directory provisioning/dev/ instead. The dev YAML files declare the same dataset (user, org, project, 3 environments, features, segments) in a readable, editable format.

5. E2E test setup

e2e_seed_data.py creates a complex dataset (2 orgs, 5 users, 7 projects, 8 environments, 6 identities, permission setups) via direct model creation. With provisioning, YAML files in provisioning/e2e/ declare the same entities. The teardown endpoint calls teardown() then provision_from_directory().

6. Demo / sandbox environments

No built-in way exists to create a rich demo instance. With provisioning, a demo YAML file ships as an example that creates a convincing dataset for contributors, sales engineers, or evaluation.

Requirements

The provisioning system reads declarative YAML files that describe the desired instance state. Files live in a directory (processed alphabetically), support environment variable interpolation (${VAR} and ${VAR:default}), and allow cross-referencing entities by name across files.

The core of the system is the python manage.py provision command with --directory, --file, and --dry-run options. It supports seven entity kinds — users, organisations (with members and subscriptions), projects, environments, features (with default_enabled / initial_value), segments (with rules), and master API keys — plus an app_domain top-level setting for configuring the site domain used in password reset and invite emails.

The provisioner is idempotent: it creates entities that don't exist and skips those that do, making it safe to run on every container startup. Master API key values are printed to stdout at creation time, since only the hash is stored. Existing bootstrap env vars (ADMIN_EMAIL, ORGANISATION_NAME, PROJECT_NAME) continue to work via interpolation, and the web-based init form remains available for interactive setup.

Related issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiIssue related to the REST API

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions