<h1 align="center">
<a href="https://prompts.chat">
A production-ready Rust backend template featuring GraphQL, PostgreSQL with SeaORM, Keycloak authentication, and observability.
Sign in to like and favorite skills
A production-ready Rust backend template featuring GraphQL, PostgreSQL with SeaORM, Keycloak authentication, and observability.
. ├── 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
cp .env.example .env # Edit .env with your settings
# Using Docker Compose (recommended) docker-compose up -d postgres keycloak # Or manually start PostgreSQL and Keycloak
createdb myapp
cargo run
The server starts at
http://localhost:8080 with:
POST /graphqlGET /graphql/playgroundGET /healthConfiguration is loaded from multiple sources (in order of precedence):
APP__, separator: __)config/local.toml (not in git, for local overrides)config/{environment}.toml (environment-specific)config/default.toml (defaults)# 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
This template uses Keycloak for authentication. The auth flow:
Authorization: Bearer <token> headermaster)my-apppublic (or confidential with secret)admin, user, etc.)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>> { ... }
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
crates/database/src/migration/crates/database/src/entities/crates/database/src/repositories/crates/graphql/src/types/// 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() } }
# 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 } }
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
Enable OpenTelemetry export:
APP__TELEMETRY__OTLP_ENDPOINT=http://localhost:4317
Compatible with Jaeger, Zipkin, or any OTLP collector.
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.
cargo test
cargo clippy --all-targets --all-features
cargo fmt
cargo build --release
APP_ENVIRONMENT=production APP__DATABASE__URL=... APP__AUTH__KEYCLOAK_URL=...
sqlx migrate run
./target/release/server
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"]
MIT