June 27, 2025   -   David Oyinbo

Actix Web Starter Template

Production-ready Actix Web API template with RBAC auth, PostgreSQL via SeaORM, Kafka-powered email, and a full Docker dev setup.

RustActix WebSeaORMPostgreSQLKafkaSMTPRBAC

Overview

A robust template for building secure, scalable REST APIs in Rust using Actix Web. Includes token-based auth with roles/permissions, email verification via OTP, background jobs, and observability. Docker Compose spins up PostgreSQL, Kafka, and Kafka UI for a smooth local dev flow.

For detailed documentation, visit the GitHub repository: https://github.com/dev-davexoyinbo/actix-web-starter-template

  • Token auth (non‑JWT), Argon2 hashes, email OTP verification
  • RBAC: roles, permissions, and route-level middleware
  • PostgreSQL + SeaORM entities, migrations, and seeders
  • Kafka + SMTP for async email delivery (Askama templates)
  • Tracing logs and request correlation IDs
  • Makefile-driven DX; .env-based configuration

Highlights

Authentication & Access Control

  • Token auth (non-JWT)
  • RBAC roles and permissions
  • Email verification (OTP)
  • Route middleware for roles/permissions/conditions

Database

  • PostgreSQL + SeaORM
  • Entities with relations
  • Migrations + seeders
  • Separate test DB config

API & Middleware

  • RESTful endpoints with DTO validation
  • Pagination and structured errors
  • Rate limiting and CORS
  • Health/readiness endpoints

Messaging & Email

  • Kafka producers/consumers
  • Async email via SMTP
  • Askama HTML templates
  • Topic-based prioritization

Observability

  • tracing + tracing-actix-web
  • Correlation IDs
  • Debuggable error types
  • Performance-ready hooks

Security

  • Argon2 password hashing
  • Request size limits
  • CORS and rate limiting
  • Secret-driven config

Background Jobs

  • actix-jobs scheduler
  • Token cleanup job
  • Extensible job registry
  • Cron-style schedules

Developer Experience

  • Docker Compose (PostgreSQL, Kafka, Kafka UI)
  • Makefile (watch, test, migrate)
  • bacon for live reload
  • .env configuration

Quick Start

  • Rust 1.86+, Docker, Docker Compose
  • Copy .env.example to .env and set values
  • Start services: make up-dev
  • Run migrations (with seeding): make migrate
  • Start app: make runhttp://localhost:9000

For full setup, API docs, seeded users, and access control examples, see the GitHub README.

Code Snippets

Route + Access Control (RBAC)

app/src/api/mod.rsrust
use actix_web::{web, HttpResponse};
use crate::middlewares::auth_middleware::{AccessControl, AccessControlCondition};

pub fn config(cfg: &mut web::ServiceConfig) {
    cfg
        // Simple role check
        .route("/api/admin", web::get().to(|| async { HttpResponse::Ok().finish() }))
        .wrap(AccessControl::Role("admin".to_string()).into_middleware())

        // Role AND permission
        .route("/api/editor-blog", web::post().to(|| async { HttpResponse::Ok().finish() }))
        .wrap(
            AccessControlCondition::all()
                .add(AccessControl::Role("editor".to_string()))
                .add(AccessControl::Permission("blog:write".to_string()))
                .into_middleware(),
        );
}

Email Verification Middleware

app/src/api/auth_middleware_usage.rsrust
use actix_web::{web, middleware::from_fn};

pub fn routes(cfg: &mut web::ServiceConfig) {
    cfg.route("/api/verified-only", web::get().to(|| async { "ok" }))
        .wrap(from_fn(crate::middlewares::auth_middleware::require_email_verification));
}

SeaORM Entity (User)

entity/src/users.rsrust
use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "users")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i64,
    pub name: String,
    pub email: String,
    pub password_hash: String,
    pub email_verified_at: Option<DateTimeWithTimeZone>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

impl ActiveModelBehavior for ActiveModel {}

Send Verification Email (Kafka + SMTP)

app/src/services/email.rsrust
use messaging::{AppMessageTopic, AppMessageWrapper, EmailMessage, VerifyEmailTemplate};
use crate::globals;

pub async fn send_verification_email(name: &str, email: &str, otp: &str) -> Result<(), anyhow::Error> {
    let messaging = globals::messaging::get()?;
    let app = common::app_config::get()?;

    let msg = AppMessageWrapper {
        key: None,
        topic: AppMessageTopic::GeneralEmail,
        message: EmailMessage {
            from: format!("{} <{}>", app.app.name, app.messaging.default_email_from),
            to: format!("{} <{}>", name, email),
            reply_to: None,
            subject: "Verify your email".into(),
            template: VerifyEmailTemplate { name: name.into(), otp: otp.into() }.into(),
        }.into(),
    };

    messaging.read().await.send_message(msg).await?;
    Ok(())
}

Quick cURL Test

login.shbash
# Login (use seeded users; see README for emails/passwords)
curl -X POST http://localhost:9000/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"admin@email.com","password":"<ADMIN_PASSWORD>"}'

For full examples and more snippets, see the README: https://github.com/dev-davexoyinbo/actix-web-starter-template

Other Projects

May 12, 2024

Canvas Gravity Balls

Pet project simulating bouncing balls with gravity, collisions, and elasticity on HTML Canvas.

JavaScriptHTML CanvasPhysics
December 4, 2024

Country flags and currency package

Lightweight TypeScript library for country flags, capitals, dial codes, currencies, and simple location distance utilities.

TypeScriptLibraryNPM
February 19, 2026

Trypema Rate Limiter

High-performance Rust rate limiting primitives with local and Redis-backed providers, atomic Redis enforcement, and absolute/suppressed strategies.

RustRate LimitingRedis

Let's build something together

Available for senior engineering roles, consulting, and architecture reviews.

© 2026 David Oyinbo