The platform test environment gives every engineer their own vCluster with the full Grounds stack — Velocity proxy, plugins, lobby, gamemodes, gRPC services — running against shared backends (NATS, Postgres, Keycloak) over the service-tailnet. You override only the components you’re actively working on, leave everything else on the bundle’s defaults, and iterate with DevSpace’s hot-reload loop.Documentation Index
Fetch the complete documentation index at: https://docs.grounds.gg/llms.txt
Use this file to discover all available pages before exploring further.
A bundle is a versioned, curated list of platform components and their default versions. You pin against a bundle release (for reproducible CI runs) or against the current edge (for daily iteration). The full schema is documented under Bundle Reference.
TL;DR
1. Prerequisites
| Tool | Why | Install |
|---|---|---|
| Tailscale | NATS / Postgres / Keycloak are exposed only over the internal Grounds tailnet (authorized engineers only) | tailscale up, accept nats.dev / postgres.dev / keycloak.dev MagicDNS routes after you’ve been added to the tailnet |
| kubectl | Hand-debug pods inside your vCluster | brew install kubectl |
| helm | Occasional raw helm + DevSpace templates do kubectl rollout restart | brew install helm |
| devspace | The hot-iteration loop | brew install devspace |
| gradle + JDK 25 | Building plugin / service JARs locally | brew install gradle openjdk@25 |
| grounds-cli | Control plane for your workspace | See CLI installation |
*.dev.
2. Bootstrap your vCluster
Ensure host namespace
A per-engineer host namespace
vcluster-<handle> (privileged PSA) is created if missing.Install vCluster
helm install of loft/vcluster, idempotent — re-runs are no-ops if the vCluster already exists.Wait for vCluster API
The reconciler polls until the inner API is up and pulls its kubeconfig out of a Secret.
Resolve bundle
The forge service fetches
bundle.yaml @ 0.4.0 and merges it with your override file (if any) into a concrete component list.grounds cluster up --bundle 0.4.0 after fixing the cause and the reconciler picks up where it left off.
3. Get your vCluster’s kubeconfig
For rawkubectl / helm / devspace access to the inner cluster, the kubeconfig lives in a Secret on the host namespace:
default namespace inside the vCluster is your stack.
A first-class
grounds cluster kubeconfig subcommand is planned but not yet shipped — for now the manual fetch above is the supported path.4. Override a component
Without overrides, every component runs the released image at the version pinned by the bundle. To swap one for your local code, write an override file:overrides/me.yaml
Override schema
| Mode | When | Required fields |
|---|---|---|
image (default) | Run the bundle’s default image | – |
image + tag: <X> | Same image, different tag | tag |
gradle-local | Local JAR sync | project, artifact, reload |
gradle-local + devspace: true | Quarkus dev mode | project |
enabled: false | Skip the component | – |
enabled: true | Turn on a default-off optional component | – |
5. Iterate on a component
The bundle’s per-componentdevspace.workflow field selects which template applies:
| Component-Type | DevSpace Workflow | Iter-Latency |
|---|---|---|
plugin-velocity | jar-sync-pod-restart (Velocity has no in-process hot-reload, so the pod is restarted) | ~10–20 s |
gamemode (Minestom/Paper) | jar-sync-pod-restart | ~10–20 s |
grpc-service (Quarkus) | quarkus-dev (Live-Reload sub-second) | ~1–3 s |
- Plugin / lobby / gamemode
- gRPC service
Use DevSpace will:
jar-sync-pod-restart:- Run
./gradlew buildlocally. - Sync the produced JAR into the plugin pod’s
/shared/plugin.jar. kubectl rollout restart deployment/velocity— Velocity’s init-containers re-fetch your JAR.- Watch
build/libs/and re-do all of the above on every change.
6. Inspect the event bus
The bundle has an opt-innats-recorder component that subscribes to chosen subjects and emits each message as JSONL on stdout — useful for debugging cross-service events without writing one-off subscribers.
grounds cluster up, tail it:
bundle.yaml (default: config.>, player.>, friends.>, match.>).
7. Tear down
down is cheap to reverse; delete requires re-running the bundle deploys from scratch. To swap one component out without losing state, use overrides — don’t delete.
8. Troubleshooting
forge says "chart not found" for a component
forge says "chart not found" for a component
The Helm chart for that component type isn’t published yet. The forge response’s
failed[] block tells you exactly which component and which chart URL failed. Either wait for the chart to be released or override the failing component with enabled: false so the rest of the stack still comes up.Pod stuck in Init waiting for fetch-<plugin>
Pod stuck in Init waiting for fetch-<plugin>
The
grounds-velocity chart’s init-containers curl each plugin’s Service at http://<plugin>:8080/plugin.jar. If a plugin pod isn’t ready (e.g. its image doesn’t exist or it’s still pulling), the velocity pod waits. kubectl get pods and look for the plugin pods that aren’t Running.DevSpace sync writes the JAR but Velocity doesn't pick it up
DevSpace sync writes the JAR but Velocity doesn't pick it up
The
jar-sync-pod-restart workflow assumes you set RESTART_TARGET=velocity for plugin-* components. Without the rollout-restart, Velocity keeps the old JAR loaded. Check the onUpload.execRemote block in your devspace.yaml.Tailscale can't resolve nats.dev / postgres.dev
Tailscale can't resolve nats.dev / postgres.dev
You’re not on the internal Grounds tailnet. This is a private network for authorized engineers — if you haven’t been invited yet, ask a maintainer. Once you’re on, run
tailscale status to confirm the routes; if they’re missing, re-run tailscale up accepting the dev-routes ACL.409 'cannot apply bundle to platform workspace'
409 'cannot apply bundle to platform workspace'
You already have a
profile=platform workspace from the older flow. The bundle workflow uses profile=platform-bundle and they’re not interchangeable. grounds cluster delete first, then re-up with --bundle.A component's helm-install errors after a successful first deploy
A component's helm-install errors after a successful first deploy
grounds cluster up --bundle X is idempotent and uses helm install/upgrade. If a chart’s values shape changed between bundle versions, a stale release can block the upgrade. Drop the specific component’s release inside the vCluster (helm uninstall <component> against the vCluster kubeconfig) and re-run cluster up.9. Reference
- Bundle Reference — every field of
bundle.yamland the override-file schema grounds-cli— CLI source + releasesgroundsgg/charts— public Helm charts referenced by bundlesgroundsgg/library-grpc-contracts— shared protobuf event schemas
