Kickstart

1. Kickstart

FusionAuth Kickstart™ is super easy and if you can do it with an API, you can do it in Kickstart. Kickstart allows you to build a template that will be executed during startup to quickly replicate development or production environments.

The kickstart file is a collection of one or more API keys and a list of API requests. You can call POST, PUT or PATCH on any API that you like and each request will be executed in order using the primary API key defined in the bootstrap file.

To kickstart FusionAuth, set an environment variable named FUSIONAUTH_KICKSTART that points to your kickstart file.

Kickstart will only run if no API keys, users or tenants exist, so you can safely leave this environment variable configured even after the system has been configured.

2. Getting Started

Let’s work from simple to complex, each example will introduce a new feature so you can learn how to best build and leverage the options available to you as you build out your kickstart file.

The examples found here, as well as community contributed examples may also be found on GitHub in the FusionAuth Kickstart repository. If you think you’ve got a cool kickstart, please submit a PR, your example may really help the community. * https://github.com/FusionAuth/fusionauth-example-kickstart

2.1. The API key

Here is the simplest kickstart file you can use, it simply adds a single API key and that’s it. This may be useful if you intend to complete the rest of your setup by calling APIs in your own application or development setup script.

{
  "apiKeys": [{
    "key": "4737ea8520bd454caabb7cb3d36e14bc1832c0d3f70a4189b82598670f11b1bd"
  }]
}

2.1.1. Scoping an API key

The first API key you specify has to have authority to all tenants and all endpoints. If you want to create subsequent API keys these can optionally be scoped to a Tenant and have restrictions on which endpoints they can call.

In this example we still have the first API key because it must have authority to all endpoints, and we will create a second API key that is restricted.

{
 "apiKeys": [{
   "key": "4737ea8520bd454caabb7cb3d36e14bc1832c0d3f70a4189b82598670f11b1bd"
 },
 {
   "key": "0ad00c5f140c43f8bc2a155dd0edf3b7d61f5dd4011843d8a28475a0d812c033",
   "description": "Restricted API key - only for Retrieve User",
   "permissions": {
     "endpoints": {
       "/api/user": ["GET"]
     }
   }
 }]
}

2.2. Using Variables

You may find yourself repeating yourself when you build your kickstart file, nobody likes to type the same value over and over. Use variables to help you reduce repetition.

To use a variable, define the key and value in the variables section of the kickstart file and then access that value anywhere outside of the variables section using the #{foo} notation where foo is the name of the variable.

Here is the same example as above, but instead of hard coding the API key, we are using a variable which can be re-used. This example is not particularly helpful, we’ve only moved the value from the apiKeys section to the variables section, but using variables may come in handy as you’ll see in the next few examples.

{
  "variables":{
    "apiKey": "4737ea8520bd454caabb7cb3d36e14bc1832c0d3f70a4189b82598670f11b1bd",
  }
  "apiKeys": [{
    "key": "#{apiKey}",
    "description": "My first API Key!"
  }]
}

2.3. Using Environment Variables

It is reasonable to think you may not want to hard code a password or API key in the kickstart file which could get checked into Git. You can use environment variables which should make this a bit easier for you.

To use an environment variable prefix the name of the environment variable with ENV..

Here is the same example as above, but instead of hard coding the API key, we are picking it up from an environment variable. Here we will resolve the value of the API key in the environment variable named FUSIONAUTH_API_KEY. This value will be set into the variable apiKey and then when the API key is constructed the value of the API key will be resolved to the apiKey variable value.

{
  "variables":{
    "apiKey": "#{ENV.FUSIONAUTH_API_KEY}"
  }
  "apiKeys": [{
    "key": "#{apiKey}"
  }]
}

2.4. Adding API Requests

Now comes the interesting part, once you have defined at least one API key, you can define one to many API requests that will be executed in order using the primary API key. You may call any API you like, you are only limited to the POST, PUT and PATCH HTTP methods.

Here is an example of creating a FusionAuth admin user using the requests object array. This example is using the Registration API to create the User and registration in a single request.

