Skip to content

Instantly share code, notes, and snippets.

@smudge1977
Last active August 2, 2025 13:50
Show Gist options
  • Save smudge1977/dd441c681fe8a6a5369b9450a076f9ff to your computer and use it in GitHub Desktop.
Save smudge1977/dd441c681fe8a6a5369b9450a076f9ff to your computer and use it in GitHub Desktop.
LXD and Docker network bridges co-habiting the same host
#!/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"
#!/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"
@smudge1977
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment