9.5 KiB
Sojorn - Deployment Guide
This guide walks through deploying the Sojorn backend to Supabase.
Prerequisites
- Supabase CLI installed
- Supabase account created
- A Supabase project (create at app.supabase.com)
- Deno installed (for local Edge Function testing)
1. Initialize Supabase Project
If you haven't already linked your local project to Supabase:
# Login to Supabase
supabase login
# Link to your Supabase project
supabase link --project-ref YOUR_PROJECT_REF
# Get your project ref from: https://app.supabase.com/project/YOUR_PROJECT/settings/general
2. Deploy Database Migrations
Apply all schema migrations to your Supabase project:
# Push all migrations to production
supabase db push
# Verify migrations were applied
supabase db remote commit
Migrations will create:
- All tables (profiles, posts, comments, etc.)
- Row Level Security policies
- Helper functions (has_block_between, is_mutual_follow, etc.)
- Trust system functions
- Trending system tables
3. Seed Categories
Run the seed script to populate default categories:
# Connect to remote database and run seed script
psql postgresql://postgres:[YOUR-PASSWORD]@db.[YOUR-PROJECT-REF].supabase.co:5432/postgres \
-f supabase/seed/seed_categories.sql
Replace:
[YOUR-PASSWORD]with your database password (from Supabase dashboard)[YOUR-PROJECT-REF]with your project reference
This creates 12 categories:
- general (default enabled)
- quiet, gratitude, learning, writing, questions (opt-in)
- grief, struggle, recovery (sensitive, opt-in)
- care, solidarity, world (opt-in)
4. Deploy Edge Functions
Deploy all Edge Functions to Supabase:
# Deploy all functions at once
supabase functions deploy publish-post
supabase functions deploy publish-comment
supabase functions deploy block
supabase functions deploy report
supabase functions deploy feed-personal
supabase functions deploy feed-sojorn
supabase functions deploy trending
supabase functions deploy calculate-harmony
Or deploy individually as you build them.
5. Set Environment Variables
Edge Functions need access to secrets. Set these in your Supabase project:
# Set CRON_SECRET for scheduled harmony calculation
supabase secrets set CRON_SECRET=$(openssl rand -base64 32)
Environment variables automatically available to Edge Functions:
SUPABASE_URL– Your Supabase project URLSUPABASE_ANON_KEY– Public anon keySUPABASE_SERVICE_ROLE_KEY– Service role key (admin access)
6. Schedule Harmony Calculation (Cron)
The calculate-harmony function should run daily to recalculate user trust scores.
Option 1: Supabase Cron (Coming Soon)
Supabase is adding native cron support. When available:
-- In SQL Editor
SELECT cron.schedule(
'calculate-harmony-daily',
'0 2 * * *', -- 2 AM daily
$$
SELECT net.http_post(
url := 'https://YOUR_PROJECT_REF.supabase.co/functions/v1/calculate-harmony',
headers := jsonb_build_object(
'Authorization', 'Bearer YOUR_CRON_SECRET',
'Content-Type', 'application/json'
)
);
$$
);
Option 2: External Cron (GitHub Actions)
Create .github/workflows/harmony-cron.yml:
name: Calculate Harmony Daily
on:
schedule:
- cron: '0 2 * * *' # 2 AM UTC daily
workflow_dispatch: # Allow manual trigger
jobs:
calculate:
runs-on: ubuntu-latest
steps:
- name: Trigger harmony calculation
run: |
curl -X POST \
https://YOUR_PROJECT_REF.supabase.co/functions/v1/calculate-harmony \
-H "Authorization: Bearer ${{ secrets.CRON_SECRET }}" \
-H "Content-Type: application/json"
Set CRON_SECRET in GitHub Secrets.
Option 3: External Cron Service
Use cron-job.org or EasyCron:
- URL:
https://YOUR_PROJECT_REF.supabase.co/functions/v1/calculate-harmony - Method: POST
- Header:
Authorization: Bearer YOUR_CRON_SECRET - Schedule: Daily at 2 AM
7. Verify RLS Policies
Test that Row Level Security is working correctly:
-- Test as a regular user (should only see their own trust state)
SET request.jwt.claims TO '{"sub": "USER_ID_HERE"}';
SELECT * FROM trust_state; -- Should return 1 row (user's own)
-- Test block enforcement (users shouldn't see each other if blocked)
INSERT INTO blocks (blocker_id, blocked_id) VALUES ('user1', 'user2');
SET request.jwt.claims TO '{"sub": "user1"}';
SELECT * FROM profiles WHERE id = 'user2'; -- Should return 0 rows
-- Reset
RESET request.jwt.claims;
8. Configure Cloudflare (Optional)
Add basic DDoS protection and rate limiting:
- Add your domain to Cloudflare
- Set up a CNAME:
api.yourdomain.com→YOUR_PROJECT_REF.supabase.co
- Enable rate limiting:
- Limit: 100 requests per minute per IP
- Apply to:
/functions/v1/*
- Enable Bot Fight Mode
9. Test Edge Functions
Using curl:
# Get a user JWT token from Supabase Auth (sign up or log in first)
export TOKEN="YOUR_JWT_TOKEN"
# Test publishing a post
curl -X POST https://YOUR_PROJECT_REF.supabase.co/functions/v1/publish-post \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"category_id": "CATEGORY_UUID",
"body": "This is a friendly test post."
}'
# Test getting personal feed
curl https://YOUR_PROJECT_REF.supabase.co/functions/v1/feed-personal \
-H "Authorization: Bearer $TOKEN"
# Test Sojorn feed
curl https://YOUR_PROJECT_REF.supabase.co/functions/v1/feed-sojorn?limit=20 \
-H "Authorization: Bearer $TOKEN"
Using Postman:
Import this collection:
- Base URL:
https://YOUR_PROJECT_REF.supabase.co/functions/v1 - Authorization: Bearer Token (paste your JWT)
- Test all endpoints
10. Monitor and Debug
View Edge Function Logs
# Tail logs for a specific function
supabase functions logs publish-post --tail
# Or view in Supabase Dashboard:
# https://app.supabase.com/project/YOUR_PROJECT/logs/edge-functions
View Database Logs
-- Check audit log for recent events
SELECT * FROM audit_log ORDER BY created_at DESC LIMIT 50;
-- Check recent reports
SELECT * FROM reports ORDER BY created_at DESC LIMIT 20;
-- Check trust state distribution
SELECT tier, COUNT(*) FROM trust_state GROUP BY tier;
Monitor Performance
-- Slow queries
SELECT * FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;
-- Active connections
SELECT * FROM pg_stat_activity;
11. Backup Strategy
Automated Backups (Supabase Pro)
Supabase Pro includes daily backups. Enable in:
- Dashboard → Settings → Database → Backups
Manual Backup
# Export database schema and data
pg_dump -h db.YOUR_PROJECT_REF.supabase.co \
-U postgres -d postgres \
--no-owner --no-acl \
> backup_$(date +%Y%m%d).sql
12. Security Checklist
Before going live:
- All RLS policies enabled and tested
- Service role key kept secret (never in client code)
- Anon key is public (safe to expose)
- CRON_SECRET is strong and secret
- Rate limiting enabled (Cloudflare or Supabase)
- HTTPS only (enforced by default)
- Database password is strong
- No SQL injection vulnerabilities in Edge Functions
- Audit log captures all sensitive actions
- Trust score cannot be manipulated directly by users
13. Rollback Plan
If something goes wrong:
Roll back migrations:
# Reset to a previous migration
supabase db reset --version 20260106000003
Roll back Edge Functions:
# Delete a function
supabase functions delete publish-post
# Redeploy previous version (if you have git history)
git checkout previous_commit
supabase functions deploy publish-post
Restore database from backup:
# Using Supabase Dashboard (Pro plan)
# Settings → Database → Backups → Restore
# Or manually:
psql postgresql://postgres:[PASSWORD]@db.[PROJECT_REF].supabase.co:5432/postgres \
< backup_20260105.sql
14. Production Checklist
Before public launch:
- All migrations deployed
- All Edge Functions deployed
- Categories seeded
- Harmony cron job scheduled
- RLS policies tested
- Rate limiting configured
- Monitoring enabled
- Backup strategy confirmed
- Error tracking set up (Sentry, LogRocket, etc.)
- Load testing completed
- Security audit completed
- Transparency pages published
- Privacy policy and ToS published
- Data export and deletion tested
- Flutter app connected to production API
Support
For deployment issues:
Example .env.local (For Development)
SUPABASE_URL=http://localhost:54321
SUPABASE_ANON_KEY=your_local_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_local_service_role_key
CRON_SECRET=test_cron_secret
Get local keys from:
supabase status
Next Steps
After deployment:
- Build and deploy Flutter client
- Set up user signup flow
- Add admin tooling for moderation
- Monitor harmony score distribution
- Gather beta feedback
- Iterate on tone detection accuracy
- Optimize feed ranking based on engagement patterns
Sojorn backend is ready to support thoughtful, structural moderation from day one.