Rust Backend Template

A production-ready Rust backend template featuring GraphQL, PostgreSQL with SeaORM, Keycloak authentication, and observability.

Views1
PublishedJan 14, 2026

Loading actions...

5 minBeginnerpromptSingle file

Skill content

Main instructions and any bundled files for this skill.

markdown

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

  1. Clone and configure:
cp .env.example .env
# Edit .env with your settings
  1. Start dependencies:
# Using Docker Compose (recommended)
docker-compose up -d postgres keycloak

# Or manually start PostgreSQL and Keycloak
  1. Create the database:
createdb myapp
  1. 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):

  1. Environment variables (prefix: APP__, separator: __)
  2. config/local.toml (not in git, for local overrides)
  3. config/{environment}.toml (environment-specific)
  4. 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:

  1. Client obtains a JWT token from Keycloak
  2. Client sends token in Authorization: Bearer <token> header
  3. Backend validates token signature using JWKS
  4. User info is extracted and available in resolvers

Setting Up Keycloak

  1. Create a realm (or use master)
  2. Create a client with:
    • Client ID: my-app
    • Access Type: public (or confidential with secret)
    • Valid Redirect URIs: Your frontend URL
  3. Create roles as needed (admin, user, etc.)
  4. Assign roles to users

Protected Routes

In GraphQL resolvers:

// Require authentication
#[graphql(guard = "AuthGuard")]
async fn me(&#x26;self, ctx: &#x26;Context&#x3C;'_>) -> Result&#x3C;User> { ... }

// Require specific role
#[graphql(guard = "RoleGuard::new(\"admin\")")]
async fn users(&#x26;self, ctx: &#x26;Context&#x3C;'_>) -> Result&#x3C;Vec&#x3C;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

  1. Create migration in crates/database/src/migration/
  2. Add entity definition in crates/database/src/entities/
  3. Add repository in crates/database/src/repositories/
  4. Add GraphQL types in crates/graphql/src/types/
  5. 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&#x3C;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

  1. Build release binary:
cargo build --release
  1. Set production configuration:
APP_ENVIRONMENT=production
APP__DATABASE__URL=...
APP__AUTH__KEYCLOAK_URL=...
  1. Run migrations (if not automatic):
sqlx migrate run
  1. 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 &#x26;&#x26; apt-get install -y ca-certificates &#x26;&#x26; rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/server /usr/local/bin/
CMD ["server"]

License

MIT

Share: