Enable Orchestration
Stategraph Orchestration is on by default on a self-hosted server. STATEGRAPH_ORCHESTRATION_ENABLED=true turns it on, false turns it off, and when the variable is unset, Orchestration is on exactly when STATEGRAPH_FDW_PASSWORD is set. To use it, give it two database passwords and your public URL, and connect a GitHub App or GitLab.
Turn it on
Add these variables to the container environment, and recreate the container:
STATEGRAPH_UI_BASE=https://stategraph.example.com
STATEGRAPH_OAUTH_REDIRECT_BASE=https://stategraph.example.com
STATEGRAPH_FDW_PASSWORD=<fdw-password>
STATEGRAPH_FDW_PROVISIONER_PASSWORD=<provisioner-password>
| Variable | Notes |
|---|---|
STATEGRAPH_UI_BASE |
Your public URL. The webhook and runner URLs derive from it |
STATEGRAPH_OAUTH_REDIRECT_BASE |
Your public URL. The callback URLs of the GitHub App are under it |
STATEGRAPH_FDW_PASSWORD |
Password of the stategraph_mql database role. Setting it turns on Orchestration. See Database |
STATEGRAPH_FDW_PROVISIONER_PASSWORD |
Password of the stategraph_provisioner database role. The console creates the GitHub App and connects GitLab groups through it |
TERRAT_API_BASE and TERRAT_UI_BASE default to STATEGRAPH_UI_BASE plus /api, and to STATEGRAPH_UI_BASE. Set them only when Orchestration has another public URL. STATEGRAPH_ORCHESTRATION_ENABLED=false turns Orchestration off with the passwords in place.
Then connect your provider: Connect GitHub or Connect GitLab.
At each start with Orchestration on, Stategraph migrates the Orchestration database and starts Orchestration. The switch takes effect only with the default container command. Anonymous telemetry is on by default: TERRAT_TELEMETRY_LEVEL=disabled turns it off.
Database
Orchestration stores its data in a second database, terrateam, on the same PostgreSQL server as stategraph. The console reads it through postgres_fdw, as the stategraph_mql role, and writes the GitHub App and the GitLab group connections as the stategraph_provisioner role. Stategraph creates the database and the roles, and keeps the grants of the roles current. You give the roles their passwords, one time.
With the Docker Compose PostgreSQL, there is nothing to do: it creates the database and the roles at the first start of a new volume, with the passwords stategraph_mql and stategraph_provisioner. Use those values in STATEGRAPH_FDW_PASSWORD and STATEGRAPH_FDW_PROVISIONER_PASSWORD.
On any other PostgreSQL, create the roles before the first start with Orchestration on. If Stategraph already created them, use ALTER ROLE instead.
CREATE ROLE stategraph_mql LOGIN PASSWORD '<fdw-password>';
CREATE ROLE stategraph_provisioner LOGIN PASSWORD '<provisioner-password>';
Managed PostgreSQL
On Amazon RDS, Cloud SQL, and other managed PostgreSQL, the role that Stategraph connects as is usually not a superuser. Then:
postgres_fdwneeds superuser rights. On Amazon RDS, grant the rolerds_superuser. Otherwise, create the foreign server and the user mapping in thestategraphdatabase in advance. Without one of these, the Stategraph server does not start, and the error is in the server log.- When the role cannot create databases, create
terrateamyourself, owned by that role. Orchestration logs the statement, waits 30 seconds, and tries again:
CREATE DATABASE terrateam OWNER stategraph;
Connect GitHub
Orchestration runs as a GitHub App that you own. An instance admin creates it from the console, or you create it by hand and pass it through the environment.
From the console
This path needs STATEGRAPH_FDW_PROVISIONER_PASSWORD. Sign in as an instance admin, and open Get Started > Set up your first repository > Connect GitHub. The first step is Create:
- Keep the App name the console suggests, or type your own. GitHub requires a name no other App uses. To create the App under an organization, enter the organization name.
- Click Create on GitHub. GitHub opens with the App filled in: the webhook URL, the callback URLs, the setup URL, the permissions and events listed below, and OAuth on install.
- Create the App on GitHub. GitHub returns you to the console.
Stategraph stores the App in the Orchestration database and starts Orchestration with it. The console shows "The App is created. Starting the orchestration engine." for a few seconds, then moves to the Install step. Nothing changes in the environment, and no restart is needed. For GitHub Enterprise Server, set the two URL variables first: see GitHub Enterprise Server.
Manage the App
An App created from the console is managed in Settings > Integrations > GitHub App, as an instance admin. The panel shows which App the server holds, when it was created, and whether Orchestration is running it.
Replace creates a new App on GitHub and stores it in place of the current one. You install the new App yourself. The installations of the old App stop being orchestrated.
Rotate credentials takes the private key, the OAuth client secret and the webhook secret that you rotate on the App's GitHub page. Fill in the ones you rotated and leave the rest empty. GitHub shows each of them one time only and has no API that reads one back, so keep what you download until the panel reports it in use. A stale webhook secret stops every run, because the events then fail their signature check. A stale client secret breaks console sign-in and leaves webhooks alone.
Remove deletes the App from Stategraph. Orchestration then answers no GitHub events. The App, its installations and their tenant links stay on GitHub. The stored copy of the private key is destroyed, and no copy remains in Stategraph.
Each of the three restarts Orchestration on the new state, which takes a few seconds. A webhook that arrives during the restart is lost, and GitHub does not redeliver it, so make these changes when no run is in flight.
An App that comes from the environment is not managed here. The panel names it and says so.
With the environment
For a deployment that keeps its secrets outside Stategraph, such as Kubernetes secrets, create the App by hand and set the six GITHUB_* variables. When GITHUB_APP_ID is set, the environment wins over an App created from the console, and the console neither stores nor manages an App.
Create a GitHub App in your organization with these permissions:
| Permission | Access |
|---|---|
| Actions | Read and write |
| Checks | Read |
| Contents | Read and write |
| Issues | Read and write |
| Metadata | Read |
| Pull requests | Read and write |
| Commit statuses | Read and write |
| Secrets | Read and write |
| Workflows | Read and write |
| Members (organization) | Read |
| Email addresses (account) | Read |
Subscribe it to the events issue_comment, issues, pull_request, pull_request_review, pull_request_review_comment, push, workflow_job, and workflow_run. Then:
- Set the webhook URL to
https://stategraph.example.com/api/github/v1/events, and a webhook secret. Put the secret inGITHUB_WEBHOOK_SECRET. - Add
https://stategraph.example.com/api/v1/vcs-installations/github/claim/callbackas a callback URL. - Generate a private key, and put its contents in
GITHUB_APP_PEM. Literal\nsequences become line breaks. - Put the App ID in
GITHUB_APP_ID, the client ID and secret inGITHUB_APP_CLIENT_IDandGITHUB_APP_CLIENT_SECRET, and the install URL,https://github.com/apps/<your-app>, inGITHUB_APP_URL.
GITHUB_WEBHOOK_SECRET is required when GITHUB_APP_ID is set: without it, Orchestration does not start, and the container log says so. With the OAuth client, the callback URL, and the Members permission in place, tenant admins link their own installation from the console, without an instance admin. See Tenants.
GitHub Enterprise Server
Set GITHUB_API_BASE_URL and GITHUB_WEB_BASE_URL to your instance, for example https://github.example.com/api/v3 and https://github.example.com.
Connect GitLab
Orchestration connects to GitLab as a bot user that you create, with an access token and an OAuth application. Set the variables, then a tenant admin connects each group from the console.
| Variable | Notes |
|---|---|
GITLAB_APP_ID |
Application ID of the OAuth application. A value that is not empty turns on GitLab in Orchestration |
GITLAB_APP_SECRET |
Secret of the application. Required with GITLAB_APP_ID |
GITLAB_ACCESS_TOKEN |
Access token of the bot user, with the api scope. Required with GITLAB_APP_ID |
GITLAB_API_BASE_URL, GITLAB_WEB_BASE_URL |
Self-managed GitLab only: the root URL of the instance, for example https://gitlab.example.com. Both default to https://gitlab.com |
STATEGRAPH_FDW_PROVISIONER_PASSWORD |
Password of the stategraph_provisioner database role. See Database. Without it, the console cannot connect a group |
When GITLAB_APP_ID is set and GITLAB_APP_SECRET or GITLAB_ACCESS_TOKEN is missing, Orchestration does not start. The container log has a CONFIG : ERROR line that names the variable.
GitLab version
Stategraph Orchestration requires GitLab 18.1 or later, Community or Enterprise Edition. gitlab.com always meets this. On self-managed GitLab, check the version with the metadata API:
curl --header "PRIVATE-TOKEN: <access-token>" "https://gitlab.example.com/api/v4/metadata"
Earlier versions start the pipeline without the inputs that carry the work token, and the job fails when it calls back.
With the setup wizard
The setup wizard collects the values and writes them to .env, and you create the GitLab user, token, and application yourself:
- Run the wizard, and open http://localhost:3000. When the wizard asks how GitLab reaches your server, enter the public host name, for example
stategraph.example.com.
docker run --rm -p 3000:3000 ghcr.io/stategraph/orchestration-setup:latest
- Create a dedicated GitLab user for Stategraph, such as
acme-stategraph-bot. As that user, create a personal access token with theapiscope. Enter your GitLab URL and the token. - As the bot user, add an application in Preferences > Applications with the
apiscope and the redirect URI that the wizard shows,https://stategraph.example.com/api/v1/gitlab/callback. Enter its application ID and secret. - Copy
GITLAB_APP_ID,GITLAB_APP_SECRET, andGITLAB_ACCESS_TOKENinto the environment of your deployment. For self-managed GitLab, addGITLAB_API_BASE_URLandGITLAB_WEB_BASE_URLyourself: the wizard does not write them.
By hand
- Create a dedicated GitLab user for Stategraph. As that user, create a personal access token with the
apiscope, and put it inGITLAB_ACCESS_TOKEN. - As the same user, create an OAuth application with the
apiscope and the redirect URIhttps://stategraph.example.com/api/v1/gitlab/callback. Put its application ID inGITLAB_APP_IDand its secret inGITLAB_APP_SECRET. - For self-managed GitLab, set
GITLAB_API_BASE_URLandGITLAB_WEB_BASE_URLto the root URL of the instance.
Connect a group
After the restart, a tenant admin connects a GitLab group from the Get Started page of the console, with the group ID and an access token with the api scope, then adds the project webhook and the .gitlab-ci.yml that the wizard shows. The steps are the same as on Stategraph Cloud: see Connect GitLab in the quickstart. The webhook secret shows one time only. To replace a lost secret, rotate the credentials in Settings > Integrations.
Self-managed GitLab
The instance must run GitLab 18.1 or later. Set GITLAB_API_BASE_URL and GITLAB_WEB_BASE_URL to its root URL, and enter the same URL in the connect wizard: Orchestration reads the variables, the console does not. Also mirror gitlab.com/terrateam-io/terrateam-template to terrateam-io/terrateam-template on the instance, because the .gitlab-ci.yml includes it from the instance that runs the pipeline. Without the mirror, pipeline creation fails.
Verify
After the container restarts with Orchestration on, search its log:
docker compose logs server | grep -E 'terrat|GITHUB_APP|GitLab|CONFIG : ERROR|GITHUB_WEBHOOK_SECRET|CREATE DATABASE'
A correct start logs that Orchestration starts and that the roles are reconciled, and with GitLab, Starting GitLab Service. With no GitHub App yet, it logs GITHUB_APP : WAITING until an instance admin creates one from the console, then GITHUB_APP : LOADED after the restart. A failed start logs the missing GitHub webhook secret, a CONFIG : ERROR line for a missing GitLab variable, or the CREATE DATABASE statement to run. Then open the console, and set up your first repository from the Get Started page. For anything else, see Orchestration issues.
Next steps
- Pull request workflows: what Orchestration does on a pull request.
- Private runners: plans and applies on GitHub Actions or GitLab runners that you host.
- Environment variables: every Orchestration variable.