Migrate from Terrateam
A self-hosted Terrateam server (ghcr.io/terrateamio/terrat-ee) becomes a Stategraph server (ghcr.io/stategraph/stategraph-server) when you replace the container. The PostgreSQL server, the Terrateam database, the GitHub App, the webhook URL, the runner workflow, the run history, and the API tokens stay. The Stategraph console replaces the Terrateam console on the same URL.
What changes
| Terrateam server | Stategraph server | |
|---|---|---|
| Image | ghcr.io/terrateamio/terrat-ee |
ghcr.io/stategraph/stategraph-server:<version> |
| Databases | terrateam |
terrateam and a new database, stategraph, on the same server |
| Console | Terrateam console, GitHub sign-in | Stategraph console, local or OIDC sign-in |
| Webhook and runner URLs | https://<host>/api/github/v1/... |
the same |
| License | none | STATEGRAPH_LICENSE_KEY |
| PostgreSQL | 14 or later | 15 or later |
Before you start
- Use PostgreSQL 15 or later.
- Start the current Terrateam image one time and wait until its migrations are complete.
- Set a webhook secret on the GitHub App and in
GITHUB_WEBHOOK_SECRET. - Set
GITHUB_APP_URLto the page of the App, for examplehttps://github.com/apps/<slug>. - Get a license key.
- Make a backup of the Terrateam database.
- Change API clients that call
GET /api/v1/whoamitoGET /api/v1/terrateam/whoami. All other API paths stay the same.
Environment
| Terrateam | Stategraph |
|---|---|
DB_NAME=terrateam |
DB_NAME=stategraph and TERRAT_DB_NAME=terrateam. TERRAT_DB_HOST, _PORT, _USER, and _PASS use the DB_* values by default. |
TERRAT_UI_BASE, TERRAT_API_BASE |
Remove. Set STATEGRAPH_UI_BASE and STATEGRAPH_OAUTH_REDIRECT_BASE to the old URL. |
TERRAT_WEB_BASE_URL |
Keep. |
GITHUB_*, GITLAB_*, TERRAT_TELEMETRY_LEVEL |
Keep. |
Add STATEGRAPH_ORCHESTRATION_ENABLED=true. |
|
Add STATEGRAPH_FDW_USER and STATEGRAPH_FDW_PROVISIONER_USER with the value of DB_USER, and STATEGRAPH_FDW_PASSWORD and STATEGRAPH_FDW_PROVISIONER_PASSWORD with the value of DB_PASS. |
|
Add STATEGRAPH_LICENSE_KEY. |
|
If the name of the Terrateam database is not terrateam, add STATEGRAPH_FDW_DBNAME with the same value as TERRAT_DB_NAME. |
|
TERRATEAM_CLIENT_MAX_BODY_SIZE, TERRAT_ACCESS_LOG |
STATEGRAPH_CLIENT_MAX_BODY_SIZE, STATEGRAPH_ACCESS_LOG |
CUSTOM_CA_CERT |
Not available. Build a derived image that includes the certificate. |
Database
Run this statement one time on the PostgreSQL server that has the Terrateam database:
CREATE DATABASE stategraph OWNER <application role>;
The stategraph database reads and writes the Terrateam database through postgres_fdw, as the application role. At each start, the server creates the roles stategraph_mql and stategraph_provisioner without LOGIN; this configuration does not use them. If the application role does not have CREATEROLE, create them one time:
CREATE ROLE stategraph_mql NOLOGIN;
CREATE ROLE stategraph_provisioner NOLOGIN;
To use these two roles for the connection instead of the application role, give them LOGIN and passwords, do not set STATEGRAPH_FDW_USER and STATEGRAPH_FDW_PROVISIONER_USER, and set the two password variables to their passwords.
If the application role is not a superuser, for example on Amazon RDS or Cloud SQL, run these statements one time in the stategraph database as a superuser:
CREATE EXTENSION IF NOT EXISTS postgres_fdw;
GRANT USAGE ON FOREIGN DATA WRAPPER postgres_fdw TO <application role>;
Docker Compose
docker compose pull serverdocker compose stop serverdocker compose exec db psql -U terrateam -d postgres -c 'create database stategraph owner terrateam'- In the
serverservice, set the Stategraph image and the environment from the table. docker compose up -d server
/health/ready returns 200 when the migrations are complete.
Kubernetes
The Stategraph chart uses the database of the Terrateam release. Keep the Terrateam release installed, with zero replicas, until the migration is final.
kubectl scale deploy/terrateam-server --replicas=0 -n <namespace>kubectl exec deploy/terrateam-db -n <namespace> -- psql -U terrateam -d postgres -c 'create database stategraph owner terrateam'- Install the Stategraph chart with these values:
stategraph:
ui:
base: https://<your Terrateam URL>
license:
key: <license key>
orchestration:
enabled: true
databaseName: terrateam
provisionDatabase: false
fdw:
user: terrateam
provisionerUser: terrateam
existingSecret: terrateam-db-password
existingSecretKeys:
password: password
provisionerPassword: password
github:
existingSecret: <Secret with the five GitHub credentials>
appUrl: https://github.com/apps/<slug>
postgresql:
enabled: false
host: terrateam-db
port: 5432
auth:
username: terrateam
database: stategraph
existingSecret: terrateam-db-password
existingSecretKey: password
terrateam-db and terrateam-db-password are the Service and the Secret of the Terrateam chart. With an external PostgreSQL, set postgresql.host and existingSecret to that server and its Secret. The GitHub Secret uses the keys github-app-id, github-app-client-id, github-app-client-secret, github-app-pem, and github-webhook-secret; the Terrateam chart has the same values in five Secrets.
Keep provisionDatabase off; its init container changes the password of the bridge users, which are now the application role. If the application role does not have CREATEROLE, create the two roles as shown in Database.
Move the Ingress host to the Service of the Stategraph release.
To go back to Terrateam, scale the Stategraph deployment to zero and the Terrateam server to one. Do not run helm uninstall terrateam while the Stategraph release uses its database.
Amazon ECS
The Stategraph module (terraform-aws-stategraph-ecs) is a second stack that uses the RDS instance of the Terrateam module (terraform-aws-terrateam).
- Make a snapshot of the RDS instance.
- Create the
stategraphdatabase on the RDS instance, withterrateamas the owner. Runpsqlfrom inside the VPC, for example as a one-off Fargate task. aws ecs update-service --cluster <name> --service <name> --desired-count 0- Apply the Stategraph module:
module "stategraph" {
source = "stategraph/stategraph-ecs/aws"
vpc_id = var.vpc_id
public_subnet_ids = var.public_subnet_ids
private_subnet_ids = var.private_subnet_ids
domain_name = "stategraph.example.com" # the Terrateam domain
certificate_arn = var.certificate_arn
license_key = var.license_key
create_database = false
external_database_host = "<terrateam RDS host>"
external_database_port = 5432
external_database_name = "stategraph"
external_database_username = "terrateam"
external_database_password = var.terrateam_db_password
extra_environment = [
{ name = "STATEGRAPH_ORCHESTRATION_ENABLED", value = "true" },
{ name = "TERRAT_DB_NAME", value = "terrateam" },
{ name = "STATEGRAPH_FDW_USER", value = "terrateam" },
{ name = "STATEGRAPH_FDW_PROVISIONER_USER", value = "terrateam" },
{ name = "GITHUB_APP_URL", value = "https://github.com/apps/<slug>" },
]
extra_secrets = [
{ name = "STATEGRAPH_FDW_PASSWORD", value_from = module.terrateam.secret_arns["db_password"] },
{ name = "STATEGRAPH_FDW_PROVISIONER_PASSWORD", value_from = module.terrateam.secret_arns["db_password"] },
{ name = "GITHUB_APP_ID", value_from = module.terrateam.secret_arns["github_app_id"] },
{ name = "GITHUB_APP_CLIENT_ID", value_from = module.terrateam.secret_arns["github_app_client_id"] },
{ name = "GITHUB_APP_CLIENT_SECRET", value_from = module.terrateam.secret_arns["github_app_client_secret"] },
{ name = "GITHUB_APP_PEM", value_from = module.terrateam.secret_arns["github_app_pem"] },
{ name = "GITHUB_WEBHOOK_SECRET", value_from = module.terrateam.secret_arns["github_webhook_secret"] },
]
}
resource "aws_vpc_security_group_ingress_rule" "stategraph_to_terrateam_rds" {
security_group_id = module.terrateam.rds_security_group_id
referenced_security_group_id = module.stategraph.security_group_ecs_id
ip_protocol = "tcp"
from_port = 5432
to_port = 5432
}
- Move the DNS record of the Terrateam domain to the Stategraph load balancer (output
alb_dns_name). - When the migration is final, remove
aws_db_instance.thisfrom the Terrateam state withterraform state rm, then destroy the Terrateam stack.
To go back to Terrateam before step 6, move the DNS record back and scale the Terrateam service up.
After the start
- Open the old URL and create the first instance admin in the setup screen. With Google or OIDC sign-in, the first person who signs in becomes the instance admin.
- Open Getting started, then Connect GitHub, and link each installation to a tenant. With the API:
PUT /api/v1/tenants/{tenant_id}/vcs-installations/github/{installation_core_id}, with the ids fromGET /api/v1/vcs-installations/github/unclaimed. For a GitLab group, usegitlabas the provider and thecore_idfrom thegitlab_installations_maptable. - Open Orchestration. It shows the runs from before the migration.
- Open a pull request. The plan runs with the same workflow. Pull requests that were planned before the migration keep their plans.
Users of the Terrateam console must sign in again.
Go back to Terrateam
The Terrateam image starts on the migrated database while the migrations table of the Terrateam database has no name that the image does not know. A Stategraph release that adds a Terrateam migration closes this window. Then restore the backup, and start the Terrateam image.
On Docker Compose, create the Terrateam container again with docker compose up -d --force-recreate server.