Configuration
Client config, daemon config, and the contract every app repo must satisfy.
Client config
The CLI reads ~/.stackcube/client.yml on every invocation. stackcube init writes it; you can also edit it by hand.
server: paas.example.com:9090
identity: ~/.ssh/id_ed25519
tls: true
Fields
server(string) — daemon address ashost:port. Default written bystackcube init:localhost:9090.identity(string) — path to the SSH private key used to authenticate. Default:~/.ssh/id_ed25519.tls(bool) — whether to dial with TLS. Required when the daemon sits behind a reverse proxy like Caddy;falsefor plain-text local connections. Default:false.
If the file is missing, the CLI prints client not configured — run 'stackcube init' first and exits.
Daemon config
The daemon reads <data-dir>/config.yml on startup, where <data-dir> defaults to ~/.stackcubed. If the file is absent, the daemon uses defaults — most installations only need to override fields if the host already uses port 9090 or a non-default Docker setup.
# ~/.stackcubed/config.yml
port: 9090
repos_dir: ~/.stackcubed/repos
deploy_dir: ~/.stackcubed/deploy
network: stackcube-net
port_range_start: 8080
compose_command: ""
docker_socket: ""
daemon_domain: paas.example.com
Fields
port(int) — gRPC server port the daemon listens on. Default:9090.repos_dir(string) — directory holding bare git repos for each app. Default:<data-dir>/repos.deploy_dir(string) — working directory the daemon checks out commits into and runsdocker composefrom. Default:<data-dir>/deploy.network(string) — Docker network apps are attached to so the front proxy can route to them by container name. Default:stackcube-net.port_range_start(int) — starting host port for app auto-allocation. The daemon hands out ports from here upward. Default:8080.compose_command(string) — override for thedocker composebinary. Empty means autodetect (docker composeordocker-compose). Default: empty.docker_socket(string) — override for the Docker socket path. Empty means use the default for the platform. Default: empty.daemon_domain(string) — the domain the bundledstackcube-proxyCaddy container listens on and reverse-proxies to the daemon's gRPC port. Set bystackcubed init --domain. Default: empty.
Unset fields fall back to the defaults above — you can keep the file minimal and only list the values you need to change.
App repo contract
Every app repo deployed to StackPaaS must satisfy these rules. stackcube lint checks them; stackcube deploy runs lint first and refuses to deploy on errors.
Required files
compose.ymlordocker-compose.ymlat the repo root..envat the repo root definingAPP_PORT— the port your app listens on inside its container.- A
Dockerfile(or any image-building setup the compose file references).
Compose service shape
Every service must set container_name (the daemon routes traffic by container name) and publish its port via the daemon-injected ${HOST_PORT}:
services:
web:
container_name: my-api
build: .
env_file: .env
ports:
- "${HOST_PORT}:${APP_PORT}"
restart: unless-stopped
# .env
APP_PORT=3000
At deploy time, the daemon injects HOST_PORT with the host port allocated for the app, so the published port mapping resolves to <allocated-port>:3000.
stackcube scaffold, which generates both files using the conventions above.
Networking
Containers are attached to stackcube-net (or whatever network is set to in the daemon config). Apps that need to talk to each other can resolve each other by container name on this network. The daemon handles attachment automatically — you don't declare the network in the app's compose file.