Skip to content

Repository files navigation

FastAPI Template

A production-ready FastAPI boilerplate designed for rapid project setup — featuring clean architecture, Docker support, CI/CD, logging and INI-based configuration.

Features

  • FastAPI with Python 3.14 and Granian (ASGI)
  • 🐳 Docker & Docker Compose for development and production
  • 🔄 CI/CD pipeline with GitHub Actions
  • 🗄️ PostgreSQL database with SQLAlchemy
  • 🔴 Redis for caching
  • 🔒 Nginx reverse proxy with rate limiting
  • 📝 Alembic for database migrations
  • 🧪 Pytest for testing
  • 📊 Logging configured and ready to use
  • 🔧 Makefile for convenient development
  • 📦 uv for fast installs (Docker & local make install)

Quick Start

Prerequisites

  • Docker and Docker Compose
  • Python 3.14+ (for local development; Docker images use 3.14)
  • uv (optional; used by Dockerfiles and make install)
  • Make (optional)

Installation

  1. Clone the repository:
git clone https://github.com/Reei-dp/fastapi-template.git
cd fastapi-template
  1. Create config.ini file from example:
cp config.ini.example config.ini
  1. Edit config.ini file according to your needs

Running (Development)

Using Docker Compose:

make dev
# or
docker compose -f docker/docker-compose.dev.yml up --build

Locally (without Docker):

python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
uv pip install -r requirements.txt
python src/main.py
# or
granian --interface asgi src.main:app --reload

Application will be available at: http://localhost:8000

API documentation:

Running (Production)

From the repository root, with config.ini present (non-empty Redis PASSWORD for production compose — see config.ini.example). Inside Docker, set [POSTGRES] IP to postgres and [REDIS] HOST to redis so the app reaches the compose services.

make up
# or
./start.sh -d

This runs docker/sync_compose_from_config.sh and then docker compose up --build from the docker/ directory.

Project Structure

fastapi-template/
├── .github/
│   └── workflows/
│       └── develop.yaml          # CI/CD pipeline
├── src/                          # Source code
│   ├── main.py                   # FastAPI application entry point
│   ├── config.py                 # Configuration loader (INI files)
│   ├── dependencies.py           # Global dependencies
│   ├── schemas.py                # Shared Pydantic schemas
│   ├── configuration/
│   │   └── app.py                # FastAPI app initialization
│   ├── middlewares/              # HTTP middlewares
│   │   ├── __init__.py
│   │   └── database.py           # Database session middleware
│   ├── routers/                  # API routers
│   │   ├── __init__.py           # Router registration
│   │   └── root/                 # Root endpoints
│   │       ├── router.py         # Route definitions
│   │       ├── actions.py        # Business logic
│   │       ├── dal.py            # Data access layer
│   │       ├── models.py         # Database models
│   │       └── schemas.py        # Request/response schemas
│   ├── database/                 # Database configuration
│   │   ├── core.py               # Database engine and sessions
│   │   ├── base.py               # Base model class
│   │   ├── dependencies.py       # Database dependencies
│   │   ├── logging.py            # Session tracking
│   │   └── alembic/              # Database migrations
│   ├── redis_client/             # Redis operations
│   │   └── redis.py              # Redis controller with caching methods
│   ├── services/                 # External service integrations
│   └── misc/                     # Utilities
│       ├── security.py           # Security utilities
│       └── timezone.py           # Timezone utilities
├── docker/
│   ├── Dockerfile                # Production image
│   ├── Dockerfile.dev            # Development image (hot-reload)
│   ├── docker-compose.yml        # App, Postgres, Redis
│   ├── docker-compose.dev.yml    # Dev stack (app + Postgres + Redis)
│   ├── entrypoint.sh             # Migrations + app in production
│   ├── sync_compose_from_config.sh  # docker/.env from config.ini
│   └── nginx/
│       └── nginx.conf            # Optional Nginx (not wired in compose by default)
├── config.ini.example            # Configuration template
├── alembic.ini.example           # Alembic configuration template
├── requirements.txt              # Python dependencies
├── Makefile                      # Build commands
├── start.sh                      # Startup script
└── README.md                     # This file

Makefile Commands

make help           # Show all available commands
make install        # Install dependencies
make dev            # Start development environment
make build          # Build production Docker image
make up             # Start production environment
make down           # Stop all containers
make logs           # Show logs
make clean          # Remove containers and volumes
make test           # Run tests
make lint           # Run linter
make format         # Format code
make migrate        # Apply migrations
make migrate-create # Create new migration

CI/CD

Workflow .github/workflows/develop.yaml (on pull requests to main):

  1. Writes config.ini and alembic.ini from secrets
  2. Copies the repository tree to the server over scp
  3. Runs ./start.sh -d on the server (writes docker/.env from config.ini, then docker compose up --build -d)

Required GitHub Secrets

  • PROD_SSH_PRIVATE_KEY — SSH private key for the server
  • PROD_SSH_HOST — Server hostname or IP
  • PROD_SSH_USER — SSH user
  • PROD_CONFIG_INI — Full contents of production config.ini (use echo -e in GitHub Actions, so use \n for newlines if needed)
  • PROD_ALEMBIC_INI — Full contents of production alembic.ini

Edit env.REMOTE_PATH in the workflow file so it matches the deploy directory on the server (default: /opt/apps/fastapi-template).

Configuration

Application uses INI files for configuration (see config.ini.example):

[POSTGRES]
# PostgreSQL database configuration
DATABASE = postgresql
DRIVER = asyncpg
DATABASE_NAME = your_database_name
USERNAME = postgres
PASSWORD = your_password
IP = localhost
PORT = 5432

# Connection pool settings
DATABASE_ENGINE_POOL_TIMEOUT = 30
DATABASE_ENGINE_POOL_RECYCLE = 3600
DATABASE_ENGINE_POOL_SIZE = 5
DATABASE_ENGINE_MAX_OVERFLOW = 10
DATABASE_ENGINE_POOL_PING = true

# Database echo (SQL logging) - set to false in production
DATABASE_ECHO = false

[GRANIAN]
# Granian server configuration
HOST = 0.0.0.0
PORT = 8000
WORKERS = 4
LOOP = uvloop          # Event loop: asyncio | uvloop | auto
HTTP = auto            # HTTP: auto | http1 | http2

[REDIS]
# Redis cache configuration
HOST = localhost
PORT = 6379
DB = 0
PASSWORD =

Key Features

Database Middleware

  • Automatic session management per request
  • Auto-commit on success, rollback on error
  • Session tracking for debugging
  • Request ID generation for tracing

Redis Client

  • Simple caching interface with get(), set(), delete(), update()
  • JSON serialization support with get_json() and set_json()
  • TTL (Time To Live) management
  • Multiple key deletion support

Health Check

  • Database connectivity check
  • Redis connectivity check
  • Returns 200 (healthy) or 503 (unhealthy)
  • Accessible at /api/root/health

Systemd Service

To run as a systemd service, create /etc/systemd/system/fastapi-app.service (adjust User, paths, and dependencies to match your server):

[Unit]
Description=FastAPI Application Service
After=network.target postgresql.service redis.service
Wants=postgresql.service redis.service

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/apps/fastapi-app
Environment="PATH=/opt/apps/fastapi-app/venv/bin"
ExecStart=/opt/apps/fastapi-app/venv/bin/python src/main.py
Restart=always
RestartSec=10

NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/apps/fastapi-app/logs

StandardOutput=append:/opt/apps/fastapi-app/logs/app.log
StandardError=append:/opt/apps/fastapi-app/logs/error.log
SyslogIdentifier=fastapi-app

[Install]
WantedBy=multi-user.target

Then:

sudo systemctl daemon-reload
sudo systemctl enable fastapi-app
sudo systemctl start fastapi-app

Testing

# Run all tests
make test

# Run with coverage
pytest --cov=app --cov-report=html

# Run specific test
pytest tests/test_api.py -v

Development

Creating new migration:

make migrate-create
# or
alembic revision --autogenerate -m "migration description"

Applying migrations:

make migrate
# or
alembic upgrade head

Code formatting:

make format

License

MIT License - see LICENSE file

About

A production-ready FastAPI boilerplate designed for rapid project setup — featuring clean architecture, logging and environment configuration support.

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages