Skip to Content

qb fix - System Repair

Fix & Repair

Troubleshoot and resolve common system issues effortlessly

The qb fix commands provide a powerful toolkit to address common issues and perform system repairs. With a focus on simplicity and effectiveness, these commands enable you to troubleshoot and resolve various problems that may arise on your server, ensuring smooth and uninterrupted operations.

CommandWhat it fixes
qb fix python
Multi-version Python (3.11, 3.13) with PEP 668 compliance
qb fix php [--security [--check]]
Moves each PHP application to its supported PHP, repairs its pool and retires the unused system PHP; --security brings each application's PHP to its security floor, --check only reports
qb fix database
Truth-aware user_software reconciler + SQLite symlink repair
qb fix permissions
System groups + /opt/username ownership
qb fix home
User home directory permissions
qb fix dlindex
Re-render per-user nginx download index configs (<user>.dlindex.conf); --if-changed acts only when a download folder moved
qb fix libcurl [--check]
Make sure rTorrent 0.16 runs on libcurl 8.14.1 or newer; --check only reports
qb fix dashboard
Re-run v4 dashboard update pipeline
qb fix version
Complete binary refresh from upstream

Run qb fix help (also qb fix --help or qb fix -h) to print the list of subcommands and their options, including dlindex [-u USER] [--if-changed] and libcurl [--check].


Fix Python

Fix Python configuration and install missing extensions:

bash
qb fix python

What it does:

  • Installs/repairs Python build dependencies and runtime packages (pip, docopt, virtualenv, etc.)
  • Ensures compiled Python 3.11 and 3.13 are present and functional, with pip/bootstrap synced
  • Applies PEP 668 safeguards (--break-system-packages when needed) and avoids downgrading system pip
  • Syncs baseline modules across 3.11, 3.13, and system Python; logs FIX_PYTHON to system_log

Distro-specific behavior:

DistributionPython 3.11Python 3.13
Debian 12 (Bookworm)Native (skip install)Compiled package
Debian 13 (Trixie)Compiled packageNative (skip install)
Ubuntu 22.04 / 24.04Compiled packageCompiled package

When to use:

  • Python apps won’t start or show ModuleNotFoundError
  • After distro/OS upgrades that changed Python
  • Broken virtualenvs or missing compiled Python runtimes (3.11/3.13)
  • Before/after installing Python-based QuickBox apps

Applications that depend on Python:

Download Clients

Core apps that rely on Python

3

Automation & Media

Core apps that rely on Python

4

Monitoring & Dashboards

Core apps that rely on Python

3
System Python Updates
Warning

Major OS upgrades can break Python applications. Always run qb fix python after upgrading your operating system.


Fix PHP

Move each PHP application to the newest PHP it supports, repair its PHP-FPM pool, or bring that PHP up to the current security fixes:

bash
qb fix php                           # Move each PHP app to its supported PHP, repair its pool, retire the unused system PHP
qb fix php --security                # Update each application's PHP to its security floor
qb fix php --security --check        # Report only, change nothing
qb fix php [VERSION] --remove-hold   # Clear an apt hold left on that PHP version's packages

QuickBox uses per-application PHP isolation rather than a single system-wide PHP. ruTorrent, phpMyAdmin and Nextcloud each run in their own PHP-FPM pool. PHP 8.1 is past its upstream end of life, so an application on an older PHP is moved up to the newest PHP it supports (8.4 today) the next time qb fix php runs, and every update runs it. The v4 dashboard needs no PHP at all.

OptionDescriptionExample
--security

Bring the PHP of every PHP application up to its security floor, the lowest build that carries the current PHP security fixes. Updates only the installed packages of that PHP version, never moves an application to another PHP version, restarts only the PHP-FPM service that needs it, and leaves a version that is already at its floor alone. Needs root.

qb fix php --security
qb fix php --security
--check

Used with --security. Report whether each PHP application is at its security floor and change nothing. Returns exit code 1 when a PHP version is below its floor.

qb fix php --security --check
qb fix php --security --check
--remove-hold

Remove an apt hold left on the packages of the target PHP version, for example one written by an older QuickBox. Exits straight after, without a repair.

qb fix php 8.4 --remove-hold
qb fix php 8.4 --remove-hold
[VERSION]

Only selects the PHP version --remove-hold acts on. Valid values: 8.1, 8.2, 8.3, 8.4, 8.5. Defaults to 8.1 when omitted. A repair, a move or a --security run works on the PHP version each application uses and ignores it.

qb fix php 8.4 --remove-hold
qb fix php 8.4 --remove-hold
The --hold option is gone
Note

QuickBox no longer holds PHP packages. A held package is skipped by apt upgrade, so a held server never receives PHP security fixes. apt cannot move an application to another PHP version, because the version is part of the package name (php8.1-* cannot turn into php8.4-*); only the move described below does that. --remove-hold stays so a hold left by an older install can be cleared.

Which PHP each application runs on

Each application has a range of PHP versions it supports. A new install gets the newest version in that range that your package source offers, and qb fix php moves an application running on an older version up to it. An application is only ever moved up, never down.

ApplicationSupported PHPPool configPool socket
ruTorrent8.1 to 8.4/etc/php/{version}/fpm/pool.d/rutorrent.conf/run/php/php{version}-fpm-rutorrent.sock
phpMyAdmin8.1 to 8.4/etc/php/{version}/fpm/pool.d/phpmyadmin.conf/run/php/php{version}-fpm-phpmyadmin.sock
Nextcloud8.3 to 8.4/etc/php/{version}/fpm/pool.d/nextcloud.conf/run/php/php{version}-fpm-nextcloud.sock

What qb fix php does (no flags)

