{"id":987,"date":"2026-11-02T13:00:00","date_gmt":"2026-11-02T13:00:00","guid":{"rendered":"https:\/\/vpslake.com\/blog\/?p=987"},"modified":"2026-11-02T13:00:00","modified_gmt":"2026-11-02T13:00:00","slug":"enable-bbr-rocky-linux-9","status":"publish","type":"post","link":"https:\/\/vpslake.com\/blog\/2026\/11\/02\/enable-bbr-rocky-linux-9\/","title":{"rendered":"How to Enable BBR on Rocky Linux 9 (Step-by-Step)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Enable BBR on Rocky Linux 9 to use a bandwidth-based TCP congestion-control algorithm with the <code>fq<\/code> packet scheduler. The change takes about five minutes on a normal VPS, survives reboots, and can be checked without opening a new network port.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Rocky Linux 9 with a current 5.14-series kernel or another kernel newer than 4.9.<\/li>\n\n\n<li>SSH access as <code>root<\/code>, or a user that can run commands with <code>sudo<\/code>.<\/li>\n\n\n<li>Permission to load kernel modules, change sysctl values, and manage the NetworkManager connection profile. Some unprivileged containers do not allow these operations.<\/li>\n\n\n<li>No domain, web server, extra disk, or special RAM allocation is needed because BBR is a kernel networking setting.<\/li>\n\n\n<li>If you need the server first, start with a <a href=\"https:\/\/vpslake.com\/buy-vps\">Linux VPS from VPSLake<\/a> and install Rocky Linux 9.<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">BBR changes how the server estimates the network path and paces TCP packets; it does not increase the bandwidth limit in your VPS plan. The remote peer, route quality, and application still determine the result.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Check Rocky Linux and the current TCP settings<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm the operating system and running kernel before installing a module so you do not apply a package for a different kernel.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \/etc\/rocky-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 must identify Rocky Linux 9. A stock installation normally reports a 5.14 kernel, while <code>cubic<\/code> is commonly the active algorithm. <code>bbr<\/code> may already appear in the available list if the provider has loaded it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Rocky Linux release 9.x (...)\n5.14.0-...el9...x86_64\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 suffixes and the order of the algorithms vary after updates. Do not replace a working provider kernel just to match this sample.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Install and load the BBR module<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The kernel must register <code>tcp_bbr<\/code> before a sysctl can select it, so install the matching extra modules package and load the module for the current boot.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dnf install -y \"kernel-modules-extra-$(uname -r)\"\nsudo modprobe tcp_bbr\nsysctl net.ipv4.tcp_available_congestion_control<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The final command should 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 listed, <code>modprobe<\/code> simply confirms that it is ready. BBR is included in Linux kernels that support it, and its pacing works best with the <code>fq<\/code> scheduler; the <a href=\"https:\/\/github.com\/google\/bbr\/blob\/master\/Documentation\/bbr-faq.md\" target=\"_blank\" rel=\"noopener\">BBR project FAQ<\/a> provides background on the algorithm.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Save BBR so it returns after reboot<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Put the module request and sysctl values in dedicated files so later kernel updates can load BBR before the setting is applied.<\/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-rocky-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-rocky-bbr.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The first file tells systemd to load the module at boot. The second selects BBR for new TCP connections and sets fair queueing as the default scheduler; the final command applies both values immediately.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Successful output is:<\/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\">Using <code>\/etc\/sysctl.d\/<\/code> instead of appending to the general <code>\/etc\/sysctl.conf<\/code> keeps this tuning easy to audit or remove. Rocky Linux follows the compatible RHEL 9 layout for persistent kernel parameters.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Apply <code>fq<\/code> to the active network interface<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The default qdisc value affects interfaces created later, but an already-running interface can still have <code>fq_codel<\/code>; inspect the interface carrying the default route.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MAIN_IFACE=$(ip -o route show default | awk '{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 command should print a device such as <code>ens3<\/code> or <code>eth0<\/code>. If the last command does not contain <code>qdisc fq<\/code>, replace the live root queue:<\/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\">You should now see a line similar to this, with different counters or limits on some VPS plans:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>qdisc fq 0: root refcnt 2 limit 10000p buckets 1024<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>tc<\/code> change lasts until the link is recreated or the server reboots. To make the per-interface setting persistent through NetworkManager, identify the active profile and update it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nmcli -g GENERAL.CONNECTION device show \"$MAIN_IFACE\"\nsudo nmcli connection modify \"YOUR_CONNECTION_NAME\" tc.qdiscs 'root fq'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Replace <code>YOUR_CONNECTION_NAME<\/code> with the profile printed by the first command. You can activate the profile immediately with <code>sudo nmcli connection up \"YOUR_CONNECTION_NAME\"<\/code>, but that may interrupt SSH. Use the VPS control panel console if a brief disconnect would be unsafe. Red Hat documents the temporary and persistent qdisc methods in its <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/9\/html\/configuring_and_managing_networking\/linux-traffic-control_configuring-and-managing-networking\" target=\"_blank\" rel=\"noopener\">RHEL 9 traffic-control guide<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verify BBR on Rocky Linux 9<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run this check after applying the settings. It confirms the active algorithm, the saved configuration, module availability, and the queue attached to the default-route interface.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MAIN_IFACE=$(ip -o route show default | awk '{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-rocky-bbr.conf\ngrep -Fx 'tcp_bbr' \/etc\/modules-load.d\/tcp-bbr.conf\ntc qdisc show dev \"$MAIN_IFACE\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Look for <code>tcp_congestion_control = bbr<\/code>, <code>default_qdisc = fq<\/code>, <code>bbr<\/code> in the available list, both lines from <code>99-rocky-bbr.conf<\/code>, the line <code>tcp_bbr<\/code>, and <code>qdisc fq<\/code> on the active interface. Congestion control is selected when a TCP connection is created, so reconnect SSH or restart the service you are evaluating before comparing traffic.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>net.ipv4.tcp_congestion_control = bbr\nnet.core.default_qdisc = fq\nnet.ipv4.tcp_available_congestion_control = reno cubic bbr\nnet.core.default_qdisc = fq\nnet.ipv4.tcp_congestion_control = bbr\ntcp_bbr\nqdisc fq 0: root refcnt 2 limit 10000p buckets 1024<\/code><\/pre>\n\n\n\n<aside class=\"vl-element vl-cta-banner\" aria-label=\"Tune Rocky Linux TCP\">\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 Rocky Linux TCP<\/h3>\n\t\t<p class=\"vl-cta-banner__text\">Run Rocky Linux 9 workloads on a VPS with persistent kernel networking settings.<\/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 does not have the matching BBR module installed, or the VPS boots a custom provider kernel. Install the current kernel and extra modules, reboot into that kernel, then repeat Step 2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dnf install -y kernel kernel-modules-extra\nsudo reboot<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After reconnecting, check <code>uname -r<\/code> and run <code>sudo modprobe tcp_bbr<\/code>. If BBR is still absent, ask the provider for a standard Rocky Linux 9 kernel with BBR support rather than copying a module from another kernel release.<\/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 applied before the module registered, or the running kernel does not expose BBR. Load the module, confirm it appears in the available list, and apply the dedicated file again:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo modprobe tcp_bbr\nsysctl net.ipv4.tcp_available_congestion_control\nsudo sysctl -p \/etc\/sysctl.d\/99-rocky-bbr.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the list never contains <code>bbr<\/code>, this is a kernel or module-package problem rather than a typo in the sysctl file.<\/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\"><code>net.core.default_qdisc = fq<\/code> does not necessarily replace the queue already attached to a live interface. Run the Step 4 <code>tc qdisc replace<\/code> command using the actual default-route device, then save <code>root fq<\/code> in its active NetworkManager profile if the setting must survive link reactivation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">BBR changes back to <code>cubic<\/code> after reboot<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check that the module-load file exists and that another sysctl file is not selected later in boot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -RnsE 'tcp_congestion_control|default_qdisc' \/etc\/sysctl.conf \/etc\/sysctl.d \/usr\/lib\/sysctl.d 2&gt;\/dev\/null\nsudo modprobe tcp_bbr\nsudo sysctl -p \/etc\/sysctl.d\/99-rocky-bbr.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Remove or update a later conflicting <code>cubic<\/code> assignment instead of creating another BBR file. Confirm <code>\/etc\/modules-load.d\/tcp-bbr.conf<\/code> contains exactly <code>tcp_bbr<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">FAQ<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Does BBR increase my VPS bandwidth limit?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. BBR changes TCP congestion control and packet pacing, but it cannot raise the port speed or transfer allowance assigned to the VPS. Test the application and remote destination that matter to you over several transfers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Does BBR affect UDP applications?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. The setting in this guide controls IPv4 TCP connections only. UDP programs use their own delivery and rate-control behavior.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Do I need to open a firewall port for BBR?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. BBR is a kernel feature and does not create a listener, service, or inbound connection. Leave Rocky Linux firewall rules unchanged.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How do I switch back 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-rocky-bbr.conf<\/code>, then run <code>sudo sysctl -p \/etc\/sysctl.d\/99-rocky-bbr.conf<\/code>. You can leave <code>tcp_bbr<\/code> in the module-load file; loading the module does not make it 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 increase my VPS bandwidth limit?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"No. BBR changes TCP congestion control and packet pacing, but it cannot raise the port speed or transfer allowance assigned to the VPS. Test the application and remote destination that matter to you over several transfers.\"}}, {\"@type\": \"Question\", \"name\": \"Does BBR affect UDP applications?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"No. The setting in this guide controls IPv4 TCP connections only. UDP programs use their own delivery and rate-control behavior.\"}}, {\"@type\": \"Question\", \"name\": \"Do I need to open a firewall port for BBR?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"No. BBR is a kernel feature and does not create a listener, service, or inbound connection. Leave Rocky Linux firewall rules unchanged.\"}}, {\"@type\": \"Question\", \"name\": \"How do I switch back to CUBIC?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Change `net.ipv4.tcp_congestion_control = bbr` to `cubic` in `\/etc\/sysctl.d\/99-rocky-bbr.conf`, then run `sudo sysctl -p \/etc\/sysctl.d\/99-rocky-bbr.conf`. You can leave `tcp_bbr` in the module-load file; loading the module does not make it the active algorithm.\"}}]}<\/script>\n\n","protected":false},"excerpt":{"rendered":"Learn how to enable bbr on rocky linux 9 quickly with persistent TCP settings, fq queueing, verification, and fixes for common VPS kernel errors.","protected":false},"author":1,"featured_media":988,"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,114,100,115],"class_list":["post-987","post","type-post","status-publish","format-standard","has-post-thumbnail","category-guides","category-vps-hosting","tag-bbr","tag-linux-networking","tag-rocky-linux-9","tag-vps-tuning","cs-entry"],"_links":{"self":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/987","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=987"}],"version-history":[{"count":1,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/987\/revisions"}],"predecessor-version":[{"id":3852,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/987\/revisions\/3852"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/media\/988"}],"wp:attachment":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/media?parent=987"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/categories?post=987"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/tags?post=987"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}