Self-hosted torrent downloader with queue controls and live piece maps.
4.7K
A Coral ecosystem module — built on TanStack Start, Tailwind v4, and the Jellyfin API.
pnpm install
cp .env.example .env
# Set your downloads directory, optional auth, and any other Tide settings
pnpm dev
App runs at http://localhost:3000.
| Tool | Purpose |
|---|---|
| TanStack Start | Full-stack React framework |
| TanStack Router | Type-safe file-based routing |
| TanStack Query | Server state management |
| Tailwind v4 | Styling |
| Biome | Linting & formatting |
| @get-coral/jellyfin | Jellyfin API client |
| Vitest | Testing |
pnpm dev # Start dev server on :3000
pnpm build # Production build
pnpm start # Run production server
pnpm typecheck # TypeScript check
pnpm check # Biome lint + format check
pnpm lint # Biome lint with auto-fix
pnpm test # Run tests
# Pull the published image
docker pull getcoral/tide:latest
# Or build it yourself
docker build -t tide .
# Run
docker run -p 3000:3000 \
-e TIDE_DOWNLOADS_DIR=/downloads \
-e TIDE_MEMORY_LIMIT_MB=8192 \
-e TIDE_MEMORY_PAUSE_MB=7168 \
-e TIDE_MEMORY_RESUME_MB=6144 \
-e TIDE_AUTH_USERNAME=admin \
-e TIDE_AUTH_PASSWORD=change-me \
getcoral/tide:latest
Tide has two independent layers, both optional.
HTTP basic auth — set TIDE_AUTH_USERNAME and TIDE_AUTH_PASSWORD and the production server
challenges every request before it reaches the app. It is a blunt front door with a single shared
credential, and it is not applied by pnpm dev.
Jellyfin sign-in — Tide can require a Jellyfin account instead of, or on top of, basic auth. It is off by default.
/manage, set the Jellyfin server URL under Access (or set TIDE_JELLYFIN_URL). Tide
verifies the URL against /System/Info/Public before storing it.Once required:
/login./manage and every mutating endpoint are limited to Jellyfin administrators.Tide stores no Jellyfin API key — only the server URL. Authentication uses Jellyfin's public
AuthenticateByName endpoint, so there is no server-wide credential for Tide to leak.
Sessions live in the same SQLite database as the rest of Tide's state and survive restarts. If you
ever lock yourself out (server moved, URL wrong), start Tide with TIDE_REQUIRE_LOGIN=false — the
env var overrides the stored setting in both directions.
Tide now includes an RSS-based memory guard for torrent activity.
TIDE_MEMORY_LIMIT_MB, TIDE_MEMORY_PAUSE_MB, and TIDE_MEMORY_RESUME_MB.TIDE_MEMORY_CHECK_INTERVAL_MS controls how often Tide re-checks memory usage. Default is 5000.For an 8 GB container limit on a NAS, a reasonable starting point is:
TIDE_MEMORY_LIMIT_MB=8192
TIDE_MEMORY_PAUSE_MB=7168
TIDE_MEMORY_RESUME_MB=6144
Published automatically on every release via GitHub Actions:
getcoral/tide on Docker Hubghcr.io/get-coral/tide on GHCR| Workflow | Trigger | What it does |
|---|---|---|
ci.yml | Every PR + push to main | Typecheck, lint, test, build, Docker build check |
docker-publish.yml | Push to main + version tags | Publishes to GHCR |
release-please.yml | Push to main | Opens release PR, publishes Docker on merge |
Releases are fully automated via Release Please. Use conventional commits:
| Commit prefix | Version bump |
|---|---|
feat: | Minor |
fix: | Patch |
feat!: / fix!: | Major |
chore:, docs: | No bump |
This module is part of the Coral ecosystem. See the contributing guide before opening PRs.
Content type
Image
Digest
sha256:5bca8d6b1…
Size
112 MB
Last updated
11 days ago
docker pull getcoral/tide