-
Notifications
You must be signed in to change notification settings - Fork 0
Installation Guide
This guide covers everything needed to get the IBF-SLM application running locally and considerations for deploying it to production.
- Prerequisites
- Clone the Repository
- Environment Configuration (.env)
- Install Python Dependencies
- Start the Database
- Run the Application
- Verify the Installation
- Production Considerations
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 --versionUpgrade pip if needed:
python3 -m pip install --upgrade pipgit clone https://github.com/Amit-RIMES/ibf-slm.git
cd ibf-slmThe 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 .envIf no .env.example exists yet, create .env from scratch:
touch .envOpen .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=trueImportant: Never commit
.envto version control. It is listed in.gitignoreby default. TheSECRET_KEYmust 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))"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.txtThis 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—.envconfiguration loader -
bcrypt— password hashing -
python-jose[cryptography]— JWT tokens -
jinja2— HTML templating
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 -dVerify the container is running:
docker compose psExpected 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 dbStop the database when not in use:
docker compose downTo also delete the stored data (full reset):
docker compose down -vWith the database running and .env configured, start the development server:
uvicorn app.main:app --reload-
--reloadwatches for file changes and restarts automatically — use this only in development. - On first startup the application's lifespan hook runs
CREATE TABLE IF NOT EXISTSfor 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 debug1. 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.toolA 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.
The steps above are tuned for local development. Before deploying to production, address each of the following.
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 headKeep migration files in version control alongside the application code.
- Remove all
DEBUG=true/APP_ENV=developmentflags. - Inject secrets via your platform's secret manager (AWS Secrets Manager, GCP Secret Manager, Vault, Kubernetes Secrets, etc.) rather than a
.envfile on disk. - Rotate
SECRET_KEYperiodically; all existing JWTs will be invalidated on rotation.
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 4Or 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 -Place nginx or a cloud load balancer in front of the app to handle:
- TLS termination (HTTPS)
- Static file serving
- Rate limiting
- Request buffering
-
Use a managed PostgreSQL service (RDS, Cloud SQL, Supabase, etc.) or a properly configured self-hosted instance — not the development Docker container.
-
Set
DATABASE_URLto 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
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.
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.
If the API is consumed by a separate front end, configure CORSMiddleware with an explicit allow_origins list. Never use allow_origins=["*"] in production.
Configure structured JSON logging and ship logs to a centralised platform (Datadog, Grafana Loki, CloudWatch, etc.) for observability in production.