Skip to content

Commit 0e0c0ea

Browse files
committed
Refine Incus IPv6/sysctl and GPU status
Adjust Incus container setup to avoid unnecessary failures and restarts: only set `kernel.keys.maxkeys` for privileged containers when the host value is below target, and stop forcing NIC `ipv6.address=none` where Incus rejects it on default bridges. Preserve `IPV6_METHOD=disable` during PVE sync so `verb_ip6()` still performs in-container IPv6 shutdown, and update menu output to report GPU passthrough as requested-but-unavailable when no host GPU device nodes exist.
1 parent b0ce148 commit 0e0c0ea

3 files changed

Lines changed: 26 additions & 8 deletions

File tree

incus/backend.func

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,15 @@ incus_create_lxc_container() {
409409
# (e.g. kernel.keys.maxkeys is not writable from an unprivileged user
410410
# namespace), so a plain set can silently persist a config that aborts the
411411
# next boot. Apply best-effort and verify with a self-healing restart below.
412+
# kernel.keys.maxkeys cannot be written from an unprivileged user namespace -
413+
# lxc aborts the start with "Permission denied - Failed to setup sysctl
414+
# parameters kernel.keys.maxkeys to 2000". This was set for CT_TYPE=1, which
415+
# IS the unprivileged case, so every unprivileged create paid a failed start
416+
# plus a rollback to reach the state it would have had anyway. Privileged
417+
# only, and only when the host default is actually below what we want.
412418
local optional_sysctl_pending=0
413-
if [[ "${CT_TYPE:-1}" == "1" ]]; then
419+
if [[ "${CT_TYPE:-1}" == "0" ]] &&
420+
(($(cat /proc/sys/kernel/keys/maxkeys 2>/dev/null || echo 2000) < 2000)); then
414421
if incus config set "${CT_NAME}" linux.sysctl.kernel.keys.maxkeys=2000 >>"$LOGFILE" 2>&1; then
415422
optional_sysctl_pending=1
416423
fi
@@ -462,11 +469,11 @@ incus_create_lxc_container() {
462469
[[ -n "${IPV6_GATE:-}" ]] && { _incus_device_set ipv6.gateway "${IPV6_GATE}" "Could not apply IPv6 gateway" && net_reconfigure=1 || true; }
463470
;;
464471
none | disable)
465-
# Bridges without stateful DHCP / security.ipv6_filtering (e.g. a default
466-
# incusbr0) reject ipv6.address on the NIC — even the value 'none'. The
467-
# actual in-container disable is handled by the sysctl in tools.func, so
468-
# only force a restart if the NIC key was genuinely applied.
469-
_incus_device_set ipv6.address none "Could not disable IPv6 on nic" && net_reconfigure=1 || true
472+
# Incus only accepts ipv6.address=none on a NIC when the bridge has
473+
# security.ipv6_filtering, so on a default incusbr0 this always failed
474+
# and warned about something it does not actually control. verb_ip6() in
475+
# tools.func does the real disabling from inside the container, so leave
476+
# the device alone and save the restart.
470477
;;
471478
esac
472479
else

incus/build.func

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,11 @@ _incus_sync_from_pve_settings() {
280280
case "${IPV6_METHOD:-auto}" in
281281
auto | dhcp) IPV6_ADDR="auto" ;;
282282
static) IPV6_ADDR="${IPV6_ADDR:-}" ;;
283-
none | disable) IPV6_ADDR="none"; IPV6_METHOD="none" ;;
283+
# Keep the method: "none" means do not assign one, "disable" means actively
284+
# turn IPv6 off in the container. Collapsing both to "none" meant verb_ip6()
285+
# in tools.func, which only fires on "disable", never ran on Incus - so
286+
# "disable" left the container with a working IPv6 address.
287+
none | disable) IPV6_ADDR="none" ;;
284288
esac
285289
}
286290

ui/menu.func

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,14 @@ echo_default() {
140140
echo -e "${INFO}${BOLD}${DGN}Architecture: ${BGN}arm64${CL}"
141141
fi
142142
if [[ -n "${var_gpu:-}" && "${var_gpu}" == "yes" ]]; then
143-
echo -e "${GPU}${BOLD}${DGN}GPU Passthrough: ${BGN}Enabled${CL}"
143+
# Say what will actually happen. A host with no DRM or NVIDIA nodes - an
144+
# arm64 board, say - has nothing to pass through, and announcing "Enabled"
145+
# only to report "no GPU devices found" later reads like a failure.
146+
if compgen -G '/dev/dri/*' >/dev/null 2>&1 || compgen -G '/dev/nvidia*' >/dev/null 2>&1; then
147+
echo -e "${GPU}${BOLD}${DGN}GPU Passthrough: ${BGN}Enabled${CL}"
148+
else
149+
echo -e "${GPU}${BOLD}${DGN}GPU Passthrough: ${BGN}Requested - no GPU devices on this host${CL}"
150+
fi
144151
fi
145152
if [ "$VERBOSE" == "yes" ]; then
146153
echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}Enabled${CL}"

0 commit comments

Comments
 (0)