docs: Update TODO and add Funkwhale deployment guide

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Britton 2026-02-17 16:03:45 -06:00
parent 135bb7f08d
commit 4315da74b2
2 changed files with 183 additions and 22 deletions

View file

@ -0,0 +1,143 @@
# Funkwhale Deployment Guide
Funkwhale provides the audio library for the audio overlay system in Quips.
## Server Setup
SSH to the server and run:
```bash
ssh -i ~/.ssh/mpls.pem patrick@116.202.231.103
# Create Funkwhale directory
mkdir -p /opt/funkwhale/{data,music,media,static,nginx}
cd /opt/funkwhale
```
## docker-compose.yml
Create `/opt/funkwhale/docker-compose.yml`:
```yaml
version: "3"
services:
funkwhale:
image: funkwhale/all-in-one:1.4.0
container_name: funkwhale
restart: unless-stopped
environment:
- FUNKWHALE_HOSTNAME=audio.sojorn.net
- FUNKWHALE_PROTOCOL=https
- NESTED_PROXY=1
- DJANGO_SECRET_KEY=${FUNKWHALE_SECRET_KEY}
- DATABASE_URL=postgresql://funkwhale:${FUNKWHALE_DB_PASS}@db/funkwhale
- CACHE_URL=redis://redis:6379/0
- EMAIL_CONFIG=smtp+tls://${SMTP_USER}:${SMTP_PASS}@${SMTP_HOST}:${SMTP_PORT}
- DEFAULT_FROM_EMAIL=no-reply@sojorn.net
volumes:
- ./data:/data
- ./music:/music:ro
- ./media:/srv/funkwhale/data/media
- ./static:/srv/funkwhale/data/static
ports:
- "127.0.0.1:5000:80"
depends_on:
- db
- redis
db:
image: postgres:15-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=funkwhale
- POSTGRES_PASSWORD=${FUNKWHALE_DB_PASS}
- POSTGRES_DB=funkwhale
volumes:
- ./data/db:/var/lib/postgresql/data
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- ./data/redis:/data
```
Create `/opt/funkwhale/.env`:
```env
FUNKWHALE_SECRET_KEY=<generate with: python3 -c "import secrets; print(secrets.token_hex(50))">
FUNKWHALE_DB_PASS=<strong-password>
```
Start it:
```bash
cd /opt/funkwhale && docker compose up -d
# Wait for startup (~60s), then create superuser:
docker compose exec funkwhale manage createsuperuser
```
## Nginx Config
Add a server block to `/etc/nginx/sites-available/sojorn` (or create a new one):
```nginx
server {
listen 443 ssl;
server_name audio.sojorn.net;
ssl_certificate /etc/letsencrypt/live/audio.sojorn.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/audio.sojorn.net/privkey.pem;
client_max_body_size 500M;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
Get the certificate:
```bash
sudo certbot --nginx -d audio.sojorn.net
sudo nginx -t && sudo systemctl reload nginx
```
## Wire into Go Backend
Add to `/opt/sojorn/.env`:
```env
FUNKWHALE_BASE=http://127.0.0.1:5000
```
Then rebuild and restart:
```bash
cd /opt/sojorn/go-backend && go build -o bin/api ./cmd/api/...
echo PASSWORD | sudo -S systemctl restart sojorn-api.service
```
## Seed With Royalty-Free Music
Funkwhale can import from local directories. Drop MP3s into `/opt/funkwhale/music/` then:
```bash
docker compose exec funkwhale manage import_files \
"/music/" --recursive --noinput
```
Good free sources: [Free Music Archive](https://freemusicarchive.org), [ccMixter](https://ccmixter.org).
## Verify
```bash
curl http://127.0.0.1:5000/api/v1/tracks/?playable=true
# Should return JSON with track list
# Via Go proxy (after adding FUNKWHALE_BASE):
curl https://api.sojorn.net/api/v1/audio/library?q=jazz \
-H "Authorization: Bearer <your-jwt>"
```

View file

@ -1,7 +1,7 @@
# Sojorn Development Status # Sojorn Development Status
**Last Updated**: February 18, 2026 **Last Updated**: February 18, 2026
**Branch**: **Status**: Active Development — substantial MVP complete, several systems still being wired **Branch**: goSojorn — **Status**: Active Development — MVP near-complete
--- ---
@ -16,6 +16,7 @@
- Feed algorithm: engagement weighting, cooling period (0.2x multiplier), 60/20/20 diversity injection, impression recording - Feed algorithm: engagement weighting, cooling period (0.2x multiplier), 60/20/20 diversity injection, impression recording
- Repost/boost: 4 repost types, amplification analytics, trending posts - Repost/boost: 4 repost types, amplification analytics, trending posts
- Image/video uploads to Cloudflare R2 with signed URLs - Image/video uploads to Cloudflare R2 with signed URLs
- GET /media/sign?path=X — resolves relative R2 keys to full URLs
- Video moderation: FFmpeg frame extraction -> R2 upload -> Google Vision AI + OpenAI analysis - Video moderation: FFmpeg frame extraction -> R2 upload -> Google Vision AI + OpenAI analysis
- Follow/unfollow, search (users/posts/hashtags/beacons) - Follow/unfollow, search (users/posts/hashtags/beacons)
- Profile widget system with layout persistence - Profile widget system with layout persistence
@ -26,10 +27,13 @@
- Capsule key distribution and auto-healing rotation - Capsule key distribution and auto-healing rotation
- Group feed endpoint - Group feed endpoint
- Capsule admin: rotate keys, invite member, remove member, settings - Capsule admin: rotate keys, invite member, remove member, settings
- GET /users/by-handle/:handle — profile lookup for capsule invite
- Health check service: /health, /health/detailed, /health/ready, /health/live - Health check service: /health, /health/detailed, /health/ready, /health/live
- Content moderation: OpenAI text + Google Vision images, Three Poisons scoring - Content moderation: OpenAI text + Google Vision images, Three Poisons scoring
- NSFW labeling, blur toggles, appeal system, safe links - NSFW labeling, blur toggles, appeal system, safe links
- GeoIP, Nginx reverse proxy + SSL/TLS - GeoIP, Nginx reverse proxy + SSL/TLS
- Audio overlay proxy: GET /audio/library, GET /audio/library/:trackId/listen
- Returns 503 until FUNKWHALE_BASE is set — gracefully handled in Flutter
### Admin Panel (Next.js, port 3001) ### Admin Panel (Next.js, port 3001)
- Dashboard, user management, post management, bulk actions - Dashboard, user management, post management, bulk actions
@ -41,18 +45,34 @@
- Groups and Capsules page (list, member management, deactivate, key rotation status) - Groups and Capsules page (list, member management, deactivate, key rotation status)
- Quip Repair page (list missing thumbnails, server-side FFmpeg repair) - Quip Repair page (list missing thumbnails, server-side FFmpeg repair)
### Flutter App
- Full audio overlay system in Quip recorder:
- AudioLibraryScreen: Device tab (file_picker) + Library tab (Funkwhale via Go proxy)
- EnhancedQuipRecorderScreen: music button, audio chip, volume slider
- VideoStitchingService: ffmpeg audio mix pass (amix with dropout_transition)
- Group navigation (clusters → GroupScreen)
- Public cluster group feed
- Share post via share_plus
- Signed media URL resolution via Go backend
--- ---
## Needs Server Deploy ## Needs Server Deploy
Code is on goSojorn branch, NOT yet live. Run from WSL Ubuntu: Code is on goSojorn branch, NOT yet live. The `internal` remote may be missing on the server.
```bash
ssh -i ~/.ssh/mpls.pem patrick@116.202.231.103 ssh -i ~/.ssh/mpls.pem patrick@116.202.231.103
cd /opt/sojorn cd /opt/sojorn
# Add internal remote if missing:
git remote get-url internal 2>/dev/null || git remote add internal https://git.mp.ls/patrick/sojorn.git
git pull internal goSojorn git pull internal goSojorn
psql "" -f go-backend/migrations/20260218_feed_impressions_and_group_keys.sql psql "$DATABASE_URL" -f go-backend/migrations/20260218_feed_impressions_and_group_keys.sql
cd go-backend && go build -o bin/api ./cmd/api/... cd go-backend && go build -o bin/api ./cmd/api/...
echo PASSWORD | sudo -S systemctl restart sojorn-api.service echo PASSWORD | sudo -S systemctl restart sojorn-api.service
```
--- ---
@ -60,23 +80,19 @@ Code is on goSojorn branch, NOT yet live. Run from WSL Ubuntu:
### High Priority ### High Priority
**Audio Overlay System** **Funkwhale Infrastructure** (audio library backend)
- Flutter: AudioLibraryScreen (Device tab + Funkwhale Library tab) - Deploy Funkwhale Docker pod on server — see sojorn_docs/FUNKWHALE_DEPLOYMENT.md
- Flutter: Voice overlay recording + ffmpeg_kit mixing - Add to /opt/sojorn/.env: `FUNKWHALE_BASE=http://127.0.0.1:5000`
- Backend: Funkwhale proxy (GET /audio/search, GET /audio/track/:id) - Seed with royalty-free tracks
- Infrastructure: Funkwhale Docker pod + Nginx proxy at /funkwhale/ - Optional: `audio.sojorn.net` Nginx block + SSL cert
**Small Backend Gaps**
- GET /media/sign?path=X endpoint (Flutter getSignedMediaUrl calls this, not yet in Go routes)
- GET /users/by-handle/:handle (used by capsule invite -- verify exists)
### Medium Priority ### Medium Priority
**Flutter Polish** **Flutter Polish**
- sojorn_rich_text.dart -- profile navigation from @mentions - sojorn_rich_text.dart profile navigation from @mentions
- post_with_video_widget.dart -- post options menu (edit, delete, report) - post_with_video_widget.dart post options menu (edit, delete, report)
- video_player_with_comments.dart -- more options button - video_player_with_comments.dart more options button
- reading_post_card.dart -- share functionality - reading_post_card.dart share functionality
**Algorithm Transparency** **Algorithm Transparency**
- Show users why a post appeared in their feed - Show users why a post appeared in their feed
@ -88,7 +104,7 @@ Code is on goSojorn branch, NOT yet live. Run from WSL Ubuntu:
- Delete go-backend/cmd/supabase-migrate/ (dead tool) - Delete go-backend/cmd/supabase-migrate/ (dead tool)
- Remove stale Supabase comments in go-backend/internal/middleware/auth.go - Remove stale Supabase comments in go-backend/internal/middleware/auth.go
- Remove forceResetBrokenKeys() from simple_e2ee_service.dart - Remove forceResetBrokenKeys() from simple_e2ee_service.dart
- go-backend root: loose check_table.go, seed_groups*.go -- conflicting main, move or delete - go-backend root: loose check_table.go, seed_groups*.go conflicting main, move or delete
**Infrastructure** **Infrastructure**
- CI/CD pipeline (currently manual deploy) - CI/CD pipeline (currently manual deploy)
@ -106,3 +122,5 @@ Code is on goSojorn branch, NOT yet live. Run from WSL Ubuntu:
- Capsule auto key rotation on open + admin modals (rotate, invite, remove, settings) - Capsule auto key rotation on open + admin modals (rotate, invite, remove, settings)
- Flutter: group navigation, group feed, share_plus, signed URL, quip repair wired to Go - Flutter: group navigation, group feed, share_plus, signed URL, quip repair wired to Go
- Health check service wired into routes - Health check service wired into routes
- GET /media/sign and GET /users/by-handle/:handle endpoints added
- Full audio overlay system: AudioLibraryScreen, Funkwhale proxy routes, ffmpeg amix