feat(rootless): default to pasta+implicit, disable userland-proxy, make net driver switchable
Switch the rootless network stack from slirp4netns+builtin to pasta+ implicit (faster and propagates the real client source IP). The earlier pasta+builtin attempt bricked the daemon because rootlesskit rejects mismatched net/port-driver pairs; expose a single CFG_ROOTLESS_NET knob (pasta default, slirp4netns fallback) and derive the matching port driver in-script so an invalid combo can't be configured. Disable userland-proxy in the rootless daemon.json (merged, not clobbered) so containers see the real source IP. Both driver binaries are always installed, so switching is a config flip + rootless re-setup. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
parent
caa197f2fa
commit
829816b826
@ -5,3 +5,4 @@
|
|||||||
CFG_NETWORK_NAME=vpn # Network Name - Docker network name for container communication
|
CFG_NETWORK_NAME=vpn # Network Name - Docker network name for container communication
|
||||||
CFG_NETWORK_SUBNET=10.100.0.0/16 # Network Subnet - Subnet range for Docker network
|
CFG_NETWORK_SUBNET=10.100.0.0/16 # Network Subnet - Subnet range for Docker network
|
||||||
CFG_NETWORK_MTU=1500 # Network MTU - Maximum transmission unit for network packets
|
CFG_NETWORK_MTU=1500 # Network MTU - Maximum transmission unit for network packets
|
||||||
|
CFG_ROOTLESS_NET=pasta # Rootless Network Driver - Network stack for rootless Docker; pasta (default): faster and preserves the real client source IP; slirp4netns: legacy fallback if pasta misbehaves. The matching rootlesskit port driver is selected automatically. [pasta:Pasta (recommended)|slirp4netns:slirp4netns (fallback)]
|
||||||
|
|||||||
@ -190,6 +190,10 @@ class ConfigOptions {
|
|||||||
{ value: 'rooted', label: 'Rooted' },
|
{ value: 'rooted', label: 'Rooted' },
|
||||||
{ value: 'rootless', label: 'Rootless' }
|
{ value: 'rootless', label: 'Rootless' }
|
||||||
],
|
],
|
||||||
|
'CFG_ROOTLESS_NET': [
|
||||||
|
{ value: 'pasta', label: 'Pasta (recommended)' },
|
||||||
|
{ value: 'slirp4netns', label: 'slirp4netns (fallback)' }
|
||||||
|
],
|
||||||
'CFG_UFW_LOGGING': [
|
'CFG_UFW_LOGGING': [
|
||||||
{ value: 'off', label: 'Off' },
|
{ value: 'off', label: 'Off' },
|
||||||
{ value: 'low', label: 'Low' },
|
{ value: 'low', label: 'Low' },
|
||||||
|
|||||||
@ -110,15 +110,30 @@ EOF
|
|||||||
checkSuccess "Setting up Rootless for $CFG_DOCKER_INSTALL_USER"
|
checkSuccess "Setting up Rootless for $CFG_DOCKER_INSTALL_USER"
|
||||||
|
|
||||||
((menu_number++))
|
((menu_number++))
|
||||||
|
|
||||||
|
# The net namespace driver and the rootlesskit port driver are a matched
|
||||||
|
# pair — mixing them makes rootlesskit reject the config and the daemon
|
||||||
|
# silently never starts (this is why an earlier pasta+builtin attempt
|
||||||
|
# bricked the install). The user picks one network stack via
|
||||||
|
# CFG_ROOTLESS_NET; we derive its only valid port driver here:
|
||||||
|
# pasta -> implicit (fastest; propagates the real client IP)
|
||||||
|
# slirp4netns -> builtin (legacy fallback)
|
||||||
|
local rootless_net="${CFG_ROOTLESS_NET:-pasta}"
|
||||||
|
local rootless_port_driver
|
||||||
|
case "$rootless_net" in
|
||||||
|
pasta) rootless_port_driver="implicit" ;;
|
||||||
|
slirp4netns) rootless_port_driver="builtin" ;;
|
||||||
|
*)
|
||||||
|
isNotice "Unknown CFG_ROOTLESS_NET='$rootless_net'; falling back to pasta."
|
||||||
|
rootless_net="pasta"
|
||||||
|
rootless_port_driver="implicit"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "---- $menu_number. Configuring rootless networking (slirp4netns + builtin port driver)."
|
echo "---- $menu_number. Configuring rootless networking ($rootless_net + $rootless_port_driver port driver)."
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# slirp4netns is the net namespace driver; the builtin rootlesskit port
|
|
||||||
# driver skips slirp4netns's userspace port-handler and shaves
|
|
||||||
# per-connection overhead. (pasta is faster but requires a recent passt
|
|
||||||
# AND port driver none/implicit — the pasta+builtin combo is rejected by
|
|
||||||
# rootlesskit, which silently kept the rootless daemon from starting.)
|
|
||||||
systemd_user_dir="/home/$CFG_DOCKER_INSTALL_USER/.config/systemd/user"
|
systemd_user_dir="/home/$CFG_DOCKER_INSTALL_USER/.config/systemd/user"
|
||||||
local result=$(dockerCommandRunInstallUser "mkdir -p $systemd_user_dir")
|
local result=$(dockerCommandRunInstallUser "mkdir -p $systemd_user_dir")
|
||||||
checkSuccess "Create the systemd user directory if it doesn't exist"
|
checkSuccess "Create the systemd user directory if it doesn't exist"
|
||||||
@ -132,14 +147,35 @@ EOF
|
|||||||
|
|
||||||
sudo bash -c "cat <<EOL > '$override_conf_file'
|
sudo bash -c "cat <<EOL > '$override_conf_file'
|
||||||
[Service]
|
[Service]
|
||||||
Environment='DOCKERD_ROOTLESS_ROOTLESSKIT_NET=slirp4netns'
|
Environment='DOCKERD_ROOTLESS_ROOTLESSKIT_NET=$rootless_net'
|
||||||
Environment='DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=builtin'
|
Environment='DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=$rootless_port_driver'
|
||||||
Environment='DOCKERD_ROOTLESS_ROOTLESSKIT_MTU=$CFG_NETWORK_MTU'
|
Environment='DOCKERD_ROOTLESS_ROOTLESSKIT_MTU=$CFG_NETWORK_MTU'
|
||||||
EOL"
|
EOL"
|
||||||
|
|
||||||
local result=$(sudo chown $CFG_DOCKER_INSTALL_USER:$CFG_DOCKER_INSTALL_USER $override_conf_file)
|
local result=$(sudo chown $CFG_DOCKER_INSTALL_USER:$CFG_DOCKER_INSTALL_USER $override_conf_file)
|
||||||
checkSuccess "Updating ownership for override.conf"
|
checkSuccess "Updating ownership for override.conf"
|
||||||
|
|
||||||
|
# Disable userland-proxy so the kernel/net driver forwards ports directly
|
||||||
|
# and the container sees the real client source IP instead of the
|
||||||
|
# rootlesskit gateway. Merge into any existing daemon.json rather than
|
||||||
|
# clobbering it.
|
||||||
|
docker_cfg_dir="/home/$CFG_DOCKER_INSTALL_USER/.config/docker"
|
||||||
|
daemon_json="$docker_cfg_dir/daemon.json"
|
||||||
|
|
||||||
|
local result=$(sudo -u "$CFG_DOCKER_INSTALL_USER" mkdir -p "$docker_cfg_dir")
|
||||||
|
checkSuccess "Create the rootless docker config directory if it doesn't exist"
|
||||||
|
|
||||||
|
if sudo test -f "$daemon_json"; then
|
||||||
|
local result=$(sudo bash -c "tmp=\$(mktemp) && jq '. + {\"userland-proxy\": false}' '$daemon_json' > \"\$tmp\" && mv \"\$tmp\" '$daemon_json'")
|
||||||
|
checkSuccess "Setting userland-proxy=false in existing daemon.json"
|
||||||
|
else
|
||||||
|
local result=$(sudo bash -c "printf '%s\n' '{\"userland-proxy\": false}' > '$daemon_json'")
|
||||||
|
checkSuccess "Writing rootless daemon.json with userland-proxy=false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local result=$(sudo chown $CFG_DOCKER_INSTALL_USER:$CFG_DOCKER_INSTALL_USER "$daemon_json")
|
||||||
|
checkSuccess "Updating ownership for daemon.json"
|
||||||
|
|
||||||
local result=$(dockerCommandRunInstallUser "systemctl --user daemon-reload")
|
local result=$(dockerCommandRunInstallUser "systemctl --user daemon-reload")
|
||||||
checkSuccess "Reload the systemd user manager configuration"
|
checkSuccess "Reload the systemd user manager configuration"
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user