#Deployment Guide
Version: 0.33.0 Updated: 2026-03-15 Applies to: ranvier, ranvier-runtime, ranvier-http Category: Operations
This guide covers containerized deployment of a Ranvier application β build strategy, Docker multi-stage, Kubernetes manifests, reverse proxy, and environment configuration.
#1. Build Strategy
Ranvier applications compile to a fully-static musl binary for production. This eliminates OS-level dependencies and enables FROM scratch runtime images.
| Build Mode | Target | Use Case |
|---|---|---|
| Native debug | host target | Local iteration |
| Native release | host target | Local integration test |
| musl release | x86_64-unknown-linux-musl |
Container / production |
# Add musl target (Linux)
rustup target add x86_64-unknown-linux-musl
cargo build --release --target x86_64-unknown-linux-muslOn Windows/macOS, use the Docker builder stage for musl compilation (see Β§2).
#2. Docker Multi-Stage Build
# ---- Builder ----
FROM clux/muslrust:stable AS builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
# Dependency caching: build dummy binary first
RUN mkdir -p src && echo 'fn main(){}' > src/main.rs
RUN cargo build --release --target x86_64-unknown-linux-musl && \
rm -rf src target/x86_64-unknown-linux-musl/release/deps/my_app*
COPY src ./src
RUN cargo build --release --target x86_64-unknown-linux-musl
# ---- Runtime ----
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/my-app /app
EXPOSE 3000
ENTRYPOINT ["/app"]Key decisions:
| Choice | Rationale |
|---|---|
clux/muslrust:stable |
Full Rust + musl toolchain |
FROM scratch |
Zero OS surface, minimal footprint |
rustls only |
No OpenSSL dependency β works in scratch |
| CA certs copy | Required for outbound HTTPS connections |
#3. Kubernetes Manifests
#Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: ranvier-app
spec:
replicas: 2
selector:
matchLabels:
app: ranvier-app
template:
metadata:
labels:
app: ranvier-app
spec:
containers:
- name: app
image: my-registry/ranvier-app:latest
ports:
- containerPort: 3000
env:
- name: RUST_LOG
value: "info"
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: ranvier-secrets
key: jwt-secret
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi#Service
apiVersion: v1
kind: Service
metadata:
name: ranvier-app
spec:
selector:
app: ranvier-app
ports:
- port: 80
targetPort: 3000
type: ClusterIP#HPA (Horizontal Pod Autoscaler)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ranvier-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ranvier-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70#4. Health Check Endpoint
use ranvier::prelude::*;
#[transition]
async fn health_check(
_state: (),
_resources: &(),
_bus: &mut Bus,
) -> Outcome<String, String> {
Outcome::Next(r#"{"status":"ok"}"#.to_string())
}
// Mount in your Axon setup
let health = Axon::simple::<String>("health")
.then(health_check);
Ranvier::http()
.bind("0.0.0.0:3000")
.route("/health", health)
.route("/api/hello", hello_axon)
.run(())
.await?;#5. Reverse Proxy (Nginx)
Nginx serves static frontend assets and proxies API calls to the Ranvier backend:
server {
listen 80;
# Static SPA
root /usr/share/nginx/html;
location / { try_files $uri $uri/ /index.html; }
# API proxy β Ranvier backend
location /api/ {
proxy_pass http://backend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Ranvier::http()is an Ingress Builder, not a web server. Using Nginx as the edge preserves the Ranvier application's role as a pure API layer.
#6. Compose Topology
βββββββββββββββββββ
β Browser :8080 β
ββββββββββ¬βββββββββ
β
ββββββββΌβββββββ
β proxy β nginx:alpine β :80
ββββ¬ββββββββ¬βββ
β β
ββββββΌββββ βββΌβββββββββ
βfrontendβ β backend β Ranvier β :3000
β(static)β ββββββββ¬βββββ
ββββββββββ β
ββββββββΌβββββββ
β db β postgres:16-alpine β :5432
ββββββββββββββββ| Setting | Dev | Prod |
|---|---|---|
| DB port exposed | Yes (5432) | No |
| RUST_LOG | debug |
info |
| restart policy | none | unless-stopped |
| JWT_SECRET | test value | env/secret |
#7. Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
JWT_SECRET |
Yes (if auth) | β | JWT signing secret (never hardcode) |
DATABASE_URL |
Yes (if persistence) | β | postgres://user:pass@host:5432/db |
RUST_LOG |
No | info |
Log filter (debug, info, warn, error) |
OTEL_EXPORTER_OTLP_ENDPOINT |
No | β | OTLP collector endpoint |
PORT |
No | 3000 |
HTTP bind port |
- Always use
.env.exampleas the source of truth - Never commit
.envto version control - In production, use Kubernetes Secrets or vault
#8. Release Build Optimization
# Cargo.toml
[profile.release]
lto = true
strip = true
codegen-units = 1
opt-level = 3cargo build --release --target x86_64-unknown-linux-musl#9. CI Pipeline (musl build)
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with: { targets: x86_64-unknown-linux-musl }
- uses: Swatinem/rust-cache@v2
- run: cargo check --workspace
- run: cargo test --workspace
- run: cargo clippy --workspace -- -D warnings
- run: cargo build --release --target x86_64-unknown-linux-musl#10. Deployment Checklist
#Required
-
--releaseprofile with LTO, strip, codegen-units=1 - Docker multi-stage build (builder β scratch)
- Health check endpoint (
/health) configured - Environment variables documented and injected
- Secrets NOT committed to version control
-
RUST_LOG=infoset for production
#Recommended
- Kubernetes readiness/liveness probes configured
- HPA for auto-scaling based on CPU
- OpenTelemetry exporter for observability
- Nginx reverse proxy for static assets + API routing
- CI pipeline with musl build verification
#Related Documents
- Production Readiness Checklist β pre-deployment checklist
- Performance Tuning β profiling, connection pools, async optimization
- Security Hardening β auth, CORS, error redaction
- OTel Ops Playbook β observability setup