Created
June 27, 2025 01:59
-
-
Save geekodour/a37f061af0801c842040d93b59c17c2a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env -S uv run --script | |
# /// script | |
# requires-python = ">=3.12" | |
# dependencies = [ | |
# "click", | |
# ] | |
# /// | |
# NOTE: This script creates a new virtual instance in ZITADEL. | |
# NOTE: Virtual instances are separated at the network level; there is no central UI to view them. | |
# See for more details: | |
# https://zitadel.com/docs/guides/integrate/zitadel-apis/access-zitadel-system-api | |
# https://zitadel.com/docs/apis/resources/system/system-service-create-instance | |
import http.client | |
import json | |
import os | |
import sys | |
import click | |
def create_zitadel_instance( | |
jwt_token, zitadel_url, instance_name, org_name, custom_domain, username, email | |
): | |
conn = http.client.HTTPSConnection(zitadel_url) | |
payload = json.dumps( | |
{ | |
"instanceName": instance_name, | |
"firstOrgName": org_name, | |
"customDomain": custom_domain, | |
"human": { | |
"userName": username, | |
"email": { | |
"email": email, | |
"isEmailVerified": True, | |
}, | |
"profile": { | |
"firstName": "Admin", | |
"lastName": "G", | |
}, | |
"password": { | |
"password": "dummyPASS0!", | |
"passwordChangeRequired": False, | |
}, | |
}, | |
} | |
) | |
headers = { | |
"Content-Type": "application/json", | |
"Accept": "application/json", | |
"Authorization": f"Bearer {jwt_token}", | |
} | |
try: | |
conn.request("POST", "/system/v1/instances/_create", payload, headers) | |
res = conn.getresponse() | |
data = res.read() | |
print(f"Status: {res.status} {res.reason}") | |
try: | |
print(json.dumps(json.loads(data.decode("utf-8")), indent=2)) | |
except json.JSONDecodeError: | |
print(data.decode("utf-8")) | |
except Exception as e: | |
print(f"An error occurred: {e}", file=sys.stderr) | |
finally: | |
conn.close() | |
@click.command(help="Create a new ZITADEL instance via the System API.") | |
@click.option( | |
"--instance-name", | |
required=True, | |
help="The name for the new ZITADEL instance (e.g., 'my-company').", | |
) | |
@click.option( | |
"--first-org-name", | |
required=True, | |
help="The name of the first organization within the new instance.", | |
) | |
@click.option( | |
"--custom-domain", | |
required=True, | |
help="The custom domain for the instance (e.g., 'auth.my-company.com').", | |
) | |
@click.option( | |
"--username", | |
required=True, | |
help="The username for the first instance administrator.", | |
) | |
@click.option( | |
"--email", required=True, help="The email for the first instance administrator." | |
) | |
def main(instance_name, first_org_name, custom_domain, username, email): | |
# Get sensitive data from environment variables | |
jwt_token = os.environ["NEW_INSTANCE_ZITADEL_JWT_TOKEN"] | |
zitadel_instance_url = os.environ["MAIN_ZITADEL_INSTANCE_URL"] | |
create_zitadel_instance( | |
jwt_token, | |
zitadel_instance_url, | |
instance_name, | |
first_org_name, | |
custom_domain, | |
username, | |
email, | |
) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment