Skip to content

Installation Guide

Amit edited this page May 29, 2026 · 1 revision

Installation Guide

This guide covers everything needed to get the IBF-SLM application running locally and considerations for deploying it to production.


Table of Contents

  1. Prerequisites
  2. Clone the Repository
  3. Environment Configuration (.env)
  4. Install Python Dependencies
  5. Start the Database
  6. Run the Application
  7. Verify the Installation
  8. Production Considerations

Prerequisites

Ensure the following are installed on your system before proceeding.

Requirement Minimum Version Notes
Python 3.11+ Required for modern asyncio and type hint support
pip Latest Comes with Python; upgrade if needed
Docker 24+ Required to run the local PostgreSQL container
Docker Compose v2 (plugin) Bundled with Docker Desktop; docker compose (no hyphen)
Git Any recent For cloning the repository

Check your versions:

python3 --version
docker --version
docker compose version
git --version

Upgrade pip if needed:

python3 -m pip install --upgrade pip

Clone the Repository

git clone https://github.com/Amit-RIMES/ibf-slm.git
cd ibf-slm

Environment Configuration (.env)

The application uses pydantic-settings to load all configuration from a .env file in the project root. No settings are hard-coded.

Copy the provided example file and fill in your values:

cp .env.example .env

If no .env.example exists yet, create .env from scratch:

touch .env

Open .env in your editor and set the following variables:

# --- Database ---
# Must match the credentials in docker-compose.yml for local development
DATABASE_URL=postgresql+asyncpg://ibf_user:ibf_password@localhost:5432/ibf_slm

# --- Security ---
# Generate a strong random secret: python3 -c "import secrets; print(secrets.token_hex(32))"
SECRET_KEY=replace_with_a_long_random_string
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

# --- Application ---
# Set to "development" locally; use "production" in prod environments
APP_ENV=development
DEBUG=true

Important: Never commit .env to version control. It is listed in .gitignore by default. The SECRET_KEY must be a cryptographically random value — do not reuse the placeholder above.

Generate a secure SECRET_KEY:

python3 -c "import secrets; print(secrets.token_hex(32))"

Install Python Dependencies

It is strongly recommended to use a virtual environment to isolate project dependencies.

Create and activate a virtual environment:

python3 -m venv .venv
source .venv/bin/activate        # Linux / macOS
# .venv\Scripts\activate.bat     # Windows (cmd)
# .venv\Scripts\Activate.ps1     # Windows (PowerShell)

Install dependencies:

pip install -r requirements.txt

This installs the core stack:

  • fastapi — web framework
  • uvicorn[standard] — ASGI server
  • sqlalchemy[asyncio] — ORM (async mode)
  • asyncpg — async PostgreSQL driver
  • alembic — database migrations
  • pydantic-settings.env configuration loader
  • bcrypt — password hashing
  • python-jose[cryptography] — JWT tokens
  • jinja2 — HTML templating

Start the Database

The project ships with a docker-compose.yml that spins up a local PostgreSQL instance. The credentials in that file must match the DATABASE_URL in your .env.

docker compose up -d

Verify the container is running:

docker compose ps

Expected output:

NAME            IMAGE         STATUS          PORTS
ibf-slm-db-1   postgres:15   Up X seconds    0.0.0.0:5432->5432/tcp

Check the logs if anything looks wrong:

docker compose logs db

Stop the database when not in use:

docker compose down

To also delete the stored data (full reset):

docker compose down -v

Run the Application

With the database running and .env configured, start the development server:

uvicorn app.main:app --reload
  • --reload watches for file changes and restarts automatically — use this only in development.
  • On first startup the application's lifespan hook runs CREATE TABLE IF NOT EXISTS for all models via SQLAlchemy, so the schema is created automatically without any manual migration step for local development.

Optional flags:

# Bind to a specific host/port (defaults: 127.0.0.1:8000)
uvicorn app.main:app --reload --host 0.0.0.0 --port 8080

# Increase log verbosity
uvicorn app.main:app --reload --log-level debug

Verify the Installation

1. Check the interactive API docs (Swagger UI):

Open your browser and navigate to:

http://127.0.0.1:8000/docs

You should see the full OpenAPI documentation for all available routes.

2. Check the ReDoc alternative:

http://127.0.0.1:8000/redoc

3. Hit the health / root endpoint:

curl -s http://127.0.0.1:8000/ | python3 -m json.tool

A 200 OK response (or the application's root page) confirms the app is up and connected to the database.

4. Confirm the database tables were created:

docker exec -it ibf-slm-db-1 psql -U ibf_user -d ibf_slm -c "\dt"

This lists all tables that were auto-created by the lifespan hook on startup.


Production Considerations

The steps above are tuned for local development. Before deploying to production, address each of the following.

Database Migrations (Alembic)

In production, do not rely on the auto-create lifespan hook. Use Alembic to manage schema changes safely.

# Apply all pending migrations
alembic upgrade head

# Create a new migration after changing a model
alembic revision --autogenerate -m "describe your change"
alembic upgrade head

Keep migration files in version control alongside the application code.

Environment Variables

  • Remove all DEBUG=true / APP_ENV=development flags.
  • Inject secrets via your platform's secret manager (AWS Secrets Manager, GCP Secret Manager, Vault, Kubernetes Secrets, etc.) rather than a .env file on disk.
  • Rotate SECRET_KEY periodically; all existing JWTs will be invalidated on rotation.

ASGI Server

Do not use --reload in production. Run uvicorn behind a process manager with multiple workers:

uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4

Or use gunicorn with the uvicorn worker class for better process management:

pip install gunicorn
gunicorn app.main:app \
  -k uvicorn.workers.UvicornWorker \
  --workers 4 \
  --bind 0.0.0.0:8000 \
  --access-logfile - \
  --error-logfile -

Reverse Proxy

Place nginx or a cloud load balancer in front of the app to handle:

  • TLS termination (HTTPS)
  • Static file serving
  • Rate limiting
  • Request buffering

PostgreSQL

  • Use a managed PostgreSQL service (RDS, Cloud SQL, Supabase, etc.) or a properly configured self-hosted instance — not the development Docker container.

  • Set DATABASE_URL to use a connection pooler (e.g., PgBouncer) if the application will have many concurrent connections.

  • Enable SSL on the database connection:

    DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/dbname?ssl=require

Password Hashing (bcrypt)

bcrypt is configured with a default work factor. Review the work factor for your target hardware to ensure it provides adequate resistance to brute-force attacks without being too slow for your throughput requirements.

JWT Token Expiry

Set ACCESS_TOKEN_EXPIRE_MINUTES to a value appropriate for your security posture. Consider implementing refresh tokens for long-lived sessions rather than extending the access token lifetime.

CORS and Trusted Hosts

If the API is consumed by a separate front end, configure CORSMiddleware with an explicit allow_origins list. Never use allow_origins=["*"] in production.

Logging and Monitoring

Configure structured JSON logging and ship logs to a centralised platform (Datadog, Grafana Loki, CloudWatch, etc.) for observability in production.