Run without options, qb fix php does three things in order and is quiet on a server where nothing needs doing. The move and the retirement need root; as another user they are skipped.

  1. Moves each PHP application to its supported PHP. An application already on the newest PHP in its range is left alone.
  2. Repairs the PHP-FPM pool of each PHP application.
  3. Retires the system PHP that no application uses.

Moving an application to a newer PHP

An application is moved only when every check below passes, and a failure at any step leaves it running exactly as it was:

  • The installed release supports the new PHP. QuickBox reads the supported PHP versions from the application’s own files. When the installed release does not support the new version, or the versions cannot be read, the application stays where it is and the output says so once. Updating the application is what lets it move.
  • The move can be checked. The check asks the pool for the application’s page over FastCGI, using libfcgi-bin, which the move installs. If that client cannot be installed or cannot run, the move is refused and the application stays on its current PHP.
  • The new pool is built and answers. The application’s PHP packages and modules are installed for the new version and it is brought to its security floor, the pool config is written for the new version, and that PHP-FPM service is started. The new pool must answer the application’s page with the same status the old pool gave, and never with a server error.
  • nginx follows. The application’s nginx socket references are pointed at the new pool, nginx is tested and reloaded, and the application’s page must answer through nginx as before.

Only then is the old pool removed. The old PHP version’s PHP-FPM service is reloaded, or stopped and disabled when it has no application pool left. If any step fails, the nginx files are put back, the new pool is removed and the old pool keeps running. One warning names the step that failed, and the next run tries again without repeating the warning until the reason changes.

A move that is refused or fails does not change the exit code of qb fix php.

Repairing application pools

For each installed PHP application the repair:

  • Finds the PHP version of the application’s pool config. If the pool config is missing it says so and tells you to reinstall that application; apart from a move to a newer PHP it does not create pools.
  • Installs any PHP package that application needs and is missing.
  • Restarts that PHP version’s php{version}-fpm service only when it installed something or the service was not running.
  • Prints one line per application when nothing needed fixing.

It also removes Apache if a PHP package pulled it in, because nginx serves the web ports, and takes leftover lines from retired PHP add-ons out of php.ini (the old SourceGuardian and ionCube loaders and a duplicate extension=memcached.so line).

The repair does not refresh package lists, upgrade packages or change system-wide PHP settings. Updating PHP within its version is qb fix php --security.

Retiring the unused system PHP

On a server with the v4 dashboard, qb fix php then removes the PHP that no application uses, so a server whose applications moved off PHP 8.1 or 8.3 loses those versions. The default nginx site refuses .php requests that no application handles, the default www pool of a version an application runs on is moved aside, a PHP version nothing uses is stopped, disabled and removed, and the php command follows ruTorrent’s PHP. Your own nginx sites are never changed, and a PHP version one of them still uses is kept. See What an update does for PHP for the detail. A server without the v4 dashboard is left as it is.

Security floor (--security)

Each PHP version has a security floor: the lowest build that carries the current PHP security fixes. The floors are listed per PHP version in /opt/quickbox/config/software/php-security-floor. An installed build passes when it is at or above the floor, so a packager suffix after the floor number still counts as at the floor.

bash
qb fix php --security --check   # report only
qb fix php --security           # update

qb fix php --security goes through each PHP version that a QuickBox application pool runs on, once even when several applications share it:

  1. A version already at its floor is left untouched, so running the command a second time changes nothing.
  2. For a version below its floor it refreshes the package lists and looks for a fixed build.
  3. When a fixed build is published, it clears any apt hold on that version’s packages and updates the installed packages of that version only, never to another PHP version.
  4. It restarts php{version}-fpm only when that service was running and its program file was replaced.
  5. It reads the installed build again and reports whether the floor is now met.

When your package source has no fixed build for your release yet, the command says so, changes nothing and exits with code 3. Run it again later; every qb update quickbox repeats it as well.

Exit codes:

CodeMeaning
0Every PHP version is at its floor, or was brought to it
1--check only: a PHP version is below its floor
3No fixed build is published for this release yet; nothing was changed
4The installed PHP version could not be read; nothing was changed
5The update failed, the package lists could not be refreshed, or PHP is still below its floor after the update

When several PHP versions disagree the most serious code wins. --security without --check must run as root.

When it runs on its own:

  • Every QuickBox update runs qb fix php, clears old PHP holds and runs qb fix php --security, including the dev and beta channel updates.
  • Installing or updating ruTorrent, phpMyAdmin or Nextcloud applies the floor to the PHP version that application runs on. If no fixed build is published yet, the application keeps running on its current PHP and the output says it will pick up the fixed build on a later update.
  • The twice-daily update check records whether each application is at its floor without changing anything.

Hold management

QuickBox does not hold PHP packages, and an update removes the holds that earlier releases left behind. --remove-hold is the manual path for the same job. It skips the repair and exits straight after removing the hold.

bash
# Clear a hold left on the PHP 8.1 packages (php8.1*)
qb fix php 8.1 --remove-hold

Examples

bash
# Move PHP applications to their supported PHP and repair their pools (e.g. Nextcloud showing 502 errors)
qb fix php
 
# Check whether every PHP application is at its security floor
qb fix php --security --check
 
# Bring every PHP application up to its security floor
qb fix php --security
 
# Clear a PHP 8.4 hold before a planned upgrade
qb fix php 8.4 --remove-hold

When to use:

Use qb fix php when

  • PHP apps show 502/504 errors or missing extensions
  • A PHP security advisory has been published and you want the fix now
  • A PHP application is still on PHP 8.1 or another PHP older than it supports
  • A PHP-FPM pool config file is missing or the PHP-FPM service is stopped
  • After installing or removing PHP-based applications
  • apt reports PHP packages as kept back

What it resolves

  • The move checks the new pool and nginx before the old pool is removed, and keeps the old pool on any failure
  • The repair installs missing PHP packages and restarts the PHP-FPM service that needs it
  • --security updates only the installed PHP packages of each application to the fixed build
  • --security --check shows where each application stands without changing anything
  • Pool verification confirms each installed application still has its pool config
  • --remove-hold lets apt upgrade the packages again

Applications that depend on PHP:

PHP Applications

Core apps that rely on PHP

3
Per-application PHP isolation
Note

Each application gets its own FPM pool config, created by that application’s install script (for example /etc/php/8.4/fpm/pool.d/rutorrent.conf). The qb fix php command verifies the pool config exists and restarts the relevant FPM service. Apart from a move to a newer PHP it does not create pools from scratch; to restore a missing one, reinstall the application.

v4 Dashboard does not use PHP
Tip

The v4 dashboard runs on Node.js/Fastify. PHP is only used by applications like ruTorrent, phpMyAdmin, and Nextcloud. If the dashboard is not working, see qb fix dashboard instead.


Fix Database

Reconcile duplicate user_software rows against live config truth, and (on legacy SQLite v3 installs) repair the database symlink:

bash
qb fix database                 # dry-run (default) -- reports only
qb fix database --apply         # execute the reconciliation
qb fix database --cron          # apply mode with reduced output for scheduled runs
OptionDescriptionExample
--dry-run

Report what would change without touching the database. This is the default -- you must pass --apply to make changes.

qb fix database --dry-run
qb fix database --dry-run
--apply

Execute the reconciliation: delete losing duplicate rows, update ports on the kept row when truth was parseable.

qb fix database --apply
qb fix database --apply
--cron

Same as --apply but with reduced output, intended for scheduled runs.

qb fix database --cron
qb fix database --cron
Dry-run is the default
Warning

qb fix database runs in dry-run mode unless you explicitly pass --apply or --cron. Nothing is deleted or updated until you opt in. Every reconciler action — dry-run or applied — is also written to the system_log table with log_source='qb fix database'.

How the reconciler decides which row to keep

Legacy install bugs can leave multiple rows in the user_software table for the same (user_id, software_name) pair. The reconciler walks every duplicate group and consults the v4 dashboard on 127.0.0.1 for the app’s live config file — the file the service is actually reading. v3 Bash never parses app config files directly; it asks v4 (the authority) for the raw file contents via GET /api/system/apps/:appId/config and then greps the expected port fields out of the returned string.

For each duplicate group, one of three things happens:

OutcomeWhenWhat the reconciler does
KEPT_BY_TRUTHv4 returned the live config and a row's software_port / software_secure_port match the parsed values.Keep that row; delete every other row in the group.
UPDATED_BY_TRUTHv4 returned the live config and parsed real ports, but no row matches.Keep the highest-id row, update its software_port / software_secure_port to the parsed truth, delete the rest.
TRUTH_PARSE_MISSv4 returned the config file but the expected port fields could not be grepped out of it.Fall back to MAX(id): keep the highest-id row, delete the rest. Emits a yellow truth_parse_miss warning.
KEPT_BY_MAX_IDv4 is unreachable on 127.0.0.1, the app is not in the mapped truth set, or the endpoint errored.Fall back to MAX(id): keep the highest-id row, delete the rest. Emits a yellow v4_unreachable warning once per run.

Apps with truth mapping today: sonarr, sonarr4k, radarr, radarr4k, lidarr, readarr, prowlarr, jellyfin, qbittorrent, deluge, rtorrent, rutorrent, plex. Any other app with duplicate rows still gets deduped — it just uses the MAX(id) fallback directly.

Example session

A dry-run identifies a duplicate sonarr group for user@host:

bash
$ qb fix database
Checking QuickBox database...
v4-dashboard detected -- skipping legacy SQLite symlink repair
Running truth-aware reconciliation (dry-run)
Found 1 duplicate group in user_software
 
Group: user@host / sonarr (2 rows)
  Truth source: v4 (config.xml) -- Port=9020, SslPort=9878
  Row id=42 port=9020 secure=9878  <- MATCH (would keep)
  Row id=37 port=8989 secure=9898  <- would delete
 
Dry-run summary: would keep 1, delete 1, update 0
Re-run with --apply to execute.

Re-running with --apply commits the change:

bash
$ qb fix database --apply
Checking QuickBox database...
Running truth-aware reconciliation
Group: user@host / sonarr (2 rows)
  Truth source: v4 -- keeping id=42 (KEPT_BY_TRUTH)
  Deleted 1 row
Reconciliation complete: kept 1, deleted 1, updated 0

On servers that do not have the v4 dashboard installed, qb fix database also repairs the legacy /opt/quickbox/db/qbpro.db symlink pointing at /opt/quickbox/config/db/qbpro.db, creates a backup (keeping the newest 3), and ensures www-data read access. When v4 is installed this step is skipped automatically — v4 manages its own database at /etc/v4-dashboard/data/db/qbpro.db through Prisma.

When to use:

Use qb fix database when

  • Dashboard shows duplicate apps for a user after a failed install or restore
  • An app shows the wrong port in the dashboard but works fine when opened directly
  • You want to audit duplicate user_software rows without committing changes
  • Legacy v3-only server with SQLite symlink drift under /opt/quickbox/db/

What it resolves

  • Dry-run reports every duplicate group with the kept row and the proposed deletions
  • --apply reconciles against the live config file v4 reads for each app
  • Falls back to MAX(id) when v4 is unreachable or the config parse misses, so the command never errors out on one bad group
  • Every action is logged to system_log with log_source='qb fix database' for later review
Always dry-run first
Tip

Run qb fix database (no flags) before qb fix database --apply. The dry-run shows you exactly which rows will be kept and which will be deleted, so you can verify the decisions against the live apps before committing the change. The reconciler writes DRY_RUN_RECONCILE entries to system_log for dry-run operations, which is useful for auditing.

v4-aware by design
Note

The reconciler requires v4 on 127.0.0.1 to resolve truth. When v4 is unreachable (service stopped, port blocked, auth token missing), the command still runs — it just degrades to the historic MAX(id)-wins rule and emits a yellow warning at the top of the run. Start v4-dashboard.service first if you want the truth-based path.


Fix Permissions (per-user apps)

Normalize system groups and application directories for a user:

bash
qb fix permissions -u username
# or
qb fix perms -u username

What it does:

  • Preserves existing groups from /etc/group, then ensures www-data is present; adds sudo only for shell users (shell_level = 1)
  • Recursively sets ownership of /opt/<username> to the user and group
  • Sets directories under /opt/<username> to 0755
  • Logs FIX_PERMISSIONS <username> to system_log

How it differs from qb fix home:

  • qb fix home -u username targets /home/<username> (files 0664, dirs 0755, home 0750, special handling for .ssh, .bin, rclone, Nextcloud)
  • qb fix permissions -u username targets /opt/<username> and group membership — use it if/when app installs/upgrades change ownership/ACLs. QuickBox handles this automatically during installs/reinstalls/updates, but this command is available when something fails or manual changes break the flow.

How QuickBox automatically maintains app config permissions

QuickBox runs a background service, qbpermmon.service, that automatically corrects ownership, file modes, and ACLs on monitored app config paths. Drift is detected and corrected within a minute of occurring.

How it works:

  • The binary (/usr/local/bin/qbpermmon) sweeps every monitored path on a 60-second interval. For each entry in the matrix, it stats the path and compares owner, group, and mode against the canonical values. If they already match, nothing happens. If they differ, the service runs chown + setfacl + chmod to restore the canonical state.
  • Enforcement is matrix-driven: a single config file (/opt/quickbox/config/system/qbpermmon.matrix.sh) declares the canonical owner, group, mode, and ACL for every monitored path. All 53 entries across 29 apps are defined there. If an app isn’t in the matrix, its paths aren’t monitored.
  • For each entry that needs correction, the service enforces all three of owner + group, file mode, and ACL in one pass — not just a chmod. Plex is the only app in the fleet with a dedicated system user (plex:plex); all other apps use the installing user.
  • Drift is detected at the next 60-second sweep — typical detection latency is well under a minute. The trade-off is near-zero CPU when nothing is wrong (the stat per path costs microseconds and only adds up to a few milliseconds per minute across the whole matrix).

Apps with automatic protection:

The matrix currently covers the *arr stack (Sonarr, Radarr, Lidarr, Readarr, Prowlarr), media servers (Plex Media Server), request and discovery tools (Jellyseerr, Overseerr, Seerr, Ombi), indexers (Jackett, NZBHydra2), download clients (rTorrent, SABnzbd, qBittorrent, Deluge, NZBGet, Transmission, pyLoad), reading apps (Kavita, Komga, LazyLibrarian), media management (Bazarr, Medusa), and utilities (Autobrr, Syncthing, rclone, TheLounge).

Limits — what qbpermmon is not:

  • It does not touch /opt/<username> or app binary directories. For those, use qb fix permissions -u username.
  • It does not repair home directory structure or .ssh permissions. For those, use qb fix home -u username.
  • Coverage is strictly matrix-driven. Paths not listed in the matrix are not monitored.
  • Runs as root; failures and corrective actions surface to journalctl -u qbpermmon.
About qbpermmon.service
Tip

qbpermmon.service is a Type=notify systemd unit with a 60-second watchdog. The service polls the matrix once per minute and only runs chown/setfacl/chmod on paths where actual drift is detected — when everything is correct, the work-per-minute is just a few stat calls. Output routes to the journal (SyslogIdentifier=qbpermmon). In practice, most app config permission drift is corrected automatically within a minute of occurring. qb fix home and qb fix permissions remain the right tools for broader repairs outside the matrix paths.


Fix dlindex

Re-render every user’s per-user nginx download index config so already-deployed installs pick up the latest symlink hardening, dynamic download-path discovery, and qbpermmon drop-ins for custom NAS paths:

bash
qb fix dlindex                  # walk every user in user_information
qb fix dlindex -u username      # single user
qb fix dlindex --if-changed     # only act when a client's download folder moved
Symptom: the downloads / browse index page fails to load (other pages work)
Tip

If a user’s downloads / file-browse index page (the directory listing of their completed downloads) fails to load — returns a 502 or 404, shows blank, or errors — while the rest of the dashboard loads normally, the per-user download-index nginx config (<user>.dlindex.conf) is missing or broken. This is a single shared per-user config that covers every download client that user has installed (qBittorrent, rTorrent, Deluge, Transmission, NZBGet, SABnzbd), so the whole browse page fails at once — but the clients themselves keep running. Run qb fix dlindex to rebuild it for every user, or qb fix dlindex -u username for the one affected user. The fix re-renders the per-user fancyindex config and reloads nginx on success, restoring the page. A failure confined to only the downloads/browse page (not the whole dashboard) is the giveaway — this is a different problem from a client’s own socket/permission errors, which take the entire client offline.

OptionDescriptionExample
-u USERNAME

Re-render the download index config for a single user only. Without this flag, every user in user_information is walked.

qb fix dlindex -u username
qb fix dlindex -u username
--if-changed

Change-detection mode. The config is rewritten, tested and reloaded in nginx, and the stored download folder updated, only when something actually changed. An unchanged run writes nothing, does not reload nginx and leaves no system_log entry. This is the mode the automatic watcher and the hourly check use.

qb fix dlindex -u username --if-changed
qb fix dlindex -u username --if-changed

What it does:

Each download client that writes to a local directory (qBittorrent, rTorrent, Deluge, Transmission, NZBGet, SABnzbd) contributes a per-user nginx fancyindex view of its completed-download directory — the https://<server>/<username>.<client>.downloads URLs you can browse with a web browser. These are stitched into one shared per-user config at /etc/nginx/software/<username>.dlindex.conf, rendered from the templates under /opt/quickbox/config/software/dlindex/.

qb fix dlindex re-renders that per-user config from the current templates. For each user it:

  • Resolves the user’s installed download clients via user_software.
  • Reads each client’s finished-download folder from the client’s own settings (it never edits them) and validates it against the allowlist (/home/<user>/, and folders at least two levels below /mnt/ or /media/). The folder must exist, contain no symlink components, and be readable by the web server user.
  • Serves the default folder instead when the configured one fails a check, and records which check failed. The dashboard shows that as a note beginning “Showing the default folder.” under the Download folder row.
  • Records the folder it serves on the user’s installed-client record, which is how the dashboard shows the Download folder row without reading client settings itself.
  • Writes the rendered <user>.dlindex.conf with www-data:www-data ownership.
  • Adds a qbpermmon drop-in for any validated /mnt or /media leaf, so the permission monitor keeps custom NAS paths readable by www-data.
  • Tests the nginx configuration (nginx -t) and reloads nginx only on PASS — a broken config is never applied.
  • Emits one NDJSON status line per user, with changed (whether the config or the stored folder moved) and fallbacks (any client:reason pairs where the default was served). The server-wide walk also writes a FIX_DLINDEX entry to system_log. Single-user mode logs FIX_DLINDEX_<username>.

Users whose home directory is missing (deleted accounts that still have a row in user_information) are skipped with "reason":"home_missing".

Automatic updates:

You rarely need to run this by hand. When a user changes a download folder in a client’s own settings, a per-user watcher on the client’s settings file runs qb fix dlindex -u <username> --if-changed and the index and the dashboard follow. A server-wide qb fix dlindex --if-changed --cron also runs hourly as a safety net, and it reloads nginx only when something moved. Run the command yourself after fixing something outside the client’s settings, such as creating the folder or changing its permissions.

When to use:

Use qb fix dlindex when

  • A user's downloads / file-browse index page fails to load -- returns a 502 or 404, shows blank, or errors -- while every other page in the dashboard loads normally
  • After a CLI update where dlindex templates or the symlink hardening logic changed
  • Browser download index shows the wrong path after switching a client to a custom /mnt or /media download directory
  • The dashboard shows "Showing the default folder." under Download folder and you have since fixed the folder (created it, changed its permissions, or replaced a symlink)
  • qbpermmon does not keep a custom NAS download path readable by www-data
  • Backfilling existing installs so they pick up the latest fancyindex hardening without reinstalling each torrent client

What it resolves

  • Re-renders <user>.dlindex.conf from the current templates for every user (or one user with -u)
  • Discovers each client's real download path and validates it against the allowlist
  • Writes a qbpermmon drop-in for custom /mnt or /media paths so permissions stay correct
  • Tests nginx and reloads only on PASS, never applying a broken config
Idempotent
Note

Re-running qb fix dlindex is safe at any time. Without --if-changed it rewrites the file every time and reloads nginx after a successful test. With --if-changed, an unchanged result is discarded: nothing is written and nginx is not reloaded. Safe to run after any CLI update that touched the dlindex templates.

Browser download index URLs
Tip

The per-user download index is the URL pattern https://<server>/<username>.deluge.downloads, <username>.qbittorrent.downloads, <username>.rtorrent.downloads, <username>.transmission.downloads, <username>.sabnzbd.downloads, and <username>.nzbget.downloads — protected by the same htpasswd file as the rest of your QuickBox access. See each download client’s documentation page for details.


Fix Dashboard

Re-run the v4 dashboard update pipeline:

bash
qb fix dashboard

What it does:

  • Equivalent to running qb update dashboard
  • Re-downloads and rebuilds the v4 dashboard from upstream
  • Restarts the v4-dashboard.service
  • Useful when the dashboard update failed partway through or the build is corrupted

When to use:

Use qb fix dashboard when

  • Dashboard showing errors or blank page after a failed update
  • Dashboard service won't start after system changes
  • Need to force a fresh dashboard rebuild
  • Dashboard version is out of sync with the CLI

What it resolves

  • Re-downloads the latest dashboard build
  • Rebuilds and restarts the dashboard service
  • Resolves partial update failures
  • Brings dashboard to the same version as the CLI
v4 Dashboard runs on Node.js
Note

The v4 dashboard is a TypeScript/Fastify application, not PHP. Its service is v4-dashboard.service. If you are troubleshooting the dashboard, check systemctl status v4-dashboard — not PHP-FPM.


Fix Version

Force update QuickBox to the latest upstream version:

bash
qb fix version

What it does:

  • Downloads all CLI binaries fresh from central.quickbox.io (the release proxy)
  • Replaces the following components with the latest upstream versions:

Binaries refreshed:

  • fix (the fix system itself), qb (CLI handler), manage (management binary)

Modules refreshed:

  • Fix modules: dbFix, homeFix, libcurlFix, permFix, phpFix, pythonFix, writebackFix
  • Management modules: apiSettings, dbSettings, fail2banSettings, langSettings, mountSettings, nginxSettings, softwareSettings, telemetrySettings, themeSettings, trackerSettings, wbSettings, wgSettings, dnsSettings
  • Update pipeline: pipeline, pipeline-environment, pipeline-dependencies, pipeline-download, pipeline-system, pipeline-nginx, pipeline-dashboard, pipeline-database, pipeline-services, pipeline-finalize, dashboardUpdate

After downloading, it re-executes itself through the update pipeline to apply all changes.

Channel detection: If dev (/opt/qb_dev) or beta (/opt/qb_beta) flags are present, the command routes to the appropriate channel-specific updater (devpull/betapull) instead.

When to use:

Symptoms

  • QuickBox commands not working properly
  • After a failed automatic update
  • Core system files are out of sync
  • Missing new features from changelog
  • Update check shows available version but update failed

Resolution

  • Forces fresh download of all CLI binaries and modules
  • Synchronizes all system components via update pipeline
  • Repairs broken update state
  • Brings system to current upstream version
  • Dev/beta users are routed to their channel automatically

What’s preserved:

  • User accounts and passwords
  • All installed applications and their data
  • Application configurations
  • Database content
  • User files and downloads

What gets updated:

  • CLI binaries (qb, fix, manage)
  • All fix and management modules (20+ files)
  • The full update pipeline (environment, dependencies, download, system, nginx, dashboard, database, services, finalize)
Not a Reinstall
Note

qb fix version is NOT a full reinstall — it’s a forced binary refresh and update pipeline re-run. All your data, applications, and configurations are preserved. Think of it as a “force refresh” to the latest version.


Fix Writeback

Detect, and with --apply clear, a kernel cgroup-writeback cleanup livelock where writeback worker threads peg a CPU and a dying control group’s cached inodes stop draining:

bash
qb fix writeback                 # read-only check, reports a verdict
qb fix writeback --apply         # drain reclaimable inodes when a livelock is detected
Symptom: server load keeps slowly rising with kernel workers pegged
Tip

If your server’s load average creeps up over hours or days while two kernel worker threads (kworker/...+inode_switch_wbs and kworker/...+events_unbound) sit near 100% of a CPU, the kernel’s per-cgroup writeback cleanup has livelocked: a dying control group’s cached inodes are not draining, so the workers spin. Run qb fix writeback to confirm, then qb fix writeback --apply to clear it. The same check and apply are available on the dashboard under System Dashboard > Hardware Health > Writeback cleanup card.

What it does (check mode, the default):

Check mode needs no root. It samples the two kernel worker classes for 3 seconds and reports one of three verdicts:

  • clear - no pegged writeback workers; nothing to do.
  • livelock - the workers are pegged and the dying-cgroup drain is stalled.
  • unsupported - the host is on cgroup v1, where this detection does not apply.

Alongside the verdict it prints the pegged worker PIDs and their CPU percent, the dying-descendant cgroup count, the open-inode count, the ext4_inode_cache size, and cached memory, plus a one-line hint on what to do next.

What --apply does (requires root):

--apply runs sync, then requests reclaim of freeable dentries and inodes (the kernel’s slab-only drop_caches reclaim) in the background so the writeback drain can finish. It never touches in-use files. It polls the release rate for up to 30 seconds without blocking, then reports drained (the backlog cleared) or still-busy (progressing but not finished in the window, with a drain rate and ETA). By default --apply acts only on a detected livelock; pass --force to apply without a livelock verdict.

OptionDescriptionExample
--apply

Run the reclaim (requires root): sync, then background slab reclaim of freeable dentries and inodes so the writeback drain can finish. Never touches in-use files.

qb fix writeback --apply
qb fix writeback --apply
--force

Apply even when no livelock is detected. Without it, --apply acts only on a confirmed livelock.

qb fix writeback --apply --force
qb fix writeback --apply --force
--json

Emit one structured JSON object for tooling. Requires an explicit --dry-run or --apply.

qb fix writeback --dry-run --json
qb fix writeback --dry-run --json
--dry-run

Force check-only mode explicitly. Pair with --json for a machine-readable verdict without applying anything.

qb fix writeback --dry-run
qb fix writeback --dry-run

Exit codes:

Exit codeMeaning
0clear (check) or drained (apply) - nothing pegged, or the backlog cleared
2livelock detected (check mode)
3still-busy - apply is draining but did not finish in the poll window
1error, or unsupported (host is on cgroup v1)

When to use:

Use qb fix writeback when

  • Load average climbs slowly over hours or days with no matching application activity
  • Two kernel workers (inode_switch_wbs and events_unbound) sit near 100% of a CPU
  • A daily service-restart cron or repeated updates precede the slow climb
  • You want a machine-readable verdict for monitoring (--json)

What it resolves

  • Confirms whether the writeback cleanup livelock is present, with the counters behind the verdict
  • --apply drains reclaimable inodes so the workers can finish, without touching in-use files
  • Reports a drain rate and ETA when the backlog is large
  • Tells you honestly when a box is deep in it and the release will take longer, and when a reboot is the only remaining option
Apply early; reboot only when it will not drain
Warning

This is an upstream Linux 6.12 kernel writeback regression; the bounded-drain fix is upstream but not yet in Debian. Run --apply early, when the workers first peg. On a box that has been livelocked a long time the release can crawl at only tens of inodes per second at first, and the command may print a long ETA - treat that ETA as a worst-case estimate, since the lock contention often breaks and the remaining inodes drain in minutes. Apply, then re-run qb fix writeback every 10 to 30 minutes; reboot at a quiet window only if the inode count is not falling at all. Never run echo 3 > /proc/sys/vm/drop_caches by hand or on a cron - the command’s slab-only reclaim is the safe path.

What it never does
Note

