Manage FusionAuth Configuration Across Environments

On this page

Most teams run more than one FusionAuth instance, such as development, staging, and production instances. Each instance needs the same Tenants, Applications, and settings. A few values differ between environments.

Keep the configuration in code. Code lets a team review each change before the change reaches production. The same code then applies the change to every instance.

Development valuesStaging valuesProduction values, afterreviewConfiguration repositoryDevelopmentStagingProduction

One configuration, applied to each instance with values for that instance.

Configuration and Data#

FusionAuth holds two kinds of objects:

  • Configuration defines how the system behaves. A team sets up configuration once and changes the configuration rarely.
  • Data changes as people use your applications.

Keep configuration in code. Let applications manage data through the APIs.

Configuration Data
Tenants, Applications, and roles Users and registrations
Signing keys and API keys Group memberships
Themes, email templates, and lambdas Refresh tokens and sessions
Identity providers, webhooks, and connectors that your team sets up Identity providers that your customers set up themselves

To add users, turn on self-service registration, create users with the User API, or migrate users from another system.

Choose a Tool#

Terraform#

The FusionAuth Terraform provider manages most configuration objects. Terraform shows each change before applying the change. Terraform also tracks which objects the configuration owns. Terraform fits most teams, and the provider works with OpenTofu too. See Manage FusionAuth With Terraform.

Scripts#

Scripts call the API directly or through a client library. Run scripts the way you run database migrations. Scripts can call every API, including APIs that the Terraform provider doesn't support yet. However, scripts don't track which changes ran on which instance. Keep a record of the scripts that ran on each instance.

The FusionAuth CLI#

The FusionAuth CLI downloads and uploads themes, email templates, lambdas, and messages as files. Keep the files in version control and edit the files with any editor. Use the CLI alongside Terraform or scripts.

The Admin UI#

The Admin UI is the quickest way to try a setting on a development instance. After the setting works, copy the change into code.

Avoid changing production through the Admin UI. A change made in the Admin UI reaches only one instance. The Audit Log at System -> Audit Log records who changed what.

Default Resources#

Every instance starts with objects that FusionAuth creates, such as the default Tenant, the FusionAuth Application, and the default theme. The FusionAuth Application runs the Admin UI. See Default Configuration for the full list and the Ids.

Code can't create or delete default resources. To change the settings of a default resource, import the resource into your tool. To use a default resource without changing the resource, look up the resource by name or Id.

The FusionAuth Application has the same Id on every instance. The default Tenant has a different Id on each instance. To set the default Tenant Id, use Kickstart.

To keep default resources out of your code, leave the default Tenant to the Admin UI. Create separate Tenants for your applications. Most of the configuration then consists of objects that your code creates.

Changes Made Outside Your Tool#

A change made outside your tool, such as an edit in the Admin UI, makes the instance drift from the code. The next run of the tool reverts the change. To prevent drift:

  • Limit who can change configuration on production with Admin UI roles.
  • Configure the tool to ignore fields that applications write on purpose, such as the data field of an Application.

Secrets#

The tool needs an API key for each instance. Store the keys in the secret store of your CI system, not in the repository. On a new instance, Kickstart can create the first key.

Terraform state contains secrets, such as OAuth client secrets. Store state in a backend that encrypts the state and restricts access. See Sensitive Data in State.

Environment Differences#

Some values differ between instances, such as hostnames, redirect URLs, and email server settings. Pass these values in as variables, such as Terraform input variables. Don't keep a separate copy of the configuration for each environment.

Theme Assets#

When you move a theme from one environment to another, the templates and styles usually stay the same. The asset locations often differ, such as the hostname that serves images and CSS.

Theme templates can only read the documented template variables. FusionAuth doesn't resolve environment variables in theme templates. To use different asset locations in each environment, choose one of these options:

  • Set variables when you build the theme. In the Helpers template, set each variable with the assign directive. Other templates can then use the variables. To generate the Helpers template for each environment, use a templating language such as Jinja.
  • Store the locations in the tenant.data field. Every template can read the tenant object, so every template can read the locations.
Note

You can't edit tenant.data in the Admin UI. Set tenant.data with the API, a client library, or the data argument of the Terraform fusionauth_tenant resource.

For example, suppose development assets live at dev.example.com/assets and production assets live at prod.example.com/assets. To serve each environment's assets with the same theme:

  1. In the development Tenant, set the asset locations in tenant.data:
    Development Tenant data
    {
      "tenant" : {
        "data" : {
          "themes": {
             "asset_base_url" : "dev.example.com/assets",
             "css_base_url" : "cdn-dev.example.com"
          }
        }
      }
    }
    
  2. In the production Tenant, set the production locations:
    Production Tenant data
    {
      "tenant" : {
        "data" : {
          "themes": {
             "asset_base_url" : "prod.example.com/assets",
             "css_base_url" : "cdn-prod.example.com"
          }
        }
      }
    }
    
  3. In the theme templates, reference images with ${tenant.data.themes.asset_base_url} and CSS files with ${tenant.data.themes.css_base_url}:
    Template that uses the asset locations
    <html>
      <head>
        <link rel="stylesheet" href="${tenant.data.themes.css_base_url}/css/font-awesome.min.css"/>
        <link rel="stylesheet" href="${tenant.data.themes.css_base_url}/css/app.css"/>
      </head>
      <body>
        <img src="${tenant.data.themes.asset_base_url}/logo.png" />
        ...
        <img src="${tenant.data.themes.asset_base_url}/other_image.png" />
      </body>
    </html>
    

What to Avoid#

Copying the Database#

On a self-hosted instance, copying the database between environments or changing settings with SQL might seem like a shortcut. FusionAuth doesn't support either approach. The database schema is internal and can change in any release. The database also holds passwords and other personal data that shouldn't move between environments.

Using Kickstart for Ongoing Changes#

Kickstart configures a new instance on the first start. Kickstart suits continuous integration and creating the first API key. Kickstart doesn't run on an instance that already has configuration, so Kickstart can't apply later changes. To follow progress on Kickstart for existing instances, upvote the Kickstart migrations issue.

Test

Production

Harden

Monitor

Troubleshoot