Running Instances

An instance is one MeshWeaver portal: its own domain, its own database, and its own sign-in, served by a dedicated Kubernetes namespace. Instances typically share one cluster, one container registry and one PostgreSQL server — only the namespace, domain and database differ, so a code change merged to main reaches all of them via self-update. They differ in data, branding, sign-in configuration, and who may log in.

Where an estate's instances are declared

Not in any doc. Every estate keeps its instances as DATA in a private configuration repository: one Hosting/Deployment record per instance, the GitSynced Spaces it serves, and the per-environment overlays and operations lanes that act on them. That repository is configuration — the actual data the instances keep — and is normally administered through the estate's control instance, not edited by hand. It is not a documentation source and not a module source: platform documentation lives here (Doc/Architecture) and in the module docs; code lives in the platform and plugin repositories. The live view is the control instance's Deployments board.

The rest of this page is the mechanism, and applies to any installation.

Shared platform (all cloud instances)

Piece Value
AKS cluster <aks-cluster> (RG <aks-resource-group>, swedencentral) — private cluster; kubectl only via az aks command invoke
Container registry meshweaver.azurecr.io (ACR), multi-arch images (amd64 + arm64)
Database server <pg-server> — private Azure PG Flexible Server 16 + pgvector, VNet-injected (one database per instance)
Workload identity One shared UAMI <portal-identity>, one federated credential per namespace, AcrPull on the ACR
App stack .NET 10 · Blazor Server · Orleans · Microsoft.Extensions.AI
Backups Managed PITR (14 days) + geo-redundant — see DatabaseBackups.md

Versioning — how to read the live version

Each instance runs the ACR image tag its in-pod self-updater last rolled to — the CI build number ci.<N>. To see what a namespace is actually running, open the Fleet Console (/Hosting/Console on the control instance): it shows the RUNNING version per instance next to the newest the self-updater has seen. The cluster read is the break-glass form (OperatingFromThePortal):

az aks command invoke -g <aks-resource-group> -n <aks-cluster> --command \
  "kubectl -n <namespace> get deployment memex-portal-deployment \
   -o jsonpath='{.spec.template.spec.containers[0].image}'"
# → meshweaver.azurecr.io/memex-portal-ai:ci.<N>

Self-update (the version channel)

Merge to main → CI builds a multi-arch image to ACR (ci.<N>) → each portal's in-pod self-updater polls ACR and patches its own Deployment to the new tag → migration Job runs → portal rolls. No manual step per instance. This is why a red main blocks the rollout for every instance, and why the merge gate requires green CI. Full model: ReleaseStrategy.md.

A manual code push to one instance (bypassing self-update) is a Roll Hosting/InstanceAction with the tag on the control instance; the operator runs the kubectl set image + rollout sequence of DeploymentAKS.md for you.

Instance lifecycle — creating and deleting instances

There is no "create instance" / "delete instance" button in the portal today. An instance is provisioned with the deploy tooling, not from the running app — the control instance is where you run that tooling (or drive it over MCP), not a control plane that spins up other instances.

Create a new instance — full runbook in OnboardingNewEnvironment.md:

  1. Add the namespace to portalNamespaces in deploy/aks/infra/main.bicep (creates its federated credential + AcrPull) and redeploy the identity module.
  2. Create the instance's database on the shared <pg-server> server.
  3. Author the env's values.<env>.yaml (host, MEMEX_DATABASENAME, TLS secret, AI + auth config, selfUpdate.azureClientId).
  4. Run the env's deploy.sh — helm install + PVCs + KV SecretProviderClass + ingress + TLS.

🚨 Env folders live in the estate's PRIVATE configuration repository, not under deploy/aks/envs/<env>/ — their directory names are tenant identities (see Where an estate's instances are declared). deploy/aks/envs/example/ in this repository is the reference template only.

  1. Wire sign-in redirect URIs + invitation/email config for the new domain.

Delete an instance:

  1. helm uninstall the release in its namespace, then delete the namespace (removes pods, PVCs, ingress, secrets).
  2. Drop (or archive-then-drop) the instance's database on <pg-server> — this is the only place its data lives, so back it up first (DatabaseBackups.md).
  3. Remove the namespace from portalNamespaces (drops its federated credential) and delete its DNS record + TLS cert + git-ignored envs/<env>/ config.

Turning the control instance into a real control plane (create / tear down instances from the UI, calling the Azure + Helm APIs behind an admin gate) is a possible future feature, not a current capability.

The admin Instances tab (control instance only)

Admin app (/Admin) ▸ Instances lists every portal on the cluster live from the k8s API — domain, namespace, running version (image tag), replica health — with per-instance Grafana/Loki log deep links and a guided create-instance plan generator (commands only; nothing deploys itself).

The tab exists only on the control instance, doubly gated:

Log links need Instances:GrafanaBaseUrl (Helm: instancesAdmin.grafanaBaseUrl) — the Grafana Explore (Loki) deep link is built per namespace. Empty until the in-cluster Grafana (monitoring ns, loki-grafana service) is exposed on a host.