docs: Update TODO and add Funkwhale deployment guide
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
135bb7f08d
commit
4315da74b2
143
sojorn_docs/FUNKWHALE_DEPLOYMENT.md
Normal file
143
sojorn_docs/FUNKWHALE_DEPLOYMENT.md
Normal 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>"
|
||||||
|
```
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
ssh -i ~/.ssh/mpls.pem patrick@116.202.231.103
|
```bash
|
||||||
cd /opt/sojorn
|
ssh -i ~/.ssh/mpls.pem patrick@116.202.231.103
|
||||||
git pull internal goSojorn
|
cd /opt/sojorn
|
||||||
psql "" -f go-backend/migrations/20260218_feed_impressions_and_group_keys.sql
|
|
||||||
cd go-backend && go build -o bin/api ./cmd/api/...
|
# Add internal remote if missing:
|
||||||
echo PASSWORD | sudo -S systemctl restart sojorn-api.service
|
git remote get-url internal 2>/dev/null || git remote add internal https://git.mp.ls/patrick/sojorn.git
|
||||||
|
|
||||||
|
git pull internal goSojorn
|
||||||
|
psql "$DATABASE_URL" -f go-backend/migrations/20260218_feed_impressions_and_group_keys.sql
|
||||||
|
cd go-backend && go build -o bin/api ./cmd/api/...
|
||||||
|
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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue