Dual-Path Rust Deployments: Git vs Direct Hotfix
A detailed guide comparing Git-based automation and manual direct binary hotfixes for deploying Rust web applications on a self-hosted server.
Since Rust applications compile down to a single self-contained binary, deploying them is usually just a matter of swapping the executable file. If you use a compile-time template engine like Askama, even the HTML files are embedded directly inside the binary, meaning you don't have to sync frontend templates separately.
Here is a quick comparison of the two workflows we use to deploy our Rust web apps: Git-driven automation for standard updates, and a direct manual binary swap for rapid hotfixes.
The Deployment Flow
Here is a visual map comparing the Git-driven pipeline and the direct binary sync pathway:
DEVELOPMENT WORKSPACE
[/opt/example-erp]
│
▼
[1. Modify Code]
(e.g., handlers.rs, admin_user.html)
│
▼
[2. cargo check]
(Verify compiles)
│
┌──────────────┴──────────────┐
▼ ▼
[METHOD A: Git-Based] [METHOD B: Manual Direct]
(Safe / Enforced) (Fast / No Commit Required)
│ │
▼ ▼
[3A. Git Commit & Push] [3B. cargo build --release]
(git add/commit/push) (Compiles release binary)
│ │
▼ ▼
[4A. Run deploy script] [4B. Copy Binary & Sync]
(Automated pull/build/sync) (cp binary + rsync migrations)
│ │
└──────────────┬──────────────┘
│
▼
PRODUCTION RUNTIME
[/www/wwwroot/app.example.com]
│
▼
[5. Restart Service]
(systemctl restart example-service)
│
▼
[6. Verify & Monitor]
(systemctl status & logs)
Step 1: Modifying and Checking Code
Before executing any deployment method, navigate to your development directory and ensure the application compiles. Using cargo check validates the Rust syntax and type-safety without spending time on full code generation:
cd /opt/example-erp
cargo check
Step 2: Choosing Your Deployment Path
Method A: Git-Based Automation (Recommended)
This workflow uses an automated bash script (/opt/deploy-example-erp.sh) on the build server. It forces code quality and version history by enforcing a clean working tree and relying entirely on committed Git tags.
Commit and push changes to your GitHub repository:
cd /opt/example-erp git add . git commit -m "feat: optimized database index query" git push origin mainTrigger the server-side deployment script:
bash /opt/deploy-example-erp.shThis script pulls the latest master code, executes a release build, and handles the deployment steps automatically.
Method B: Manual Direct Deploy (Fast Hotfix)
Use this pathway when you need to deploy uncommitted local hotfixes or verify changes immediately in staging without cluttering the Git commit history.
Build the release executable locally in your workspace:
cd /opt/example-erp cargo build --releaseBack up the existing production binary and copy the newly compiled binary to the webroot directory:
# Create backup of current active production binary cp -p /www/wwwroot/app.example.com/target/release/example-service /www/wwwroot/app.example.com/target/release/example-service.prev # Copy new release binary cp target/release/example-service /www/wwwroot/app.example.com/target/release/example-service # Sync database migrations folder (if database schema changed) rsync -a --delete migrations/ /www/wwwroot/app.example.com/migrations/
Step 3: Restarting and Monitoring the Service
Since the application binary is managed as a standard systemd service, restart the service to load the new binary into memory, and monitor the logs to verify everything is running smoothly:
# Restart the service
systemctl restart example-service
# Inspect systemd runtime status
systemctl status example-service
# Monitor application logs in real-time
journalctl -u example-service -f -n 50
[!NOTE] When using compile-time HTML template engines (like Askama), your HTML templates are parsed, checked for type-safety, and compiled directly into the binary executable at build time. This means you do not need to sync or copy
.htmltemplates to the production directory separately; updating the compiled binary is sufficient.
Thanks for reading. See you in the next sharing.


