- Remove .emergent/ state dir, tracked .gitconfig, @emergentbase/visual-edits dep + craco wiring, emergent.sh script/meta tags, PostHog telemetry snippet - Rename UI/docs branding Kino -> StreamHoard (README, DEPLOY.md, Navbar, Login, Register, AdminShowEpisodes, FastAPI title, health check response) - Rename docker-compose container/network names to streamhoard-* - Default admin email domain -> admin@streamhoard.local
5.2 KiB
StreamHoard — Deployment on a Proxmox LAMP host
StreamHoard is FastAPI + MongoDB + React. It runs happily alongside your existing LAMP stack (Apache/MySQL/PHP) because we run everything in Docker containers on their own network. Apache keeps port 80/443, MySQL is untouched, StreamHoard uses whatever port you pick.
Prerequisites on the Proxmox host (or LXC / VM)
# Ubuntu/Debian
sudo apt update
sudo apt install -y docker.io docker-compose-plugin git
sudo systemctl enable --now docker
# Verify
docker compose version
If you already have Docker and Compose v2, skip this step.
Deploy
# 1. Clone the repo
git clone https://github.com/YOU/kino-media-server.git /opt/kino
cd /opt/kino
# 2. Configure
cp .env.compose.example .env
nano .env
# - Set KINO_HTTP_PORT (default 8080; anything not used by Apache)
# - Set MEDIA_ROOT_HOST to your bulk storage path (e.g. /mnt/nas/movies)
# - Set a strong JWT_SECRET: openssl rand -hex 32
# - Set a strong ADMIN_PASSWORD
# - Optional: change ADMIN_EMAIL
# 3. Start
docker compose up -d
# 4. Check
docker compose ps
docker compose logs -f backend # confirm "Transcode worker started"
Visit http://<proxmox-ip>:8080 (or whatever KINO_HTTP_PORT you set).
Log in with the admin credentials from .env.
Running behind your existing Apache (optional, recommended)
If you already have Apache on port 80/443 with virtual hosts, add a StreamHoard vhost
that reverse-proxies to the container. This gives you https://kino.example.com
instead of http://ip:8080.
/etc/apache2/sites-available/kino.conf
<VirtualHost *:80>
ServerName kino.local # or kino.yourdomain.tld
ProxyPreserveHost On
ProxyRequests Off
# SPA + API
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
# Streaming needs disabled buffering
SetEnv proxy-sendchunked 1
# Multi-GB uploads
LimitRequestBody 21474836480
</VirtualHost>
sudo a2enmod proxy proxy_http headers
sudo a2ensite kino
sudo systemctl reload apache2
For HTTPS, either terminate TLS at Apache (add certbot/SSLEngine on) or
put Caddy in front of it.
Common ops
# Update to latest code
cd /opt/kino
git pull
docker compose build
docker compose up -d
# Stop
docker compose down
# Logs
docker compose logs -f backend # FastAPI + transcode worker
docker compose logs -f frontend # nginx access
docker compose logs -f mongo
# Shell into backend
docker compose exec backend bash
# Backup MongoDB
docker compose exec mongo mongodump --out /data/db/backup-$(date +%F)
Where does data live?
| What | Where |
|---|---|
| Movie files, HLS, subs | $MEDIA_ROOT_HOST on host (bind-mounted) |
| MongoDB data | Docker volume mongo-data (managed by Docker) |
| TMDB / Radarr keys | In MongoDB (db.settings collection) |
| Uploads via web UI | $MEDIA_ROOT_HOST/videos/ |
To reset everything: docker compose down -v (deletes the mongo-data volume).
Coexistence with your LAMP stack
| StreamHoard uses | LAMP uses | Conflict? |
|---|---|---|
Port KINO_HTTP_PORT |
Apache 80/443 | No — different ports |
| MongoDB (internal only) | MySQL | No — different DBs, Mongo not exposed to host |
| ffmpeg (in container) | anything | No |
| Docker networks | native host services | No — bridged network |
You can happily keep running Wordpress, phpMyAdmin, Nextcloud, whatever on the same box.
Radarr integration
If Radarr is running on the same Proxmox host (native or container), point StreamHoard at it via Admin → Settings → Radarr:
- URL:
http://<host-ip>:7878(use the host IP, notlocalhost— containers can't reach the host'slocalhostunless you addhost.docker.internal) - API key: from Radarr → Settings → General → Security
Important: For StreamHoard to actually play the imported movies, the path Radarr
reports (e.g. /movies/Inception (2010)/Inception.mkv) must be readable from
inside the StreamHoard backend container. Mount Radarr's media path into StreamHoard:
# docker-compose.yml — extend the backend volumes
backend:
volumes:
- ${MEDIA_ROOT_HOST:-./media}:/media
- /mnt/radarr-movies:/mnt/radarr-movies:ro # <— add this
Radarr's file paths must be identical inside both Radarr and StreamHoard containers (easiest: match the paths exactly).
Health check
curl -s http://localhost:${KINO_HTTP_PORT:-8080}/api/ | jq
# {"app":"StreamHoard","status":"ok"}
Firewalling
StreamHoard has no built-in rate limiting or IP allowlist. Since you confirmed internal network only, keep it that way:
# ufw example — allow only your LAN
sudo ufw allow from 192.168.0.0/16 to any port ${KINO_HTTP_PORT:-8080}
sudo ufw deny ${KINO_HTTP_PORT:-8080}