initium 1.0.4

Swiss-army toolbox for Kubernetes initContainers
initium-1.0.4 is not a library.

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, run migrations, render config files, fetch secrets, and more — all with structured logging, retries, and safe defaults.

CI License

Features

  • Single static binary — zero runtime dependencies, built FROM scratch
  • Tiny image — ~1.8 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-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]

Apply a full example

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

Why Initium?

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

Subcommands

Command Description Status
wait-for Wait for TCP/HTTP/HTTPS endpoints ✅ Available
migrate Run database migrations ✅ 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

# 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
Feature Default Description
sqlite SQLite driver
postgres PostgreSQL driver
mysql MySQL/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-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.

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

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

How do I run database migrations?

Use the migrate subcommand — it wraps your migration tool with structured logging:

initContainers:
  - name: migrate
    image: ghcr.io/kitstream/initium:latest
    args: ["migrate", "--", "flyway", "migrate"]
    env:
      - name: FLYWAY_URL
        value: "jdbc:postgresql://postgres:5432/mydb"

How do I render config templates?

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

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: Build and push your own image
make docker-build VERSION=dev
make docker-push 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:

Tool Language Image size Multi-tool Database seeding Security posture
Initium Rust ~1.8 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 migrations, 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

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