
Show HN: Tiny Tube – A self hosted video sharing server in a single Go binary
Tiny Tube is a self-hosted video-sharing server for training videos,
以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。
Tiny Tube is a self-hosted video-sharing server for training videos, presentations, and recorded meetings. It runs as a single Go binary, with an embedded web interface, SQLite metadata, and video files stored on disk.
Download a release · Installation · Configuration · HTTP API · License
Run one server process per video directory. HLS currently provides a single 720p rendition; backups, storage quotas, and adaptive quality are not built in. See the review and remaining limitations for deployment details.
The examples below use demonstration content.
Library: browse by category, search, and sort videos by date, views, or title.
Watch: play a video, adjust playback speed, and share or download the original.
Upload: add a video and choose its title, category, description, and visibility.
- Download and extract
Download the archive for your system from GitHub Releases: Windows (.zip), Linux, or macOS (.tar.gz), choosing amd64 for Intel/AMD or arm64 for ARM, including Apple Silicon. Extract it and open a terminal in the extracted folder. The binaries are unsigned; Windows or macOS may show a security prompt.
The release contains the server, the tiny-tube-cli administration tool, configuration examples, documentation, and VERSION.txt. Go and a separate database server are not required: SQLite and the web interface are included. You need a writable video directory with space for originals and generated media.
To verify the download, compare its hash with the matching filename in the release's SHA256SUMS. For example, for the v1.0.3 amd64 archives:
Windows PowerShell
Get-FileHash .\tiny-tube-v1.0.3-windows-amd64.zip -Algorithm SHA256
Linux
sha256sum tiny-tube-v1.0.3-linux-amd64.tar.gz
macOS (use darwin-arm64 for Apple Silicon)
shasum -a 256 tiny-tube-v1.0.3-darwin-amd64.tar.gz
Use the filename for the version and platform you downloaded.
For a new installation, copy .env.example to .env in the extracted folder:
Windows PowerShell
Copy-Item .env.example .env
Linux / macOS
cp .env.example .env
Open .env in a text editor and set ADMIN_PASS to a strong password. The default administrator name is admin; change ADMIN_USER if you prefer. The password cannot be empty or changeme. Keep .env private: it may contain credentials. Do not replace an existing .env when upgrading.
Windows PowerShell
.\tiny-tube.exe
Linux / macOS
./tiny-tube
Open http://localhost:8081 on the same computer. Sign in with the administrator credentials, then use Upload video to add a video or Administration to manage users. Press Ctrl+C in the terminal to stop the server.
On the first start with an empty user table, Tiny Tube creates the administrator. After that, manage users and passwords at /admin; changing ADMIN_USER or ADMIN_PASS does not change existing accounts. The library starts empty. By default, videos and the SQLite database are stored in videos/ under the working directory.
For HLS conversion and automatically generated posters, install FFmpeg separately with the libx264 and AAC encoders, and make it available on PATH (or set FFMPEG_BIN). Without FFmpeg, original-file playback remains available when the browser supports the video's format and codecs.
The default address only accepts local connections. For network access, configure the address and HTTPS; see Configuration and the Nginx example. Plan backups of the videos and database; Tiny Tube does not create them automatically. See Security and remaining limitations.
For a long-running Linux deployment, configure a service with the intended working directory, absolute VIDEO_DIR, and credentials. If conversion is needed, ensure the service can find FFmpeg. A systemd unit is not included.
For operator role fixes without the web UI, the release's tiny-tube-cli provides users list and users set-role --username U --role admin|editor|viewer. Use the same VIDEO_DIR, STORE, and DB_PATH settings as the server. The CLI refuses to demote the last active administrator.
Public videos stay visible to everyone. For sensitive material, an administrator creates any number of locked lists at /admin/lists, each with its own long random key. Uploads and edits offer a visibility picker: public by default, or one locked list per video. Existing videos stay public unless moved.
For scripts, pass the key as ?key=… on /api/videos, /api/video, /watch and /videos/…, or reuse the unlock cookie from a link visit.
The server loads .env from its working directory. Explicit environment variables take precedence, including empty values. Values may be quoted; there is no variable expansion or inline-comment support. .env is ignored by Git.
Empty optional values fall back to the defaults. For direct LAN access, set HOST explicitly (or set ADDR=0.0.0.0:8081) and configure the firewall. Session cookies need HTTPS when used over a network; the Go server itself serves HTTP. Video files and public metadata are public. Login sessions last 24 hours sliding, with expiry and the browser cookie renewed at most once per five minutes of activity. Refresh only updates live sessions and cannot recreate a revoked token. Password resets, deactivation and user deletion revoke sessions. Unlock cookies are session cookies signed per process and die with the browser session or a restart; reopening the list link restores them.
When upgrading an older build that automatically adopted local usernames into LDAP, review its existing LDAP role grants. The new login path prevents future adoption but preserves existing accounts/roles; it does not reconstruct their previous authentication source.
Browser mutations must originate from this site. Cross-origin upload/edit/delete requests return 403, including JSON clients; command-line clients without browser origin headers continue to work. Changing Accept/format=json does not bypass authentication, request limits or origin protection. CSP blocks inline scripts and embedding the interface in frames; MIME sniffing is disabled.
The auth limit uses the actual socket source address and ignores forwarding headers. Behind Nginx, clients share its IP bucket: tune the Go aggregate limit and apply per-client limits at the trusted edge. Public viewing/API reads remain available during an auth cooldown. Limiter memory is bounded.
Headers have a 10-second timeout and a 64 KiB limit. Ordinary request reads are limited to 30 seconds; authenticated uploads use their separate configured deadline. Response writes are limited to `max(30 minutes, UPLOAD_TIMEOUT_SECONDS
The interface supports English and Greek on every page, including administration, upload validation and player messages. Use the language selector in the header; the choice is saved in a browser cookie for one year and works without JavaScript. Until a choice is saved, the browser's Accept-Language preference selects a supported language; unsupported preferences fall back to English. Switching preserves the current page, search/filter/pagination parameters and locked-list key. Switching reloads the page, so save edits or finish an upload first. Dates, file sizes and view/video counts follow the selected language. Titles, descriptions, categories, list names and other user content retain their original text. JSON API fields, status values, errors, server logs and CLI output retain their existing format/language for automation.
English is the source catalog in web/locales/en.json; el.json translates the same stable message IDs (for example upload.title). The server uses go-i18n for named variables and CLDR plural rules, and golang.org/x/text for language matching and number formatting. Browser messages use the same catalogs, with Intl.PluralRules and Intl.NumberFormat; CSP needs no inline exceptions. Missing translations fall back to English. To add another language, add its standard go-i18n JSON catalog with a language.name entry and rebuild: discovery, cookies, negotiation and the selector automatically include it. No Go/HTML/JS language lists need editing. See the translation guide for examples, plural forms and validation. No frontend packages are required.
The interface defaults to light mode. The theme button switches between light and dark and remembers the selection in browser-local storage; it does not follow the operating system's theme automatically. Library, watch, and upload pages adapt to mobile, tablet, and desktop screens. Categories can be combined with text search. Library and locked-list pages show 24 videos by default, with Previous/Next navigation preserving search, category and sort. Long visibility labels fit narrow screens. Administrator deletion confirmations apply to every row and identify whether a video, user or list is being deleted.
The upload page supports file selection or drag-and-drop, shows the chosen file, and reports upload progress and errors without discarding the form. Without JavaScript, its standard multipart form still works. The watch page provides link copying and access to the original file. The interface uses restrained colors and task-oriented wording for workplace use. Cards display an extracted poster when available and a neutral placeholder otherwise. The player offers speeds from 0.5× to 2× and attempts playback with sound; where the browser blocks it, the viewer presses play. The video is never muted.
The watch page links to /edit?id=<id> and provides deletion with a confirmation prompt. GET /edit and POST /api/edit require an editor or administrator login; POST /api/delete and /admin require an administrator. The watch page shows management actions only to users holding the matching role. Editing changes title/description/category/visibility while preserving playback data. Deletion cancels and waits for active conversion, then removes the original, HLS, poster and metadata. There is no undo.
Each authorized watch-page load counts one view, debounced to one per viewer address per video every 24 hours so refreshes do not inflate totals; denied requests never count. Totals appear on library cards and the watch page, and the library and locked-list pages offer most-viewed and title sorts alongside the default recency order. Title sorting is case-insensitive and orders numbers naturally, so Lesson 2 comes before Lesson 10. The library and API accept sort=views or sort=title; paging and filters preserve the selection.
GET /api/videos is paginated: use page (starting at 1) and page_size (default 50, maximum 100; HTML defaults to 24). Responses include total (visible library size), filtered (matching visible videos), count (items on this page), page, page_size, pages and items. Clients that assumed one request returned every video must iterate through the pages. Out-of-range positive pages resolve to the last page; invalid/oversized parameters return 400. Authorization applies before counts, category totals or paging. SQLite filters and pages in queries, retaining Greek search and precise date ordering; legacy FS still scans JSON records. Readiness and conversion polling use lightweight SQLite queries. View debounce memory has a hard 8,192-entry cap; eviction can permit an extra view under heavy churn.
Programmatic clients log in with POST /api/login ({"username", "password"}) and reuse the session cookie, exactly like a browser. For scripts that should not juggle cookies, an administrator can issue a long-lived API key per user at /admin in the API keys section or with cli.bat users api-key --username U --name N, and the client sends it as Authorization: Bearer tt-…. Keys carry the user's role, never expire, and are revoked from /admin or with users api-key-revoke --prefix P; only their SHA-256 is stored and the plaintext is shown once at creation. Uploads stay multipart/form-data; only the response format changes. Send Accept: application/json (or ?format=json) to get JSON instead of the browser 303 redirect. Error responses use the same HTTP status codes with a {"error": "..."} body. Anonymous JSON clients get 401; lo
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。