{"id":973,"date":"2026-10-31T18:00:00","date_gmt":"2026-10-31T18:00:00","guid":{"rendered":"https:\/\/vpslake.com\/blog\/?p=973"},"modified":"2026-10-31T18:00:00","modified_gmt":"2026-10-31T18:00:00","slug":"enable-bbr-rocky-linux-10","status":"publish","type":"post","link":"https:\/\/vpslake.com\/blog\/2026\/10\/31\/enable-bbr-rocky-linux-10\/","title":{"rendered":"How to Enable BBR on Rocky Linux 10 (Step-by-Step)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Enable BBR on Rocky Linux 10 to make new TCP connections use BBR with the <code>fq<\/code> queueing discipline. You can apply the kernel settings immediately and make them survive reboots in about five minutes, without opening another firewall 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>A Rocky Linux 10 VPS with the standard 6.12-series kernel or another kernel newer than 4.9.<\/li>\n\n\n<li>SSH access as <code>root<\/code>, or an administrator account with working <code>sudo<\/code> privileges. Rocky Linux 10 normally expects you to manage the server from a sudo-enabled account.<\/li>\n\n\n<li>Permission to load kernel modules, change sysctl values, and modify NetworkManager settings. An unprivileged container may deny one or more of these operations.<\/li>\n\n\n<li>No domain, web server, extra RAM, or extra disk space is needed 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 Rocky Linux 10.<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">BBR changes TCP congestion control and packet pacing; it does not increase the bandwidth limit of your VPS. The result depends on the route, the remote peer, and the application using TCP.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Confirm Rocky Linux 10 and inspect TCP<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check the release and running kernel before changing anything so a provider image or custom kernel does not surprise you.<\/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 line should identify Rocky Linux release 10, and a standard installation should show a <code>6.12<\/code> kernel. The current algorithm is often <code>cubic<\/code>; BBR may be absent from the available list until its module is loaded.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Rocky Linux release 10.x (Red Quartz)\n6.12.0-...el10_...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\">Patch numbers and the algorithm order 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\">The kernel must register BBR before a sysctl can select it, so load the module and check the available algorithms in the same session.<\/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 result should contain <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 the running kernel can use it. You do not need to unload or reload the network driver.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Save BBR and <code>fq<\/code> permanently<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use separate boot and sysctl files so a kernel update can restore the module and the TCP settings without changing unrelated configuration.<\/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 asks systemd to load <code>tcp_bbr<\/code> at boot. The second selects BBR for new TCP connections and sets fair queueing as the default scheduler; the final command applies both values now.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/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\">The <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/10\/html\/managing_monitoring_and_updating_the_kernel\/configuring-kernel-parameters-at-runtime\" target=\"_blank\" rel=\"noopener\">RHEL 10 kernel-parameter documentation<\/a> describes the compatible <code>\/etc\/sysctl.d\/<\/code> method. Rocky Linux 10 also uses the EL10 <code>modules-load.d<\/code> layout for persistent modules.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Put <code>fq<\/code> on the active interface<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Changing <code>net.core.default_qdisc<\/code> controls interfaces created later, but the interface already carrying SSH may still have Rocky Linux&#8217;s usual <code>fq_codel<\/code> queue. Inspect the default-route device before changing it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ip -o route show default\nMAIN_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\">If the last command does not show <code>qdisc fq<\/code>, replace the live root queue for this 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\">Successful output contains <code>qdisc fq<\/code>, although the counters and limits differ by system:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>default via 198.51.100.1 dev ens3 proto dhcp src 198.51.100.20 metric 100\nens3\nqdisc fq 0: root refcnt 2 limit 10000p buckets 1024<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Rocky Linux 10 uses NetworkManager; legacy <code>ifup<\/code> and <code>ifdown<\/code> commands are not available. To retain a deliberate per-interface qdisc when NetworkManager reactivates the link, identify the active profile and set it with <code>nmcli<\/code>:<\/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'\nsudo nmcli connection up \"YOUR_CONNECTION_NAME\"\ntc qdisc show dev \"$MAIN_IFACE\"<\/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. Activating the profile can briefly interrupt SSH, so use the VPS control panel console if you cannot risk losing the session. The <a href=\"https:\/\/docs.redhat.com\/en\/documentation\/red_hat_enterprise_linux\/10\/html\/configuring_and_managing_networking\/linux-traffic-control\" target=\"_blank\" rel=\"noopener\">RHEL 10 traffic-control documentation<\/a> documents the <code>tc<\/code> and NetworkManager approach.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verify BBR on Rocky Linux 10<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run the complete check below to confirm the live algorithm, saved files, module availability, and 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\">You want <code>tcp_congestion_control = bbr<\/code>, <code>default_qdisc = fq<\/code>, <code>bbr<\/code> in the available list, both assignments from <code>99-rocky-bbr.conf<\/code>, the line <code>tcp_bbr<\/code>, and <code>qdisc fq<\/code> on the active device. These values apply to new TCP connections, so reconnect SSH or restart a long-lived service before comparing network behavior.<\/p>\n\n\n\n<aside class=\"vl-element vl-cta-banner\" aria-label=\"Tune Rocky Linux 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 Rocky Linux networking<\/h3>\n\t\t<p class=\"vl-cta-banner__text\">Run Rocky Linux 10 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 does not provide the BBR module, or its module files do not match the kernel returned by <code>uname -r<\/code>. Install Rocky Linux&#8217;s current kernel package, reboot into it, and repeat Step 2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dnf install -y kernel\nsudo reboot<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the VPS still boots a provider-managed custom kernel, ask the provider for a Rocky Linux 10 kernel with BBR support. Do not copy a module from a different 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\">BBR was selected before the kernel registered it. Run <code>sudo modprobe tcp_bbr<\/code>, confirm that <code>bbr<\/code> appears in <code>net.ipv4.tcp_available_congestion_control<\/code>, and reload the saved file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo sysctl -p \/etc\/sysctl.d\/99-rocky-bbr.conf<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If <code>bbr<\/code> never appears, the problem is kernel support rather than the sysctl syntax.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>RTNETLINK answers: Operation not permitted<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The VPS is likely an unprivileged container without the capability needed to replace a qdisc. The TCP setting may still work, but the live <code>fq<\/code> queue cannot be changed inside that container; enable it on the host or use a full VPS with traffic-control permissions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">BBR returns to <code>cubic<\/code> after a reboot<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The module-load file may be missing, or another sysctl file may load after yours and select <code>cubic<\/code>. Inspect all local assignments, then reload the module and Rocky Linux 10 file:<\/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 systemctl restart systemd-modules-load\nsudo sysctl -p \/etc\/sysctl.d\/99-rocky-bbr.conf\nsysctl net.ipv4.tcp_available_congestion_control net.ipv4.tcp_congestion_control<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Remove or update a later conflicting assignment rather than creating multiple BBR files.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Next steps<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">BBR is a transport-level change, so judge it with the traffic your server actually sends rather than with a single generic speed test. A long-lived download, reverse proxy, backup job, or game connection may need to be restarted before it reflects the new algorithm.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Reboot during a maintenance window and rerun the verification block to prove that both the module and sysctl file load automatically.<\/li>\n\n\n<li>Compare several transfers to the same remote peer before and after the change; record latency and throughput instead of relying on one result.<\/li>\n\n\n<li>If the server has more than one active interface, inspect each device with <code>tc qdisc show<\/code> and apply a deliberate NetworkManager profile only where it is needed.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">FAQ<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Does BBR open a firewall port?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. BBR changes TCP behavior inside the kernel and does not create a listener, so Rocky Linux firewall rules do not need a new entry. Keep your existing SSH and application rules in place.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Will existing SSH connections switch to BBR?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The algorithm is chosen when a TCP connection is created. Reconnect SSH and restart the service you are evaluating; an already-open session may retain its original TCP state.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why can BBR be available but not active?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Loading <code>tcp_bbr<\/code> only makes the algorithm usable. The <code>net.ipv4.tcp_congestion_control = bbr<\/code> value selects it, so check both the live sysctl and <code>\/etc\/sysctl.d\/99-rocky-bbr.conf<\/code>.<\/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 the congestion-control value in <code>\/etc\/sysctl.d\/99-rocky-bbr.conf<\/code> to <code>cubic<\/code>, run <code>sudo sysctl -p \/etc\/sysctl.d\/99-rocky-bbr.conf<\/code>, and verify the live value. You can leave <code>tcp_bbr<\/code> in the module-load file because loading a module does not select it.<\/p>\n\n\n\n<script type=\"application\/ld+json\">{\"@context\": \"https:\/\/schema.org\", \"@type\": \"FAQPage\", \"mainEntity\": [{\"@type\": \"Question\", \"name\": \"Does BBR open a firewall port?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"No. BBR changes TCP behavior inside the kernel and does not create a listener, so Rocky Linux firewall rules do not need a new entry. Keep your existing SSH and application rules in place.\"}}, {\"@type\": \"Question\", \"name\": \"Will existing SSH connections switch to BBR?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"The algorithm is chosen when a TCP connection is created. Reconnect SSH and restart the service you are evaluating; an already-open session may retain its original TCP state.\"}}, {\"@type\": \"Question\", \"name\": \"Why can BBR be available but not active?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Loading `tcp_bbr` only makes the algorithm usable. The `net.ipv4.tcp_congestion_control = bbr` value selects it, so check both the live sysctl and `\/etc\/sysctl.d\/99-rocky-bbr.conf`.\"}}, {\"@type\": \"Question\", \"name\": \"How do I switch back to CUBIC?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Change the congestion-control value in `\/etc\/sysctl.d\/99-rocky-bbr.conf` to `cubic`, run `sudo sysctl -p \/etc\/sysctl.d\/99-rocky-bbr.conf`, and verify the live value. You can leave `tcp_bbr` in the module-load file because loading a module does not select it.\"}}]}<\/script>\n\n","protected":false},"excerpt":{"rendered":"Learn how to enable bbr on rocky linux 10 with persistent kernel settings, fq queueing, live verification, and fixes for missing-module errors on a VPS.","protected":false},"author":1,"featured_media":974,"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,99,115],"class_list":["post-973","post","type-post","status-publish","format-standard","has-post-thumbnail","category-guides","category-vps-hosting","tag-bbr","tag-linux-networking","tag-rocky-linux-10","tag-vps-tuning","cs-entry"],"_links":{"self":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/973","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=973"}],"version-history":[{"count":1,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/973\/revisions"}],"predecessor-version":[{"id":3825,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/973\/revisions\/3825"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/media\/974"}],"wp:attachment":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/media?parent=973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/categories?post=973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/tags?post=973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}