kuber
kuber is Astral's internal Docker Compose to Kubernetes translation layer.
It reads a local Compose file, renders Kubernetes resources, applies them to the cluster, and can build images remotely from your working tree without requiring Docker on your machine.
What It Does
- Reads
compose.ymlordocker-compose.yml - Converts supported Compose services into Kubernetes resources
- Applies those resources into a namespace named after the current directory
- Turns
env_fileentries into Kubernetes Secrets and mounts them throughenvFrom - Translates file mounts into ConfigMaps and directory/volume mounts into PVC-backed volumes
- Builds images on the remote builder by syncing:
- committed git state
- tracked local diffs
- untracked files
- ignored
.env*files
- Supports host-based
portssyntax that renders KubernetesIngressrules - Supports managed Postgres claims through special pseudo-volumes such as
postgresql:app
Environment Assumptions
This tool is built for Astral's cluster and workstation setup. It is not intended to work unchanged outside that environment.
Expected local setup:
- Tailscale access to the remote builder and Kubernetes network
- a working
~/.kube/config sshavailable locally
Not required locally:
- Docker
kubectl
Docker is not required because builds happen on the remote builder after kuber syncs your repo state there. kubectl is not required because cluster access is handled through the bundled Kubernetes client.
Running
During development:
bun run index.ts up
Other useful commands:
bun run index.ts ps
bun run index.ts logs
bun run index.ts logs -f
bun run index.ts exec app sh
bun run index.ts start
bun run index.ts stop
bun run index.ts restart
bun run index.ts db ls
Commands
up: build images if needed, render manifests, apply them, restart deployments, and wait for rolloutstart: same asupbut skips image buildsstop: scale managed deployments to zerorestart: roll out a restart across managed deploymentsdown: delete managed resources while keeping ingress, PVCs, and managed databasesdown -f: also delete ingress, PVCs, managed database resources, and the namespaceps: list deployments in the current project namespacelogs [deployment]: print logs for one deployment or all managed deploymentslogs -f [deployment]: follow logs continuouslyexec <deployment> <command...>: execute a command inside a running deployment poddb ls: list managed Postgres claims declared in the current Compose filedb creds <service>: print the generated connection details for a managed Postgres claim
Compose Conventions
kuber supports a few project-specific Compose conventions on top of normal service translation.
Host-Based Ports
If a ports entry uses a hostname instead of a numeric published port, kuber treats it as an ingress host and routes traffic to the target container port.
Example:
services:
app:
ports:
- somedomain.astrxl.dev:3000
That produces a Kubernetes Ingress rule for somedomain.astrxl.dev pointing at the service port for container port 3000.
Managed Postgres
You can declare a managed Postgres database with a pseudo-volume:
services:
app:
volumes:
- postgresql:app
Or with an explicit username and database name:
services:
app:
volumes:
- postgresql:user/database
This creates or reuses the managed CNPG role secret, reconciles the database resource, and injects DATABASE_URL into the generated app secret in Kubernetes.
Environment Files
env_file entries are read locally and turned into a Kubernetes Secret named <service>-env. Deployments then consume that secret through envFrom.
This is also where generated values such as DATABASE_URL are injected.
Volumes
kuber treats different volume shapes differently:
- file bind mounts become ConfigMaps
- directory bind mounts become PVC-backed mounts
- named volumes become PVC-backed mounts
tmpfsbecomesemptyDirwith memory backingpostgresql:...is treated as a managed database claim, not as a filesystem mount
Building
To build distributable binaries:
bun run build.ts
If you only want a plain JavaScript bundle for quick local use in another workspace, build index.ts directly:
bun build index.ts --target bun --minify --sourcemap --outdir dist
Notes
- Resource names and namespaces are derived from the current working directory.
- The remote build flow is optimized for local iteration, not for producing a perfectly clean export of the repository.
- Managed database support is Kubernetes-only. It injects
DATABASE_URLinto the generated app secret and does not rewrite local.envfiles. kuberoperates on managed resources in the namespace matching the current directory name.