
Ubuntu 26.04 LTS, codenamed Resolute Raccoon, was released on April 23, 2026. Standard support runs until May 2031. For a torrent client that is a comfortable runway. You can build a seedbox or a Linux ISO mirror helper on it and not think about the OS for years.
The install itself takes about thirty seconds. The trouble starts afterwards. A fresh qBittorrent setup usually works until the first reboot, then the service doesn’t come back. Or the WebUI works on localhost but not through the reverse proxy. Or the downloads folder fills a root partition and the box becomes unresponsive. Or the login password “doesn’t work”, because it changes on every restart.
None of these problems are the installer’s fault. They come from skipping the unglamorous parts: a dedicated user, proper permissions, a sane systemd unit, a firewall rule, and a few kernel limits. This guide covers the unglamorous parts too.
It walks through three installation paths on Ubuntu 26.04: the default Universe package, the official qBittorrent Team PPA, and Flatpak. It then covers the headless build (qbittorrent-nox) as a managed service, WebUI hardening, Nginx reverse proxying, performance tuning, and troubleshooting. The commands target Ubuntu 26.04, but most also apply to Debian and Ubuntu derivatives. A short section at the end covers RHEL-family systems.
One note on use. qBittorrent is a neutral tool. It is fine for Linux distributions, open datasets, game patches and your own content. Use it only for material you have the right to download and share.
Pick the Right Build First
qBittorrent ships in two flavours, and choosing the wrong one costs time.
- qbittorrent: the Qt desktop application. It needs a graphical session.
- qbittorrent-nox: the headless daemon with a built-in web interface, no X server and no Qt GUI libraries. Servers, VPS instances, NAS boxes and home-lab machines should use this one.
Both come from the same codebase and share the libtorrent engine, so features and behaviour match. The only difference is the front end. Some people install both on a workstation, but running two clients against the same download directory causes conflicts. Pick one per machine.
Which Source Should You Use?
| Method | Version on 26.04 | Best for | Trade-off |
|---|---|---|---|
| Ubuntu Universe (APT) | 5.1.x series (5.1.4 at the time of writing) | Most users, stable servers | Updates follow Ubuntu’s pace |
| qBittorrent Team PPA | Newest stable build | Anyone wanting current fixes | Third-party archive, must be trusted |
| Flatpak (Flathub) | Current upstream | Desktop users wanting sandboxing | Sandbox limits file access |
On older LTS releases the gap was painful. Ubuntu 24.04 and 22.04 still ship older 4.x packages unless you switch to the PPA or Flathub. On 26.04 the default package is already in the modern 5.x line, so the PPA is optional rather than a necessity. For production machines, the repository build is usually the safer choice. Security updates arrive through the same channel as the rest of the system, and nothing extra needs auditing.
Before Installing: Prepare the System
Skip this section and you will come back to it later.
Update and Check the Basics
sudo apt update
sudo apt upgrade -y
lsb_release -a
Confirm the release reads 26.04 and that Universe is enabled. A stock Ubuntu install has Universe on. Minimal cloud images sometimes do not.
sudo add-apt-repository universe
sudo apt update
Check Disk Layout and Free Space
Do this before choosing a download path. A torrent client writes constantly, and a full root filesystem takes down SSH, logging and package management with it.
df -hT
lsblk -f
If the server has a separate data disk, mount it and use it for downloads. If it does not, at least create a dedicated directory and set a quota or alert on it. A 2 TB torrent queue on a 40 GB root volume is a classic way to ruin a Friday.
On RAM, Ubuntu 26.04’s own minimum is modest. qBittorrent itself is light. Its memory use grows with the number of active torrents, the disk cache, and how many peers it tracks. A VPS with 1 to 2 GB is workable for a few dozen torrents. Hundreds of active torrents need more headroom.
Method 1: Install qBittorrent from the Ubuntu Repository
This is the simplest option and the one to start with.
Desktop (GUI)
sudo apt install qbittorrent
Launch it from the application menu or run qbittorrent in a terminal. On first launch it shows a legal notice you must accept.
Verify the installed version:
qbittorrent --version
apt policy qbittorrent
apt policy is worth the habit. It shows which repository supplied the package and whether a newer candidate exists.
Headless (qbittorrent-nox)
sudo apt install qbittorrent-nox
Everything from the next section onward applies to this build. Installing the package starts nothing automatically. You still have to create a user and enable a service.
Method 2: Use the Official qBittorrent Team PPA
The qBittorrent Team publishes stable packages in a Launchpad archive. Their download page confirms that qBittorrent is in the official Ubuntu repositories and that more up-to-date packages are published on their stable and unstable PPAs. The stable PPA has builds for Ubuntu 26.04, and its listing showed a package uploaded on 2026-07-07.
sudo add-apt-repository ppa:qbittorrent-team/qbittorrent-stable
sudo apt update
sudo apt install qbittorrent # or qbittorrent-nox
Launchpad itself labels this as an untrusted PPA. That is boilerplate for every PPA, but the point stands. You are letting a third-party archive supply software that runs as a network-facing daemon. For a personal workstation that is generally reasonable. For a regulated production box, think about it, or stay on the Ubuntu package.
Pinning and Rollback
If a PPA update ever misbehaves, ppa-purge can revert to the stock version:
sudo apt install ppa-purge
sudo ppa-purge ppa:qbittorrent-team/qbittorrent-stable
Check what is installed and from where:
apt policy qbittorrent-nox
An experienced admin snapshots the VM or at least backs up the qBittorrent profile directory before a major version jump. The 4.x to 5.x transition changed the on-disk format, and a downgrade was not always clean.
Method 3: Flatpak from Flathub
On desktops where you want sandboxing or the very latest upstream, Flatpak works.
sudo apt install flatpak
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak install flathub org.qbittorrent.qBittorrent
flatpak run org.qbittorrent.qBittorrent
The sandbox is the catch. By default the app only sees certain directories. If you want downloads on /mnt/data, grant access:
flatpak override --user --filesystem=/mnt/data org.qbittorrent.qBittorrent
Flatpak is a poor fit for the headless server case. Use APT for that.
Running qBittorrent-nox as a Proper Service
This is the part that matters for servers. The old shortcut was to run qbittorrent-nox -d from a shell or as root. Don’t. A network daemon that parses data from strangers should never run as root.
Step 1: Create a Dedicated System User
sudo useradd --system --create-home \
--home-dir /var/lib/qbittorrent \
--shell /usr/sbin/nologin \
qbtuser
The user gets a home directory for its profile and no login shell. Nobody can SSH in as it, and a compromise of the daemon doesn’t hand over an interactive account.
Step 2: Create the Download Directories
sudo mkdir -p /srv/torrents/{complete,incomplete,watch}
sudo chown -R qbtuser:qbtuser /srv/torrents
sudo chmod -R 750 /srv/torrents
Separating incomplete from complete has a practical benefit. Partial files stay out of your media library scanner, and you can place incomplete downloads on faster storage if you have it. If other users (a Plex or Jellyfin account, say) need to read the finished files, add them to the qbtuser group instead of loosening permissions to 777. Using chmod 777 on a downloads folder is the quick fix everyone regrets.
Step 3: Check Whether the Package Ships a Unit File
The Ubuntu 26.04 package includes the templated unit qbittorrent-nox@.service. Confirm it:
systemctl cat qbittorrent-nox@qbtuser
If it prints a unit, you are set. The template takes the username after the @. The upstream wiki describes the same pattern, with systemctl start qbittorrent-nox@qbtuser and systemctl enable for boot.
If it says the unit cannot be found, create it yourself:
sudo tee /etc/systemd/system/qbittorrent-nox@.service > /dev/null <<'EOF'
[Unit]
Description=qBittorrent-nox service for user %I
Documentation=man:qbittorrent-nox(1)
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target
[Service]
Type=simple
User=%i
ExecStart=/usr/bin/qbittorrent-nox
Restart=on-failure
TimeoutStopSec=1800
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
That unit is modelled on the upstream template, with Restart=on-failure added. TimeoutStopSec=1800 looks odd but is deliberate. On shutdown qBittorrent flushes resume data and announces to trackers. Killing it after the default 90 seconds on a busy instance can leave torrents needing a recheck.
Step 4: Accept the Legal Notice and Start
The first run needs the legal notice accepted. Do that once, interactively, as the service user:
sudo -u qbtuser qbittorrent-nox --confirm-legal-notice
Stop it with Ctrl+C after it prints the WebUI address. Then enable the service:
sudo systemctl enable --now qbittorrent-nox@qbtuser
sudo systemctl status qbittorrent-nox@qbtuser
The --now flag enables it for boot and starts it in the same step.
Step 5: Log In and Fix the Password Problem
By default the WebUI listens on port 8080 with the username admin. Recent versions do not use the old default password adminadmin. They generate a random temporary password at each start until you set your own. Find it in the journal:
sudo journalctl -u qbittorrent-nox@qbtuser -n 50 --no-pager
Look for a line that says a temporary password was set for the WebUI. Open http://SERVER-IP:8080, log in as admin, then go to Tools, Options, WebUI and set a permanent username and password. Until you do, the password changes each restart, which is the cause of many “I can’t log in anymore” reports.
Use a long passphrase. A password manager is the right tool here.
Configure qBittorrent Sensibly
The defaults are fine for a test and wrong for a server. Set these in the WebUI under Tools, Options.
Downloads
- Default save path:
/srv/torrents/complete - Keep incomplete torrents in:
/srv/torrents/incomplete - Automatically add torrents from:
/srv/torrents/watch(handy for drop-in automation) - Enable pre-allocation only on filesystems where fragmentation matters. On ext4 and XFS it is usually unnecessary, and on btrfs or ZFS it defeats copy-on-write.
Connection
- Pick a fixed listening port, for example 51413, instead of a random one. A random port per launch makes firewall rules and router forwarding impossible to maintain.
- Disable UPnP/NAT-PMP on a server. Forward the port deliberately.
- Set global connection limits to something realistic. The defaults are high, and consumer routers can choke on thousands of simultaneous connections.
Speed and Queueing
- Cap active downloads at around 3 to 5 and active torrents around 10 to 20 on small VPS instances.
- Use alternative speed limits with a schedule if the server shares a link with production services. A torrent client that saturates the uplink at 9 AM hurts everything else on the line.
Seeding Limits
Set a ratio or time limit, and an action: pause or remove. Without it, a long-lived instance accumulates thousands of idle torrents and its memory footprint creeps up.
Open the Firewall Correctly
Ubuntu ships with UFW, which is a front end to nftables. The goal is to open the peer port to the internet and keep the WebUI private.
sudo ufw allow OpenSSH
sudo ufw allow 51413/tcp
sudo ufw allow 51413/udp
sudo ufw allow from 192.168.1.0/24 to any port 8080 proto tcp
sudo ufw enable
sudo ufw status verbose
Adjust the subnet to your LAN. The WebUI rule only admits local addresses. If you manage the server remotely, do not open 8080 to the world. Reach it through an SSH tunnel, a VPN such as WireGuard, or a reverse proxy with TLS.
An SSH tunnel is the quickest private option:
ssh -L 8080:127.0.0.1:8080 user@your-server
Then browse to http://127.0.0.1:8080 on your own machine.
Put Nginx and TLS in Front of the WebUI
When the WebUI must be reachable over the internet, never expose it on plain HTTP. Passwords would cross the network in clear text. A reverse proxy with a Let’s Encrypt certificate fixes that.
First bind qBittorrent to localhost only. In the WebUI options, set the IP address to 127.0.0.1, or edit the config with the service stopped:
sudo systemctl stop qbittorrent-nox@qbtuser
sudo nano /var/lib/qbittorrent/.config/qBittorrent/qBittorrent.conf
Look in the [Preferences] section for the WebUI address key and set it to 127.0.0.1. The exact key name can vary slightly between releases, so open the file and match what is there rather than pasting blindly. Then start the service again.
Install Nginx and Certbot:
sudo apt install nginx certbot python3-certbot-nginx
Create /etc/nginx/sites-available/qbit.example.com:
server {
listen 80;
server_name qbit.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host 127.0.0.1:8080;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_hide_header Referer;
proxy_hide_header Origin;
proxy_set_header Referer '';
proxy_set_header Origin '';
}
}
The Host, Referer and Origin handling is not decoration. qBittorrent’s CSRF and host header validation rejects requests that look cross-origin, and the symptom is a login page that loads but returns “Unauthorized” on every action. If you prefer to keep the original Host header, add your domain to the WebUI’s “Server domains” option instead and drop the rewriting.
Enable and test:
sudo ln -s /etc/nginx/sites-available/qbit.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d qbit.example.com
Certbot rewrites the server block for HTTPS and sets up renewal. Check the timer with systemctl list-timers | grep certbot. In the WebUI options, tick “Enable Secure Cookie Flag” once you are on HTTPS. Add HSTS only after confirming HTTPS works for every client.
If the site is public, consider extra layers: HTTP basic auth at Nginx, an IP allow list, or putting the entire thing behind WireGuard. A torrent WebUI exposed to the internet will be scanned within hours.
Harden the Service with systemd
Because qBittorrent runs as a systemd unit, you can sandbox it without touching the application. Use a drop-in override, which survives package upgrades:
sudo systemctl edit qbittorrent-nox@qbtuser
Add:
[Service]
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictSUIDSGID=true
ReadWritePaths=/var/lib/qbittorrent /srv/torrents
LimitNOFILE=65536
Save, then apply:
sudo systemctl daemon-reload
sudo systemctl restart qbittorrent-nox@qbtuser
sudo systemd-analyze security qbittorrent-nox@qbtuser
systemd-analyze security gives an exposure score, which is a quick way to compare before and after. If the service fails to start after hardening, nine times out of ten a path is missing from ReadWritePaths. Add every location qBittorrent has to write, including any extra download mount or an external “move completed to” folder.
LimitNOFILE deserves a word. Every connection and every open file in a torrent consumes a descriptor. Hundreds of torrents with many peers can exhaust the default limit, and the log fills with “too many open files” errors.
Performance Tuning
Disk I/O
Disk is the usual bottleneck, not the network. Random reads and writes of small pieces punish spinning disks.
- Put the incomplete folder on SSD or NVMe if possible, and move finished files to bulk storage.
- Mount download volumes with
noatimeto avoid a write on every read. - Use XFS or ext4 for large file workloads. On btrfs, mark the download directory
nodatacow(chattr +C) before files are created, or fragmentation gets ugly. - Use
iostat -x 2(from thesysstatpackage) andiotopto see whether the device is saturated.
In qBittorrent’s Advanced options, the disk cache and asynchronous I/O thread count matter. Raising the thread count on fast SSDs helps. On a single HDD it can make things worse by creating more seek contention. Test one change at a time.
Network Buffers
For fast links with many peers, larger socket buffers help. Create a sysctl file:
sudo tee /etc/sysctl.d/99-torrent.conf > /dev/null <<'EOF'
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.somaxconn = 4096
net.ipv4.tcp_fastopen = 3
fs.inotify.max_user_watches = 524288
EOF
sudo sysctl --system
The values are moderate, not extreme. Blindly copying a “10 Gbps tuning” template onto a 1 vCPU VPS wastes memory. Also check which congestion control your kernel uses: sysctl net.ipv4.tcp_congestion_control. BBR can help on lossy links, though it is not a miracle.
CPU and RAM
CPU use mostly comes from hashing and encryption. Rechecking a large torrent saturates a core for a while. On a shared host, lower the priority:
[Service]
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=7
Put it in the same drop-in. Your web server and database then win when the box is busy. For hard limits, use MemoryMax= and CPUQuota=. A runaway client can then not starve a production workload, which matters on a box that also serves a WordPress site. Take it from someone who has watched exactly that happen: a torrent recheck should never be why a site’s TTFB doubles, since search crawlers notice slow responses.
Monitor with htop, vmstat 2, ss -s, and journalctl -u qbittorrent-nox@qbtuser -f.
Using a VPN or Interface Binding
If you need all torrent traffic to leave through a VPN, bind qBittorrent to the VPN interface under Advanced, Network interface (for example wg0). If the VPN drops, the client stops sending traffic rather than leaking over the regular interface. Test it. Do not assume.
Automating with the qBittorrent API
The WebUI doubles as a REST API. That makes it easy to feed torrents from scripts or monitoring.
curl -s -c /tmp/qb.cookie --data "username=admin&password=YOURPASS" \
http://127.0.0.1:8080/api/v2/auth/login
curl -s -b /tmp/qb.cookie http://127.0.0.1:8080/api/v2/torrents/info | head -c 500
You can also run an external program on completion, which helps with media post-processing. Keep such scripts owned by root and not writable by qbtuser. Otherwise a compromised client can rewrite a script that it then executes.
Backups and Migration
The state that matters lives in two places:
/var/lib/qbittorrent/.config/qBittorrent/for settings/var/lib/qbittorrent/.local/share/qBittorrent/for torrents and resume data
Stop the service before copying for a consistent backup:
sudo systemctl stop qbittorrent-nox@qbtuser
sudo tar czf /root/qbt-profile-$(date +%F).tar.gz /var/lib/qbittorrent/.config /var/lib/qbittorrent/.local
sudo systemctl start qbittorrent-nox@qbtuser
Moving to a new server is then a matter of restoring the archive, fixing ownership with chown -R qbtuser:qbtuser /var/lib/qbittorrent, and pointing paths at the new mounts.
Troubleshooting Common Problems
The Service Won’t Start
Check the journal first. Guessing wastes time.
sudo journalctl -xeu qbittorrent-nox@qbtuser
systemctl status qbittorrent-nox@qbtuser
Frequent causes: the legal notice was never accepted, the user does not exist, the home directory has the wrong owner, or a hardening directive blocks a path. A user mismatch between the instance name and the real account is easy to make. The text after @ must match an actual user.
Port 8080 Is Already in Use
sudo ss -tulpn | grep 8080
Jenkins, Tomcat and various dashboards love 8080. Change the WebUI port in the options, or start with --webui-port=8081. Some older tutorials use the -d daemon flag with Type=forking. Modern templated units use Type=simple instead, so do not mix the two styles.
Cannot Log In or Password Keeps Changing
If you never saved a permanent password, a new temporary one is generated each start. Read it from the journal and set a real one. If you did set one and still fail, repeated bad attempts trigger a temporary IP ban, so wait or restart from a different address.
“Unauthorized” Behind a Reverse Proxy
This is almost always host header or CSRF validation. Either rewrite Host, Origin and Referer as in the Nginx example above, or register your domain in the Server domains option. Also confirm the proxy forwards to the correct port.
Permission Denied When Saving Files
The download path must be writable by the service user:
sudo -u qbtuser touch /srv/torrents/complete/testfile && echo ok
namei -l /srv/torrents/complete
namei -l shows the permissions of every directory in the path. A single parent directory missing the execute bit will break everything below it. If systemd hardening is on, also confirm the path is in ReadWritePaths.
Torrents Stuck on “Stalled” or No Incoming Connections
Test whether the port is reachable from outside. Check that UFW allows the port, that the cloud provider’s security group allows it, and that the router forwards it. The status icon at the bottom of the WebUI shows a connection state. A red or yellow indicator typically means a firewalled port. Try a trusted public port checker, and remember it only works while the client is running.
High Memory Use
Reduce the disk cache, lower the number of active torrents, and check whether you are on a libtorrent build using memory-mapped I/O. Memory-mapped files make the kernel page cache look like qBittorrent’s RSS, which alarms people. Check actual pressure with free -h and vmstat before panicking.
Stuck at “Checking” After a Reboot
Usually the service was killed before it could save resume data, which is why the long TimeoutStopSec is worth keeping. Another cause is a download mount that was not ready at boot. Add RequiresMountsFor=/srv/torrents to the unit’s drop-in so the service waits for the mount.