Rust Backend Template
A production-ready Rust backend template featuring GraphQL, PostgreSQL with SeaORM, Keycloak authentication, and observability.
Loading actions...
Skill content
Main instructions and any bundled files for this skill.
Rust Backend Template
A production-ready Rust backend template featuring GraphQL, PostgreSQL with SeaORM, Keycloak authentication, and observability.
Features
- GraphQL API with async-graphql
- PostgreSQL database with SeaORM (async ORM with migrations)
- Keycloak authentication with JWT validation
- Structured logging with tracing
- OpenTelemetry support for distributed tracing
- Modular architecture with reusable crates
Project Structure
.
├── Cargo.toml # Workspace configuration
├── config/ # Configuration files
│ ├── default.toml # Default settings
│ ├── development.toml # Development overrides
│ └── production.toml # Production overrides
└── crates/
├── app/ # Main application (binary)
│ └── src/
│ ├── main.rs # Entry point
│ ├── server.rs # HTTP server setup
│ └── state.rs # Application state
├── auth/ # Authentication crate (reusable)
│ └── src/
│ ├── claims.rs # JWT claims structures
│ ├── jwks.rs # JWKS client for key fetching
│ ├── middleware.rs # Axum auth middleware
│ └── roles.rs # Role/permission definitions
├── common/ # Shared types (reusable)
│ └── src/
│ ├── error.rs # Error types
│ └── types.rs # Common types (pagination, etc.)
├── config/ # Configuration management (reusable)
│ └── src/
│ └── lib.rs # Config loading and structures
├── database/ # Database layer (reusable)
│ └── src/
│ ├── connection.rs # Connection management
│ ├── entities/ # SeaORM entity definitions
│ ├── migration/ # SeaORM migrations
│ └── repositories/ # Repository pattern implementations
├── graphql/ # GraphQL schema and resolvers
│ └── src/
│ ├── context.rs # GraphQL context
│ ├── guards.rs # Authorization guards
│ ├── mutation.rs # Mutation resolvers
│ ├── query.rs # Query resolvers
│ └── types/ # GraphQL type definitions
└── telemetry/ # Observability (reusable)
└── src/
└── lib.rs # Logging and tracing setup
Getting Started
Prerequisites
- Rust 1.75+ (for async traits)
- PostgreSQL 14+
- Keycloak 20+ (or compatible OIDC provider)
Setup
- Clone and configure:
cp .env.example .env
# Edit .env with your settings
- Start dependencies:
# Using Docker Compose (recommended)
docker-compose up -d postgres keycloak
# Or manually start PostgreSQL and Keycloak
- Create the database:
createdb myapp
- Run the application:
cargo run
The server starts at http://localhost:8080 with:
- GraphQL endpoint:
POST /graphql - GraphQL Playground:
GET /graphql/playground - Health check:
GET /health
Configuration
Configuration is loaded from multiple sources (in order of precedence):
- Environment variables (prefix:
APP__, separator:__) config/local.toml(not in git, for local overrides)config/{environment}.toml(environment-specific)config/default.toml(defaults)
Environment Variables
# Application
APP_ENVIRONMENT=development
# Server
APP__SERVER__PORT=8080
# Database
APP__DATABASE__URL=postgres://user:pass@localhost/myapp
# Auth (Keycloak)
APP__AUTH__KEYCLOAK_URL=http://localhost:8180
APP__AUTH__REALM=master
APP__AUTH__CLIENT_ID=my-app
# Telemetry
APP__TELEMETRY__LOG_LEVEL=debug
APP__TELEMETRY__OTLP_ENDPOINT=http://localhost:4317
Authentication
This template uses Keycloak for authentication. The auth flow:
- Client obtains a JWT token from Keycloak
- Client sends token in
Authorization: Bearer <token>header - Backend validates token signature using JWKS
- User info is extracted and available in resolvers
Setting Up Keycloak
- Create a realm (or use
master) - Create a client with:
- Client ID:
my-app - Access Type:
public(orconfidentialwith secret) - Valid Redirect URIs: Your frontend URL
- Client ID:
- Create roles as needed (
admin,user, etc.) - Assign roles to users
Protected Routes
In GraphQL resolvers:
// Require authentication
#[graphql(guard = "AuthGuard")]
async fn me(&self, ctx: &Context<'_>) -> Result<User> { ... }
// Require specific role
#[graphql(guard = "RoleGuard::new(\"admin\")")]
async fn users(&self, ctx: &Context<'_>) -> Result<Vec<User>> { ... }
Database
Migrations
Migrations are defined using SeaORM's migration system in crates/database/src/migration/. They run automatically in development mode (run_migrations = true).
For production, you can run migrations manually or use the sea-orm-cli:
# Using the CLI
cargo install sea-orm-cli
sea-orm-cli migrate up -d crates/database
# Or via the application
APP__DATABASE__RUN_MIGRATIONS=true cargo run
Adding New Entities
- Create migration in
crates/database/src/migration/ - Add entity definition in
crates/database/src/entities/ - Add repository in
crates/database/src/repositories/ - Add GraphQL types in
crates/graphql/src/types/ - Add resolvers in query/mutation files
SeaORM Entity Example
// crates/database/src/entities/post.rs
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "posts")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: Uuid,
pub title: String,
pub content: String,
pub user_id: Uuid,
pub created_at: DateTimeUtc,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::user::Entity",
from = "Column::UserId",
to = "super::user::Column::Id"
)]
User,
}
impl Related<super::user::Entity> for Entity {
fn to() -> RelationDef {
Relation::User.def()
}
}
GraphQL API
Example Queries
# Get current user
query Me {
me {
id
email
name
isMe
}
}
# List users (admin only)
query Users {
users(pagination: { limit: 10, offset: 0 }) {
items {
id
email
name
}
total
hasMore
}
}
# Sync user from auth provider
mutation SyncUser {
syncUser {
id
email
}
}
Telemetry
Logging
Logs are structured and configurable:
# Set log level
APP__TELEMETRY__LOG_LEVEL=debug
# Enable JSON logs (for production)
APP__TELEMETRY__JSON_LOGS=true
# Or use RUST_LOG for fine-grained control
RUST_LOG=debug,tower_http=debug,sqlx=warn
Distributed Tracing
Enable OpenTelemetry export:
APP__TELEMETRY__OTLP_ENDPOINT=http://localhost:4317
Compatible with Jaeger, Zipkin, or any OTLP collector.
Reusing Crates
The crates are designed to be reusable in other projects:
# In another project's Cargo.toml
[dependencies]
auth = { path = "../rust-backend-template/crates/auth" }
Or publish to a private registry.
Development
Running Tests
cargo test
Linting
cargo clippy --all-targets --all-features
Formatting
cargo fmt
Production Deployment
- Build release binary:
cargo build --release
- Set production configuration:
APP_ENVIRONMENT=production
APP__DATABASE__URL=...
APP__AUTH__KEYCLOAK_URL=...
- Run migrations (if not automatic):
sqlx migrate run
- Start the server:
./target/release/server
Docker
FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build --release
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/server /usr/local/bin/
CMD ["server"]
License
MIT
Related Skills
Frontend Typescript Linting.mdc
TypeScript and ESLint rules that MUST be followed when creating, modifying, or reviewing any file under apps/frontend/, including .ts, .tsx, .js, and .jsx files. Also apply when discussing frontend li...
2. Apply Deepthink Protocol (reason about dependencies
risks