Last active
August 2, 2025 13:50
-
-
Save smudge1977/dd441c681fe8a6a5369b9450a076f9ff to your computer and use it in GitHub Desktop.
LXD and Docker network bridges co-habiting the same host
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Fix LXD and Docker iptables conflicts | |
# Run this script with sudo to permanently fix networking issues | |
set -e | |
echo "Fixing LXD and Docker iptables conflicts..." | |
# Check if running as root | |
if [ "$EUID" -ne 0 ]; then | |
echo "Please run this script as root (sudo $0)" | |
exit 1 | |
fi | |
# Get LXD bridge information | |
LXD_BRIDGE=$(lxc network list --format csv | grep -E "^lxd" | cut -d',' -f1 | head -1) | |
if [ -z "$LXD_BRIDGE" ]; then | |
LXD_BRIDGE="lxdbr0" # Default fallback | |
echo "Using default LXD bridge: $LXD_BRIDGE" | |
else | |
echo "Found LXD bridge: $LXD_BRIDGE" | |
fi | |
# Get LXD bridge subnet | |
LXD_SUBNET=$(lxc network get $LXD_BRIDGE ipv4.address 2>/dev/null || echo "10.0.0.1/24") | |
LXD_SUBNET_RANGE=$(echo $LXD_SUBNET | cut -d'/' -f1 | sed 's/\.[0-9]*$/\.0\/24/') | |
echo "LXD Subnet Range: $LXD_SUBNET_RANGE" | |
# Function to add iptables rule if it doesn't exist | |
add_rule_if_not_exists() { | |
local table="$1" | |
local chain="$2" | |
local rule="$3" | |
if [ "$table" = "filter" ]; then | |
if ! iptables -C $chain $rule 2>/dev/null; then | |
iptables -I $chain $rule | |
echo "Added rule: iptables -I $chain $rule" | |
else | |
echo "Rule already exists: iptables -C $chain $rule" | |
fi | |
else | |
if ! iptables -t $table -C $chain $rule 2>/dev/null; then | |
iptables -t $table -I $chain $rule | |
echo "Added rule: iptables -t $table -I $chain $rule" | |
else | |
echo "Rule already exists: iptables -t $table -C $chain $rule" | |
fi | |
fi | |
} | |
# Add DOCKER-USER rules to allow LXD traffic | |
echo "Adding DOCKER-USER rules..." | |
add_rule_if_not_exists "filter" "DOCKER-USER" "-i $LXD_BRIDGE -o $LXD_BRIDGE -j ACCEPT" | |
add_rule_if_not_exists "filter" "DOCKER-USER" "-s $LXD_SUBNET_RANGE -d $LXD_SUBNET_RANGE -j ACCEPT" | |
add_rule_if_not_exists "filter" "DOCKER-USER" "-i $LXD_BRIDGE ! -o $LXD_BRIDGE -j ACCEPT" | |
add_rule_if_not_exists "filter" "DOCKER-USER" "-o $LXD_BRIDGE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" | |
# Add FORWARD rules | |
echo "Adding FORWARD rules..." | |
add_rule_if_not_exists "filter" "FORWARD" "-i $LXD_BRIDGE -o $LXD_BRIDGE -j ACCEPT" | |
add_rule_if_not_exists "filter" "FORWARD" "-i $LXD_BRIDGE ! -o $LXD_BRIDGE -j ACCEPT" | |
add_rule_if_not_exists "filter" "FORWARD" "-o $LXD_BRIDGE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" | |
# Add NAT rules | |
echo "Adding NAT rules..." | |
add_rule_if_not_exists "nat" "POSTROUTING" "-s $LXD_SUBNET_RANGE ! -d $LXD_SUBNET_RANGE -j MASQUERADE" | |
# Create systemd service to apply rules on boot | |
cat > /etc/systemd/system/lxd-docker-iptables-fix.service << EOF | |
[Unit] | |
Description=Fix LXD and Docker iptables conflicts | |
After=docker.service lxd.service | |
Wants=docker.service lxd.service | |
[Service] | |
Type=oneshot | |
ExecStart=/usr/local/bin/lxd-docker-iptables-fix.sh | |
RemainAfterExit=yes | |
[Install] | |
WantedBy=multi-user.target | |
EOF | |
# Create the script that will be called by systemd | |
cat > /usr/local/bin/lxd-docker-iptables-fix.sh << 'EOF' | |
#!/bin/bash | |
# Get LXD bridge information | |
LXD_BRIDGE=$(lxc network list --format csv | grep -E "^lxd" | cut -d',' -f1 | head -1) | |
if [ -z "$LXD_BRIDGE" ]; then | |
LXD_BRIDGE="lxdbr0" | |
fi | |
LXD_SUBNET=$(lxc network get $LXD_BRIDGE ipv4.address 2>/dev/null || echo "10.0.0.1/24") | |
LXD_SUBNET_RANGE=$(echo $LXD_SUBNET | cut -d'/' -f1 | sed 's/\.[0-9]*$/\.0\/24/') | |
# Add rules (ignore errors if they already exist) | |
iptables -I DOCKER-USER -i $LXD_BRIDGE -o $LXD_BRIDGE -j ACCEPT 2>/dev/null || true | |
iptables -I DOCKER-USER -s $LXD_SUBNET_RANGE -d $LXD_SUBNET_RANGE -j ACCEPT 2>/dev/null || true | |
iptables -I DOCKER-USER -i $LXD_BRIDGE ! -o $LXD_BRIDGE -j ACCEPT 2>/dev/null || true | |
iptables -I DOCKER-USER -o $LXD_BRIDGE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true | |
iptables -I FORWARD -i $LXD_BRIDGE -o $LXD_BRIDGE -j ACCEPT 2>/dev/null || true | |
iptables -I FORWARD -i $LXD_BRIDGE ! -o $LXD_BRIDGE -j ACCEPT 2>/dev/null || true | |
iptables -I FORWARD -o $LXD_BRIDGE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true | |
iptables -t nat -I POSTROUTING -s $LXD_SUBNET_RANGE ! -d $LXD_SUBNET_RANGE -j MASQUERADE 2>/dev/null || true | |
EOF | |
chmod +x /usr/local/bin/lxd-docker-iptables-fix.sh | |
# Enable the service | |
systemctl enable lxd-docker-iptables-fix.service | |
echo "" | |
echo "✅ LXD and Docker iptables conflict fix completed!" | |
echo "" | |
echo "The following has been configured:" | |
echo "1. Added iptables rules to allow LXD traffic through Docker's DOCKER-USER chain" | |
echo "2. Created systemd service to apply rules on boot" | |
echo "3. Enabled NAT for LXD containers" | |
echo "" | |
echo "You may need to restart LXD and Docker services:" | |
echo " sudo systemctl restart lxd" | |
echo " sudo systemctl restart docker" | |
echo "" | |
echo "To test LXD connectivity after restart:" | |
echo " lxc launch ubuntu:22.04 test" | |
echo " lxc exec test -- ping -c 3 8.8.8.8" | |
echo " lxc delete test --force" | |
echo "Or use test_lxd_networking.sh to verify LXD networking" | |
echo " ./tests/test_lxd_networking.sh" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Test LXD networking after applying the iptables fix | |
set -e | |
echo "Testing LXD networking..." | |
# # Check if LXD is running | |
# if ! systemctl is-active --quiet lxd; then | |
# echo "❌ LXD service is not running. Start it with: sudo systemctl start lxd" | |
# exit 1 | |
# else | |
# echo "✅ LXD service is running" | |
# fi | |
# Check if Docker is running | |
if ! systemctl is-active --quiet docker; then | |
echo "⚠️ Docker service is not running." | |
else | |
echo "✅ Docker service is running" | |
fi | |
# Launch a test container | |
echo "Launching test container..." | |
lxc launch ubuntu:22.04 network-test --quiet | |
# Wait for container to be ready | |
echo "Waiting for container to initialize..." | |
sleep 10 | |
# Test network connectivity | |
echo "Testing internet connectivity from container..." | |
if lxc exec network-test -- ping -c 3 8.8.8.8 >/dev/null 2>&1; then | |
echo "✅ Internet connectivity: WORKING" | |
else | |
echo "❌ Internet connectivity: FAILED" | |
echo "Container cannot reach the internet" | |
fi | |
# Test DNS resolution | |
echo "Testing DNS resolution from container..." | |
if lxc exec network-test -- nslookup google.com >/dev/null 2>&1; then | |
echo "✅ DNS resolution: WORKING" | |
else | |
echo "❌ DNS resolution: FAILED" | |
fi | |
# Test package installation | |
echo "Testing package installation..." | |
if lxc exec network-test -- apt update >/dev/null 2>&1; then | |
echo "✅ Package repository access: WORKING" | |
else | |
echo "❌ Package repository access: FAILED" | |
fi | |
# Cleanup | |
echo "Cleaning up test container..." | |
lxc delete network-test --force | |
echo "" | |
echo "Network test completed!" | |
echo "" | |
echo "If any tests failed, run the fix script:" | |
echo " sudo ./fix_lxd_docker_iptables.sh" | |
echo "Then restart the services:" | |
echo " sudo systemctl restart lxd" | |
echo " sudo systemctl restart docker" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Credit to co-pilot for writting this script to fix up bridge networking and iptables routing and NAT rules to allow both Docker and LXC to work.