This guide covers upgrading VLog between versions.
Always backup before upgrading:
# Backup database
pg_dump -U vlog -Fc vlog > /backup/vlog-pre-upgrade-$(date +%Y%m%d).dump
# Verify backup
pg_restore --list /backup/vlog-pre-upgrade-*.dump | headsudo systemctl stop vlog.targetcd /path/to/vlog
git fetch origin
git checkout main
git pull origin mainsource venv/bin/activate
pip install -e .alembic upgrade head# Build new container image
docker build -f Dockerfile.worker.gpu -t vlog-worker-gpu:rocky10 .
# Push to registry or import to containerd
docker save vlog-worker-gpu:rocky10 | sudo k3s ctr images import -
# Rollout new version
kubectl rollout restart deployment/vlog-worker-nvidia -n vlog
kubectl rollout restart deployment/vlog-worker-intel -n vlog
kubectl rollout status deployment/vlog-worker-nvidia -n vlogsudo systemctl start vlog.target# Health checks
curl http://localhost:9000/health
curl http://localhost:9001/health
curl http://localhost:9002/api/health
# Check workers
vlog worker statusImpact: If you access the admin UI from a different origin than the API, you MUST configure CORS.
What Changed:
- Previous behavior: Admin API allowed all origins by default (
*) - New behavior: Admin API defaults to same-origin only (empty list)
Who is affected:
- Users with reverse proxy setups serving UI and API from different hosts
- Users running development servers (e.g., Vite on :3000, API on :9001)
- Users with Docker Compose using separate UI and API containers on different ports
Who is NOT affected:
- Users accessing admin UI directly from the server (same hostname) - most common setup
- Single-origin deployments where UI and API share the same hostname
How to tell if you need to configure CORS:
- After upgrading, open browser console when accessing admin UI
- If you see "CORS policy" errors, configure
VLOG_ADMIN_CORS_ORIGINS - Same-origin setups (typical) need no changes
Action Required (if affected):
# Set the origin(s) that should access the admin API
export VLOG_ADMIN_CORS_ORIGINS=http://192.168.1.100:3000,http://devbox.local:3000
# Restart admin API
sudo systemctl restart vlog-adminConfiguration notes:
- Origins must include protocol:
http://example.com:3000(correct),example.com:3000(wrong) - Origins must NOT have trailing slash:
http://example.com:3000(correct),http://example.com:3000/(wrong) - Do not mix
*with specific origins - use either*alone or specific origins only - Invalid origin format will cause startup failure with clear error message
This version adds significant new features: playlists, chapters, sprite sheets, advanced player features, and reliability improvements.
New Features:
- Playlists & Collections - Organize videos into playlists, collections, series, or courses
- Video Chapters - Timeline navigation with chapter markers (max 50 per video)
- Sprite Sheets - Thumbnail previews for timeline scrubbing
- Featured Videos - Mark videos as featured for homepage prominence
- Display Settings - Configurable public UI settings
- Cursor-based Pagination - Improved API performance for large datasets
- Table Partitioning -
playback_sessionspartitioned by month for analytics performance - Streaming Segment Upload - Progressive upload during transcoding (optional)
- Circuit Breaker - Worker HTTP client resilience pattern
Database Migrations:
# Run all migrations (020-025)
alembic upgrade head
# Migrations included:
# 020 - playlists and playlist_items tables
# 021 - playback_sessions table partitioning
# 022 - is_featured column on videos
# 023 - playback_sessions composite index
# 024 - chapters table and has_chapters column
# 025 - sprite_queue table and sprite sheet columnsNew Environment Variables (all optional):
# Display settings
VLOG_DISPLAY_SHOW_VIEW_COUNTS=true
VLOG_DISPLAY_SHOW_TAGLINE=true
VLOG_DISPLAY_TAGLINE="Your video platform"
# Circuit breaker
VLOG_HTTP_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5
VLOG_HTTP_CIRCUIT_BREAKER_RECOVERY_TIMEOUT=30
VLOG_HTTP_CIRCUIT_BREAKER_SUCCESS_THRESHOLD=2
# Streaming segment upload (optional, default off)
VLOG_WORKER_STREAMING_UPLOAD=false
# Sprite sheet generation
VLOG_SPRITE_INTERVAL=10
VLOG_SPRITE_TILE_SIZE=10
VLOG_SPRITE_FRAME_WIDTH=160
# Worker version gating (optional)
VLOG_WORKER_VERSION_CHECK_ENABLED=false
VLOG_REQUIRED_WORKER_VERSION=0.0.3New API Endpoints:
| Endpoint | Description |
|---|---|
GET/POST /api/playlists |
Playlist management |
GET/POST /api/playlists/{id}/videos |
Playlist video management |
GET/POST /api/videos/{id}/chapters |
Chapter management |
GET/POST /api/videos/{id}/sprites |
Sprite sheet management |
GET /api/config/display |
Public display settings |
Worker Container Update:
# Rebuild worker containers with new dependencies
docker build -f Dockerfile.worker.gpu -t vlog-worker-gpu:rocky10 .
# Deploy to Kubernetes
kubectl rollout restart deployment/vlog-worker-nvidia -n vlog
kubectl rollout restart deployment/vlog-worker-intel -n vlogPost-Upgrade Steps:
-
Verify new tables exist:
psql -U vlog -d vlog -c "\dt playlists; \dt chapters; \dt sprite_queue;" -
Verify API endpoints work:
curl http://localhost:9001/api/playlists curl http://localhost:9000/api/config/display
-
Optional: Configure display settings:
vlog settings set display.show_view_counts true vlog settings set display.tagline "My Video Platform"
This version adds webhook notifications, video downloads, and security improvements.
New Features:
- Webhook Notifications - Event-driven notifications for external integrations
- Video Downloads - Allow users to download video files
- argon2id API Key Hashing - Upgraded from SHA-256 for worker authentication
- Deployment Events - Track worker container deployments
- Enhanced Bulk Operations - Improved batch operations in Admin UI
Database Migrations:
# Run all migrations
alembic upgrade head
# Migrations included:
# 026 - worker_api_keys hash_version column (argon2id migration)
# 027 - webhooks and webhook_deliveries tables
# 028 - deployment_events tableNew Environment Variables (all optional):
# Webhook settings
VLOG_WEBHOOKS_ENABLED=true
VLOG_WEBHOOKS_MAX_RETRIES=5
VLOG_WEBHOOKS_RETRY_BASE_DELAY=30
VLOG_WEBHOOKS_REQUEST_TIMEOUT=10
# Video downloads
VLOG_DOWNLOADS_ENABLED=false # Disabled by default
VLOG_DOWNLOADS_ALLOW_ORIGINAL=false # Original files require explicit enable
VLOG_DOWNLOADS_ALLOW_TRANSCODED=true
VLOG_DOWNLOADS_RATE_LIMIT_PER_HOUR=10
VLOG_DOWNLOADS_MAX_CONCURRENT=2New API Endpoints:
| Endpoint | Description |
|---|---|
POST /api/auth/login |
Session-based admin authentication |
POST /api/auth/logout |
End admin session |
GET /api/auth/check |
Verify session status |
GET /api/auth/csrf-token |
Get CSRF token for forms |
GET/POST /api/webhooks |
Webhook management |
GET /api/webhooks/{id}/deliveries |
View delivery history |
POST /api/webhooks/{id}/test |
Test webhook delivery |
GET /api/videos/{slug}/download |
Download video files |
Security Changes:
Worker API keys are now hashed using argon2id instead of SHA-256:
- Existing keys continue to work (auto-migrated on use)
- New keys use argon2id by default
- No action required for existing workers
Post-Upgrade Steps:
-
Verify new tables exist:
psql -U vlog -d vlog -c "\dt webhooks; \dt webhook_deliveries; \dt deployment_events;" -
Verify API endpoints work:
curl http://localhost:9001/api/webhooks curl http://localhost:9000/api/videos/test/download # Should return 403 if disabled -
Optional: Enable downloads:
export VLOG_DOWNLOADS_ENABLED=true sudo systemctl restart vlog-public -
Optional: Configure webhooks via Admin UI
This version introduces the database-backed settings system.
What Changed:
- Settings can now be stored in the database
- Runtime configuration changes without restart
- Admin UI settings tab
Migration Steps:
-
First startup auto-seeds: The database will be automatically populated with default settings on first startup.
-
Or migrate manually:
vlog settings migrate-from-env
-
Verify migration:
vlog settings list
Environment Variables:
- Environment variables still work as fallbacks
- You can keep them or remove them after migration
- Bootstrap settings (ports, secrets) still require env vars
This version adds CMAF streaming format with DASH support.
What Changed:
- New streaming format: CMAF with fMP4 segments
- DASH manifest generation (manifest.mpd)
- Shaka Player for DASH playback
- HEVC and AV1 codec support
Migration Steps:
-
New videos use CMAF by default:
- No action needed for new uploads
- They will automatically use CMAF format
-
Existing videos (optional):
- Legacy HLS/TS videos continue to work
- To upgrade: use the re-encode queue
# Queue all legacy videos for re-encoding # Via Admin UI or API POST /api/reencode/queue-all
-
Database migration:
alembic upgrade head # Adds streaming_format and primary_codec columns
Configuration:
VLOG_STREAMING_FORMAT=cmaf # Default for new videos
VLOG_STREAMING_CODEC=hevc # Default codec
VLOG_STREAMING_ENABLE_DASH=true # Generate DASH manifestsThis version adds Prometheus metrics endpoints.
What Changed:
/metricsendpoint on Admin API (port 9001)/api/metricsendpoint on Worker API (port 9002)- prometheus-client Python package dependency
Migration Steps:
-
Dependencies:
pip install -e . # prometheus-client is in requirements
-
Configure Prometheus scraping:
# prometheus.yml scrape_configs: - job_name: 'vlog' static_configs: - targets: ['your-server:9001', 'your-server:9002']
-
No database migration required.
This version adds automated PostgreSQL backups.
What Changed:
- New CronJob manifest:
k8s/backup-cronjob.yaml - Daily backups with 7-day retention
Migration Steps:
-
Create backup secret:
kubectl create secret generic postgres-backup-credentials \ --namespace vlog \ --from-literal=PGHOST=your-postgres-host \ --from-literal=PGPORT=5432 \ --from-literal=PGDATABASE=vlog \ --from-literal=PGUSER=vlog \ --from-literal=PGPASSWORD=your-password
-
Deploy CronJob:
kubectl apply -f k8s/backup-cronjob.yaml
-
Verify:
kubectl get cronjob -n vlog
This version adds security improvements.
What Changed:
- Container security contexts (non-root, read-only fs, seccomp)
- NetworkPolicy for worker pods
- PodDisruptionBudgets
- CI/CD security scanning
Migration Steps:
-
Update deployments:
kubectl apply -f k8s/worker-deployment-nvidia.yaml kubectl apply -f k8s/worker-deployment-intel.yaml
-
Apply NetworkPolicy (optional but recommended):
# Configure Worker API address first vim k8s/networkpolicy.yaml kubectl apply -f k8s/networkpolicy.yaml -
Apply PodDisruptionBudgets:
kubectl apply -f k8s/worker-pdb.yaml kubectl apply -f k8s/worker-pdb-nvidia.yaml kubectl apply -f k8s/worker-pdb-intel.yaml
VLog uses Alembic for database migrations.
source venv/bin/activate
alembic upgrade headalembic currentalembic history --verbose# Roll back one migration
alembic downgrade -1
# Roll back to specific version
alembic downgrade <revision>If an upgrade fails:
sudo systemctl stop vlog.target# Drop and recreate database
psql -U postgres -c "DROP DATABASE vlog"
psql -U postgres -c "CREATE DATABASE vlog OWNER vlog"
# Restore from backup
pg_restore -U vlog -d vlog /backup/vlog-pre-upgrade-*.dumpgit checkout <previous-tag>
pip install -e .sudo systemctl start vlog.targetkubectl rollout undo deployment/vlog-worker-nvidia -n vlog
kubectl rollout undo deployment/vlog-worker-intel -n vlog| Version | Migration | Description |
|---|---|---|
| 0.0.3 | 020_add_playlists | playlists and playlist_items tables |
| 0.0.3 | 021_partition_playback_sessions | Partitioned playback_sessions by month |
| 0.0.3 | 022_add_featured_video_columns | is_featured column on videos |
| 0.0.3 | 023_add_playback_sessions_composite_index | Composite index optimization |
| 0.0.3 | 024_add_chapters | chapters table, has_chapters on videos |
| 0.0.3 | 025_add_sprite_sheets | sprite_queue table, sprite columns on videos |
| 0.1.x | 012_add_settings | Database-backed settings system |
| 0.1.x | 013_add_streaming_format | streaming_format, primary_codec columns |
| 0.1.x | 014_add_reencode_queue | Re-encode queue table |
| 0.1.x | 015_extend_video_qualities | segment_format column |
| 0.2.x | 026_add_hash_version | worker_api_keys hash_version for argon2id |
| 0.2.x | 027_add_webhooks | webhooks and webhook_deliveries tables |
| 0.2.x | 028_add_deployment_events | deployment_events table |
| Version | Endpoint | Change |
|---|---|---|
| 0.0.3 | /api/playlists |
Added (Public & Admin) |
| 0.0.3 | /api/playlists/{id}/videos |
Added (Admin) |
| 0.0.3 | /api/videos/{id}/chapters |
Added (Admin) |
| 0.0.3 | /api/videos/{id}/sprites |
Added (Admin) |
| 0.0.3 | /api/config/display |
Added (Public) |
| 0.0.3 | /api/videos?featured= |
Added featured filter |
| 0.1.x | /metrics |
Added (Admin API) |
| 0.1.x | /api/metrics |
Added (Worker API) |
| 0.1.x | /api/reencode/* |
Added (Admin API) |
| 0.1.x | /api/settings/* |
Added (Admin API) |
| 0.2.x | /api/auth/login |
Added (Admin API) |
| 0.2.x | /api/auth/logout |
Added (Admin API) |
| 0.2.x | /api/auth/check |
Added (Admin API) |
| 0.2.x | /api/auth/csrf-token |
Added (Admin API) |
| 0.2.x | /api/webhooks |
Added (Admin API) |
| 0.2.x | /api/webhooks/{id}/deliveries |
Added (Admin API) |
| 0.2.x | /api/webhooks/{id}/test |
Added (Admin API) |
| 0.2.x | /api/videos/{slug}/download |
Added (Public API) |
| Version | Setting | Change |
|---|---|---|
| 0.0.3 | VLOG_DISPLAY_* |
Added (display settings) |
| 0.0.3 | VLOG_HTTP_CIRCUIT_BREAKER_* |
Added (circuit breaker) |
| 0.0.3 | VLOG_WORKER_STREAMING_UPLOAD |
Added (streaming upload) |
| 0.0.3 | VLOG_SPRITE_SHEET_* |
Added (sprite sheet settings) |
| 0.0.3 | VLOG_WORKER_VERSION_CHECK_* |
Added (version gating) |
| 0.1.x | VLOG_STREAMING_FORMAT |
Added (default: cmaf) |
| 0.1.x | VLOG_STREAMING_CODEC |
Added (default: hevc) |
| 0.1.x | VLOG_CDN_ENABLED |
Added |
| 0.1.x | VLOG_CDN_BASE_URL |
Added |
| 0.2.x | VLOG_WEBHOOKS_* |
Added (webhook delivery settings) |
| 0.2.x | VLOG_DOWNLOADS_* |
Added (video download settings) |
Before upgrading:
- Read release notes
- Backup database
- Check disk space
- Plan maintenance window
- Notify users (if applicable)
After upgrading:
- Run database migrations
- Check health endpoints
- Verify workers connected
- Test video upload
- Test video playback
- Check metrics endpoint
- Review logs for errors
If you encounter issues during upgrade:
-
Check logs:
journalctl -u vlog-* --since "30 minutes ago"
-
Check migration status:
alembic current
-
Open an issue: https://github.com/filthyrake/vlog/issues