Skip to content

Deployment

Turno LMS is deployed on AWS EC2 with PM2 process manager, Docker for Fineract, Nginx with SSL, and local PostgreSQL.

Production URLs

ServiceURLPort
Ops UIturnoops.incentius.net3000 (built)
Prefect Dashboardturnoprefect.incentius.net4201
Fineractturnomifos.incentius.net8443
Quart API(behind Nginx)5002

Infrastructure Components

PostgreSQL 16 (Local)

Not in Docker - runs directly on the server. Hosts both the application database and Fineract's tenant database.

Databases:

DatabasePurpose
fineractApplication data (RAW, BASE, CORE schemas)
fineract_defaultFineract's default tenant data
fineract_tenantsFineract's tenant metadata
prefect_dbPrefect flow run history

Docker (Fineract Only)

Fineract runs in Docker but connects to the local PostgreSQL:

bash
# Start Fineract
cd ~/mifos/fineract-fork
docker compose -f docker-compose-local-postgresql.yml up -d

Docker log rotation (prevents disk bloat):

json
// /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

PM2 Processes

Three processes managed by PM2:

bash
pm2 start deploy/ecosystem.config.js
ProcessCommandLog Rotation
prefect-stackbash start_prefect.sh10MB, 3 files
quart-appgunicorn -k uvicorn.workers.UvicornWorker -b 0.0.0.0:5002 app:app10MB, 3 files
rq-workerpython worker.py10MB, 3 files

Redis

bash
redis-server   # Port 6379

Used by RQ for job queuing and Quart sessions.

Nginx

SSL termination and reverse proxy for all services. Key config:

nginx
# Important: increase for file uploads
client_max_body_size 20M;

Initial Setup

1. Clone and Install

bash
cd ~
git clone <repo-url> turno-fineract-lms
cd turno-fineract-lms

# Python backend
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
cp config.py.sample config.py   # Edit with real credentials

# Frontend — build and deploy to /var/www/html/ops_ui
bash deploy/build_ops_ui.sh

The build script (deploy/build_ops_ui.sh) installs npm dependencies, builds the production bundle, and copies it to /var/www/html/ops_ui (served by Nginx).

2. Database Setup

bash
# Create databases
sudo -u postgres createdb fineract
sudo -u postgres createdb fineract_default
sudo -u postgres createdb fineract_tenants
sudo -u postgres createdb prefect_db

# Initialize schemas and tables
./venv/bin/python scripts/init_all_tables.py

3. Start Fineract

bash
cd ~/mifos/fineract-fork
docker compose -f docker-compose-local-postgresql.yml up -d

# Register loan outstanding report (for loan-level recon)
cd ~/turno-fineract-lms
./venv/bin/python scripts/register_loan_outstanding_report.py

4. Start Services

bash
# Redis
redis-server &

# PM2 (Prefect + Quart + RQ Worker)
pm2 start deploy/ecosystem.config.js

# Register Prefect deployments
PREFECT_API_URL=http://127.0.0.1:4201/api ./venv/bin/python scripts/register_deployments.py

5. Verify

bash
# Fineract health
curl -sk https://localhost:8443/fineract-provider/api/v1/authentication \
  -H "Fineract-Platform-TenantId: default" \
  -d '{"username":"mifos","password":"password"}'

# Quart health
curl http://localhost:5002/

# Prefect health
curl http://localhost:4201/api/health

# dbt connection
cd dbt && ../venv/bin/dbt debug

Deploying Updates

bash
cd ~/turno-fineract-lms
git pull

# If Python deps changed
./venv/bin/pip install -r requirements.txt

# If frontend changed
bash deploy/build_ops_ui.sh

# If Prefect deployments changed
PREFECT_API_URL=http://127.0.0.1:4201/api ./venv/bin/python scripts/register_deployments.py

# Restart services
pm2 restart all

RAW Layer Rewrite (One-Time Migration)

When deploying the YAML-based lender mapping rewrite:

bash
# 1. Add file_hash column
sudo -u postgres psql -d fineract -c '
  ALTER TABLE "RAW"."RAW_S3_FILE_PROCESSING_LOG"
  ADD COLUMN IF NOT EXISTS file_hash VARCHAR(32);
  CREATE INDEX IF NOT EXISTS idx_s3_log_file_hash
  ON "RAW"."RAW_S3_FILE_PROCESSING_LOG" (file_hash);
'

# 2. Clear stale processed data
sudo -u postgres psql -d fineract -c '
  TRUNCATE TABLE "CORE"."CORE_TRANSACTION_DATA_PROCESSED";
'

# 3. Reset RAW + BASE tables
./venv/bin/python scripts/reset_raw_nach_tables.py --execute

# 4. Rebuild with dbt
cd dbt && ../venv/bin/dbt run --full-refresh

Log Cleanup

Automated daily cleanup prevents disk bloat:

bash
# Add to crontab
crontab -e
0 2 * * * /home/ubuntu/turno-fineract-lms/scripts/cleanup_logs.sh --execute >> /home/ubuntu/logs/cleanup.log 2>&1

Cleans: PM2 logs, Docker container logs, dbt logs, S3 temp files, old daily log directories.

Monitoring

WhatHow
Service statuspm2 status
PM2 logspm2 logs
Fineractdocker ps + docker logs fineract-fork-fineract-1
PostgreSQLsudo -u postgres psql -d fineract -c "SELECT pg_size_pretty(pg_database_size('fineract'))"
Disk usagedf -h /
Prefect flow runshttps://turnoprefect.incentius.net
File processingOps UI > Processing Log

Turno Fineract LMS Documentation