Skip to main content

Kubernetes deployment with Argo CD

aidj-gitops is the deployment repository. Its manifests/ Kustomize application targets namespace prochain-aidj on the existing microk8s cluster. The Argo CD project restricts the application to that repository and namespace. Automatic synchronization and self-healing are enabled; automatic pruning is disabled. Persistent volume claims additionally opt out of pruning/deletion.

Services

ComponentDeploymentAccess
Rust API / offline B2B labaidj-apiCluster service on 8787; browser requests proxied through the UI gateway
Next.js UI and gatewayaidj-uiadmin.bitview.club
Documentationaidj-docscheckpoint.bitview.club
Four virtual CDJscdj1 through cdj4Internal authenticated HTTP services on 8788
Shared virtual mixermixerInternal authenticated HTTP service on 8788
Rust analyzeraidj-analyzerSuspended CronJob template; explicit one-track Jobs
MongoDBExisting serviceExisting database prochain_aidj, scoped runtime credentials
QdrantExisting nexus-qdrant serviceCollection prochain_aidj_tracks_v1
RabbitMQrabbitmq StatefulSet in prochain-rabbitmqPrivate AMQP on 5672; queue runbook

The UI image uses relative /api/v1 and /api/v1/ws URLs. The gateway forwards those paths to the API and preserves WebSocket upgrades; Next.js continues serving its own /api/live-clubs routes. In the deployed Keycloak environment, all pages connect through the authenticated gateway without a browser connection token. Explicit operator tokens and signed cookies remain available only for standalone local development. Cross-origin/cross-site controls are rejected, and token rotation invalidates sessions. Anonymous loopback mode is retained only when remote operator authentication is not configured.

Images are built from the application repositories, pushed to the private Harbor project prochain-aidj, and referenced by digest in GitOps. Argo CD reads a Kubernetes repository Secret. The GitHub repository disallows deploy keys; the initial bootstrap uses the current GitHub CLI credential in that Secret. Replace it with a suitably scoped GitHub App/HTTPS credential for long-term operations. No application, registry, Mongo or Qdrant credential is stored in Git.

Storage and analysis

aidj-data holds imported originals, canonical PCM, session artifacts and exports. aidj-models holds the separately provisioned ONNX runtime and optional research weights. Both use microk8s-hostpath on the current single node. These are local persistent volumes, not replicated storage or backups.

The initial migration copies the existing imported assets, not the entire Windows source library. The 6,005-file source inventory still points at D:\_Music\_DJ_Deck_Main (/mnt/d/_Music/_DJ_Deck_Main in WSL) and remains paused. Whole-library ingestion in Kubernetes requires a mounted or copied music source with a cluster-valid path; do not resume that source inside a pod before provisioning it. The imported tracks can already be inspected, played, analyzed and indexed from the shared data volume.

Research voice/genre/mood weights retain their separate licensing requirements and are not included in Git or application images. The runtime shared libraries and notices are copied alongside them. The analyzer's scheduled template is suspended and only reports source status by default. The GitOps helper creates a bounded Job:

python3 tools/analyze-track.py TRACK_UUID
# Or refresh only the derived index, without decoding/inference:
python3 tools/analyze-track.py TRACK_UUID --index-only

A full analysis Job runs analyzerd analyze and then index-tracks for that one UUID. It does not drain or unpause the library queue. Inspect Job logs and the resulting immutable report before approving track analysis.

Booth boundary

The cluster deployment runs the four HTTP player services and one shared mixer. It does not automatically reproduce the earlier Hyper-V/macvlan PRO DJ LINK LAN setup. Kubernetes pod networking is not a broadcast LAN for physical rekordbox/CDJs. Physical discovery, separate device IP/MAC identities and physical mixer audio outputs need a dedicated network/audio deployment profile. The original VM booth remains stopped.

The live UI exposes this virtual cluster setup, while the offline planner and live four-player scheduling remain separate. No automatic AI session, physical hardware command or full-library analysis is started by deploying these services.

Operations

kubectl -n argocd get application prochain-aidj
kubectl -n prochain-aidj get deployments,pods,services,pvc,cronjobs
kubectl -n prochain-aidj logs deployment/aidj-api

Bootstrap/recovery instructions and the exact resource definitions live in the GitOps repository. Use a Git commit to update image digests or configuration. Roll back by reverting that commit. Runtime Secrets must be provisioned separately on a replacement cluster. Protect the data volume with backups before destructive maintenance; Argo pruning is not a backup strategy.

Admin sign-in and audio monitoring

The admin site requires Keycloak sign-in in the dedicated aidj realm at identity.bitview.club and the prochain-aidj-admin:admin client role. The documentation site remains public. OAuth2 Proxy runs beside the UI and protects pages, APIs, WebSockets and audio. Both the ingress and the old UI NodePort target this proxy; the Next.js server and gateway bind only to loopback inside their pod.

The OIDC client uses an exact HTTPS callback and authorization code flow with PKCE S256. It does not enable password grants or self-registration. The existing realm's login policy is unchanged. Credentials are in the aidj-oidc Kubernetes Secret, outside Git. The GitOps repository contains the client specification and an explicit tools/configure-keycloak.py --realm aidj --user alexl helper for granting existing users the dedicated role. See its deployment manifest for the selected realm; roles and credentials are bootstrapped, not reconciled by Argo.

SSO cookies are Secure, HttpOnly and host-only, with an eight-hour expiry and five-minute refresh. Role revocation takes effect on a subsequent refresh; existing open connections may continue until closed. /oauth2/sign_out clears the application's SSO cookie but does not end the Keycloak session for other applications. Engine tokens remain server-side; users do not enter them after Keycloak sign-in.

After signing in, open Live Clubs, select your booth, and click Listen to master. The stream plays through the browser's selected local speakers at an initial monitor volume of 25%. A track must be loaded and playing, with channel and master levels above zero. Browser buffering adds delay, so this monitor is not a sample-synchronized cue output.

The initial operator is aidj / alexl. The new account requires a password change at first login. Self-registration and email password reset are disabled; later password resets are performed by a Keycloak administrator. No existing realm account password was changed or copied.

Personal libraries and shared booths

Sign-in opens the provisioned booth under Live clubs. User profiles and booth access live in MongoDB. User identity is the Keycloak issuer plus subject, so changing a username does not transfer data ownership. The original music library and Festival B2B setup belong to aidj/alexl. Additional admitted users receive a private library/API and their own four-CDJ/shared-mixer runtime. Source music is not copied into other accounts automatically.

Booth rolePermissions
OwnerManage members and DJ positions; control all decks and mixer
DJLoad own-library tracks and control the assigned two decks; shared mixer access while assigned
ListenerView the booth and listen to master audio

Owners use Booth members and DJ positions to invite a username after that person has signed in once, grant a role, assign DJ A/B, or revoke access. Each position can be human or AI, representing human–human, human–AI and AI–AI sessions. Assigning an AI position does not start live autonomous scheduling; the existing AI planner runs in the offline B2B lab. Owners may manually override all decks.

Access checks run server-side for every booth read, load, command and permission change. Changing membership never shares a personal library or session archive. Active listener streams recheck membership every three seconds. Concurrent access changes require the current revision, and MongoDB records an audit entry.

Per-user runtimes isolate metadata with Mongo collection prefixes, use dedicated Qdrant collections, and store assets under separate PVC subdirectories. These application-managed workloads come from the GitOps runtime template. Existing runtimes require an explicit image update; user deletion does not automatically delete music, Mongo metadata, credentials or Kubernetes workloads. See the GitOps README for provisioning permissions, backups and coordinated key rotation.