Configuring SSL/TLS for qBittorrent Connections: Web UI HTTPS and Torrent Encryption Guide

qBittorrent supports SSL/TLS in two distinct modes: HTTPS encryption for the Web UI via Http::Server::setupHTTPS(), and per-torrent TLS parameters through the BitTorrent::SSLParameters struct, with both utilizing Utils::SSLKey::load() for automatic EC/RSA key detection.

Enabling SSL/TLS for qBittorrent connections protects both your management interface and peer-to-peer traffic. The qbittorrent/qBittorrent repository implements these features through Qt's QSslSocket infrastructure and libtorrent's encrypted peer support. This guide explains the implementation details, configuration paths, and API methods for securing your qBittorrent deployment.

HTTPS for the Web UI

The Web UI encryption begins in src/base/http/server.cpp with the Http::Server::setupHttps() method. When you enable HTTPS in Options → Web UI or via command-line flags, the application loads your PEM-encoded certificate and private key through Utils::Net::loadSSLCertificate() and Utils::SSLKey::load().

// src/base/http/server.cpp
bool Server::setupHttps(const QByteArray &certificates,
                       const QByteArray &privateKey)
{
    const QList<QSslCertificate> certs = Utils::Net::loadSSLCertificate(certificates);
    const QSslKey key = Utils::SSLKey::load(privateKey);
    // Configuration applied to m_sslConfig
}

If loading succeeds, the server stores the resulting QSslConfiguration in m_sslConfig. All subsequent incoming connections are wrapped in QSslSocket instances created inside Server::incomingConnection(). The implementation further hardens security through Server::safeCipherList(), which filters out weak ciphers like IDEA or RSA-only key-exchange suites before the server advertises its cipher suite.

Result: All HTTP traffic to the Web UI—including API calls, JSON responses, and static assets—is encrypted with your provided certificate.

Per-Torrent SSL Parameters

Individual torrents can maintain dedicated TLS configurations for encrypted peer connections through the BitTorrent::SSLParameters structure defined in src/base/bittorrent/sslparameters.h.

// src/base/bittorrent/sslparameters.h
struct SSLParameters
{
    QSslCertificate certificate {};
    QSslKey          privateKey;
    QByteArray       dhParams;
    bool isValid() const;
};

API Injection Point

When adding a torrent via the Web API, the TorrentsController::addAction method extracts SSL parameters from the request and constructs the BitTorrent::SSLParameters object:

// src/webui/api/torrentscontroller.cpp
.sslParameters = {
    .certificate = QSslCertificate(params()[KEY_PROP_SSL_CERTIFICATE].toLatin1()),
    .privateKey  = Utils::SSLKey::load(params()[KEY_PROP_SSL_PRIVATEKEY].toLatin1()),
    .dhParams    = params()[KEY_PROP_SSL_DHPARAMS].toLatin1()
}

Storage and Persistence

The parameters propagate through SessionImpl::loadTorrentParams and reside in TorrentImpl::m_sslParams inside src/base/bittorrent/torrentimpl.cpp. During peer connection establishment, libtorrent reads these values to create TLS-encrypted sockets.

For persistence across restarts, DBResumeDataStorage serializes the certificate and key data into the SQLite resume database:

// src/base/bittorrent/dbresumedatastorage.cpp
query.bindValue(DB_COLUMN_SSL_CERTIFICATE.placeholder,
               QString::fromLatin1(m_resumeData.sslParameters.certificate.toPem()));
query.bindValue(DB_COLUMN_SSL_PRIVATE_KEY.placeholder,
               QString::fromLatin1(m_resumeData.sslParameters.privateKey.toPem()));
query.bindValue(DB_COLUMN_SSL_DH_PARAMS.placeholder,
               m_resumeData.sslParameters.dhParams);

Result: Torrent-specific SSL configurations survive application restarts and are automatically reapplied to peer connections.

Low-Level SSL Key Loading

Both Web UI HTTPS and torrent SSL parameters share the key detection logic in src/base/utils/sslkey.cpp. The Utils::SSLKey::load() helper automatically detects key type:

// src/base/utils/sslkey.cpp
QSslKey Utils::SSLKey::load(const QByteArray &data)
{
    if (const QSslKey key{data, QSsl::Ec}; !key.isNull())
        return key;
    return {data, QSsl::Rsa};
}

This utility abstracts format detection, allowing qBittorrent to handle both EC and RSA private keys without manual user specification.

Practical Configuration Examples

Enable Web UI HTTPS via GUI

  1. Open Options → Web UI
  2. Check Enable HTTPS
  3. Select PEM-encoded certificate and private key files
  4. Restart qBittorrent
  5. Access https://127.0.0.1:8080

Add Torrent with SSL via HTTP API

Send a POST request to /api/v2/torrents/add with URL-encoded SSL parameters:

POST /api/v2/torrents/add HTTP/1.1
Content-Type: application/x-www-form-urlencoded

urls=http://example.com/file.torrent&
ssl_certificate=%2F-----BEGIN%20CERTIFICATE-----%0A...%0A-----END%20CERTIFICATE-----%2F&
ssl_private_key=%2F-----BEGIN%20PRIVATE%20KEY-----%0A...%0A-----END%20PRIVATE%20KEY-----%2F&
ssl_dh_params=%2F-----BEGIN%20DH%20PARAMETERS-----%0A...%0A-----END%20DH%20PARAMETERS-----%2F

Programmatic Key Loading

If handling raw PEM data in custom extensions:

QByteArray pem = QFile::readAll("custom-key.pem");
QSslKey key = Utils::SSLKey::load(pem);
if (!key.isNull()) {
    // Key ready for QSslSocket or BitTorrent::SSLParameters
}

Summary

  • Web UI HTTPS is configured via Http::Server::setupHttps() in src/base/http/server.cpp, using QSslConfiguration with cipher suite filtering through safeCipherList().
  • Per-torrent SSL uses the BitTorrent::SSLParameters struct, injected via TorrentsController::addAction and stored in TorrentImpl::m_sslParams.
  • Persistence is handled by DBResumeDataStorage, which writes certificate PEM data to SQLite columns DB_COLUMN_SSL_CERTIFICATE, DB_COLUMN_SSL_PRIVATE_KEY, and DB_COLUMN_SSL_DH_PARAMS.
  • Key loading automatically handles EC and RSA formats through Utils::SSLKey::load() in src/base/utils/sslkey.cpp.

Frequently Asked Questions

Does qBittorrent support HTTPS for the Web UI?

Yes. Enable HTTPS in Options → Web UI and provide PEM-encoded certificate and private key files. The Http::Server class in src/base/http/server.cpp implements this via setupHttps(), which configures QSslSocket for all incoming connections and filters weak ciphers through safeCipherList().

How do I add a torrent with SSL parameters via the API?

Send a POST request to /api/v2/torrents/add including ssl_certificate, ssl_private_key, and ssl_dh_params parameters containing PEM-encoded data. The TorrentsController::addAction method processes these into a BitTorrent::SSLParameters object, which libtorrent uses for encrypted peer connections.

What SSL key formats does qBittorrent accept?

The Utils::SSLKey::load() function in src/base/utils/sslkey.cpp automatically detects and handles both EC (Elliptic Curve) and RSA private keys. It attempts EC parsing first, falling back to RSA if necessary, eliminating the need for manual format specification.

Are SSL parameters persisted across restarts?

Yes. Torrent-specific SSL configurations are serialized to the resume database by DBResumeDataStorage in src/base/bittorrent/dbresumedatastorage.cpp. The system stores certificate and key PEM data in dedicated SQLite columns, reloading them automatically when the application restarts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →