Files
membership-be/DEPLOYMENT.md
2026-01-04 19:08:54 +07:00

6.8 KiB

Deployment Guide - LOAF Membership Platform

Fresh Database Installation

Follow these steps in order for a brand new deployment:

Step 1: Create PostgreSQL Database

# Connect to PostgreSQL
psql -U postgres

# Create database
CREATE DATABASE membership_db;

# Create user (if needed)
CREATE USER loaf_admin WITH PASSWORD 'your-secure-password';
GRANT ALL PRIVILEGES ON DATABASE membership_db TO loaf_admin;

# Exit PostgreSQL
\q

Step 2: Run Initial Schema

cd backend

# Apply the complete schema (creates all 17 tables, 8 enums, indexes)
psql -U loaf_admin -d membership_db -f migrations/000_initial_schema.sql

What this creates:

  • 17 tables: users, events, subscriptions, roles, permissions, etc.
  • 8 custom enums: UserStatus, UserRole, RSVPStatus, etc.
  • All indexes and foreign keys
  • All constraints and defaults

Step 3: Mark Database for Alembic Tracking

# Mark the database as being at the baseline
alembic stamp head

Step 4: Verify Setup

# Check Alembic status
alembic current
# Expected output: 001_initial_baseline (head)

# Check database tables
psql -U loaf_admin -d membership_db -c "\dt"
# Should show 17 tables

Step 5: Set Environment Variables

Create backend/.env:

# Database
DATABASE_URL=postgresql://loaf_admin:your-password@localhost:5432/membership_db

# JWT
JWT_SECRET=your-secret-key-minimum-32-characters-long
JWT_ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

# Email (SMTP)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=noreply@loafmembers.org
SMTP_FROM_NAME=LOAF Membership

# Frontend URL
FRONTEND_URL=https://members.loafmembers.org

# Cloudflare R2
R2_ENDPOINT_URL=https://your-account-id.r2.cloudflarestorage.com
R2_ACCESS_KEY_ID=your-r2-access-key
R2_SECRET_ACCESS_KEY=your-r2-secret-key
R2_BUCKET_NAME=loaf-membership
R2_PUBLIC_URL=https://cdn.loafmembers.org

# Stripe
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PRICE_ID_ANNUAL=price_...
STRIPE_PRICE_ID_GROUP=price_...

Step 6: Install Dependencies

# Backend
cd backend
pip install -r requirements.txt

# Frontend
cd ../frontend
yarn install

Step 7: Start Services

# Backend (in backend/)
uvicorn server:app --host 0.0.0.0 --port 8000

# Frontend (in frontend/)
yarn start

Step 8: Create First Superadmin User

# Connect to database
psql -U loaf_admin -d membership_db

# Create superadmin user
INSERT INTO users (
    id, email, password_hash, first_name, last_name,
    status, role, email_verified, created_at, updated_at
) VALUES (
    gen_random_uuid(),
    'admin@loafmembers.org',
    '$2b$12$your-bcrypt-hashed-password-here',  -- Use bcrypt to hash password
    'Admin',
    'User',
    'active',
    'superadmin',
    true,
    NOW(),
    NOW()
);

Generate password hash:

import bcrypt
password = b"your-secure-password"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
print(hashed.decode())

Existing Database Update

For updating an existing deployment with new code:

Step 1: Backup Database

pg_dump -U loaf_admin membership_db > backup_$(date +%Y%m%d_%H%M%S).sql

Step 2: Pull Latest Code

git pull origin main

Step 3: Install New Dependencies

# Backend
cd backend
pip install -r requirements.txt

# Frontend
cd ../frontend
yarn install

Step 4: Apply Database Migrations

cd backend

# Check current migration status
alembic current

# Apply pending migrations
alembic upgrade head

# Verify
alembic current

Step 5: Restart Services

# Restart backend
systemctl restart membership-backend

# Rebuild and restart frontend
cd frontend
yarn build
systemctl restart membership-frontend

First-Time Alembic Setup (Existing Database)

If you have an existing database that was created with 000_initial_schema.sql but hasn't been marked for Alembic tracking:

cd backend

# Mark database as being at the baseline (one-time only)
alembic stamp head

# Verify
alembic current
# Expected output: 001_initial_baseline (head)

Database Schema Verification

Check all tables exist:

psql -U loaf_admin -d membership_db -c "\dt"

Expected tables (17 total):

  • users
  • events
  • event_rsvps
  • subscriptions
  • subscription_plans
  • permissions
  • roles
  • role_permissions
  • user_invitations
  • import_jobs
  • import_rollback_audit
  • event_galleries
  • newsletter_archives
  • financial_reports
  • bylaws_documents
  • donations
  • storage_usage

Check enums:

psql -U loaf_admin -d membership_db -c "\dT"

Expected enums (8 total):

  • userstatus
  • userrole
  • rsvpstatus
  • subscriptionstatus
  • donationtype
  • donationstatus
  • invitationstatus
  • importjobstatus

Rollback Procedures

Rollback Last Migration

cd backend
alembic downgrade -1

Rollback to Specific Revision

alembic downgrade <revision_id>

Complete Database Reset

# WARNING: This deletes ALL data!

# 1. Backup first
pg_dump -U loaf_admin membership_db > emergency_backup.sql

# 2. Drop database
dropdb membership_db

# 3. Recreate database
createdb membership_db

# 4. Run initial schema
psql -U loaf_admin -d membership_db -f backend/migrations/000_initial_schema.sql

# 5. Mark for Alembic
cd backend
alembic stamp head

Troubleshooting

"relation does not exist" error

The database wasn't initialized properly.

Solution:

psql -U loaf_admin -d membership_db -f backend/migrations/000_initial_schema.sql
alembic stamp head

"Target database is not up to date"

Migrations haven't been applied.

Solution:

cd backend
alembic upgrade head

"Can't locate revision"

Alembic tracking is out of sync.

Solution:

# Check what revision the database thinks it's at
alembic current

# If empty or wrong, manually set it
alembic stamp head

Database connection errors

Check .env file has correct DATABASE_URL.

Format:

DATABASE_URL=postgresql://username:password@host:port/database

Production Checklist

Before going live:

  • Database created and schema applied
  • Alembic marked as up-to-date (alembic current shows baseline)
  • All environment variables set in .env
  • Dependencies installed (Python + Node)
  • Superadmin user created
  • SSL certificates configured
  • Backup system in place
  • Monitoring configured
  • Domain DNS pointing to server
  • Email sending verified (SMTP working)
  • Stripe webhook endpoint configured
  • R2 bucket accessible and CORS configured

Support

For issues:

  1. Check logs: tail -f backend/logs/app.log
  2. Check Alembic status: alembic current
  3. Verify environment variables: cat backend/.env
  4. Test database connection: psql -U loaf_admin -d membership_db