Self-hosted  ·  Docker  ·  Open Source

Local Link Downloader

A self-hosted web UI for downloading files from URLs, uploading local files, or pulling torrents — all saved to folders on your machine.

$ docker pull ghcr.io/whispyy/local-link-downloader:latest

Everything you need

Deploy once on your homelab or NAS. Download from anywhere, any format.

Download from URL

Paste any HTTP/HTTPS URL. The server fetches the file server-side and saves it directly to your configured folder.

Local File Upload

Drag-and-drop or browse to upload files directly from your browser. Configurable size limit up to 10gb by default.

Torrent Downloads

Paste a magnet link or drop a .torrent file. Supports multi-file torrents with live speed and peer count display.

Live Progress

Real-time progress bar with bytes downloaded, total size, and percentage. No page reload needed — auto-refreshes in place.

Multiple Destinations

Configure any number of named folders via DOWNLOAD_FOLDERS. Map each to a volume on your NAS or local disk.

Optional Auth + Admin

Set APP_PASSWORD for 8-hour sessions. The /admin page shows all jobs with live status and cancel controls.

Quick Start

No build step. Add one service to any existing docker-compose.yml.

1

Pull the image

$ docker pull ghcr.io/whispyy/local-link-downloader:latest
2

Add to your docker-compose.yml

services:
  web-downloader:
    image: ghcr.io/whispyy/local-link-downloader:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      DOWNLOAD_FOLDERS: "images:/downloads/images;videos:/downloads/videos"
      ALLOWED_EXTENSIONS: ".jpg,.png,.gif,.zip,.mp4,.pdf"
      APP_PASSWORD: "your_secret_password"
    volumes:
      - /mnt/nas/images:/downloads/images
      - /mnt/nas/videos:/downloads/videos
      - ./logs/web-downloader:/app/logs
3

Start the stack

$ docker compose up -d

Open http://localhost:3000 — done!

Updating — pull and restart in one line:

$ docker compose pull web-downloader && docker compose up -d web-downloader

Configuration

All settings are environment variables. No config files, no YAML schemas.

Variable Default Description
DOWNLOAD_FOLDERS Semicolon-separated key:/path pairs. E.g. images:/mnt/img;tmp:/mnt/tmp
ALLOWED_EXTENSIONS all Comma-separated list of permitted extensions. E.g. .jpg,.png,.mp4. Does not apply to torrents.
APP_PASSWORD unset When set, requires a password prompt before access.
SESSION_TTL_HOURS 168 How long an authenticated session stays valid, in hours (default 7 days).
ENABLE_TRANSCODING false Set to true to enable on-the-fly video transcoding via FFmpeg.
MAX_UPLOAD_SIZE 10gb Max size for direct browser uploads. Accepts b, kb, mb, gb.
API_PORT 3000 Port the Express server listens on inside Docker.
LOG_DIR ./logs Directory where downloads.log and usage data are written.
DISCORD_WEBHOOK_URL unset Discord webhook URL for download/upload notifications.
DISCORD_ERROR_WEBHOOK_URL unset Separate Discord webhook for error-level notifications.

Volume Mapping

How files land on your host machine rather than inside the container.

Files are downloaded inside the container to paths defined in DOWNLOAD_FOLDERS. Bind-mount a host directory to the same container path to make files appear on your machine.

# The container-path is the bridge — it must match on both sides

DOWNLOAD_FOLDERS=images:/downloads/images
volumes:
- /mnt/nas/images:/downloads/images

The container path (the right side of the colon in volumes:) must exactly match what you set in DOWNLOAD_FOLDERS.

Published Image Tags

Automatically built and pushed on every commit and version tag.

:latest

Published on every push to main. Always points to the newest build.

:v1.2.3

Immutable version tag. Pin to this in production for stable deployments.

:v1.2

Minor-version tag — always points to the latest patch of that minor.

:sha-abc1234

Unique short-SHA tag for every build. Useful for debugging exact versions.