Disclaimer This is an ai made project only made to test the ai models capabilities, I have done a couple changes myself but nothing really major. The project does work but again you might prefer not to use it scince it is ai
Kubernetes for Rust.
Deploy, manage, and monitor Rust services across a cluster of servers from one CLI.
| Capability | What it does |
|---|---|
| Multi host clusters | Deploy to a fleet of servers, not just one |
| Rolling updates | Hosts updated one at a time with health gates |
| Canary & blue-green | Deploy to a subset, or spin a full parallel stack |
| Embedded reverse proxy | Built in HTTP proxy with Host based routing. No nginx needed. |
| Declarative state | Declare targets in sortie.toml; sortie apply reconciles |
| Auto rollback | Failed health checks trigger automatic rollback |
| Service registry | Register services, resolve by name, generate ingress config |
| Secrets management | Encrypted key-value store on servers (SSH is the boundary) |
| Auto scaling | CPU-based scaling loop, adjusts systemd instances |
| Self healing | sortie-agent watchdog restarts dead services |
| kubectl style CLI | apply, get, describe, logs, rollback, scale |
| Multi cluster federation | Deploy to all targets with one command |
| TLS provisioning | Auto certs via certbot (Let's Encrypt) |
| Observability | Per-host metrics (CPU, memory) and log aggregation |
| Environment config | Inline env vars for per-target service configuration |
cargo install sortie
sortie init
Edit sortie.toml with your server details, then deploy:
sortie apply production
This builds your binary, uploads it via SCP to every host, installs a systemd service, starts it, and waits for the health endpoint to respond. If a health check fails, that host rolls back.
To see what would change without deploying:
sortie apply production --check
No nginx, no caddy, no setup. Install the proxy on your server and it reads the service registry to route requests.
sortie svc register production my-api 8080
sortie proxy install production --port 80
The proxy matches the Host header against registered service names. If your server IP is 1.2.3.4:
curl -H "Host: my-api" http://1.2.3.4/
No domain needed. The service name you registered is the hostname clients send. You can use any string.
To add TLS, run sortie tls setup with a real domain first (Let's Encrypt), then point DNS at the server.
Roll out to a subset of hosts before full deploy:
sortie apply production --canary 20
Or deploy a full parallel stack and flip:
sortie apply production --blue-green
sortie deploy all
Iterates every target in sortie.toml. Also works with --canary and --blue-green.
cargo install sortie
Or build from source:
git clone <repo-url>
cd sortie
cargo build --release
Requires Rust 1.70+, Linux servers with SSH + systemd, key-based auth.
| Command | Like kubectl | Action |
|---|---|---|
sortie init |
Create a sortie.toml | |
sortie apply <target> |
kubectl apply | Rolling deploy across all hosts. --check for dry-run, --canary/--blue-green for strategies |
sortie deploy <target> |
Same as apply, with --all for federation |
|
sortie get |
kubectl get | Show all targets with version, timestamp, services |
sortie describe <target> |
kubectl describe | Target config + per-host status |
sortie logs <target> [host] |
kubectl logs | Fetch service logs from a host |
sortie rollback <target> |
kubectl rollout undo | Revert to previous binary |
sortie status <target> |
kubectl get pods | Check service status per host |
sortie health <target> |
Check host connectivity and service health | |
sortie svc register <target> <name> <port> |
Register a service in the cluster | |
sortie svc list <target> |
List all registered services | |
sortie svc resolve <target> <name> |
Resolve a service name to host:port | |
sortie svc restart <host> <target> <name> |
kubectl rollout restart | Restart a service on a host |
sortie svc stop <host> <target> <name> |
Stop a service on a host | |
sortie svc start <host> <target> <name> |
Start a service on a host | |
sortie proxy install <target> |
Install embedded reverse proxy as a systemd service | |
sortie scale <target> <n> |
kubectl scale | Set systemd instance count per host |
sortie autoscale <target> |
Start CPU-based auto-scaling loop | |
sortie secret set <target> <key> <value> |
Store a secret file on the server | |
sortie secret get <target> <key> |
Read a stored secret | |
sortie secret rm <target> <key> |
Delete a stored secret | |
sortie tls setup <target> <domain> <email> |
Provision Let's Encrypt certs via certbot | |
sortie ingress <target> |
Generate nginx config from service registry | |
sortie metrics <target> |
Show CPU and memory per host |
[targets.production]
hosts = ["10.0.0.1", "10.0.0.2"]
port = 22
user = "deploy"
key_path = "~/.ssh/id_rsa"
target_triple = "x86_64-unknown-linux-gnu"
deploy_path = "/opt/myapp"
health_check_url = "http://localhost:8080/health"
health_check_timeout_secs = 30
pre_deploy = "cd /opt/myapp && ./run_migrations.sh"
post_deploy = "echo 'Deployment completed'"
[targets.production.service]
name = "myapp"
restart = "always"
[targets.production.env]
DATABASE_URL = "postgres://localhost:5432/myapp"
RUST_LOG = "info"| Field | Required | Default | Description |
|---|---|---|---|
hosts |
yes | Server addresses in the cluster | |
port |
no | 22 | SSH port |
user |
yes | SSH user | |
key_path |
no | ~/.ssh/id_rsa |
SSH key path |
target_triple |
yes | Rust target triple | |
deploy_path |
yes | Server directory for binary | |
health_check_url |
no | URL to check after deploy | |
health_check_timeout_secs |
no | 30 | Max wait for health |
instances |
no | 1 | Expected replicas per host |
pre_deploy |
no | Command to run on each host before the new binary takes traffic | |
post_deploy |
no | Command to run on each host after the deploy succeeds | |
service.name |
yes | systemd service name | |
service.restart |
no | always |
Restart policy |
env.* |
no | Environment variables |
Reads desired state from sortie.toml. Builds the binary. Performs a rolling deployment across all hosts: upload via SCP, install systemd unit with env vars, verify health, next host. If a health check fails, that host rolls back and the deploy stops.
Previous versions are kept as .bak files for instant rollback. Cluster state is stored in .sortie/state.json on each host.
sortie/
Cargo.toml
Cargo.lock
LICENSE
README.md
CHANGELOG.md
CONTRIBUTING.md
CODE_OF_CONDUCT.md
SECURITY.md
SECURITY_CONTACTS
SUPPORT.md
OWNERS
OWNERS_ALIASES
.gitattributes
.gitignore
rust-toolchain.toml
Makefile
cmd/
sortie/
main.rs
agent/
main.rs
pkg/
lib.rs
cli.rs
types.rs
config.rs
init.rs
build.rs
ssh.rs
cluster.rs
deploy.rs
systemd.rs
health.rs
rollback.rs
proxy.rs
logo/
sortie.png
build/
build-release.bash
hack/
ci.bash
tests/
smoke_test.rs
docs/
architecture/
images/
c4-context--0.svg
c4-dynamic-build--0.svg
build-lifecycle--0.svg
c4-containers--0.svg
c4-components--0.svg
c4-deployment--0.svg
LICENSES/
README.md
examples/
basic.toml
multi-host.toml
with-env.toml
third_party/
README.md
CHANGELOG/
v0.1.0.md
v0.2.0.md
Pull requests welcome. See CONTRIBUTING.md.
MIT. See LICENSE.
