Kinotic
Kinotic OS

Deployment Guide

Deploying and operating Kinotic OS in various environments.
Detailed deployment guide coming soon.

Overview

Kinotic OS deploys to Kubernetes and provides several deployment configurations for different environments.

Deployment Options

Helm Charts

Production-ready Helm charts are available in deployment/helm/ for deploying:

  • Kinotic servers — deployment/helm/kinotic: the org, system and app servers in one release, each a Deployment, Service and ConfigMap of its own with its replicas, resources, service type and TLS certificate, and the migration Job that precedes them. Every server's pods join one headless Service, through which Ignite discovers its peers, so the three form one cluster, and each server signs tokens with a JWT key set of its own, <server>-jwt-signing-keys
  • Elasticsearch — Search and persistence cluster
  • Load Generator — For performance testing

Each server mounts a platform-secrets volume, projected from the global Key Vault. It holds the server's JWT key set and the secrets the server imports as properties when it starts, each file named after the property it sets:

FileKey Vault secretMounted on
jwt-signing-keys<server>-jwt-signing-keyseach server, its own key set
kinotic.domain.secretStorage.masterKeykinotic-secret-storage-master-keyevery server
kinotic.managementApi.github.appPrivateKeykinotic-github-app-private-keythe servers with githubApp set: the org and system servers, which load management-api
kinotic.managementApi.github.webhookSecretkinotic-github-webhook-secretthe same
kinotic.domain.publishedSites.cloudflare.apiTokenkinotic-cloudflare-dns-api-tokenthe servers with cloudflareDns set: the management and system servers, which create an organization's sites record
kinotic.managementServer.turnstile.secretKeykinotic-turnstile-secret-keythe server with turnstile set: the management server, which verifies the find-my-organizations challenge

kinotic.domain.secretStorage.backend selects where SecretStorageService persists secrets. IN_MEMORY, the default, keeps them in process memory, so a restart loses every stored secret. AZURE stores them in the Key Vault at kinotic.domain.secretStorage.azure.vaultUrl; that backend is an Enterprise Feature in the kinotic-ee module, which the org, system and app servers include, and its production use needs a Kinotic Enterprise License agreement with Minds Ignited (see Enterprise License). A server configured with a backend whose module is not on its classpath fails at startup.

A server picks up a rotated JWT key set while it runs, and an imported secret when it restarts. On Azure the global terraform seeds the master key and takes the GitHub App's key and webhook secret from TF_VAR_github_app_private_key and TF_VAR_github_webhook_secret.

Docker Compose (Local Development)

A Docker Compose configuration in deployment/docker-compose/ provides a complete local development environment including the org, system and app servers (compose.kinotic-servers.yml), Elasticsearch, and supporting services. This is the recommended way to run Kinotic OS during development.

Development Server

A single-host development environment on Proxmox — a container per service, the three servers behind an edge that routes the one forwarded port by SNI, three Elasticsearch nodes on their own disks, and Cloud Hypervisor nodes on machines of their own — that keeps the sites account and email in Azure, the sites on Cloudflare, and is designed to migrate its organizations to Kinotic Cloud. See Development Server.

Cloud Providers (Terraform)

Terraform configurations in deployment/terraform/ support deployment to:

  • AWS — EC2-based deployment with configurable instance types
  • Azure — VM-based deployment on Azure infrastructure

UI sites on Cloudflare

Published UIs live on the customer domain, a Cloudflare zone (kinotic.io) separate from the platform's own, so that no customer content is ever under the domain the portal's cookies live on. sites.tf calls deployment/terraform/azure/modules/sites for the sites storage account st<prefix>sites every site's files live in under sites/<hostname>/, private, with a read-only SAS on its container minted for the edge; cloudflare.tf calls modules/cloudflare-sites for the edge, once per environment: the zone's settings (Full (strict), HTTPS only, TLS 1.2) and Total TLS, the proxied records apps-api.<zone> and *.apps-api.<zone> to the app server's load balancer, and the sites Worker (deployment/cloudflare/sites-worker) bound to *.<zone>/*, with the apps-api hosts bound to no Worker so API calls and WebSockets reach the app server directly. A site is <app>--<ui>.<org>.<zone>; the Worker reads it from the account and serves a route of the single-page application its index. Nothing is created per application, UI or tenant.

Per organization, two proxied records are created, and the platform creates them: the wildcard *.<org>.<zone> for its sites and <org>.<zone> for its own host, at sign-up (the management server) or before the organization's first publish (the system server), through CloudflareOrganizationDnsRecordProvisioner with a token holding DNS edit on the zone and nothing else, which the global root stores in the platform vault as kinotic-cloudflare-dns-api-token. Total TLS issues the organization's certificate from the record within minutes, and <org>.<zone> itself, covered by the zone's universal certificate, redirects to the portal's login for the organization. The app server's names in the zone are on the cluster certificate: cert-manager answers their DNS-01 challenges through Cloudflare with the same token (tls.tf), so Full (strict) validates the origin.

The portal's find-my-organizations form presents a Cloudflare Turnstile challenge, and the management server verifies each request's token: the global root stores the site's secret key in the platform vault as kinotic-turnstile-secret-key (TF_VAR_turnstile_secret_key), and the cluster root passes the site key as turnstile_site_key, which Helm hands the management server as kinotic.managementServer.turnstile.siteKey. The site is created in the Cloudflare dashboard under Turnstile, for the portal's hostname.

kinotic.tf passes the zone as the sites domain and the account's blob endpoint to the system server as KINOTIC_SYSTEMAPI_UIDEPLOYMENT_*, the app server's apps-api.<zone> base, and the KINOTIC_DOMAIN_PUBLISHEDSITES_* settings every server provisions organizations with (see Configuration). The cluster root takes the zone's id, the account id and two tokens as variables: the operator's, which terraform applies the zone and the Worker with, and the DNS token. The system server's development profile disables the provisioner instead.

A developer machine gets the same modules from deployment/terraform/azure/dev, under <environment>.<zone>. The contributing guide walks through it.

Copyright © 2026