The panel now fronts user domains with HAProxy 3.4 LTS (official performance packages) instead of Traefik: about 100 MB of RSS and 200 MB of disk saved for a feature set that never used more than Host routing on :80 and SNI passthrough on :443. - hpx: publish the proxy configuration as immutable GENERATIONS. Every domain mutation renders the whole set from the DB, validates it with the pinned `haproxy -c`, and only then repoints the `current` symlink, so a rejected candidate leaves the running proxy untouched and a stale domain can never survive into a later generation. Routing is carried by two map files (Host -> backend, SNI -> backend): per-domain frontend rules cannot work from a second file because HAProxy rejects duplicate section names since 3.3 and attaches bare directives to the section opened last. - mgr: republish and reload (SIGUSR2, i.e. `systemctl reload`) after every domain change, so a change takes effect without dropping established HTTP or TLS connections. Rollback semantics (DB first, then publish) are unchanged. - cfg,db: `net.traefik` is renamed to `net.haproxy` with identical values. A pre-rename config.yaml key and the legacy VPSMGR_TRAEFIK env var are still read (new name wins), and schema migration v18 moves the settings mirror from `traefik` to `haproxy`, keeping a newer value when both rows exist. - 30-haproxy.sh: install the pinned branch from the vendor repository and migrate a Traefik host in one run — install and validate HAProxy first, then remove Traefik's binary, unit, service account and dynamic rules (only its config file is kept, inert). No fallback keeps both proxies alive. - upgrade-haproxy.sh: follow the pinned branch to its newest patch, with a configuration check and a graceful reload; `install.sh --update` runs it. - tests: generation publish/rollback, map rendering, config-key and settings migrations, plus real-binary tests (skipped unless VPSMGR_TEST_HAPROXY_BIN is set) that run the generated configuration through `haproxy -c` and start it in a network namespace. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
53 lines
2.2 KiB
Bash
Executable File
53 lines
2.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# 20-network.sh — sysctl + nftables basics.
|
|
set -uo pipefail
|
|
|
|
log(){ echo "[20] $*"; }
|
|
|
|
# ip_forward + BBR/fq TCP tuning + io_uring attack-surface clamp. Written every
|
|
# run (idempotent). io_uring_disabled=1 lets only init-userns CAP_SYS_ADMIN (the
|
|
# host's own root services) create io_uring; container tenants — even container
|
|
# root, which only has userns-scoped caps — get EPERM, closing the biggest
|
|
# kernel LPE attack surface for tenants. Value 1, not 2: the host stack (Incus,
|
|
# ZFS, Go panel/HAProxy) is untouched. Matches RHEL 9.3+'s shipped default.
|
|
cat > /etc/sysctl.d/99-vpsmgr.conf <<EOF
|
|
# Managed by vpsmgr — generated file, do not edit by hand.
|
|
# Changes are overwritten on the next install.
|
|
net.ipv4.ip_forward=1
|
|
net.core.default_qdisc=fq
|
|
net.ipv4.tcp_congestion_control=bbr
|
|
kernel.io_uring_disabled=1
|
|
net.ipv6.conf.all.use_tempaddr = 0
|
|
net.ipv6.conf.default.use_tempaddr = 0
|
|
net.core.netdev_max_backlog = 8192
|
|
net.core.rmem_default = 262144
|
|
net.core.wmem_default = 262144
|
|
net.ipv4.tcp_rmem = 8192 262144 4194304
|
|
net.ipv4.tcp_wmem = 4096 16384 4194304
|
|
net.core.rmem_max = 4194304
|
|
net.core.wmem_max = 4194304
|
|
net.ipv4.tcp_window_scaling = 1
|
|
net.ipv4.tcp_slow_start_after_idle = 0
|
|
EOF
|
|
# IPv6 pass-through: forwarding must be on so the host relays container v6.
|
|
if [[ -n "${VPSMGR_IPV6_SUBNET:-}" ]]; then
|
|
cat >> /etc/sysctl.d/99-vpsmgr.conf <<'EOF'
|
|
net.ipv6.conf.all.forwarding=1
|
|
net.ipv6.conf.default.forwarding=1
|
|
EOF
|
|
fi
|
|
log "wrote /etc/sysctl.d/99-vpsmgr.conf (ip_forward + bbr/fq + io_uring_disabled${VPSMGR_IPV6_SUBNET:+ + ipv6 forwarding})"
|
|
SYSCTL_ARGS=(net.ipv4.ip_forward=1 net.core.default_qdisc=fq net.ipv4.tcp_congestion_control=bbr kernel.io_uring_disabled=1)
|
|
[[ -n "${VPSMGR_IPV6_SUBNET:-}" ]] && SYSCTL_ARGS+=(net.ipv6.conf.all.forwarding=1)
|
|
if ! sysctl -q -w "${SYSCTL_ARGS[@]}" 2>/dev/null; then
|
|
log "warn: live sysctl apply failed (e.g. kernel too old for bbr/io_uring_disabled); config persisted and will apply on reboot"
|
|
fi
|
|
log "tcp congestion: $(sysctl -n net.ipv4.tcp_congestion_control 2>/dev/null || echo 'n/a')"
|
|
|
|
if ! dpkg -s nftables >/dev/null 2>&1; then
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq nftables
|
|
fi
|
|
log "nftables: $(nft --version 2>/dev/null | head -1)"
|
|
|
|
echo "[20] network ready"
|