Skip to content

Repository files navigation

Initium

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.

CILicense

Features

  • 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 restricted compatible — runs as non-root (UID 65534), read-only filesystem, all capabilities dropped
  • Sidecar mode--sidecar flag 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

Quickstart

Wait for Postgres before starting your app

initContainers:
- name: wait-for-postgresimage: ghcr.io/kitstream/initium:latestargs:
- wait-for
- --target
- tcp://postgres:5432
- --timeout
- "120s"securityContext:
runAsNonRoot: truerunAsUser: 65534readOnlyRootFilesystem: trueallowPrivilegeEscalation: falsecapabilities:
drop: [ALL]

Apply a full example

kubectl apply -f https://raw.githubusercontent.com/kitstream/initium/main/examples/nginx-waitfor/deployment.yaml

Why Initium?

Bash scriptsInitium
Retries with backoffDIY, error-proneBuilt-in, configurable
Structured loggingecho statementsJSON or text with timestamps
SecurityRuns as root, full shellNon-root, no shell, read-only FS
Secret handlingEasily leaked in logsAutomatic redaction
Multiple toolsInstall curl, netcat, psql…Single small image
ReproducibilityShell differences across distrosSingle Rust binary, FROM scratch
Vulnerability surfaceFull OS + shell utilsZero OS packages

Subcommands

CommandDescriptionStatus
wait-forWait for TCP/HTTP/HTTPS endpoints✅ Available
seedStructured database seeding from YAML/JSON with MiniJinja templating✅ Available
renderRender config templates✅ Available
fetchFetch secrets/config from HTTP✅ Available
execRun commands with structured logging✅ Available

wait-for

# 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-tls

Cargo Features

Database 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
FeatureDefaultDescription
sqliteSQLite driver
postgresPostgreSQL driver
mysqlMySQL/MariaDB driver

Helm Chart

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.

Security

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.

FAQ

How do I wait for Postgres?

initContainers:
- name: wait-for-postgresimage: ghcr.io/kitstream/initium:latestargs: ["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.

How do I wait for multiple services?

Pass multiple --target flags. They are checked sequentially:

args:
- wait-for
- --target
- tcp://postgres:5432
- --target
- tcp://redis:6379
- --target
- http://config-service:8080/healthz

How do I seed data?

Use the seed subcommand with a YAML/JSON spec file that defines your seed data declaratively:

initContainers:
- name: seed-dataimage: ghcr.io/kitstream/initium:latestargs: ["seed", "--spec", "/seeds/seed.yaml"]env:
- name: DATABASE_URLvalueFrom:
secretKeyRef:
name: db-credentialskey: urlvolumeMounts:
- name: seed-specsmountPath: /seedsreadOnly: true

See docs/seeding.md for the full schema, features, and examples.

How do I render config templates?

Use the render subcommand with environment variable substitution:

initContainers:
- name: render-configimage: ghcr.io/kitstream/initium:latestargs: ["render","--template","/templates/app.conf.tmpl","--output","app.conf","--workdir","/work",]env:
- name: DB_HOSTvalue: postgres

How do I run initium as a sidecar container?

Use the --sidecar global flag to keep the process alive after tasks complete:

containers:
- name: initium-sidecarimage: ghcr.io/kitstream/initium:latestrestartPolicy: Alwaysargs: ["--sidecar", "wait-for", "--target", "tcp://postgres:5432"]

The process sleeps indefinitely after success. On failure it exits with code 1 immediately.

How do I get JSON logs?

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"}

How do I allow self-signed TLS certificates?

Use --insecure-tls (must be explicitly opted in):

args: ["wait-for","--target","https://vault:8200/v1/sys/health","--insecure-tls",]

Can I use Initium outside Kubernetes?

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:5432

Does Initium need special permissions?

No. 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.

How do I customize retry behavior?

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"

Examples

How to Run Locally

# 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

How to Try in a Cluster

# 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'

Alternatives

Initium was built to address limitations in existing init container tools:

ToolLanguageImage sizeMulti-toolDatabase seedingSecurity posture
InitiumRust~5 MBYesYesPSA restricted, no OS
wait-for-itBashNeeds shellNoNoRequires shell + netcat
dockerizeGo~17 MBPartialNoFull OS image
k8s-wait-forBashNeeds shellNoNoRequires shell + kubectl
wait4xGo~12 MBNoNoMinimal 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.

Documentation

  • 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

Development

Prerequisites

  • 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

Cross-compile for linux/amd64 and linux/arm64

make cross-build
file bin/initium-amd64 bin/initium-arm64

Build and push multi-arch Docker images

make docker-multiarch VERSION=dev IMAGE=ghcr.io/kitstream/initium

This runs cross-build then uses docker buildx to assemble and push multi-arch images for both initium (scratch) and initium-jyq (alpine + jq/yq).

Contributing

Contributions are welcome! See CONTRIBUTING.md for build instructions, test commands, and PR expectations. See the design doc for how to add new subcommands.

License

Apache License 2.0

Releases

Packages

Contributors

Languages