tino 0.1.24

tino: tiny init process (PID 1) for Docker/Kubernetes containers, written in Rust (tini alternative)
Documentation

tino is a tiny init process (PID 1) for Docker, Kubernetes, and other container workloads. It is a practical tini alternative with signal forwarding, subreaper support, command argument expansion without /bin/sh, and optional Linux Landlock restrictions.

Why Use tino as PID 1

  • Runs as PID 1 and forwards signals to the managed process.
  • Reaps orphaned children with -s/--subreaper.
  • Supports parent-death signals, grace timeouts, and exit-code remapping.
  • Expands ${VAR} and ${VAR:-default} in child arguments without requiring /bin/sh.
  • On Linux, can restrict writes, TCP ports, IPC scope, executable paths, and device ioctl with Landlock.

Install tino

Install with Cargo:

cargo install tino

Build a release binary:

cargo build --release --target x86_64-unknown-linux-musl

Copy tino into your own image:

COPY --from=lvillis/tino:latest /sbin/tino /sbin/tino
ENTRYPOINT ["/sbin/tino", "-g", "-s", "--"]
CMD ["/opt/app/service"]

Use tino in Docker and Kubernetes

Run a command locally:

tino -- /usr/bin/sleep 10

Use argument expansion without a shell:

ENTRYPOINT ["/sbin/tino", "--expand-env", "--"]
CMD ["/opt/app/service", "--port=${SERVICE_PORT:-8900}"]

Inspect the final command and effective restrictions without executing the child:

/sbin/tino --expand-env --write-preset runtime --write-allow /data/logs --explain -- \
  /opt/app/service --port=${SERVICE_PORT:-8900}

--expand-env is not a shell. Supported forms are ${VAR}, ${VAR:-default}, and $$ for a literal dollar sign. Unbraced $VAR is left unchanged.

Restrict container access with Landlock

Landlock-based restrictions require Linux 5.13+ with Landlock enabled.

  • --write-restrict, --write-allow, --write-preset, --write-no-dev, --write-warn-only
  • --bind-tcp-allow, --connect-tcp-allow require Landlock ABI v4+
  • --device-ioctl-allow requires Landlock ABI v5+
  • --scope-signals, --scope-abstract-unix require Landlock ABI v6+
  • --exec-allow restricts which executables the child may launch after startup

Example:

/sbin/tino \
  --write-preset runtime \
  --write-allow /data/logs \
  --bind-tcp-allow 8900 \
  --exec-allow /opt/app/service \
  -- \
  /opt/app/service --port=8900

If Docker blocks landlock_* syscalls, use the bundled seccomp profile:

docker run --rm -it \
  --security-opt seccomp=./seccomp-landlock.json \
  <image> \
  /sbin/tino --write-restrict --write-allow /data -- /opt/app/service

To make that the Docker default:

{
  "seccomp-profile": "/etc/docker/seccomp-landlock.json"
}

Refresh the profile with:

python scripts/update-seccomp-landlock.py

Download binary releases

GitHub Releases publish versioned archives with a single top-level directory:

tino-<version>-<os>-<arch>-<abi>/
  tino
  LICENSE
  README.md

Supported assets:

OCI platform Rust target Release asset
linux/amd64 x86_64-unknown-linux-gnu tino-<version>-linux-x86_64-gnu.tar.gz
linux/amd64 x86_64-unknown-linux-musl tino-<version>-linux-x86_64-musl.tar.gz
linux/arm64 aarch64-unknown-linux-musl tino-<version>-linux-aarch64-musl.tar.gz
linux/arm/v6 arm-unknown-linux-gnueabihf tino-<version>-linux-arm-gnueabihf.tar.gz
linux/arm/v7 armv7-unknown-linux-gnueabihf tino-<version>-linux-armv7-gnueabihf.tar.gz

Each release also includes:

  • SHA256SUMS
  • per-asset *.spdx.json SBOM files
  • GitHub artifact attestations for archives and SBOMs

Environment defaults

These environment variables act as defaults. Explicit CLI flags still win.

  • TINI_SUBREAPER
  • TINI_KILL_PROCESS_GROUP
  • TINI_VERBOSITY

Testing

cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all --verbose
cargo bench --bench logic_paths

On Unix targets, tests/unix_behaviour.rs covers the CLI license output, missing-command errors, exit-code remapping, environment expansion, and Landlock behavior.