Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c9a8553
Add provider-agnostic cloud storage and release packaging
Oct 25, 2026
efbf754
test(storage): disable import-time badge sync to fix flaky teardown
Oct 31, 2026
3faa053
fix(core,recorder): stop-before-unlock, bounded waits, retry budget
Oct 31, 2026
86e1ff2
fix(worker): guard folder cleanup against live writes, drop fuser -k -9
Oct 31, 2026
fdf5fa0
feat(webui): health parser module, import-only guard, transcribe helper
Oct 31, 2026
5684443
test(recorder): add reliability regression suite (33 tests)
Oct 31, 2026
f331430
docs(deploy): document VOD_SECURE_COOKIES=false for HTTP-only Nginx
Oct 31, 2026
2330871
feat(scripts): add VPS deployment and Linux validation script
Oct 31, 2026
d2e6e38
docs: add CLAUDE.md engine guide
Oct 31, 2026
6343f0f
fix(webui): restore Python 3.10/3.11 compatibility
Oct 31, 2026
2bb6057
chore: add .gitattributes to pin line endings
Oct 31, 2026
19f13db
fix(docker): give the recorder time to finalize MP4s on stop
Nov 1, 2026
0f97e83
fix(recorder): use config.LIVE_HLS_ROOT as the single live HLS root
Nov 1, 2026
d20dc7c
fix(webui): report service health on systemd hosts
Nov 1, 2026
5223302
feat(webui)!: remove Smart-TV mode and gatekeeper auto-login
Nov 3, 2026
87e8054
feat(webui)!: remove Chromecast/AirPlay casting and ?cast= media tokens
Nov 3, 2026
c3cc175
fix(webui): stop client IP spoofing via X-Forwarded-For
Nov 3, 2026
d07a19e
fix(content): add frontmatter to the privacy policy
Nov 3, 2026
d8f6367
fix(worker): fail closed when checking for an active recording
Nov 3, 2026
f04f5bf
fix(webui): keep corrupt JSON state instead of overwriting it
Nov 3, 2026
06e873d
fix(worker): never delete code or dot-directories as archives
Nov 3, 2026
4c6bf32
fix(docker): keep data out of the code tree, drop wildcard media CORS
Nov 3, 2026
8d4f924
fix: drop built-in third-party proxies and host-specific /root paths
Nov 3, 2026
123e777
fix(webui): remove community-instance branding from login and titles
Nov 3, 2026
cbb566b
fix(webui): fit the login heading and bust static caches automatically
Nov 3, 2026
d6fe736
fix(webui): stop mobile layouts from cutting off content
Nov 3, 2026
53f54f1
chore: add ruff config and clear all remaining lint findings
Nov 3, 2026
e660b54
ci: test on Python 3.10-3.12, lint and check shell syntax
Nov 3, 2026
d166827
docs: add contributing, security, conduct, changelog and templates
Nov 3, 2026
ffd2ef3
docs(readme): rewrite for the open-source release
Nov 3, 2026
8ef73f5
docs: add Buy Me a Coffee funding link
Nov 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.git
.gitignore
.env
.env.*
!.env.example
.venv
venv
__pycache__
*.py[cod]
*.db
*.db-wal
*.db-shm
*.sqlite
*.sqlite3
data
files
.thumbs
.meta
.hls
.hls_live
.vodcache
.gunicorn
logs
*.log
*.mp4
*.mkv
*.ts
*.m3u8
*.part
*.tmp
docs/screenshots
node_modules
.pytest_cache
.coverage
htmlcov
43 changes: 40 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,43 @@
# --- Core WebUI Server Settings ---
VOD_HOST=0.0.0.0
VOD_PORT=8080
VOD_PUBLIC_BASE=http://localhost:8080
VOD_SECRET_KEY=change-this-to-a-very-secure-random-secret-key-32-chars-minimum
# Reverse proxies whose X-Real-IP / X-Forwarded-For headers are trusted
# (comma-separated IPs or CIDR networks). Rate limits and login bans use the
# client IP these proxies report; never list addresses clients can reach directly.
VOD_TRUSTED_PROXIES=127.0.0.1,::1
# Public base URL used for share links and OAuth callbacks.
# Leave empty to derive it from the incoming request (recommended behind a proxy).
# For OAuth providers set the exact public HTTPS origin, e.g. https://recorder.example.com
VOD_PUBLIC_BASE=
# Required. Generate with: python -c "import secrets; print(secrets.token_hex(32))"
VOD_SECRET_KEY=
VOD_SECURE_COOKIES=false

