Swiss-army toolbox for Kubernetes initContainers.
Initium replaces fragile bash scripts in your initContainers with a single, security-hardened, multi-tool binary. Wait for dependencies, seed databases, render config files, fetch secrets, and more — all with structured logging, retries, and safe defaults.
- Single static binary — zero runtime dependencies, built
FROM scratch - Tiny image — ~5 MB multi-arch container (amd64 + arm64)
- Zero CVEs — no OS packages, no shell, no attack surface
- PSA
restrictedcompatible — runs as non-root (UID 65534), read-only filesystem, all capabilities dropped - Sidecar mode —
--sidecarflag keeps the process alive for use as a Kubernetes sidecar container - Structured logging — JSON or text output with automatic secret redaction
- Retries with backoff — exponential backoff, jitter, and configurable deadlines on all network operations
- Declarative database seeding — YAML/JSON specs with MiniJinja templating, cross-table references, and idempotency
- Multi-database support — PostgreSQL, MySQL, and SQLite drivers (optional Cargo features)
- Environment variable config — all flags configurable via
INITIUM_*env vars
initContainers:
- name: wait-for-postgres
image: ghcr.io/kitstream/initium:latest
args:
- wait-for
- --target
- tcp://postgres:5432
- --timeout
- "120s"
securityContext:
runAsNonRoot: true
runAsUser: 65534
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]kubectl apply -f https://raw.githubusercontent.com/kitstream/initium/main/examples/nginx-waitfor/deployment.yaml| Bash scripts | Initium | |
|---|---|---|
| Retries with backoff | DIY, error-prone | Built-in, configurable |
| Structured logging | echo statements |
JSON or text with timestamps |
| Security | Runs as root, full shell | Non-root, no shell, read-only FS |
| Secret handling | Easily leaked in logs | Automatic redaction |
| Multiple tools | Install curl, netcat, psql… | Single small image |
| Reproducibility | Shell differences across distros | Single Rust binary, FROM scratch |
| Vulnerability surface | Full OS + shell utils | Zero OS packages |
| Command | Description | Status |
|---|---|---|
wait-for |
Wait for TCP/HTTP/HTTPS endpoints | ✅ Available |
seed |
Structured database seeding from YAML/JSON with MiniJinja templating | ✅ Available |
render |
Render config templates | ✅ Available |
fetch |
Fetch secrets/config from HTTP | ✅ Available |
exec |
Run commands with structured logging | ✅ Available |
# Wait for a TCP endpoint
initium wait-for --target tcp://postgres:5432
# Wait for an HTTP health check
initium wait-for --target http://api:8080/healthz
# Wait for multiple endpoints
initium wait-for \
--target tcp://postgres:5432 \
--target tcp://redis:6379 \
--target http://config:8080/healthz
# HTTPS with self-signed certificates
initium wait-for --target https://vault:8200/v1/sys/health --insecure-tlsDatabase drivers are optional Cargo features, all enabled by default. Disable unused drivers for a smaller binary:
# All drivers (default)
cargo build --release
# PostgreSQL + SQLite only (no MySQL)
cargo build --release --no-default-features --features postgres,sqlite
# SQLite only (smallest binary)
cargo build --release --no-default-features --features sqlite| Feature | Default | Description |
|---|---|---|
sqlite |
✅ | SQLite driver |
postgres |
✅ | PostgreSQL driver |
mysql |
✅ | MySQL/MariaDB driver |
The Helm chart makes it easy to inject Initium initContainers into your deployments.
helm install my-app charts/initium \
--set sampleDeployment.enabled=true \
--set 'initContainers[0].name=wait-for-db' \
--set 'initContainers[0].command[0]=wait-for' \
--set 'initContainers[0].args[0]=--target' \
--set 'initContainers[0].args[1]=tcp://postgres:5432'See charts/initium/values.yaml for all options.
Initium is designed to run in security-restricted environments:
- Non-root: Runs as UID 65534 (nobody)
- Read-only filesystem: Compatible with
readOnlyRootFilesystem: true - No capabilities: Drops all Linux capabilities
- No shell: Commands executed via
execve, not through a shell - Secret redaction: Sensitive values automatically redacted in logs
- Minimal image: Built
FROM scratch— zero OS packages, zero CVEs - PSA
restricted: Fully compatible with the Kubernetes restricted Pod Security Standard
See docs/security.md for the full threat model and SECURITY.md for vulnerability reporting.
initContainers:
- name: wait-for-postgres
image: ghcr.io/kitstream/initium:latest
args: ["wait-for", "--target", "tcp://postgres:5432", "--timeout", "120s"]Initium will retry connecting to postgres:5432 with exponential backoff until it succeeds or the timeout is reached.
Pass multiple --target flags. They are checked sequentially:
args:
- wait-for
- --target
- tcp://postgres:5432
- --target
- tcp://redis:6379
- --target
- http://config-service:8080/healthzUse the seed subcommand with a YAML/JSON spec file that defines your seed data declaratively:
initContainers:
- name: seed-data
image: ghcr.io/kitstream/initium:latest
args: ["seed", "--spec", "/seeds/seed.yaml"]
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
volumeMounts:
- name: seed-specs
mountPath: /seeds
readOnly: trueSee docs/seeding.md for the full schema, features, and examples.
Use the render subcommand with environment variable substitution:
initContainers:
- name: render-config
image: ghcr.io/kitstream/initium:latest
args: [
"render",
"--template",
"/templates/app.conf.tmpl",
"--output",
"app.conf",
"--workdir",
"/work",
]
env:
- name: DB_HOST
value: postgresUse the --sidecar global flag to keep the process alive after tasks complete:
containers:
- name: initium-sidecar
image: ghcr.io/kitstream/initium:latest
restartPolicy: Always
args: ["--sidecar", "wait-for", "--target", "tcp://postgres:5432"]The process sleeps indefinitely after success. On failure it exits with code 1 immediately.
Add the --json global flag:
args: ["--json", "wait-for", "--target", "tcp://postgres:5432"]Output: {"time":"2025-01-15T10:30:00Z","level":"INFO","msg":"target is reachable","target":"tcp://postgres:5432","attempts":"1"}
Use --insecure-tls (must be explicitly opted in):
args: [
"wait-for",
"--target",
"https://vault:8200/v1/sys/health",
"--insecure-tls",
]Yes. Initium is a standalone binary. Use it in Docker Compose, CI pipelines, or anywhere you need to wait for services:
docker run --rm ghcr.io/kitstream/initium:latest wait-for --target tcp://db:5432No. Initium runs as a non-root user with no capabilities and a read-only filesystem. It is compatible with the Kubernetes restricted Pod Security Standard.
All retry parameters are configurable:
args:
- wait-for
- --target
- tcp://postgres:5432
- --max-attempts
- "30"
- --initial-delay
- "500ms"
- --max-delay
- "10s"
- --backoff-factor
- "1.5"
- --jitter
- "0.2"- nginx-waitfor: Nginx deployment waiting for a backend service
- postgres-seed: Wait → Seed workflow with PostgreSQL
- config-render: Render config from templates before app starts
# Build
make build
# Run wait-for against a local service
./bin/initium wait-for --target tcp://localhost:5432 --max-attempts 5
# Run with JSON logs
./bin/initium --json wait-for --target http://localhost:8080/healthz
# Run all tests
make test# Option 1: Use the pre-built image
kubectl apply -f examples/nginx-waitfor/deployment.yaml
# Option 2: Cross-build and push multi-arch images
make docker-multiarch VERSION=dev
# Option 3: Use the Helm chart
helm install my-app charts/initium \
--set sampleDeployment.enabled=true \
--set 'initContainers[0].name=wait-db' \
--set 'initContainers[0].command[0]=wait-for' \
--set 'initContainers[0].args[0]=--target' \
--set 'initContainers[0].args[1]=tcp://postgres:5432'Initium was built to address limitations in existing init container tools:
| Tool | Language | Image size | Multi-tool | Database seeding | Security posture |
|---|---|---|---|---|---|
| Initium | Rust | ~5 MB | Yes | Yes | PSA restricted, no OS |
| wait-for-it | Bash | Needs shell | No | No | Requires shell + netcat |
| dockerize | Go | ~17 MB | Partial | No | Full OS image |
| k8s-wait-for | Bash | Needs shell | No | No | Requires shell + kubectl |
| wait4x | Go | ~12 MB | No | No | Minimal OS |
If you only need TCP/HTTP readiness checks, any of these tools work. Initium is designed for teams that also need seeding, config rendering, and secret fetching in a single security-hardened binary.
- FAQ — Common questions about functionality, security, and deployment
- Usage Guide — All subcommands, flags, and examples
- Security — Threat model, safe defaults, PSA compatibility
- Architecture & Design — How Initium works and how to extend it
- Rust toolchain with musl targets:
rustup target add x86_64-unknown-linux-musl aarch64-unknown-linux-musl
- Zig for cross-compilation:
brew install zig - cargo-zigbuild:
cargo install cargo-zigbuild - (Optional) sccache for build caching across worktrees:
brew install sccache export RUSTC_WRAPPER=sccache
make cross-build
file bin/initium-amd64 bin/initium-arm64make docker-multiarch VERSION=dev IMAGE=ghcr.io/kitstream/initiumThis runs cross-build then uses docker buildx to assemble and push multi-arch images for both initium (scratch) and initium-jyq (alpine + jq/yq).
Contributions are welcome! See CONTRIBUTING.md for build instructions, test commands, and PR expectations. See the design doc for how to add new subcommands.