You’ll notice we are using a special variable that we did not define in the variables object. This is one of two reserved variables provided for your convenience.

  • FUSIONAUTH_APPLICATION_ID - The Id of the FusionAuth application

  • FUSIONAUTH_TENANT_ID - The Id of the default Tenant which is where the FusionAuth application resides

{
  "variables":{
    "apiKey": "#{ENV.FUSIONAUTH_API_KEY}",
    "adminPassword": "#{ENV.FUSIONAUTH_ADMIN_PASSWORD}"
  },
  "apiKeys": [{
    "key": "#{apiKey}"
  }],
  "requests": [{
    "method": "POST",
    "url": "/api/user/registration",
    "body": {
      "user": {
        "email": "monica@piedpiper.com",
        "password": "#{adminPassword}",
        "data": {
          "Company": "PiedPiper"
        }
      },
      "registration": {
        "applicationId": "#{FUSIONAUTH_APPLICATION_ID}",
        "roles": [
          "admin"
        ]
      }
    }
  }]
}

2.4.1. Tenants

If you don’t create a tenant using the Tenant API in your kickstart file then you’re all set. If you do find yourself creating more than one tenant then you will need to specify the Tenant Id on the API requests.

There is a top level property in the request called tenantId and you simply set that value to indicate which Tenant you wish to use.

In this example, we’ll create a new application and we’ll do it in a second tenant that we create. Because I need to know the tenantId I am generating a new UUID using the #{UUID()} variable value and assigning it to secondTenantId. Now I can re-use this value to create the tenant, and to make the Create Application API request.

This kickstart will create a second tenant named Aviato which will contain a single application named My Cool Application.

{
  "variables": {
    "apiKey": "#{ENV.FUSIONAUTH_API_KEY}",
    "adminPassword": "#{ENV.FUSIONAUTH_ADMIN_PASSWORD}",
    "secondTenantId": "#{UUID()}"
  },
  "apiKeys": [{
    "key": "#{apiKey}"
  }],
  "requests": [{
    "method": "POST",
    "url": "/api/tenant/#{secondTenantId}",
    "body": {
      "tenant": {
        "name": "Aviato"
      }
    }
  },
  {
    "method": "POST",
    "url": "/api/application",
    "tenantId": "#{secondTenantId}",
    "body": {
      "application": {
        "name": "My Cool Application"
      }
    }
  }]
}

2.4.2. Tenants API Keys

An API key may also be configured to be restricted to a single tenant. To do this, add the tenantId to the API key configuration.

In this example we will modify the restricted API key example from above to further limit it for use with one tenant.

{
  "variables": {
    "secondTenantId": "#{UUID()}"
  },
  "apiKeys": [{
    "key": "4737ea8520bd454caabb7cb3d36e14bc1832c0d3f70a4189b82598670f11b1bd"
  },
  {
    "key": "0ad00c5f140c43f8bc2a155dd0edf3b7d61f5dd4011843d8a28475a0d812c033",
    "description": "Restricted API key - only for Retrieve User in Aviato",
    "permissions": {
      "endpoints": {
        "/api/user": ["GET"]
      }
    },
    "tenantId": "#{secondTenantId}"
  }],
  "requests": [{
    "method": "POST",
    "url": "/api/tenant/#{secondTenantId}",
    "body": {
      "tenant": {
        "name": "Aviato"
      }
    }
  }]
}

3. Advanced Concepts

3.1. Modify the default Tenant Id

FusionAuth generates the Id for the default tenant when the database schema is first created. For development and production environments it may be helpful to have a known tenantId for consistency across environments.

You may modify the default Tenant Id in your kickstart file by setting a special variable. In this example we have set the default Tenant Id to 30663132-6464-6665-3032-326466613934. This value must be a valid UUID.

The value resolved when using the FUSIONAUTH_TENANT_ID variable will reflect this change.

{
  "variables":{
    "defaultTenantId": "30663132-6464-6665-3032-326466613934"
  }
}

3.2. Set your License Id

If you have a paid edition you will be provided with a License Id. If you would like to set this value during kickstart you will set the value in a top level field called licenseId.

