* Add DNS-01 challenge support for Let's Encrypt Co-authored-by: mathieumoran1 <[email protected]> * Refactor letsencrypt script to use /dev/tty for interactive prompts Co-authored-by: mathieumoran1 <[email protected]> * feat: Add optional DNS hook mode for certonly Co-authored-by: mathieumoran1 <[email protected]> * Refactor: Improve MongoDB connection and add certifi Co-authored-by: mathieumoran1 <[email protected]> * Checkpoint before follow-up message Co-authored-by: mathieumoran1 <[email protected]> --------- Co-authored-by: Cursor Agent <[email protected]>
3.7 KiB
Python video server (Range streaming + JWT + Mongo)
This is a small standalone server that mirrors the app’s /api/video/:id behavior:
- Looks up
movies._id == :idin MongoDB and reads thevideo_filefield - Streams the file from
VIDEO_FILES_DIRwith HTTP Range support (seeking works) - Auth via the same JWT (
Authorization: Bearer ...), plus avideo_authcookie for<video>
Run
python -m pip install -r python_video_server/requirements.txt
export MONGO_URI="..."
export JWT_SECRET="..."
export VIDEO_FILES_DIR="/absolute/path/to/public/video" # optional (default: ./public/video)
export VIDEO_SESSION_MAX_AGE_SECONDS="28800" # optional (default: 8h)
uvicorn python_video_server.server:app --host 0.0.0.0 --port 8000
HTTPS (Let’s Encrypt, Python-only)
This server can be served over HTTPS by running uvicorn with --ssl-certfile and --ssl-keyfile.
To obtain/renew a trusted cert from Let’s Encrypt without installing system certbot, this repo includes a small wrapper that uses the certbot Python package.
1) Issue a certificate (HTTP-01 standalone)
Requirements:
- Your domain’s DNS
A/AAAArecords must point to this machine. - Port 80 must be reachable from the internet for the ACME challenge.
python3 -m pip install -r python_video_server/requirements.txt
# Staging by default (recommended first). Add --production when it works.
sudo -E python3 -m python_video_server.letsencrypt certonly \
--email [email protected] \
--domains example.com,www.example.com
1b) Issue a certificate (DNS-01 manual TXT record — no port 80, no root)
If your host already uses port 80 (or you don't have permission to bind it), use DNS-01. This does not require any inbound ports on the machine, but you must be able to edit DNS for the domain.
python3 -m pip install -r python_video_server/requirements.txt
# Add --production when staging works.
python3 -m python_video_server.letsencrypt certonly \
--challenge dns \
--email [email protected] \
--domains example.com,www.example.com
During issuance, certbot will prompt you to create a TXT record like:
- Name:
_acme-challenge.example.com - Type:
TXT - Value: (a token certbot prints)
After it propagates, press Enter and certbot will continue.
If you run into a situation where the prompt/token only shows up in logs, you can try the hook-based mode:
python3 -m python_video_server.letsencrypt certonly \
--challenge dns \
--dns-hooks \
--email [email protected] \
--domains example.com,www.example.com
Certificates will be written under:
python_video_server/certs/config/live/<primary-domain>/fullchain.pempython_video_server/certs/config/live/<primary-domain>/privkey.pem
2) Run the video server on 443 with TLS
sudo -E uvicorn python_video_server.server:app --host 0.0.0.0 --port 443 \
--ssl-certfile python_video_server/certs/config/live/example.com/fullchain.pem \
--ssl-keyfile python_video_server/certs/config/live/example.com/privkey.pem
Notes:
- Binding to ports 80/443 usually requires
sudo(or a reverse proxy / port forwarding). - If you’re behind a proxy/ingress, keep sending
X-Forwarded-Proto: httpsso/api/video/sessionsetsSecurecookies correctly.
3) Renew certificates
# Dry-run renewal (safe)
sudo -E python3 -m python_video_server.letsencrypt renew --dry-run
# Actual renew (typically run via cron/systemd timer)
sudo -E python3 -m python_video_server.letsencrypt renew --production
Endpoints
-
POST /api/video/session
Setsvideo_authcookie (sendAuthorization: Bearer <token>). -
GET|HEAD /api/video/{movieId}
Streams the movie file (supportsRange: bytes=...). -
GET /healthz