Override DNS server for alpine LXC in DHCP mode #576

Closed
opened 2026-02-04 20:02:51 +03:00 by OVERLORD · 15 comments
Owner

Originally created by @de666 on GitHub (Mar 3, 2025).

Originally assigned to: @michelroegl-brunner on GitHub.

🌟 Briefly describe the feature

Manage correctly the override of DNS server on alpine LXC in DHCP

📝 Detailed description

As already discussed on discord
https://discord.com/channels/1302816934508630047/1330235805943337144

For alpine based containers, if you select both DHCP and a custom DNS server, the server are not overridden because proxmox writes the correct resolve.conf file but alpine (udhcpc) overwrite it back at every LXC startup putting the DNS servers sent by DHCP server.
It is possible to prevent this action enabling the line

RESOLV_CONF="no" # Prevents overwriting of /etc/resolv.conf

in /etc/udhcpc/udhcpc.conf

see https://wiki.alpinelinux.org/wiki/Udhcpc

So, when an alpine based container is created, if the user select dhcp and doesn't leave dns server empty (i.e. specifies a custom DNS server), the script should enable the option above (modifying the conf file) and this has to be done before doing any dns query (before updating the OS).

💡 Why is this useful?

It's a kind of bug cause now it's not working as expected.
The user who specifies a custom DNS server expects that server is used even if DHCP is selected (otherwise it has no meaning the wizard ask for a DNS server when DHCP is selected).
Furthermore it works well for non alpine (debian/ubuntu) LXC and it should work the same way for alpine containers.

Originally created by @de666 on GitHub (Mar 3, 2025). Originally assigned to: @michelroegl-brunner on GitHub. ### 🌟 Briefly describe the feature Manage correctly the override of DNS server on alpine LXC in DHCP ### 📝 Detailed description As already discussed on discord https://discord.com/channels/1302816934508630047/1330235805943337144 For alpine based containers, if you select both DHCP and a custom DNS server, the server are not overridden because proxmox writes the correct resolve.conf file but alpine (udhcpc) overwrite it back at every LXC startup putting the DNS servers sent by DHCP server. It is possible to prevent this action enabling the line ``` RESOLV_CONF="no" # Prevents overwriting of /etc/resolv.conf ``` in ```/etc/udhcpc/udhcpc.conf``` see https://wiki.alpinelinux.org/wiki/Udhcpc So, when an alpine based container is created, if the user select dhcp and doesn't leave dns server empty (i.e. specifies a custom DNS server), the script should enable the option above (modifying the conf file) and this has to be done before doing any dns query (before updating the OS). ### 💡 Why is this useful? It's a kind of bug cause now it's not working as expected. The user who specifies a custom DNS server expects that server is used even if DHCP is selected (otherwise it has no meaning the wizard ask for a DNS server when DHCP is selected). Furthermore it works well for non alpine (debian/ubuntu) LXC and it should work the same way for alpine containers.
OVERLORD added the enhancement label 2026-02-04 20:02:51 +03:00
Author
Owner

@michelroegl-brunner commented on GitHub (May 5, 2025):

@de666 If added the function to the Dev Repo, can you check if it works as you expected? Test with for example: bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/alpine-rclone.sh)"

@michelroegl-brunner commented on GitHub (May 5, 2025): @de666 If added the function to the Dev Repo, can you check if it works as you expected? Test with for example: `bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/alpine-rclone.sh)"`
Author
Owner

@de666 commented on GitHub (May 5, 2025):

@de666 If added the function to the Dev Repo, can you check if it works as you expected? Test with for example: bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/alpine-rclone.sh)"

Indeed I can. Please let me know when it will be available and how to test it (the link to the bash script).

@de666 commented on GitHub (May 5, 2025): > @de666 If added the function to the Dev Repo, can you check if it works as you expected? Test with for example: `bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/alpine-rclone.sh)"` Indeed I can. Please let me know when it will be available and how to test it (the link to the bash script).
Author
Owner

@MickLesk commented on GitHub (May 5, 2025):

