salus 0.1.3

Single-shot container health check probe runner for Docker and Kubernetes workloads
Documentation
<p align="center">
  <img src="assets/salus-logo.svg" alt="salus logo" width="720">
</p>

# salus

`salus` is a Rust health check tool for Docker and Kubernetes workloads. It provides a single-shot probe execution model that fits container health checks cleanly.

Supported probe types:

- `http` / `https`
- `tcp`
- `grpc` (standard `grpc.health.v1.Health/Check` only)
- `exec`
- `file`

## Design Goals

- Single execution with stable exit codes for Docker `HEALTHCHECK` and Kubernetes `exec` probes
- Works in minimal container images without requiring a shell
- Supports strict TLS, custom CAs, client certificates, and SNI / hostname overrides
- Failure output is optimized for troubleshooting, while successful probes stay quiet by default

## Architecture

`salus` is easiest to understand as a runtime adapter between the container platform and the probe target inside the workload.

```mermaid
flowchart LR
    subgraph Platform["Container platform"]
        Docker["Docker HEALTHCHECK"]
        K8s["Kubernetes exec probe"]
    end

    subgraph Container["Application container"]
        Salus["salus"]
        HttpTarget["HTTP / HTTPS endpoint"]
        TcpTarget["TCP listener / Unix socket"]
        GrpcTarget["gRPC health service"]
        FileTarget["State / readiness file"]
        ExecTarget["Local validation command"]
    end

    Docker --> Salus
    K8s --> Salus

    Salus --> HttpTarget
    Salus --> TcpTarget
    Salus --> GrpcTarget
    Salus --> FileTarget
    Salus --> ExecTarget

    Salus --> Result["Exit code 0 / 1 / 3 / 4"]
    Result --> Docker
    Result --> K8s
```

## Exit Codes

- `0`: healthy
- `1`: probe failure
- `3`: invalid arguments or configuration
- `4`: internal error

## Examples

HTTP:

```bash
salus http --url http://127.0.0.1:8080/healthz
salus http --url http://127.0.0.1:8080/healthz --request-header x-api-key:secret
salus http --url https://127.0.0.1:8443/ready --ca-file /etc/ssl/health-ca.pem --server-name localhost
salus http --url https://127.0.0.1:8443/ready --ca-file /etc/ssl/health-ca.pem --server-name localhost --response-header-contains x-ready:ok
```

TCP:

```bash
salus tcp --address 127.0.0.1:5432
```

gRPC health:

```bash
salus grpc --address 127.0.0.1:50051
salus grpc --address 127.0.0.1:50051 --tls --ca-file /etc/ssl/grpc-ca.pem --server-name localhost
```

Exec:

```bash
salus exec --stdout-contains ok -- /app/bin/check-ready
```

File:

```bash
salus file --path /tmp/ready --non-empty --contains ready
```

## Docker

The production Dockerfile builds a static musl binary and runs it from `scratch`.
Published images are pushed to `ghcr.io/lvillis/salus:<tag>` and stable tags also update `ghcr.io/lvillis/salus:latest`.

```dockerfile
HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD ["/bin/salus", "http", "--url", "http://127.0.0.1:8080/healthz"]
```

Copy `salus` into an application image:

```dockerfile
FROM ghcr.io/lvillis/salus:latest AS salus

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=salus /bin/salus /bin/salus
COPY ./my-app /bin/my-app

HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD ["/bin/salus", "http", "--url", "http://127.0.0.1:8080/healthz", "--body-contains", "ok"]

ENTRYPOINT ["/bin/my-app"]
```

## Kubernetes

Prefer native `httpGet`, `tcpSocket`, and `grpc` probes for simple cases. Use `exec` with `salus` when you need stricter TLS controls, file checks, process-based checks, or richer assertions.

```yaml
livenessProbe:
  exec:
    command:
      - /bin/salus
      - grpc
      - --address
      - 127.0.0.1:50051
      - --tls
      - --ca-file
      - /etc/tls/ca.pem
      - --server-name
      - localhost
```