Na domácím serveru mám běžné věci pro homelabu: Jellyfin, Immich a občas i "stáhnu si to teď a roztřídím později". Dlouho jsem na to používal JDownloader2. Je to silný a osvědčený nástroj, který řeší spoustu reálných problémů.
Moje konkrétní použití bylo ale nepohodlné. JDownloader2 běžel v Dockeru na serveru a já ho ovládal přes VNC v prohlížeči. Fungovalo to, ale zbytečně těžkopádně. Sdílení schránky bylo dvoufázové, měnění velikosti desktopového UI v prohlížeči bylo téměř nemožné a na mobilu úplně nemožné. Přidávání odkazů z CLI šlo jedině s MyJDownloader online účtem, a to jsem nechtěl.
Postupně mi došlo, že nepotřebuji download manager, který se tváří jako desktopová aplikace. Potřebuji malou službu, která vystaví přes CLI jednoduchou frontu.
A tak vznikl DLQ (Download Queue): headless download-queue daemon a CLI, inspirované tou částí JDownloaderu, kterou jsem opravdu potřeboval, ale celek byl navržený pro Docker, SSH, terminál a domácí server. Zároveň jsem chtěl reálnou záminku se naučit Go a SvelteKit.
Repo projektu: github.com/Witriol/dlq-download-queue
Co DLQ je
DLQ je záměrně minimalističtější jak JDownloader2. Nesnaží se být univerzální download manager s obrovským ekosystémem pluginů, captcha workflow, s link grabberrem a desktopovou automatizací. Cílem jsou základní akce: přidat odkazy, držet frontu po restartu, automaticky spustit stahování, obnovit stahování a ukládat soubory do připojených složek.
Jádro je dlqd, Go daemon s HTTP API na portu 8099. Ukládá "joby" do SQLite db, vyhodnocuje URL a samotné stahování deleguje na aria2 přes JSON-RPC. CLI klient dlq mluví se stejným API, takže frontu jde ovládat z SSH skriptů, cron-like workflow i interaktivního terminálu. Volitelný dlq-webui container běží jako SvelteKit UI na portu 8098 a server-side používá API volání.
Zjednodušeně to vypadá takto:
Prohlížeč
-> dlq-webui (:8098)
-> dlqd API (:8099) <- dlq CLI
-> resolver
-> queue service
- SQLite (/state/dlq.db)
- události/logy
-> aria2 RPC
-> /data
Nejdůležitější je perzistence. Job není jen aria2 proces; je to záznam ve frontě se stavem, počtem pokusů, výstupní složkou, resolver metadaty, filename, událostmi a dostatkem historie, aby šlo později vyhodnotit co se s procesem dělo. Když se server restartuje, fronta se obnoví. Když stahování selže, můžu se podívat na záznamy stahování.
Jak se chová
Samotné CLI je záměrně jednoduché:
# Přidat job
docker exec -it dlq dlq add "<url>" --out /data/downloads
# Sledovat v reálném čase frontu
docker exec -it dlq dlq status --watch
# Prohlédnout si chyby
docker exec -it dlq dlq logs 12 --tail 80

Joby jde pozastavit nebo obnovit, obnovit, smazat a filtrovat podle stavu. DLQ sleduje jasné stavové přechody:
queued,resolving,downloading— běžná správná cestapaused— pozastavenodecrypting— práce s archivem po staženícompleted,failed,decrypt_failed— koncové stavy
U Webshare jobů se pause/resume navenek chová spíš jako stop/retry, protože starý stav bývá méně použitelný než čerstvě vyhodnocený nový link.
Resolvery jsou "pluggable", tedy se dají libovolně přidávat nové. Aktuální sada obsahuje jednoduchý HTTP/HTTPS passthrough, Webshare anonymous mode a veřejné MEGA file linky. Chyby resolverů jsou konkrétní:
login_requiredquota_exceededcaptcha_neededtemporarily_unavailableunknown_site
Post-processing se stal větší částí projektu, než jsem původně čekal. DLQ umí po úspěšném stažení spustit archive decrypt/extract, ukládá archive heslo pro celou dávku odkazů, maskuje citlivé hodnoty a selhané rozbalení přesune do samostatného stavu decrypt_failed. MEGA linky mají vlastní post-download payload decryption s ověřením integrity. Archivy s více částmi se seskupují, takže .partNN.rar a starší .rar / .r00 sady jde obnovit nebo odstranit jako celek, místo abych musel řešit každou část zvlášť.
Docker, UI a hranice
DLQ je Docker-first, protože takhle podobné služby doma provozuji. Daemon validuje out_dir vůči nakonfigurovaným DATA_* mountům, takže joby mohou zapisovat jen tam, kam bylo úložiště explicitně připojené. Stejné DATA_* hodnoty se v API a UI promění na destination presets, což se hodí hlavně na Unraidu, kde služba může mít připojených několik media složek do různých cest.
Web UI je komfortní vrstva pro dávkové přidávání, procházení cílových složek, označení oblíbených výstupních adresářů, sledování seskupených jobů, změnu runtime nastavení a kontrolu logů. CLI i UI mluví se stejným daemonem, takže workflow je identické.


Bezpečnost je záměrně přímočará: DLQ je pro důvěryhodné sítě, typicky domácí LAN nebo Docker network. API nemá autentizaci, takže pokud je potřeba vzdálený přístup, je potřeba použít reverse proxy s autentizací. aria2 by také mělo mít nastaveno ARIA2_SECRET, protože jeho JSON-RPC endpoint je součást runtime.
aria2 jsem vybral proto, že jsem nechtěl znovu implementovat spolehlivé stahování souborů. Umí obnovení stahování, paralelismus, sledování stavu i reporting. DLQ se soustředí na orchestraci nad ariou.
Aktuální stav
První verze byla hlavně malý daemon, CLI, SQLite fronta, aria2 integrace a Webshare resolver. Všechno od té doby vyplynulo z něčeho, na co jsem při používání reálně narazil: volitelné SvelteKit UI pro chvíle, kdy se mi nechtělo používat CLI, podpora stahování z MEGA, rozbalení archivů a podpora více částí archivů, oblíbené složky a možnost nastavení, Unraid deploy skripty.
Jako projekt pro naučení se se DLQ trefil do správné velikosti. Go dávalo smysl pro daemon a CLI: jedna malá binárka, přímočará konkurence a praktická HTTP služba. SvelteKit fungoval dobře pro jednoduchý dashboard, který hlavně používá API volání daemona a vykresluje aktuální stav fronty. Výsledek není univerzální download program, ale nahradil nepohodlný VNC workflow, které mě už nebavilo používat.