Deploy Rust
This guide will help you deploy a Rust application to Deployxa.
Overview
Rust is a systems programming language focused on safety, speed, and concurrency. Deployxa provides optimized deployments for Rust applications with automatic configuration.
Features:
- Automatic framework detection
- Rust 1.70+ support
- Axum, Actix-web, Rocket support
- PostgreSQL, MySQL support
- Automatic HTTPS
- Global CDN
- Minimal container size
Prerequisites
- A Rust application
- A GitHub repository with your code
- A Deployxa account
Quick Start
1. Create Your Rust App
If you don't have a Rust app yet:
cargo new my-rust-app
cd my-rust-app
Add dependencies to Cargo.toml:
[dependencies]
axum = "0.7"
tokio = { version = "1", features = ["full"] }
Create src/main.rs:
use axum::{routing::get, Router};
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(|| async { "Hello, Deployxa!" }));
let port = std::env::var("PORT").unwrap_or_else(|_| "8080".to_string());
let addr = format!("0.0.0.0:{}", port);
println!("Server running on {}", addr);
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
axum::serve(listener, app).await.unwrap();
}
2. Push to GitHub
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/yourusername/my-rust-app.git
git push -u origin main
3. Deploy to Deployxa
- Go to Deployxa Dashboard
- Click "New Project"
- Select your GitHub repository
- Deployxa will automatically detect Rust
- Click "Deploy"
Your app will be live in under 60 seconds!
Configuration
Detected Settings
Deployxa automatically detects these settings:
| Setting | Value |
|---|---|
| Framework | Rust |
| Build Command | cargo build --release |
| Output Directory | target/release |
| Start Command | ./target/release/my-rust-app |
| Port | 8080 |
Custom Configuration
If you need to customize settings:
- Go to Project → Settings → Build
- Modify settings as needed
- Save changes
Example Custom Settings:
{
"buildCommand": "cargo build --release",
"startCommand": "./target/release/my-rust-app"
}
Environment Variables
Adding Environment Variables
- Go to Project → Environment
- Click "Add Variable"
- Enter key and value
- Click "Save"
Common Rust Environment Variables:
PORT=8080
RUST_LOG=info
# Database
DATABASE_URL=postgresql://user:pass@host:5432/dbname
DB_HOST=your-db-host
DB_NAME=your-database
DB_USER=your-username
DB_PASSWORD=your-password
Using Environment Variables
In your Rust app:
use std::env;
fn main() {
let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string());
let db_host = env::var("DB_HOST").unwrap_or_else(|_| "localhost".to_string());
println!("Server running on port {}", port);
}
Database Configuration
Using PostgreSQL with SQLx
Add dependencies to Cargo.toml:
[dependencies]
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres"] }
tokio = { version = "1", features = ["full"] }
use sqlx::postgres::PgPoolOptions;
use std::env;
#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
let pool = PgPoolOptions::new()
.max_connections(5)
.connect(&database_url)
.await?;
println!("Successfully connected to PostgreSQL!");
Ok(())
}
Using MySQL with SQLx
Add dependencies to Cargo.toml:
[dependencies]
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "mysql"] }
tokio = { version = "1", features = ["full"] }
use sqlx::mysql::MySqlPoolOptions;
use std::env;
#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
let pool = MySqlPoolOptions::new()
.max_connections(5)
.connect(&database_url)
.await?;
println!("Successfully connected to MySQL!");
Ok(())
}
Web Frameworks
Using Axum
Add dependencies to Cargo.toml:
[dependencies]
axum = "0.7"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
use axum::{
routing::get,
Router,
Json,
};
use serde::Serialize;
use std::env;
#[derive(Serialize)]
struct Message {
message: String,
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(|| async {
Json(Message {
message: "Hello, Deployxa!".to_string(),
})
}));
let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string());
let addr = format!("0.0.0.0:{}", port);
println!("Server running on {}", addr);
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Using Actix-web
Add dependencies to Cargo.toml:
[dependencies]
actix-web = "4"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
use actix_web::{get, web, App, HttpServer, HttpResponse};
use serde::Serialize;
use std::env;
#[derive(Serialize)]
struct Message {
message: String,
}
#[get("/")]
async fn index() -> HttpResponse {
HttpResponse::Ok().json(Message {
message: "Hello, Deployxa!".to_string(),
})
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string());
let port = port.parse::<u16>().unwrap();
println!("Server running on port {}", port);
HttpServer::new(|| {
App::new()
.service(index)
})
.bind(("0.0.0.0", port))?
.run()
.await
}
Using Rocket
Add dependencies to Cargo.toml:
[dependencies]
rocket = "0.5"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
#[macro_use] extern crate rocket;
use rocket::serde::json::Json;
use serde::Serialize;
#[derive(Serialize)]
struct Message {
message: String,
}
#[get("/")]
fn index() -> Json<Message> {
Json(Message {
message: "Hello, Deployxa!".to_string(),
})
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
Custom Domains
Adding a Custom Domain
- Go to Project → Domains
- Click "Add Domain"
- Enter your domain (e.g.,
example.com) - Configure DNS records
- Wait for verification
DNS Configuration
For Apex Domain (example.com):
Type: A
Name: @
Value: 76.76.21.21
For Subdomain (www.example.com):
Type: CNAME
Name: www
Value: cname.deployxa.com
Performance Optimization
Enable Compression
Using Axum with tower-http:
[dependencies]
tower-http = { version = "0.5", features = ["compression-gzip"] }
use axum::Router;
use tower_http::compression::CompressionLayer;
let app = Router::new()
.route("/", get(handler))
.layer(CompressionLayer::new());
Enable Caching
use axum::{
response::IntoResponse,
http::StatusCode,
};
async fn handler() -> impl IntoResponse {
(
StatusCode::OK,
[("Cache-Control", "public, max-age=3600")],
"Hello, Deployxa!",
)
}
Database Connection Pooling
SQLx provides connection pooling by default:
let pool = PgPoolOptions::new()
.max_connections(10)
.min_connections(2)
.connect_timeout(std::time::Duration::from_secs(5))
.connect(&database_url)
.await?;
Monitoring
Viewing Logs
- Go to Project → Logs
- Select log type:
- Build Logs: Deployment process
- Runtime Logs: Application output
- Error Logs: Application errors
Rust Logging
Add dependency:
[dependencies]
env_logger = "0.10"
log = "0.4"
use log::info;
use std::env;
fn main() {
env::set_var("RUST_LOG", "info");
env_logger::init();
info!("Application started");
}
Monitoring Metrics
- Go to Project → Analytics
- View metrics:
- Request count
- Response times
- Error rates
- Bandwidth usage
- CPU/RAM usage
Health Checks
Deployxa automatically monitors your application:
- HTTP health checks every 30 seconds
- Automatic restart on failure
- Alerts on consecutive failures
Add a health check endpoint:
use axum::{routing::get, Json};
use serde::Serialize;
#[derive(Serialize)]
struct Health {
status: String,
}
async fn health() -> Json<Health> {
Json(Health {
status: "healthy".to_string(),
})
}
let app = Router::new()
.route("/health", get(health));
Troubleshooting
Application Crashes on Start
Problem: Application crashes immediately
Solution:
- Check runtime logs for errors
- Verify environment variables
- Check for missing dependencies
- Ensure PORT is configured correctly
- Check for port conflicts
Database Connection Failed
Problem: Cannot connect to database
Solution:
- Verify DATABASE_URL is correct
- Check database host and port
- Ensure database exists
- Check firewall rules
- Verify database credentials
Build Failed
Problem: cargo build fails
Solution:
- Check build logs for specific errors
- Verify dependencies are correct
- Check for syntax errors
- Test build locally
- Ensure Rust version is compatible
Slow Build Times
Problem: Build takes too long
Solution:
- Use release mode:
cargo build --release - Enable incremental compilation
- Reduce dependencies
- Use build cache
- Consider upgrading plan
Slow Response Times
Problem: Application responds slowly
Solution:
- Enable compression
- Use caching
- Optimize database queries
- Use connection pooling
- Upgrade plan for more resources
Best Practices
Project Structure
my-rust-app/
├── src/
│ ├── main.rs
│ ├── handlers/
│ │ └── mod.rs
│ ├── models/
│ │ └── mod.rs
│ └── db/
│ └── mod.rs
├── Cargo.toml
├── Cargo.lock
├── .env.example
└── README.md
Environment Variables
- Never commit
.envfile - Use
.env.exampleas template - Rotate secrets regularly
- Use different values per environment
Security
- Keep dependencies updated
- Use HTTPS only
- Validate all inputs
- Use parameterized queries
- Enable CORS properly
- Use authentication/authorization
Performance
- Enable compression
- Use caching
- Optimize database queries
- Use connection pooling
- Use async/await properly
- Minimize allocations
Database
- Use connection pooling
- Index frequently queried columns
- Use transactions for complex operations
- Backup database regularly
- Use prepared statements
Advanced Configuration
Custom Build Configuration
Create .cargo/config.toml:
[build]
rustflags = ["-C", "target-cpu=native"]
[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "link-arg=-s"]
Docker Support
For local development with Docker:
FROM rust:1.75-bookworm AS builder
WORKDIR /app
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim
WORKDIR /app
COPY /app/target/release/my-rust-app .
EXPOSE 8080
CMD ["./my-rust-app"]
Graceful Shutdown
use tokio::signal;
use axum::Router;
#[tokio::main]
async fn main() {
let app = Router::new();
let port = std::env::var("PORT").unwrap_or_else(|_| "8080".to_string());
let addr = format!("0.0.0.0:{}", port);
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
axum::serve(listener, app)
.with_graceful_shutdown(shutdown_signal())
.await
.unwrap();
}
async fn shutdown_signal() {
let ctrl_c = async {
signal::ctrl_c().await.expect("failed to install Ctrl+C handler");
};
#[cfg(unix)]
let terminate = async {
signal::unix::signal(signal::unix::SignalKind::terminate())
.expect("failed to install signal handler")
.recv()
.await;
};
#[cfg(not(unix))]
let terminate = std::future::pending::<()>();
tokio::select! {
_ = ctrl_c => {},
_ = terminate => {},
}
}
Examples
Basic Rust App
use std::env;
#[tokio::main]
async fn main() {
let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string());
println!("Server running on port {}", port);
// Your server code here
}
REST API with Axum
use axum::{
routing::{get, post},
Router,
Json,
extract::Path,
};
use serde::{Deserialize, Serialize};
use std::env;
use std::sync::{Arc, Mutex};
#[derive(Clone, Serialize, Deserialize)]
struct User {
id: u32,
name: String,
}
struct AppState {
users: Mutex<Vec<User>>,
}
#[tokio::main]
async fn main() {
let state = Arc::new(AppState {
users: Mutex::new(vec![
User { id: 1, name: "John".to_string() },
User { id: 2, name: "Jane".to_string() },
]),
});
let app = Router::new()
.route("/users", get(get_users))
.route("/users/:id", get(get_user))
.route("/users", post(create_user))
.with_state(state);
let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string());
let addr = format!("0.0.0.0:{}", port);
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
axum::serve(listener, app).await.unwrap();
}
async fn get_users(
axum::extract::State(state): axum::extract::State<Arc<AppState>>,
) -> Json<Vec<User>> {
let users = state.users.lock().unwrap();
Json(users.clone())
}
async fn get_user(
axum::extract::State(state): axum::extract::State<Arc<AppState>>,
Path(id): Path<u32>,
) -> Json<User> {
let users = state.users.lock().unwrap();
let user = users.iter().find(|u| u.id == id).unwrap();
Json(user.clone())
}
async fn create_user(
axum::extract::State(state): axum::extract::State<Arc<AppState>>,
Json(user): Json<User>,
) -> Json<User> {
let mut users = state.users.lock().unwrap();
users.push(user.clone());
Json(user)
}
With Database
use sqlx::postgres::PgPoolOptions;
use axum::{routing::get, Router, Json};
use serde::Serialize;
use std::env;
#[derive(Serialize, sqlx::FromRow)]
struct User {
id: i32,
name: String,
}
#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
let pool = PgPoolOptions::new()
.max_connections(5)
.connect(&database_url)
.await?;
let app = Router::new()
.route("/users", get(move || get_users(pool.clone())));
let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string());
let addr = format!("0.0.0.0:{}", port);
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
axum::serve(listener, app).await.unwrap();
Ok(())
}
async fn get_users(pool: sqlx::PgPool) -> Json<Vec<User>> {
let users = sqlx::query_as::<_, User>("SELECT id, name FROM users")
.fetch_all(&pool)
.await
.unwrap();
Json(users)
}
Related Topics
Resources
- Rust Documentation
- Axum Documentation
- Actix-web Documentation
- Deployxa CLI
- API Reference
- Community Discord
Need Help? Contact support@deployxa.com or join our community Discord.