{"id":967,"date":"2026-10-31T03:00:00","date_gmt":"2026-10-31T03:00:00","guid":{"rendered":"https:\/\/vpslake.com\/blog\/?p=967"},"modified":"2026-10-31T03:00:00","modified_gmt":"2026-10-31T03:00:00","slug":"enable-bbr-debian-11","status":"publish","type":"post","link":"https:\/\/vpslake.com\/blog\/2026\/10\/31\/enable-bbr-debian-11\/","title":{"rendered":"How to Enable BBR on Debian 11 (Step-by-Step)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Enable BBR on Debian 11 to use a modern TCP congestion-control algorithm together with the <code>fq<\/code> packet scheduler. The change takes about five minutes, applies without opening a firewall port, and can be retained after a reboot.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>A Debian 11 (Bullseye) VPS with a kernel newer than 4.9; the standard Debian 11 kernel is from the 5.10 series.<\/li>\n\n\n<li>SSH access as <code>root<\/code>, or a normal user with working <code>sudo<\/code> privileges.<\/li>\n\n\n<li>Permission to load kernel modules and write files under <code>\/etc<\/code>; a restricted container may not provide either capability.<\/li>\n\n\n<li>No domain, web server, extra RAM, or extra disk is required because BBR is a kernel-level TCP setting.<\/li>\n\n\n<li>If you need the server first, choose a <a href=\"https:\/\/vpslake.com\/buy-vps\">Linux VPS from VPSLake<\/a> and install Debian 11.<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">BBR changes TCP pacing and capacity estimation; it cannot increase the bandwidth limit of your VPS. Results depend on the route, remote peer, and application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Confirm Debian 11 and inspect TCP<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check the release and running kernel before changing sysctl values so you do not tune a different image or provider-supplied kernel by mistake.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \/etc\/os-release\nuname -r\nsysctl net.ipv4.tcp_available_congestion_control\nsysctl net.ipv4.tcp_congestion_control<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The release output should identify Debian GNU\/Linux 11, and a standard Bullseye installation normally reports a <code>5.10<\/code> kernel. The active algorithm is commonly <code>cubic<\/code>; BBR may already be listed as available.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PRETTY_NAME=\"Debian GNU\/Linux 11 (bullseye)\"\n5.10.0-...-amd64\nnet.ipv4.tcp_available_congestion_control = reno cubic\nnet.ipv4.tcp_congestion_control = cubic<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Kernel patch numbers and the available algorithm list vary. Do not replace a working provider kernel just to match the sample output.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Load BBR for the current boot<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On Debian, BBR can be supplied as the <code>tcp_bbr<\/code> kernel module. Load it before selecting the algorithm so the kernel knows the name when the sysctl is applied.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo modprobe tcp_bbr\nsysctl net.ipv4.tcp_available_congestion_control<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The second command should now include <code>bbr<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>net.ipv4.tcp_available_congestion_control = reno cubic bbr<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If <code>bbr<\/code> was already present, <code>modprobe<\/code> simply confirms that the module can be used. The exact order of the algorithms is not important.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Make BBR persistent<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Keep the module request and kernel parameters in separate files so the change is easy to audit or remove without touching unrelated Debian settings.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tee \/etc\/modules-load.d\/tcp-bbr.conf &gt;\/dev\/null &lt;&lt;'EOF'\ntcp_bbr\nEOF\nsudo tee \/etc\/sysctl.d\/99-bbr.conf &gt;\/dev\/null &lt;&lt;'EOF'\nnet.core.default_qdisc = fq\nnet.ipv4.tcp_congestion_control = bbr\nEOF\nsudo sysctl -p \/etc\/sysctl.d\/99-bbr.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The first file asks the boot-time module loader to prepare BBR. The second selects BBR for new TCP connections and sets fair queueing as the default scheduler; the last command applies both values immediately.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Successful output looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>net.core.default_qdisc = fq\nnet.ipv4.tcp_congestion_control = bbr<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Debian&#8217;s sysctl files are read from <code>\/etc\/sysctl.d\/<\/code>; the <a href=\"https:\/\/www.debian.org\/doc\/manuals\/debian-reference\/ch05.en.html\" target=\"_blank\" rel=\"noopener\">Debian Reference documentation<\/a> explains this configuration layout.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Check the queue on the active interface<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Changing <code>net.core.default_qdisc<\/code> sets the default for interfaces created later, while an interface that is already up may still have its previous queueing discipline.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MAIN_IFACE=$(ip route show default | awk '\/^default\/ {print $5; exit}')\nprintf '%s\\n' \"$MAIN_IFACE\"\ntc qdisc show dev \"$MAIN_IFACE\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The first line should print the device used by the default route, such as <code>ens3<\/code> or <code>eth0<\/code>. If the qdisc is not <code>fq<\/code>, apply it for the current boot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tc qdisc replace dev \"$MAIN_IFACE\" root fq\ntc qdisc show dev \"$MAIN_IFACE\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Look for <code>qdisc fq<\/code> in the result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ens3\nqdisc fq 0: root refcnt 2 limit 10000p buckets 1024<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The interface name and queue details differ between VPS images. The <code>tc<\/code> change is runtime state and may be lost if the interface is recreated; the <code>net.core.default_qdisc<\/code> setting will apply again during the next boot. If <code>tc<\/code> is missing, install Debian&#8217;s <code>iproute2<\/code> package with <code>sudo apt-get update &amp;&amp; sudo apt-get install -y iproute2<\/code> and repeat the check.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verify BBR on Debian 11<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run one final check to confirm the active algorithm, saved values, available BBR support, and qdisc on the main network interface.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MAIN_IFACE=$(ip route show default | awk '\/^default\/ {print $5; exit}')\nsysctl net.ipv4.tcp_congestion_control net.core.default_qdisc\nsysctl net.ipv4.tcp_available_congestion_control\ngrep -Ev '^[[:space:]]*(#|$)' \/etc\/sysctl.d\/99-bbr.conf\ntc qdisc show dev \"$MAIN_IFACE\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You want <code>tcp_congestion_control = bbr<\/code>, <code>default_qdisc = fq<\/code>, <code>bbr<\/code> in the available list, both lines from <code>99-bbr.conf<\/code>, and <code>qdisc fq<\/code> for the active interface. These settings affect new TCP connections, so reconnect SSH clients or restart long-lived services before comparing network behavior. The <a href=\"https:\/\/docs.kernel.org\/networking\/ip-sysctl.html\" target=\"_blank\" rel=\"noopener\">Linux kernel IP sysctl reference<\/a> describes the TCP controls involved.<\/p>\n\n\n\n<aside class=\"vl-element vl-cta-banner\" aria-label=\"Tune Debian networking\">\n\t<div class=\"vl-cta-banner__content\">\n\t\t<p class=\"vl-cta-banner__eyebrow\">Linux VPS<\/p>\n\t\t<h3 class=\"vl-cta-banner__title\">Tune Debian networking<\/h3>\n\t\t<p class=\"vl-cta-banner__text\">Run Debian 11 workloads on a VPS ready for persistent TCP network tuning.<\/p>\n\t<\/div>\n\t<a class=\"vl-cta-banner__button\" href=\"\/buy-vps\" aria-label=\"View Linux VPS plans\">View Linux VPS plans<\/a>\n<\/aside>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><code>modprobe: FATAL: Module tcp_bbr not found<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The running kernel may lack the BBR module, or its module package may not match the kernel. First check <code>sysctl net.ipv4.tcp_available_congestion_control<\/code>; if <code>bbr<\/code> is absent, install Debian&#8217;s standard kernel meta-package and reboot into it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get update\nsudo apt-get install -y linux-image-amd64\nsudo reboot<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After reconnecting, run Step 2 again. If the VPS boots a provider-managed custom kernel, the standard package may not be the kernel in use; ask the provider for a Debian 11 kernel with BBR support.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>sysctl: cannot set net.ipv4.tcp_congestion_control<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The sysctl file was loaded before BBR became available. Run <code>sudo modprobe tcp_bbr<\/code>, confirm that <code>bbr<\/code> appears in the available list, and reload the saved file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo sysctl -p \/etc\/sysctl.d\/99-bbr.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the error returns after reboot, check that <code>\/etc\/modules-load.d\/tcp-bbr.conf<\/code> contains exactly <code>tcp_bbr<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>tc qdisc show<\/code> still reports <code>fq_codel<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The default scheduler value does not necessarily replace the qdisc already attached to an existing interface. Run the <code>tc qdisc replace<\/code> command from Step 4 with the actual default-route interface, then check the result again.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">BBR is active until the next reboot<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Inspect both persistent files and confirm that the rebooted system is using the same kernel family shown by <code>uname -r<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \/etc\/modules-load.d\/tcp-bbr.conf\ncat \/etc\/sysctl.d\/99-bbr.conf\nsudo systemctl restart systemd-modules-load\nsudo sysctl -p \/etc\/sysctl.d\/99-bbr.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If BBR still disappears, the VPS kernel or boot policy may prevent module loading. Use the VPS control panel console while checking the boot messages, or request a supported Debian kernel from the provider.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">FAQ<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Does BBR require a firewall rule?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. BBR changes TCP behavior inside the kernel and does not create a listening service or open an inbound port. Keep your existing SSH and application firewall rules unchanged.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Will BBR make every download faster?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Not necessarily. It can improve how a sender uses some congested paths, but the remote server, route, transfer size, and VPS bandwidth limit still matter. Compare the service you care about over multiple runs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Does enabling BBR change existing connections?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The algorithm is selected when TCP connections are created. Reconnect SSH and restart persistent services before evaluating the change; already-open sessions may retain their original state.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How do I return to CUBIC?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Change <code>net.ipv4.tcp_congestion_control = bbr<\/code> to <code>cubic<\/code> in <code>\/etc\/sysctl.d\/99-bbr.conf<\/code>, then run <code>sudo sysctl -p \/etc\/sysctl.d\/99-bbr.conf<\/code>. You can leave the module-load file in place because loading <code>tcp_bbr<\/code> does not select it as the active algorithm.<\/p>\n\n\n\n<script type=\"application\/ld+json\">{\"@context\": \"https:\/\/schema.org\", \"@type\": \"FAQPage\", \"mainEntity\": [{\"@type\": \"Question\", \"name\": \"Does BBR require a firewall rule?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"No. BBR changes TCP behavior inside the kernel and does not create a listening service or open an inbound port. Keep your existing SSH and application firewall rules unchanged.\"}}, {\"@type\": \"Question\", \"name\": \"Will BBR make every download faster?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Not necessarily. It can improve how a sender uses some congested paths, but the remote server, route, transfer size, and VPS bandwidth limit still matter. Compare the service you care about over multiple runs.\"}}, {\"@type\": \"Question\", \"name\": \"Does enabling BBR change existing connections?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"The algorithm is selected when TCP connections are created. Reconnect SSH and restart persistent services before evaluating the change; already-open sessions may retain their original state.\"}}, {\"@type\": \"Question\", \"name\": \"How do I return to CUBIC?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Change `net.ipv4.tcp_congestion_control = bbr` to `cubic` in `\/etc\/sysctl.d\/99-bbr.conf`, then run `sudo sysctl -p \/etc\/sysctl.d\/99-bbr.conf`. You can leave the module-load file in place because loading `tcp_bbr` does not select it as the active algorithm.\"}}]}<\/script>\n\n","protected":false},"excerpt":{"rendered":"Learn how to enable bbr on debian 11, save settings across reboots, verify the live queue, and fix common Debian VPS kernel errors safely, too.","protected":false},"author":1,"featured_media":968,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_singular_sidebar":"","csco_page_header_type":"","csco_page_load_nextpost":"","footnotes":""},"categories":[5,9],"tags":[113,96,114,115],"class_list":["post-967","post","type-post","status-publish","format-standard","has-post-thumbnail","category-guides","category-vps-hosting","tag-bbr","tag-debian-11","tag-linux-networking","tag-vps-tuning","cs-entry"],"_links":{"self":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/967","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/comments?post=967"}],"version-history":[{"count":1,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/967\/revisions"}],"predecessor-version":[{"id":3813,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/967\/revisions\/3813"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/media\/968"}],"wp:attachment":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/media?parent=967"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/categories?post=967"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/tags?post=967"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}