Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

megaduck

A Mega.nz download manager that runs inside a container, behind a PIA WireGuard tunnel, with adaptive concurrency and auto-rotating exits. Built because the official client and most third-party tools can't sustain parallel public-share downloads without throttling or stalling.

  • Single binary deployment. Container brings up its own WireGuard interface in its netns; nothing on the host is touched apart from a published HTTP port and the download bind-mount.
  • Resumable, chunked, integrity-checked. Range fetches, AES-CTR streaming decryption, per-chunk checkpoints in SQLite, and a full Mega meta-MAC verification pass after the file lands.
  • Adaptive parallelism. AIMD probing tunes global and per-host concurrency to wherever the knee of the throughput curve is, without a hard-coded cap.
  • Self-healing tunnel. When ≥80 % of a download's active chunks stall, the runner rotates to a fresh PIA region (round-robin, no repeats until the full deck is exhausted), then recreates the workers so wedged TCP sockets on the dead tunnel are abandoned.

Features

  • Public file links — both mega.nz/file/ID#KEY and legacy #!ID!KEY.
  • Public folder linksmega.nz/folder/ID#KEY (with optional /file/NODEHANDLE suffix). Folders are walked at add time and expanded into one queued download per file; per-file keys are cached so each download resolves with a single Mega API call instead of re-walking the folder.
  • Mega API retry-with-backoff on transient integer errors (-3 EAGAIN, -4 ERATELIMIT, -6 ETOOMANY) — adding a many-file folder no longer trips the rate limiter.
  • Integrity verification. Mega's per-chunk MAC is recomputed locally after every file (in a worker thread, with a live progress bar) and compared against the meta-MAC embedded in the file key. Mismatches surface as error in the UI with computed vs. expected values.
  • Web UI. Paste a link or batch of links, watch real-time throughput, pause / resume / delete per download, manual VPN rotate button.
  • Authenticated Mega accounts: not supported. Public shares only.

Quickstart

git clone <this-repo> megaduck && cd megaduck
cp .env.example .env
# Edit .env: put your PIA creds in MEGADUCK_PIA_USER / MEGADUCK_PIA_PASS,
# or leave blank to run without a VPN (dev mode).
podman-compose up -d --build
# Open http://localhost:8080

The container needs NET_ADMIN and /dev/net/tun so it can bring up its own WireGuard interface inside its netns. The compose file already grants both.

Without PIA creds, the VPN controller logs intended rotations instead of running wg-quick, so all the adaptive logic still exercises end-to-end.

Install as a boot service

sudo ./scripts/install-host.sh

Templates systemd/megaduck.service with the absolute path of the repo, installs it to /etc/systemd/system/, enables it, and starts it. The unit just shells out to podman-compose up -d --build; the container's own restart: unless-stopped policy keeps it alive across crashes. Uninstall with sudo ./scripts/uninstall-host.sh.

Configuration

All settings are environment variables prefixed MEGADUCK_ and are documented in .env.example. The defaults are tuned for a gigabit symmetric link.

Variable Default What it does
MEGADUCK_PIA_USER / _PASS empty PIA credentials. Blank disables the VPN.
MEGADUCK_PIA_REGIONS 10 US/CA regions Comma-separated PIA region codes to round-robin through.
MEGADUCK_PIA_INITIAL_REGION us_atlanta Region brought up by the container entrypoint.
MEGADUCK_HOST_PORT 8080 Host port the web UI is published on.
MEGADUCK_DOWNLOAD_DIR /mnt/bulk/downloads/megaduck Where files land.
MEGADUCK_STATE_DIR /var/lib/megaduck SQLite + scratch state.
MEGADUCK_MAX_GLOBAL_CONCURRENCY 64 Hard ceiling for the AIMD controller.
MEGADUCK_CHUNK_SIZE 16 MiB Range-fetch size per chunk.
MEGADUCK_STALL_WINDOW_S 60 Idle/low-bps duration before a chunk is "stalled".
MEGADUCK_VPN_ROTATION_COOLDOWN_S 300 Minimum time between rotations.
MEGADUCK_MIN_BYTES_BETWEEN_ROTATIONS 5 GiB Don't rotate until at least this much data has moved (overridden by force-rotate when throughput is near zero).
MEGADUCK_VERIFY_MAC true Run the Mega meta-MAC check after every file.

How adaptive concurrency works

Per-chunk throughput meters feed an aggregate EMA over the probe window (MEGADUCK_PROBE_INTERVAL_S, default 15 s). Each tick:

  1. If saturated (all slots busy) and <25 % of slots are starved, add a slot.
  2. If a previous expansion failed to improve aggregate throughput by MEGADUCK_PROBE_IMPROVEMENT_THRESHOLD (default 7 %) or per-slot rates collapsed, drop a slot and freeze probing for two windows.
  3. Per-host: if ≥2 of a host's slots fall below MEGADUCK_MIN_SLOT_THROUGHPUT_BPS two ticks running, shrink that host's cap; if all are healthy and saturated, grow it.

Result: parallelism climbs until either the server, the path, or your link stops paying for additional connections, and we stay just below that knee.

How VPN rotation works

A per-download _stall_watcher task wakes every stall_window_s / 2 seconds and counts how many of the download's chunks have either gone idle for stall_window_s or are pulling under stall_min_bps. If the stalled fraction crosses stall_fraction_to_rotate (default 80 %), it asks the PIA controller to rotate.

Rotation:

  1. Pops a region from a deck-shuffled queue. The deck is reshuffled only when empty, guaranteeing every other region is tried before any repeats.
  2. Re-runs PIA's run_setup.sh inside the container netns with the new region. The default route, DNS, and WireGuard config all swap in place.
  3. Marks the download for auto-restart and hard-cancels its task — the workers' httpx streams are wedged on the dead tunnel's TCP and would never recover otherwise. The done-callback then schedules a fresh start() after a short grace period.

Rotations honour a global cooldown and a minimum-bytes-since-last-rotation guard, both bypassed when aggregate throughput is essentially zero (we're dead in the water; rotate now).

Without containers (development)

python -m venv .venv && source .venv/bin/activate
pip install -e .
MEGADUCK_DOWNLOAD_DIR=$PWD/downloads \
MEGADUCK_STATE_DIR=$PWD/.state \
megaduck

The VPN controller becomes a no-op in this mode.

Networking isolation

megaduck does not use network_mode: host. All VPN-related state lives in the container's network namespace.

Action inside the container Host impact
Creates a WireGuard pia/wg0 interface None (per-netns)
Adds default route via the VPN None
Rewrites /etc/resolv.conf to PIA DNS None
Sets net.ipv4.conf.all.src_valid_mark=1 Container-netns sysctl only
Adds nftables/iptables rules Per-netns, not visible to host
Publishes MEGADUCK_HOST_PORT (default 8080) → container 8765 One port on the host

The only host-visible side effects are the published port and the bind-mount on MEGADUCK_DOWNLOAD_DIR. If the host itself runs a VPN, the container's traffic exits the bridge, hits the host's default route, and gets nested-encapsulated by PIA inside the container's netns. The two WireGuard interfaces live in different netns and use different routing tables, so there's no contention.

No kill-switch is installed: if the container's tunnel drops, traffic falls back through the bridge → host default route. Integrity-MAC verification still detects any tampering, and the stall watcher rotates the tunnel back up within ~30 s.

Repository layout

megaduck/
  app.py                 FastAPI HTTP API + WebSocket status feed
  config.py              Pydantic settings (all MEGADUCK_* env vars)
  db.py                  aiosqlite wrapper, schema migrations
  bandwidth.py           Per-slot meters + global aggregate
  concurrency.py         AIMD controller, per-host slot pool
  downloader/
    mega.py              Mega.nz protocol: parsing, key crypto, API, MAC
    runner.py            Chunked downloader, stall watcher, auto-restart
  vpn/
    pia.py               Region-rotation controller (deck-shuffle)
  web/
    templates/index.html
    static/{app.js,app.css}

docker/                  Dockerfile + entrypoint (PIA setup → app)
scripts/                 install-host.sh / uninstall-host.sh
systemd/megaduck.service Templated systemd unit
tests/                   (empty placeholder)

License

MIT.

About

A tool to access mega files and manage downloading large data sets

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages