Workflow: Deploy & Release ​
Updated Mar 2026Overview ​
This workflow covers optimizing Rust binaries for production, publishing to crates.io, cross-compilation, Docker containers, and CI/CD release pipelines.
Release Pipeline ​
Release Profile Optimization ​
toml
# Cargo.toml
[profile.release]
opt-level = 3 # Maximum optimization
lto = true # Link-Time Optimization — slower build, faster binary
strip = true # Strip debug symbols — smaller binary
codegen-units = 1 # Single codegen unit — better optimization
panic = "abort" # No unwinding — smaller binary
# For even smaller binaries
[profile.release-small]
inherits = "release"
opt-level = "z" # Optimize for size
strip = true
lto = true
codegen-units = 1
panic = "abort"Binary Size Optimization ​
bash
# Check binary size
ls -lh target/release/my_app
# Analyze what's contributing to size
cargo install cargo-bloat
cargo bloat --release --crates # Size by crate
cargo bloat --release -n 20 # Top 20 functions by size
# Strip symbols manually (if strip = true isn't enough)
strip target/release/my_app
# UPX compression (optional, reduces size further)
upx --best target/release/my_appCross-Compilation ​
bash
# Install cross-compilation toolchain
rustup target add x86_64-unknown-linux-musl # Static Linux
rustup target add x86_64-apple-darwin # macOS
rustup target add x86_64-pc-windows-msvc # Windows
rustup target add aarch64-unknown-linux-gnu # ARM Linux
# Build for specific target
cargo build --release --target x86_64-unknown-linux-musl
# Using cross (easier, uses Docker)
cargo install cross
cross build --release --target x86_64-unknown-linux-musl
cross build --release --target aarch64-unknown-linux-gnuDocker Deployment ​
dockerfile
# Multi-stage build for minimal image
FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build --release
# Minimal runtime image
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/my_app /usr/local/bin/my_app
EXPOSE 8080
CMD ["my_app"]dockerfile
# Even smaller: static musl build + scratch
FROM rust:1.75 as builder
RUN rustup target add x86_64-unknown-linux-musl
WORKDIR /app
COPY . .
RUN cargo build --release --target x86_64-unknown-linux-musl
FROM scratch
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/my_app /my_app
EXPOSE 8080
ENTRYPOINT ["/my_app"]Publishing to crates.io ​
bash
# Verify everything is ready
cargo package --list # Check included files
cargo doc --open # Verify documentation
cargo publish --dry-run # Test the publish
# Publish
cargo login # Login with API token from crates.io
cargo publish # Publish the crate!
# Versioning
# In Cargo.toml, bump version:
# 0.1.0 → 0.1.1 (patch: bug fix)
# 0.1.0 → 0.2.0 (minor: new feature, backward compatible)
# 0.1.0 → 1.0.0 (major: breaking change)GitHub Actions Release Pipeline ​
yaml
# .github/workflows/release.yml
name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
jobs:
build:
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
ext: ""
- target: x86_64-apple-darwin
os: macos-latest
ext: ""
- target: x86_64-pc-windows-msvc
os: windows-latest
ext: ".exe"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Build
run: cargo build --release --target ${{ matrix.target }}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: my_app-${{ matrix.target }}
path: target/${{ matrix.target }}/release/my_app${{ matrix.ext }}
release:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: |
my_app-*/my_app*
generate_release_notes: trueSystemd Service (Linux Deployment) ​
ini
# /etc/systemd/system/my_app.service
[Unit]
Description=My Rust Application
After=network.target
[Service]
Type=simple
User=appuser
ExecStart=/usr/local/bin/my_app
Restart=on-failure
RestartSec=5
Environment=RUST_LOG=info
Environment=PORT=8080
[Install]
WantedBy=multi-user.targetbash
sudo systemctl daemon-reload
sudo systemctl enable my_app
sudo systemctl start my_app
sudo systemctl status my_app
journalctl -u my_app -f # View logsRelease Checklist ​
- [ ] All tests pass (
cargo test --release) - [ ] No clippy warnings (
cargo clippy -- -D warnings) - [ ] Code formatted (
cargo fmt --check) - [ ] CHANGELOG updated
- [ ] Version bumped in Cargo.toml
- [ ] Documentation builds (
cargo doc) - [ ] Release profile optimized
- [ ] Git tag created (
git tag v0.1.0) - [ ] CI builds and publishes artifacts
- [ ] Verify published package / binary works