In this example I have a license Id of eb7244dc-5d8e-40cd-a005-70b116fbda31.

{
  "licenseId": "eb7244dc-5d8e-40cd-a005-70b116fbda31"
}

3.3. Include Text files

When making API requests to create an Email template or request which may have lengthy values, it may be helpful to separate these values into separate files. The directories shown here are just examples, and you can use your own convention.

To include a file in your kickstart definition use the @{fileName} syntax where the fileName is a relative path from your kickstart file.

For example, consider the following directory structure:

|- kickstart.json
|- emails/
|  |- setup-password.html
|  |- setup-password.txt

In this example we are creating an Email template and reading in the values for the text and html values from files in a sub-directory named emails. Reading files in like this allows you to format your emails nicely and Kickstart will handle the necessary JSON escaping to complete the API request.

{
  "variables":{
    "apiKey": "#{ENV.FUSIONAUTH_API_KEY}"
  },
  "apiKeys": [{
    "key": "#{apiKey}"
  }],
  "requests": [ {
    "method": "POST",
    "url": "/api/email/template/0502df1e-4010-4b43-b571-d423fce978b2",
    "body": {
      "emailTemplate": {
        "defaultFromName": "No Reply",
        "defaultSubject": "Setup your password",
        "defaultHtmlTemplate": "@{emails/setup-password.html}",
        "defaultTextTemplate": "@{emails/setup-password.txt}",
        "fromEmail": "no-replay@piedpiper.com",
        "name": "Setup Password"
      }
    }
  } ]
}

3.4. Include JSON files

If you’re making a lot of API requests, or simply want to manage each API request body separately it may be helpful to read in external JSON files. The directories shown here are just examples, and you can use your own convention.

To include a JSON file in your kickstart definition use the &{fileName} syntax where the fileName is a relative path from your kickstart file.

For example, consider the following directory structure:

|- kickstart.json
|- emails/
|  |- setup-password.html
|  |- setup-password.txt
|- json/
|  |- setup-password.json

Here are the contents of the json/setup-password.json file, you’ll see that in this example we are still reading in the values for defaultHtmlTemplate and defaultTextTemplate.

{
  "emailTemplate": {
    "defaultFromName": "No Reply",
    "defaultSubject": "Setup your password",
    "defaultHtmlTemplate": "@{emails/setup-password.html}",
    "defaultTextTemplate": "@{emails/setup-password.txt}",
    "fromEmail": "no-replay@piedpiper.com",
    "name": "Setup Password"
  }
}

We will replicate the previous example but the entire JSON body of the request will move to setup-password.json.

{
  "variables":{
    "apiKey": "#{ENV.FUSIONAUTH_API_KEY}"
  },
  "apiKeys": [{
    "key": "#{apiKey}"
  }],
  "requests": [ {
    "method": "POST",
    "url": "/api/email/template/0502df1e-4010-4b43-b571-d423fce978b2",
    "body": "&{json/setup-password.json}"
  } ]
}

You may also include an entire request using this pattern, consider the following directory structure:

|- kickstart.json
|- emails/
|  |- setup-password.html
|  |- setup-password.txt
|- json/
|  |- setup-password.json
|- requests/
|  |- setup-password.json

Here are the contents of the requests/setup-password.json file.

{
"method": "POST",
  "url": "/api/email/template/0502df1e-4010-4b43-b571-d423fce978b2",
  "body":{
    "emailTemplate": {
      "defaultFromName": "No Reply",
      "defaultSubject": "Setup your password",
      "defaultHtmlTemplate": "@{emails/setup-password.html}",
      "defaultTextTemplate": "@{emails/setup-password.txt}",
      "fromEmail": "no-replay@piedpiper.com",
      "name": "Setup Password"
    }
  }
}

And the usage in the kickstart file:

{
  "variables":{
    "apiKey": "#{ENV.FUSIONAUTH_API_KEY}"
  },
  "apiKeys": [{
    "key": "#{apiKey}"
  }],
  "requests": [
    "&{requests/setup-password.json}"
  ]
}