How to Permanently Configure Search Domains and resolv.conf Settings in Ubuntu with NetworkManager


2 views

Many Ubuntu users face this common frustration: NetworkManager automatically manages /etc/resolv.conf, overwriting manual changes made for domain search paths or DNS settings. This becomes particularly problematic in corporate environments where specific domain search configurations are required.

Modern Ubuntu systems use a symbolic link for /etc/resolv.conf that points to /run/systemd/resolve/stub-resolv.conf. NetworkManager interacts with systemd-resolved to manage DNS settings dynamically.

Here are three robust approaches to configure search domains permanently:

Method 1: Using NetworkManager Connection Profiles

Edit your connection profile directly:

nmcli connection modify "YourConnectionName" ipv4.dns-search "example.com example.org"
nmcli connection modify "YourConnectionName" ipv4.dns "8.8.8.8 8.8.4.4"
nmcli connection up "YourConnectionName"

Method 2: Configuring systemd-resolved

For more advanced control, configure systemd-resolved:

sudo mkdir -p /etc/systemd/resolved.conf.d/
sudo nano /etc/systemd/resolved.conf.d/search-domains.conf

Add these contents:

[Resolve]
Domains=example.com example.org
DNS=8.8.8.8 8.8.4.4

Then restart the service:

sudo systemctl restart systemd-resolved

Method 3: Disabling Automatic Management

As a last resort, you can disable NetworkManager's DNS management:

sudo nano /etc/NetworkManager/NetworkManager.conf

Add under [main]:

dns=none

Then create a static /etc/resolv.conf:

sudo rm /etc/resolv.conf
sudo nano /etc/resolv.conf

Add your custom configuration:

search example.com example.org
nameserver 8.8.8.8
nameserver 8.8.4.4

After making changes, verify with:

systemd-resolve --status
cat /etc/resolv.conf
nmcli dev show | grep DNS

If you need different configurations for different networks, consider using NetworkManager dispatcher scripts:

sudo nano /etc/NetworkManager/dispatcher.d/99-custom-dns

Add this script (make it executable with chmod +x):

#!/bin/bash
INTERFACE="$1"
STATUS="$2"

if [ "$STATUS" = "up" ]; then
    if [ "$INTERFACE" = "eth0" ]; then
        nmcli connection modify "$CONNECTION_UUID" ipv4.dns-search "corp.example.com"
    elif [[ "$INTERFACE" =~ "wlan" ]]; then
        nmcli connection modify "$CONNECTION_UUID" ipv4.dns-search "home.example.com"
    fi
fi

NetworkManager's automatic management of /etc/resolv.conf is both a blessing and a curse. While it simplifies network configuration, it makes persistent DNS customizations challenging - especially for enterprise environments requiring specific search domains.

Here are the most robust approaches to enforce your DNS settings:

Method 1: NetworkManager Connection Profiles

Edit your connection profile (replace "Wired connection 1" with your connection name):

nmcli connection edit "Wired connection 1"
nmcli> set ipv4.dns-search "yourdomain.com,sub.yourdomain.com"
nmcli> save
nmcli> quit

This stores the search domain permanently in NetworkManager's configuration.

Method 2: Using dhclient hooks

Create a custom dhclient hook script:

sudo nano /etc/dhcp/dhclient-enter-hooks.d/custom_search

Add this content:

#!/bin/sh
make_resolv_conf() {
    echo "search yourdomain.com sub.yourdomain.com" > /etc/resolv.conf
    echo "nameserver 8.8.8.8" >> /etc/resolv.conf
}

Make it executable:

sudo chmod +x /etc/dhcp/dhclient-enter-hooks.d/custom_search

Method 3: Disabling resolv.conf management

For ultimate control, you can tell NetworkManager to stop managing resolv.conf:

sudo nano /etc/NetworkManager/conf.d/90-dns-none.conf

Add:

[main]
dns=none

Then manually create your resolv.conf:

sudo nano /etc/resolv.conf

Add your configuration:

search yourdomain.com sub.yourdomain.com
nameserver 8.8.8.8
nameserver 8.8.4.4

After making changes, verify with:

nmcli dev show | grep DOMAIN
cat /etc/resolv.conf
systemd-resolve --status

Remember to restart NetworkManager after configuration changes:

sudo systemctl restart NetworkManager

As a last resort, you can create a monitoring script:

#!/bin/bash
# /usr/local/bin/resolv_watchdog.sh
SEARCH_DOMAIN="yourdomain.com"
CURRENT_SEARCH=$(grep ^search /etc/resolv.conf | awk '{print $2}')

if [ "$CURRENT_SEARCH" != "$SEARCH_DOMAIN" ]; then
    sed -i "s/^search.*/search $SEARCH_DOMAIN/" /etc/resolv.conf
fi

Then add a cron job:

* * * * * /usr/local/bin/resolv_watchdog.sh