# --- Cloud / External Storage (optional) ---
# Dedicated AES-GCM key for provider credentials. Falls back to VOD_SECRET_KEY.
# Generate with: python -c "import secrets; print(secrets.token_hex(32))"
# STORAGE_ENCRYPTION_KEY=
# Background worker threads for uploads/restores (default: 1)
# WORKER_STORAGE_THREADS=1
# Auto-upload, local deletion and retention are configured in the WebUI
# (Systemsteuerung -> Cloud-Speicher) or via `streamvault storage settings`.

# --- Authentication & Initial Bootstrap ---
# NOTE: Required in production. Cannot be 'admin'/'admin'.
VOD_USER=vaultadmin
VOD_PASS=GenerateAStrongPasswordHere123!
# Required. Generate with: python -c "import secrets; print(secrets.token_urlsafe(24))"
VOD_PASS=
VOD_ALLOW_ENV_LOGIN=false
VOD_SESSION_MAX_AGE_SEC=0
VOD_SESSION_COOKIE_MAX_AGE_SEC=34560000

# --- Error Monitoring (optional) ---
# SENTRY_DSN=
# PII is opt-in; keep disabled unless your privacy policy allows it.
# SENTRY_SEND_DEFAULT_PII=false
# Performance tracing is sampled and disabled by default (0.0 - 1.0).
# SENTRY_TRACES_SAMPLE_RATE=0.0

# --- Storage Paths ---
# Base directory for recordings, metadata, and database
# Default: ./data (or the app directory)
Expand All @@ -40,10 +65,22 @@ VOD_USE_X_ACCEL=true
# LIVE_TWITCH_OAUTH=
# LIVE_TWITCH_ANONYMOUS=true

# Optional playlist proxy. Off by default and no proxy is built in: name one
# you operate or trust yourself. Check the platform's terms before enabling.
# STREAM_RECORDER_USE_PROXY=false
# TWITCH_PROXY_PLAYLIST=https://proxy.example.com
# STREAMLINK_PLUGIN_DIR=

# Optional Twitch API Client (for metadata auto-sync and EventSub)
# TWITCH_CLIENT_ID=your_twitch_client_id_here
# TWITCH_CLIENT_SECRET=your_twitch_client_secret_here

# --- System Backups (Admin -> Backups) ---
# Directory listed for streamrecorder_*.tar.gz files (default: <VOD_META_DIR>/backups)
# BACKUP_DIR=/var/backups/streamvault
# Script run by "Backup erstellen"; it must write streamrecorder_*.tar.gz into BACKUP_DIR
# VOD_BACKUP_SCRIPT=/usr/local/bin/streamvault-backup.sh

# --- Performance & Caching ---
# Optional Redis cache for high-concurrency deployments
# REDIS_URL=redis://127.0.0.1:6379/0
Expand Down
27 changes: 27 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Keep repository content LF-normalised regardless of core.autocrlf.
* text=auto

# Executed on Linux (VPS, Docker): CRLF breaks the shebang / bash parsing.
*.sh text eol=lf
bin/streamvault text eol=lf
Dockerfile text eol=lf
*.conf text eol=lf
.env.example text eol=lf

# Windows helpers keep CRLF.
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf

