Stop Re-Pairing Your Bluetooth Devices on Linux: The Ultimate Dual-Boot Fix

dual-boot Bluetooth fix
Frustrated with re-pairing your Bluetooth devices every time you switch between Windows and Linux? It’s a common dual-boot problem that wastes time and disrupts your workflow. The good news is, there's a permanent fix. We'll show you how to force your Linux system to use the same Bluetooth MAC address as Windows. This tricks your devices into thinking they're always connected to the same machine, giving you seamless, hassle-free productivity.

The Why: Unmasking the Problem

Here's the lowdown on why this happens. When you pair a Bluetooth device on, say, Windows, the OS generates a unique pairing key and stores it. This key is tied to the Bluetooth adapter's unique identifier, its MAC address. When you switch to Linux, a different OS takes over, and it generates its own unique pairing key for the same device and adapter. The device gets confused because it's seeing the same adapter MAC address but a different key. It assumes something is wrong and refuses to connect automatically.

Our solution? We’ll make Linux use the same MAC address as Windows. By doing this, we bypass the pairing key conflict entirely. We'll be using a tool called btmgmt to achieve this, but there's a catch: btmgmt can be finicky and often requires an interactive TTY session to work correctly. Don't worry, we have a clever workaround for that, which is where systemd and the script utility come in.
*I've tried it on Ubuntu/Kubuntu 24.04 LTS.


Step-by-Step Guide

Step 1: Create and Test Your Script

First, let's create a script that will do the heavy lifting for us. This script needs to be executable and accessible. We'll put it in /usr/local/bin/.

sudo nano /usr/local/bin/change-bt-mac.sh

Paste the following code into the file. Be sure to replace 44:E5:17:22:FC:4F with the MAC address you want to use. Make sure not to use the default mac address as that will be used by the windows.

#!/bin/bash
# Send all output to a log file for easy debugging
exec >> /tmp/btmac.log 2>&1
set -x

# Ensure essential command paths are available
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# Bring the Bluetooth adapter down
hciconfig hci0 down

# Change the public MAC address - replace the mac address to whatever you want to use
btmgmt -i hci0 public-addr 44:E5:17:22:FC:4F

# Bring the adapter back up
hciconfig hci0 up

# Re-initialize the Bluetooth service
echo -e 'power on\nquit' | bluetoothctl

Save and exit (Ctrl + X, then Y, then Enter). Now, make the script executable:

sudo chmod +x /usr/local/bin/change-bt-mac.sh

Step 2: Create the sudoers Entry

To allow a systemd user service to run this script with elevated privileges without a password prompt, we need to add an entry to the sudoers file. This is the cleanest and most secure way to handle it.

sudo visudo -f /etc/sudoers.d/btmac

Add the following line, replacing yourusername with your actual username.

yourusername ALL=(ALL) NOPASSWD: /usr/local/bin/change-bt-mac.sh

This grants your user permission to run only this specific script with sudo without a password. A perfect example of the principle of least privilege.


Step 3: Set Up a systemd User Service

Now for the magic. We'll create a systemd user service that runs our script every time you log in. The key here is using script -qfc to fake an interactive TTY, which satisfies btmgmt's peculiar requirement.

First, create the directory for the user service file if it doesn't exist:

mkdir -p ~/.config/systemd/user

Then, create the service file itself:

nano ~/.config/systemd/user/change-bt-mac.service

Paste this content into the file:

[Unit]
Description=Change Bluetooth MAC at login via sudo
After=default.target
Wants=default.target

[Service]
Type=exec
ExecStart=/usr/bin/script -qfc "sudo /usr/local/bin/change-bt-mac.sh" /dev/null

[Install]
WantedBy=default.target

Save and exit.


Step 4: Enable and Test the Service

With the service file in place, let's enable it so it runs automatically at every login.

systemctl --user daemon-reload
systemctl --user enable change-bt-mac.service

Since this is a user service, it's tied to your user's session. To ensure it runs even if you're not logged in, you can enable lingering:

sudo loginctl enable-linger yourusername

Finally, let's give it a test run without a full reboot:

systemctl --user start change-bt-mac.service

Give it a few seconds, then check the log file to see if the script ran successfully.

cat /tmp/btmac.log

If you see output from the commands, you're good to go! Log out and log back in, and your Bluetooth MAC address should now be set to match your Windows one. Your devices will connect seamlessly, no re-pairing required.


Troubleshooting: When Things Go Wrong

Even the best-laid plans can have a hiccup. If it's not working, here's what to check.

  • No output in the log file (/tmp/btmac.log)? Make sure you ran sudo chmod +x on the script and systemctl --user enable. Also, double-check your sudoers file entry for any typos. The visudo command will flag syntax errors, which is a lifesaver.
  • Permissions errors? btmgmt and hciconfig require root privileges. This is precisely why we're using sudo with the NOPASSWD entry. If you're still getting permission denied errors, re-verify your sudoers configuration.
  • Still have to re-pair? make sure your mac address is changes when you manually run the script, also try rebooting and running the service manually, check if that changes the mac address. If they are not changing it, try to figure out which step is not working and troubleshoot accordingly. Try changing your bluetooth device name by going to setting and reboot after changing it. 

Conclusion

You've done it! You've conquered one of the most annoying dual-boot issues with a simple, elegant solution. By leveraging the power of systemd user services and a little command-line trickery, you've ensured your Bluetooth devices will connect effortlessly, no matter which OS you're in. This little project not only boosts your productivity but also showcases the incredible flexibility and power of the Linux ecosystem.

There is one more way to resolve this, where you need to get the pairing key from the windows and then use that key on the Linux so that both your windows and Linux will have same key. 
You can try this method from here

What other dual-boot pains have you solved? Share your tips and tricks in the comments below

Post a Comment

Previous Post Next Post