You can test it with default alpine lxc, its present in Dev Repo

bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/alpine.sh)"

@MickLesk commented on GitHub (May 5, 2025): You can test it with default alpine lxc, its present in Dev Repo bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/alpine.sh)"
Author
Owner

@de666 commented on GitHub (May 6, 2025):

@de666 If added the function to the Dev Repo, can you check if it works as you expected? Test with for example: bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/alpine-rclone.sh)"

@michelroegl-brunner Tested with bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/alpine.sh)"

It doesn't seem to work

It gives me a DNS error and the script exit when trying to update Alpine OS, it's not able to resolve the repository url. Looking inside the created container, it seems the content of /etc/udhcpc/udhcpc.conf is not correct, the line
#RESOLV_CONF="no"
shuold not be commented. As I wrote, that conf file modification has to be done before doing any dns query (before updating the OS).
Maybe the following operations has to be performed in order to get it working:

  • container creation
  • uncomment the configuration line
  • container restart (?)
  • OS update

Please let me know if you need me to test it again

@de666 commented on GitHub (May 6, 2025): > [@de666](https://github.com/de666) If added the function to the Dev Repo, can you check if it works as you expected? Test with for example: `bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/alpine-rclone.sh)"` @michelroegl-brunner Tested with ```bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/alpine.sh)"``` **It doesn't seem to work** It gives me a DNS error and the script exit when trying to update Alpine OS, it's not able to resolve the repository url. Looking inside the created container, it seems the content of ```/etc/udhcpc/udhcpc.conf``` is not correct, the line ```#RESOLV_CONF="no" ``` shuold not be commented. As I wrote, that conf file modification has to be done before doing any dns query (before updating the OS). Maybe the following operations has to be performed in order to get it working: - container creation - uncomment the configuration line - container restart (?) - OS update Please let me know if you need me to test it again
Author
Owner

@michelroegl-brunner commented on GitHub (May 6, 2025):

This line is commented by default.
Inthought we need to comment it out?

@michelroegl-brunner commented on GitHub (May 6, 2025): This line is commented by default. Inthought we need to comment it out?
Author
Owner

@de666 commented on GitHub (May 6, 2025):

This line is commented by default. Inthought we need to comment it out?

that line has to be commented out (uncommented) but that is already done the right way from what I see here
cbf47a6962/misc/alpine-install.func (L202)
The problem is not that, the problem is that config file mod is done by the script after checking network and updating the OS and it shuold be done before, it shuold be the very first thing the script does immediatley after building the container as I wrote

  1. container creation
  2. uncomment the configuration line
  3. container restart (?)
  4. OS update

In other words, the point 2 is already accomplished by the customize function at
cbf47a6962/misc/alpine-install.func (L202)
The problem is the customize function is called at the very end of the process so it cannot work because that correction is necessary to make OS update and network check working correctly (which at the moment are performed before the customize function)
af89f730ad/install/alpine-install.sh (L25)

I hope I made myself clear, let me know if you need further details about that.

@de666 commented on GitHub (May 6, 2025): > This line is commented by default. Inthought we need to comment it out? that line has to be commented out (uncommented) but that is already done the right way from what I see here https://github.com/community-scripts/ProxmoxVED/blob/cbf47a69627e544a77b07e6b727a7ad370ba14fd/misc/alpine-install.func#L202 The problem is not that, the problem is that config file mod is done by the script **after** checking network and updating the OS and it shuold be done **before**, it shuold be the very first thing the script does immediatley after building the container as I wrote > 1. container creation > 2. uncomment the configuration line > 3. container restart (?) > 4. OS update In other words, the point 2 is already accomplished by the customize function at https://github.com/community-scripts/ProxmoxVED/blob/cbf47a69627e544a77b07e6b727a7ad370ba14fd/misc/alpine-install.func#L202 The problem is the customize function is called at the very end of the process so it cannot work because that correction is necessary to make OS update and network check working correctly (which at the moment are performed **before** the customize function) https://github.com/community-scripts/ProxmoxVED/blob/af89f730addcce00a4cf354da0d3296eede79406/install/alpine-install.sh#L25 I hope I made myself clear, let me know if you need further details about that.
Author
Owner

@michelroegl-brunner commented on GitHub (May 6, 2025):

Ah, i see. I changed it around so it is the first thing wich happens befor setting anything else up.

@michelroegl-brunner commented on GitHub (May 6, 2025): Ah, i see. I changed it around so it is the first thing wich happens befor setting anything else up.
Author
Owner

@de666 commented on GitHub (May 6, 2025):

Ah, i see. I changed it around so it is the first thing wich happens befor setting anything else up.

same error and the configuration file is still unmodified (line was not uncommented as it shuold be)

@de666 commented on GitHub (May 6, 2025): > Ah, i see. I changed it around so it is the first thing wich happens befor setting anything else up. same error and the configuration file is still unmodified (line was not uncommented as it shuold be)
Author
Owner

@MickLesk commented on GitHub (May 7, 2025):

You can check it again.

Image
@MickLesk commented on GitHub (May 7, 2025): You can check it again. <img width="520" alt="Image" src="https://github.com/user-attachments/assets/ae8b4827-01a6-4552-8594-084441370c84" />
Author
Owner

@de666 commented on GitHub (May 7, 2025):

Image

As I pointed out, modifying that file is the very first thing the script shuold do, before everything, even before installing the bash package o any other package couse that involves a DNS lookup. Also, as I wrote, maybe the container has to be restarted after enabling that option, if it is not possibile (I don't know if it is possible) to modify the file after the creation of the container but before starting it.
Furthermore from my point of view that option also can be and shuold be always enabled since the resolve.conf is managed and should be managed by PVE as it is for the debian containers so that file cuold be modified even in the alpine template, regardless of the chosen network configuration.

@de666 commented on GitHub (May 7, 2025): ![Image](https://github.com/user-attachments/assets/5fa565c2-edc4-47f5-a0e3-8191de35dd9a) As I pointed out, modifying that file is the very first thing the script shuold do, before **everything**, even before installing the bash package o any other package couse that involves a DNS lookup. Also, as I wrote, maybe the container has to be restarted after enabling that option, if it is not possibile (I don't know if it is possible) to modify the file after the creation of the container but before starting it. Furthermore from my point of view that option also can be and shuold be always enabled since the resolve.conf is managed and should be managed by PVE as it is for the debian containers so that file cuold be modified even in the alpine template, regardless of the chosen network configuration.
Author
Owner

@MickLesk commented on GitHub (May 7, 2025):

Everything happens exactly as you say it does. It is the first one after the container has been created. A restart is not possible, otherwise it will lose the session.

How you get these messages, idk. You get DNS lookup errors, I don't. I have tested the function several times today.

Image Image
@MickLesk commented on GitHub (May 7, 2025): Everything happens exactly as you say it does. It is the first one after the container has been created. A restart is not possible, otherwise it will lose the session. How you get these messages, idk. You get DNS lookup errors, I don't. I have tested the function several times today. <img width="515" alt="Image" src="https://github.com/user-attachments/assets/0fb666af-54fa-4a18-b6c5-0640b9541b35" /> <img width="455" alt="Image" src="https://github.com/user-attachments/assets/46501451-d66a-49b2-bb78-e028fba2e78b" />
Author
Owner

@de666 commented on GitHub (May 7, 2025):

The errors I get afaik are due to a wrong dns server, that is the reason why I found and proposed this feature.
In the first instance I say it happens the following:

  1. The container is started with the default udhcpc.conf
  2. The resolve.conf is overwritten by the OS (since the line is commented)
  3. The script modifies udhcpc.conf
  4. The script tries to install some packages but the resolve.conf is still not the one provided by PVE since it was overwritten and the container not yet restarted
  5. The script fails because of DNS lookup error (DNS are still wrong)

The point 3 is placed in that position based on what you said.

Everything happens exactly as you say it does. It is the first one after the container has been created.

But this is in conflict with what I see after the error looking at the contents of udhcpc.conf of the already started (even if not completely configured) container.

@de666 commented on GitHub (May 7, 2025): The errors I get afaik are due to a wrong dns server, that is the reason why I found and proposed this feature. In the first instance I say it happens the following: 1. The container is started with the default udhcpc.conf 2. The resolve.conf is overwritten by the OS (since the line is commented) 3. The script modifies udhcpc.conf 4. The script tries to install some packages but the resolve.conf is still not the one provided by PVE since it was overwritten and the container not yet restarted 5. The script fails because of DNS lookup error (DNS are still wrong) The point 3 is placed in that position based on what you said. > Everything happens exactly as you say it does. It is the first one after the container has been created. But this is in conflict with what I see after the error looking at the contents of udhcpc.conf of the already started (even if not completely configured) container.
Author
Owner

@MickLesk commented on GitHub (May 7, 2025):

lemme test something in pre creation.

@MickLesk commented on GitHub (May 7, 2025): lemme test something in pre creation.
Author
Owner

@IT-Yohan commented on GitHub (Jun 12, 2025):

Hey, it should be pointed that the problem is the same on Debian based CT's.
The /etc/resolv.conf set by pve gets overwritten by the DHCP client when it fetches the DNS.

My solution was to remove domain-name-servers from the request line in /etc/dhcp/dhclient.conf so that it stops managing it, but it is not ideal do do that each time.

Here's a script that removes this from all my currently running Debian based CT's, for eah of them it creates a backup of the dhclient.conf then removes the domain-name-servers from the request line :

#!/bin/bash
#
# Surgically removes 'domain-name-servers' from the active 'request' block
# in the dhclient.conf file for all running Debian-based LXC containers.
#

GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\03_p[0;31m'
NC='\033[0m' # No Color

echo -e "${YELLOW}Starting DHCP configuration check for all running containers...${NC}"

# --- Step 1: Find all running containers ---
HEADER=$(pct list | head -n 1)
STATUS_COL=$(echo "$HEADER" | awk '{for(i=1; i<=NF; i++) if (tolower($i) == "status") print i}')

if [ -z "$STATUS_COL" ]; then
    echo -e "${RED}Error: Could not determine 'status' column from 'pct list'.${NC}"
    exit 1
fi

RUNNING_CTS=$(pct list | awk -v col="$STATUS_COL" 'NR>1 && $col=="running" {print $1}')

if [ -z "$RUNNING_CTS" ]; then
    echo "No running containers found to process."
    exit 0
fi

echo "---"

# --- Step 2: Process each container individually ---
for CTID in $RUNNING_CTS; do
    echo -n -e "Processing CT ${YELLOW}$CTID${NC}... "

    if ! pct exec $CTID -- test -f /etc/debian_version &>/dev/null; then
        echo -e "${YELLOW}Skipping (Not Debian-based).${NC}"; continue;
    fi

    DHCLIENT_CONF="/etc/dhcp/dhclient.conf"
    if ! pct exec $CTID -- test -f $DHCLIENT_CONF &>/dev/null; then
        echo -e "${YELLOW}Skipping (dhclient.conf not found).${NC}"; continue;
    fi

    # Define the precise check and fix commands
    CHECK_CMD="awk '/^\\s*request\\s/{in_req=1} in_req && /domain-name-servers/{found=1} /;/{in_req=0} END{if(found) exit 0; else exit 1}' $DHCLIENT_CONF"
    FIX_CMD="sed -i.bak '/^\\s*request\\s/,/;/s/domain-name-servers,?\\s*//g' $DHCLIENT_CONF"

    # Execute the check and fix logic
    if pct exec $CTID -- bash -c "$CHECK_CMD"; then
        echo -n "Updating... "
        if pct exec $CTID -- bash -c "$FIX_CMD"; then
            echo -e "${GREEN}SUCCESS.${NC}"
        else
            echo -e "${RED}ERROR.${NC}"
        fi
    else
        echo -e "${GREEN}OK (Already configured).${NC}"
    fi
done

# --- Step 3: Final instructions ---
echo "---"
echo -e "${GREEN}Script finished.${NC}"
echo -e "A ${YELLOW}reboot${NC} is required for any container marked with 'SUCCESS' to apply the new configuration."
@IT-Yohan commented on GitHub (Jun 12, 2025): Hey, it should be pointed that the problem is the same on Debian based CT's. The /etc/resolv.conf set by pve gets overwritten by the DHCP client when it fetches the DNS. My solution was to remove domain-name-servers from the request line in /etc/dhcp/dhclient.conf so that it stops managing it, but it is not ideal do do that each time. Here's a script that removes this from all my currently running Debian based CT's, for eah of them it creates a backup of the dhclient.conf then removes the domain-name-servers from the request line : ``` #!/bin/bash # # Surgically removes 'domain-name-servers' from the active 'request' block # in the dhclient.conf file for all running Debian-based LXC containers. # GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\03_p[0;31m' NC='\033[0m' # No Color echo -e "${YELLOW}Starting DHCP configuration check for all running containers...${NC}" # --- Step 1: Find all running containers --- HEADER=$(pct list | head -n 1) STATUS_COL=$(echo "$HEADER" | awk '{for(i=1; i<=NF; i++) if (tolower($i) == "status") print i}') if [ -z "$STATUS_COL" ]; then echo -e "${RED}Error: Could not determine 'status' column from 'pct list'.${NC}" exit 1 fi RUNNING_CTS=$(pct list | awk -v col="$STATUS_COL" 'NR>1 && $col=="running" {print $1}') if [ -z "$RUNNING_CTS" ]; then echo "No running containers found to process." exit 0 fi echo "---" # --- Step 2: Process each container individually --- for CTID in $RUNNING_CTS; do echo -n -e "Processing CT ${YELLOW}$CTID${NC}... " if ! pct exec $CTID -- test -f /etc/debian_version &>/dev/null; then echo -e "${YELLOW}Skipping (Not Debian-based).${NC}"; continue; fi DHCLIENT_CONF="/etc/dhcp/dhclient.conf" if ! pct exec $CTID -- test -f $DHCLIENT_CONF &>/dev/null; then echo -e "${YELLOW}Skipping (dhclient.conf not found).${NC}"; continue; fi # Define the precise check and fix commands CHECK_CMD="awk '/^\\s*request\\s/{in_req=1} in_req && /domain-name-servers/{found=1} /;/{in_req=0} END{if(found) exit 0; else exit 1}' $DHCLIENT_CONF" FIX_CMD="sed -i.bak '/^\\s*request\\s/,/;/s/domain-name-servers,?\\s*//g' $DHCLIENT_CONF" # Execute the check and fix logic if pct exec $CTID -- bash -c "$CHECK_CMD"; then echo -n "Updating... " if pct exec $CTID -- bash -c "$FIX_CMD"; then echo -e "${GREEN}SUCCESS.${NC}" else echo -e "${RED}ERROR.${NC}" fi else echo -e "${GREEN}OK (Already configured).${NC}" fi done # --- Step 3: Final instructions --- echo "---" echo -e "${GREEN}Script finished.${NC}" echo -e "A ${YELLOW}reboot${NC} is required for any container marked with 'SUCCESS' to apply the new configuration." ```
Author
Owner

@MickLesk commented on GitHub (Jul 17, 2025):

I have not found a solution to the problem - it would have to be changed hard before the template runs. When creating the container, it's a 50:50 chance whether it takes it over or not. I think our hands are currently bound. If you find a solution to this during runtime before it connects the network, you are welcome to PR it. You are also welcome to post it in the ProxmoxVED repo, where you can find the latest developments.

@MickLesk commented on GitHub (Jul 17, 2025): I have not found a solution to the problem - it would have to be changed hard before the template runs. When creating the container, it's a 50:50 chance whether it takes it over or not. I think our hands are currently bound. If you find a solution to this during runtime before it connects the network, you are welcome to PR it. You are also welcome to post it in the ProxmoxVED repo, where you can find the latest developments.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/ProxmoxVE#576