Phoenix 5.0 is the first stable release of a ground-up rebuild. The whole 4.x
line was the development series with several sub-versions, and that version
number has been skipped for stable.
For an operator on 3.x the short version: everything has changed.
Work through MIGRATING.md carefully, this upgrade is major.
That guide starts from 3.2.x, the last stable line. If you are on 3.1 or
earlier, upgrade to 3.2.2 first — its own schema changes are not repeated
there.
Breaking
- BREAKING: Only
public/is web-served. The repository root is no longer the document root —src/,bin/,config/,sql/andtests/all sit above it. Re-point your web server atpublic/(#48); see APACHE.md / NGINX.md. - BREAKING: Configuration moves from
_settings/phoenix.custom.phptoconfig/phoenix.custom.php. Existing overrides are forward-compatible; copy the file across. - BREAKING: Cron jobs move and change.
_cron/hourly/*becomesbin/prune-database.php(prune expired rows, refresh statistics),bin/optimize-database.php(rebuild tables, on a slower schedule) andbin/backup-database.php. All entries must be updated. - BREAKING: Minimum PHP is 8.2, up from 7.1.
- BREAKING: Every table is InnoDB. Concurrent announces take row locks rather than queueing on the table, and an unclean shutdown replays from the redo log. In exchange an unqualified
COUNT(*)scans an index,OPTIMIZE TABLEis a full rebuild, and the data takes roughly 2.1x the space. Fresh installs get InnoDB automatically; existing installs convert each table by hand — see MIGRATING.md. - BREAKING: The database schema changes. A
usercolumn and torrent meta (filename, files, trackers, webseeds) ontorrents, a signedleftonpeers, asourcecolumn ontasks, and neweventsandtask_runstables. MIGRATING.md carries the whole change as one SQL block. - BREAKING: Settings renamed for consistency.
external_ip→allow_client_ip,announce_interval→announce_rec_interval,min_interval→announce_min_interval,random_limit→random_peers_threshold,clean_with_requests→clean_request_percent,allow_any_proxy→trust_any_forwarded,backup_rotate→backup_retention. An unrecognised key silently falls back to the new default, so update any overrides. - BREAKING: Forwarded-header handling is fail-closed. The
honor_xffflag is replaced by aforwarded_headersallowlist honoured only whenREMOTE_ADDRfalls inside atrusted_proxiesrange. The default trusts nothing but the direct connection, so an install that relied onhonor_xffmust now name the header its proxy sets. - BREAKING: The version is reported as two values, and without its wrapper.
?statsused to report a single string wrapped as$Id: … $,— a Subversion keyword inherited from PeerTracker that git never expanded, plus a stray comma. It is nowversion(v5.0) andrelease(Boulevard) as separate values in the JSON and XML forms, so a client comparing versions never parses a codename out of a display string. Anything stripping that wrapper should stop.
Feature
- FEATURE: A web admin panel (#54) — dashboard, torrents, peers, clients, bandwidth, geography, task history, backups, server support, DB utilities and settings — behind a required password, a hardened session, a failed-login throttle and CSRF on every state-changing form, with an optional TOTP second factor.
admin_auth_optionalruns it unauthenticated for a panel already protected by a reverse proxy or an IP allowlist. - FEATURE: A first-run installer that writes the configuration, creates the schema and enrols 2FA, protected by a one-time token written to
config/so only someone with filesystem access can complete setup. - FEATURE: An authenticated management REST API (#53) — add, update, list, delist and delete torrents — keyed per user, with keys stored as SHA-256 hashes and compared timing-safe. Every endpoint answers JSON or XML. Documented end to end in API.md.
- FEATURE: A redesign onto a shared design system — a vendored
ds.css, Lucide icons, the flame mark and a persisted light/dark theme that applies before first paint. The public index and stats pages, previously near-unstyled, are first-class. No build step. - FEATURE: Privacy-preserving stat-tracking. An optional
eventsledger records completions with a coarse client label and country code derived from the peer_id and IP — never the address itself — feeding the Clients, Bandwidth and Geography pages. Geo enrichment needscomposer require maxmind-db/reader, andext-maxminddbif your distribution packages it — the pure-PHP reader is around 40x slower. - FEATURE: Torrent meta — filename, file list, trackers and webseeds — stored, searchable, and served on the public index when
index_show_metais on. - FEATURE: Selective backups. A backup is a dated directory holding
schema.sqland one data file per table, so restoring one table is importing one file. See RECOVERY.md. - FEATURE: Maintenance alerts. Overdue and never-run maintenance is flagged on the dashboard and in the sidebar, against configurable thresholds.
- FEATURE: BEP 24 external IP in the announce response, and a
min_request_intervalscrape-throttle hint. - FEATURE: Retry hints on errors —
"never"for a permanent rejection, or the rate-limit window in seconds for a throttled announce (#69). - FEATURE: Per-IP announce rate limiting (
announce_rate_limit,announce_rate_window) that no longer cross-blocks unrelated peers behind one NAT. - FEATURE: Error reporting hooks, shipping wired for Sentry and inert by default.
Improvement
- IMPROVES: The listings page, search and sort in SQL rather than loading a whole table into the browser, so a million-row install renders a page in constant memory.
- IMPROVES: The closed-tracker permission check is one indexed query rather than a read of every registered info hash — which at 200k torrents cost 48.8 MB and 57 ms per announce to answer a question about one of them.
- IMPROVES: Geo lookups are 73x faster than the first implementation: a cached reader and the raw record rather than a model graph take an announce's enrichment from 606 µs to 7.5 µs.
- IMPROVES: An MVC-inspired layout —
src/controller/,src/model/,src/views/,src/functions/— one function per file, each requiring its own dependencies. - IMPROVES: A single bencode emitter owns length prefixes, container tokens and BEP 3 dict-key ordering; no view hand-assembles bencode.
- IMPROVES: Announce and scrape answer JSON and XML as well as bencode, for debugging and tooling.
- IMPROVES: Atomic configuration writes — a temp file under an exclusive lock, renamed over the target — so a concurrent request never includes a half-written config.
- IMPROVES: Security headers on every response, with a Content-Security-Policy scoped per surface.
- IMPROVES: A full PHPUnit suite with smoke tests against a real server, and CI across PHP 8.2–8.6.
Bugfix
- BUGFIX: Duplicate
completedannounces no longer double-count downloads. Transmission sends every announce twice; a completion is counted only on the leech-to-seed transition. - BUGFIX: Announces without
left, or with an out-of-range port, no longer fail against a strict-mode database. Theleft = -1sentinel round-trips in a signed column, and an invalid port drops only its own address family. - BUGFIX: Database failures surface as tracker errors, not HTTP 500s. On PHP 8.1+ every mysqli failure was an uncaught exception.
- BUGFIX: Malformed scrape output fixed — full and multi-hash scrapes emitted invalid bencode whenever more or fewer than exactly one torrent matched, XML scrapes had no root element, and JSON scrapes returned
nullfor an empty result. - BUGFIX: The admin redirect cannot be steered off-site; protocol-relative and absolute targets fall back to a local page.
- BUGFIX: Client labels are sanitised so raw peer_id bytes can never reach the admin views or the stored label.
- BUGFIX: Maintenance failures are noticed.
CHECK/ANALYZE/OPTIMIZEreport problems as rows inside their result sets whilemysqli_errno()stays0, so a rebuild that died partway used to log a successful run.
Documentation
- DOCS: API.md — every HTTP endpoint, with parameters, JSON and XML shapes, errors and a summary table.
- DOCS: CONFIGURATION.md — every operator setting, with defaults.
- DOCS: RECOVERY.md — admin lockout, disabling 2FA, and restoring the database.
- DOCS: LIMITS.md — measured ceilings: how many peers and torrents an install carries, and what binds first.
- DOCS: MIGRATING.md — the 3.x to 5.0 upgrade, step by step.
- DOCS: BEPs.md — which BEPs Phoenix implements, and which it deliberately does not.