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 13, 2024

Canvas Infinity & Circle Mouse

Pet project exploring HTML Canvas and JavaScript animations—drawing an infinity curve and a circle following the mouse.

JavaScriptHTML CanvasAnimation
June 1, 2022

iPay (Nuxt 3 Pet Project)

A simple Nuxt 3 site built to explore the Nuxt 3 ecosystem, routing, layouts, and component patterns.

Nuxt 3VuePet Project
January 22, 2025

Auth module for Nuxt server apps

Auth module for Nuxt 3 server apps with local and social providers, tokens, middlewares, and typed composables.

TypeScriptNuxt 3Auth

Let's build something together

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

© 2025 David Oyinbo