qb fix writeback never evicts in-use files or the page cache of running processes - the reclaim is limited to freeable slab objects (unreferenced dentries and inodes). Check mode changes nothing at all and needs no root.


Fix libcurl

Make sure rTorrent 0.16.x runs on libcurl 8.14.1 or newer, and restart the rTorrent instances that still run the old one:

bash
qb fix libcurl                   # repair, then restart rTorrent where something changed
qb fix libcurl --check           # report the libcurl rTorrent uses; change nothing
Symptom: rTorrent 0.16.x restarts every few minutes on a large library
Tip

On a large, tracker-heavy library, rTorrent 0.16.x restarts every few minutes and its log shows epoll_ctl(DEL) ... Bad file descriptor or event mismatch on a curl_socket. Older libcurl builds lose track of a socket after removing it, and libtorrent then aborts rTorrent. Run qb fix libcurl --check to see which libcurl rTorrent uses, then qb fix libcurl to repair it. See rTorrent troubleshooting.

What it does:

The command reads the libcurl that libtorrent actually uses, not a package name, so it works the same where the package is renamed or libcurl is built into libtorrent. At or above 8.14.1 it installs nothing. Below it, what happens depends on the release:

  • Debian 12 - adds a bookworm-backports apt source when none exists, then installs libcurl4 and curl from it, plus libcurl3-gnutls and libcurl4-openssl-dev when they are installed. Backports stay at apt’s default low priority, so nothing else moves. If backports offers no libcurl at 8.14.1 or newer, nothing is changed.
  • Ubuntu 22.04 and 24.04 - never touches the system libcurl. It reinstalls the rTorrent and libtorrent pair at the installed version through qb update rtorrent, and only when a rebuilt pair that carries its own libcurl is published for your release. With none published it changes nothing and tells you to use rTorrent 0.15.7.
  • Debian 13, and rTorrent 0.15.x or older - nothing to repair: Debian 13 already ships a new enough libcurl, and 0.15.x does not have the requirement. When rTorrent 0.16 is not installed the command says so and exits 0.

A running rTorrent keeps the libcurl it loaded, so after a repair the command restarts rtorrent@username for each account whose live process still holds the old one. A process that already runs a good libcurl is left alone, so running the command again changes nothing. Installing, updating or reinstalling rTorrent 0.16.x runs the same check before any rTorrent service starts.

If the repair cannot be done on your release, switch to the 0.15.7 pair, which has no such requirement:

bash
qb update rtorrent -u username -o '0.15.7'

That swaps the system-wide rTorrent package for every rTorrent user on the server.

OptionDescriptionExample
--check

Report only. Prints the libcurl rTorrent uses and whether it meets 8.14.1, and changes nothing. --dry-run is accepted as the same flag.

qb fix libcurl --check
qb fix libcurl --check

The command must run as root, including --check.

Exit codes:

Exit codeMeaning
0At the floor, repaired, or nothing to do
1--check found libcurl below 8.14.1, or the command was not run as root
3Below the floor and no fixed build is available for this release; nothing was attempted or changed
4The libcurl version could not be read; nothing was changed
5A repair was attempted and failed, or libcurl is still below the floor after it

When to use:

Use qb fix libcurl when

  • rTorrent 0.16.x restarts every few minutes on a large library
  • The rTorrent log shows Bad file descriptor or event mismatch on a curl_socket
  • You want to confirm which libcurl rTorrent runs on before upgrading to 0.16.x

What it resolves

  • --check reports the libcurl rTorrent uses and whether it meets the 8.14.1 floor
  • The repair raises libcurl through Debian backports or a rebuilt rTorrent pair, then restarts only the instances that need it
  • Where no repair is published, the command says so and points to rTorrent 0.15.7

Common Workflows

Use these as quick checklists. Details and caveats live in the sections above so we avoid repeating full instructions.

Application Won’t Start

Systematic troubleshooting approach:

bash
# 1. Check if it's a permission issue
qb fix home -u username
 
# 2. Restart the application
systemctl restart [application]@username
 
# 3. If PHP-based (ruTorrent, phpMyAdmin, Nextcloud), repair the PHP-FPM pools
qb fix php
 
# 4. If Python-based, fix Python
qb fix python
 
# 5. Check logs for errors
journalctl -u [application]@username -f

After System Upgrade

Post-upgrade maintenance routine:

bash
# 1. Fix Python (often breaks during upgrades)
qb fix python
 
# 2. Fix PHP
qb fix php
 
# 3. Fix user permissions
qb fix home -u username
 
# 4. Update QuickBox if needed
qb update quickbox

Dashboard Not Working

v4 Dashboard (current) troubleshooting:

bash
# 1. Check the dashboard service
systemctl status v4-dashboard
 
# 2. Restart the dashboard service
systemctl restart v4-dashboard
 
# 3. If still broken, re-run the dashboard update pipeline
qb fix dashboard
 
# 4. Check Nginx is running
systemctl status nginx
nginx -t
systemctl restart nginx
 
# 5. If still broken, force a full system refresh
qb fix version
v4 Dashboard uses Node.js, not PHP
Warning

The v4 dashboard service is v4-dashboard.service. Do not troubleshoot it with PHP-FPM commands. If PHP-based applications (like ruTorrent or Nextcloud) are broken, use qb fix php for those separately.


Multiple Users Having Issues

When all users experience problems:

bash
# 1. Move PHP applications to their supported PHP and repair their pools
qb fix php
 
# 2. Fix Python (system-wide)
qb fix python
 
# 3. Fix each user's permissions
for user in user1 user2 user3; do
  echo "Fixing $user..."
  qb fix home -u $user
done
 
# 4. If issues persist, fix QuickBox
qb fix version

Troubleshooting Guide

”Command Not Found” After Fix

bash
# Reload shell configuration
source ~/.bashrc
 
# Or logout and login again
exit

Fix Commands Don’t Resolve Issue

bash
# 1. Check system logs
journalctl -xe
 
# 2. Generate support logs
qb generate log
 
# 3. Ask for help in Discord
# Include the generated support logs

Permission Fix Doesn’t Work

bash
# 1. Check if user exists
id username
 
# 2. Verify home directory
ls -la /home/username
 
# 3. Manual permission fix
chown -R username:username /home/username
chmod 755 /home/username
 
# 4. Try automated fix again
qb fix home -u username

PHP Fix Fails

bash
# Check which PHP versions are installed
dpkg -l | grep php-fpm
 
# Check FPM status for each version
systemctl status php8.1-fpm
systemctl status php8.4-fpm
 
# Check installed extensions for a specific version
php8.1 -m
php8.4 -m
 
# Check if any PHP packages are held (empty on a default install)
apt-mark showhold | grep php
 
# Move each PHP application to its supported PHP and repair its pool
qb fix php
 
# Check whether each PHP application is at its security floor
qb fix php --security --check
 
# If a leftover hold is interfering with a planned upgrade
qb fix php 8.4 --remove-hold
An application did not move to the newer PHP
Info

qb fix php prints why: the installed release of the application does not support the newer PHP (update the application to move it), the FastCGI client that checks the move could not be installed, or a step of the move failed and the application was left on its current PHP, still working. Fix the cause the warning names and run qb fix php again.

Avoid manual PHP management
Caution

Do not run apt-get install --reinstall php8.1 or manually upgrade PHP packages. QuickBox manages per-application FPM pools. Manual apt operations can break the isolation between PHP versions. Use qb fix php to repair PHP issues and qb fix php --security to update PHP to its security fixes. Use --remove-hold to clear a leftover hold.


”The following packages have been kept back”

QuickBox does not hold PHP packages, so a current install upgrades PHP patch releases with a normal apt upgrade. If apt upgrade or apt-get upgrade reports PHP packages as kept back or held (typically php8.1-bcmath, php8.1-cli, php8.1-fpm, or php8.1-common), a hold was placed earlier by an older QuickBox install. A QuickBox update clears every PHP hold on its own.

What the output looks like:

plaintext
The following packages have been kept back:
  php8.1-bcmath php8.1-cli php8.1-common php8.1-fpm php8.1-opcache
0 upgraded, 0 newly installed, 0 to remove and 15 not upgraded.

To see what is held:

bash
apt-mark showhold | grep php

To clear the hold on one PHP version, then upgrade:

bash
# 1. Remove the hold so apt can upgrade
qb fix php 8.1 --remove-hold
 
# 2. Run the upgrade
apt-get upgrade
 
# 3. Confirm each PHP application is at its security floor
qb fix php --security --check

For PHP 8.4, run qb fix php 8.4 --remove-hold.

Prefer qb fix php over apt-mark
Warning

Use qb fix php [VERSION] --remove-hold instead of running apt-mark unhold php8.1* yourself, or let qb update quickbox clear the holds. The update also clears a hold on libfcgi0ldbl, which earlier releases placed together with the PHP packages.

Kept-back packages are not always PHP
Info

Some non-PHP packages are held on purpose by their applications (for example the libtorrent and Transmission packages). Run apt-mark showhold to see exactly which packages are held. You only need to act if a PHP-based application (ruTorrent, phpMyAdmin, Nextcloud) is broken; in that case run qb fix php to repair its pool.

Python Fix Doesn’t Help

bash
# Check Python versions
python3 --version
python3.11 --version
python3.13 --version
 
# Check pip for each version
python3.11 -m pip --version
python3.13 -m pip --version
 
# Try fix again
qb fix python

Best Practices

Do

  • Try specific fixes before qb fix version
  • Fix permissions after manual file operations
  • Run qb fix php and qb fix python after OS upgrades
  • Run qb fix php --security --check to see whether your PHP applications are at their security floor, and qb fix php --security to update them
  • Use qb fix php [VERSION] --remove-hold to clear a leftover PHP hold before a planned apt upgrade
  • Use qb fix dashboard for dashboard issues, not PHP fixes
  • Generate logs before asking for help
  • Test applications after running fixes

Don't

  • Run qb fix version without trying other fixes first
  • Manually install or upgrade PHP packages with apt
  • Run apt-mark unhold on PHP packages directly -- use qb fix php [VERSION] --remove-hold
  • Ignore error messages during fix operations
  • Run multiple fixes simultaneously
  • Troubleshoot the v4 dashboard with PHP-FPM commands
  • Forget to restart services after fixes

Prevention Tips

Avoid Permission Issues

bash
# Always use proper commands for file operations
# Instead of: cp /source /home/user/
# Use: sudo -u username cp /source /home/username/
 
# Or fix after copying
cp /source /home/username/
qb fix home -u username

Maintain Healthy System

bash
# Regular maintenance prevents issues
qb clean memory          # Weekly
qb update check          # Weekly
qb fix php               # After updates (moves PHP apps to their supported PHP and repairs their pools)
qb fix php --security --check   # Confirm PHP is at its security floor
qb fix python            # After updates

Before Major Changes

Preparation checklist:

  • Create system snapshot or backup
  • Document current working state
  • Test changes in isolation first
  • Have rollback plan ready
  • Note which applications are currently working
  • Backup critical configurations manually


Need Help?

Join the Community

Media server operators sharing configs, getting support, and shaping the future of QuickBox Pro.

  • Dedicated Support
  • Feature Previews
  • Community Configs
  • Active Discussions
Join Discord Server
Last updated on