# Binary assets.
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.webp binary
*.mp3 binary
*.mp4 binary
*.woff binary
*.woff2 binary
*.db binary
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
buy_me_a_coffee: blackwellcode
52 changes: 52 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Bug report
description: Something does not work as documented
labels: [bug]
body:
- type: markdown
attributes:
value: |
Security issues: please do **not** file them here, see SECURITY.md.
- type: textarea
id: what
attributes:
label: What happened?
description: What did you do, what did you expect, what happened instead?
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
placeholder: |
1. ...
2. ...
validations:
required: true
- type: dropdown
id: deployment
attributes:
label: Deployment
options:
- install.sh (systemd)
- Docker Compose
- Manual
validations:
required: true
- type: input
id: version
attributes:
label: Version or commit
placeholder: e.g. v1.0.0 or 1a2b3c4
validations:
required: true
- type: input
id: environment
attributes:
label: OS and Python version
placeholder: e.g. Ubuntu 22.04, Python 3.10.12
- type: textarea
id: logs
attributes:
label: Relevant log output
description: "`streamvault logs <service>` or `docker compose logs`. Remove tokens and passwords."
render: text
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/Blackwellcode/streamvault/security/advisories/new
about: Report vulnerabilities privately, not as a public issue.
21 changes: 21 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Feature request
description: Suggest an improvement
labels: [enhancement]
body:
- type: textarea
id: problem
attributes:
label: Problem
description: What are you trying to do, and what gets in the way today?
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed solution
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: pip
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5

- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
11 changes: 11 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## What and why

<!-- What does this change, and which problem does it solve? Link the issue. -->

## Checks

- [ ] `ruff check .` passes
- [ ] `python -m unittest discover -s tests` passes
- [ ] New behaviour has a test
- [ ] Operator-visible changes (env vars, migrations, manual steps) are in `CHANGELOG.md`
- [ ] UI changes: screenshots at desktop and phone width attached
56 changes: 56 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: CI

on:
push:
branches: [master]
pull_request:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
name: Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# 3.10 = Ubuntu 22.04, 3.11 = Debian 12 (production targets); 3.12 = current.
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: requirements.txt

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt ruff==0.17.3

- name: Compile (target interpreter catches PEP 701 f-strings)
run: python -m compileall -q core recorder WEBUI bin run_transcribe.py tests

- name: Lint
run: ruff check .

- name: Unit tests
run: python -m unittest discover -s tests -v

shell:
name: Shell scripts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Syntax check
run: |
for script in install.sh scripts/streamvault_vps.sh bin/streamvault; do
bash -n "$script"
done
51 changes: 51 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Changelog

All notable changes to this project are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

### Breaking changes

- **Docker data directory.** `docker-compose.yml` now uses
`VOD_BASE_DIR=/app/data`. Before upgrading, move archives,
`streamrecorder.db` and the dot-directories (`.meta`, `.thumbs`, `.hls`,
`.vodcache`) from the project root into `./data`.
- **Casting removed.** Chromecast/AirPlay buttons, the signed `?cast=` media
URLs and `/api/live/cast-url` are gone. Media is only served to logged-in
sessions and without `Access-Control-Allow-Origin: *`.
- **OBS pages need a login.** `/live/obs/<channel>` and `/chat/obs/<channel>`
require a session; log in once inside the OBS browser source
("Interact").
- **Smart-TV mode removed**, including `/login/tv` and the gatekeeper
auto-login.
- **Playlist proxy is opt-in only.** No proxy hosts are built in; set
`TWITCH_PROXY_PLAYLIST` (and `STREAMLINK_PLUGIN_DIR` if needed) together
with `STREAM_RECORDER_USE_PROXY=true`.
- **Backups.** `BACKUP_DIR` defaults to `<VOD_META_DIR>/backups`; "create
backup" runs the script named in `VOD_BACKUP_SCRIPT`.

### Security

- Client IPs behind a proxy come from `X-Real-IP` or the right-most
`X-Forwarded-For` hop; rotating `X-Forwarded-For` no longer bypasses login
rate limits and bans. `VOD_TRUSTED_PROXIES` accepts CIDR networks.
- Code and dot-directories below `VOD_BASE_DIR` can no longer be deleted as
streamer archives.

### Fixed

- `/agb` and `/datenschutz` returned HTTP 500 on fresh installs.
- The worker could remux a recording that was still being written when its
status file was half-written or owned by another user.
- A corrupt JSON state file (favorites, profiles, shares, settings) was
silently replaced by an empty one; it is now kept as `<file>.corrupt-<ts>`.
- Login heading overflowed its card; mobile admin pages clipped buttons,
tabs and tables.
- Browsers kept stale CSS/JS after updates; static URLs now carry a version
derived from the shipped files.

### Added

- GitHub Actions CI (Python 3.10–3.12, ruff, unit tests, shell syntax),
Dependabot, contribution and security guidelines.
Loading
Loading