Remove secondary-disk discovery and whole-disk ZFS creation from the
installer. New installations now always create a sparse ZFS loop-file
pool from free space on /, while existing vpsmgr pools are still adopted.
The installer no longer scans, selects, formats, or modifies devices such
as /dev/vdb, including virtual ISO/CD devices.
Update storage documentation and keep the existing reclaim, pool sizing,
and ZFS quota behavior.
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
- net.ipv6_pool is now operator-editable (was immutable): accept bare
addresses or explicit /128 (any other prefix length rejected), stored
normalized to the bare form.
- New admin "IPv6 Pool" page (visible in pool mode): multi-line
batch-add box, list with per-address state (free / used + owner), and
remove for free addresses (assigned ones are refused — a user keeps
its address for life).
- Adding addresses re-applies the host plumbing so any address the
provider bound on the external interface is detached immediately.
- mgr: AddPoolIPv6s / RemovePoolIPv6 / PoolList / PoolEntries with tests.
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
Empirically this is what makes discrete whitelist addresses work:
- The provider binds every address on the host's NIC at boot; while the
host holds an address the kernel treats it as LOCAL and drops the
container's packets using it as a source (source-address validation),
so outbound v6 silently fails. Pool mode now removes each pool address
from the external interface (vps ip6 addr-del), on add/reinstall and
every ipv6-reapply/boot — self-healing after a reboot re-binds them.
- Containers get TWO NICs: eth0 = nictype routed on the external
interface with ipv6.address=<pool /128> (Incus programs the /128 route
+ proxy_ndp + fe80::1 gateway), eth1 = bridged on incusbr0 for the
shared IPv4. systemd-networkd binds the /128 statically on eth0 and
DHCPv4s on eth1.
- The manual bridge /128-route + proxy_ndp plumbing (SetupIPv6BridgePool,
WireIPv6Pool route/neigh) is gone — Incus programs everything.
Verified end-to-end on the whitelist host: container reaches out over v6
(curl -6 returns its own /128) and v4 (eth1 NAT) simultaneously, external
Globalping hits the container /128 with 0% loss, delete releases the
address and a new container reuses it.
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
Pool mode adds a create-user dropdown (auto first-free / a specific free
address / no IPv6) and an IPv6 column in the user table. Docs cover the
two modes, the installer flow, and the empirically verified per-address
routing.
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
The UI already speaks "bandwidth"; the internals still said "traffic"
for the same concept (monthly quota, NIC counters, throttling). Align
the whole stack:
- db: table `traffic` -> `bandwidth`, column `traffic_quota_gb` ->
`bandwidth_quota_gb` (fresh schema, no migration needed)
- lx: `Traffic`/`TrafficMap` -> `Bandwidth`/`BandwidthMap`
- mgr: `SampleTraffic`/`TrafficFor`/`EnforceTrafficLimits`/
`ParseTrafficGB`/`UpdateQuotasAndTraffic` -> bandwidth equivalents
- panel/admin/main: template fields, form names, CLI flags and vars
- docs and AGENTS.md updated; ordinary English uses of "traffic"
(forwarded traffic, inter-container traffic) are kept
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
The Incus line is a new project, not an upgrade path — remove every
piece of cross-version compatibility:
- version gate: ver.Blocked/MinAdoptable/SemVerLT, blockUnadoptable,
cmdNoteVersion, the installed_version/uninstalled_version config
fields and registry entries, install.sh old-binary detection and the
uninstall note-version call.
- DB migrations for pre-0.3 schemas: migrateAuditTargetDrop,
migrateUserColumns, migrateDomainColumns, migrateCPU and their tests.
- legacy admin-pass migration from config.yaml into the DB.
- duplicate static sudoers file (configs/sudoers.d/vps) — the Go
ensureSudoers embedded copy is the only source.
- docs swept of version-gate and 0.2.x/0.3.x language.
Also rename the bridge lxdbr0 -> incusbr0 across code, scripts, config
and docs, and adapt NIC isolation to Incus 7.0 validation: ipv6_filtering
is only applied when the eth0 device actually carries an IPv6 address or
route (Incus rejects it on a v6-less device, unlike LXD).
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
The panel now talks to Incus over its Unix socket REST API
(/var/lib/incus/unix.socket, group incus-admin) exclusively:
- internal/lx: exec moved from the `lxc` CLI to the API websocket
transport (Exec/ExecSH/RunInitScript); EnsureImage pulls a
remote-qualified fallback (images:debian/13) before Launch since the
API cannot auto-fetch it inside the create call; per-container df
probe in mgr/batch.go uses the same API path.
- cfg: config key renamed lxd.* -> incus.* (image, image_fallback,
pool, bridge, socket); DefaultSocket is the Debian-package path.
- mgr: container disk probe and image handling updated; comment sweep
from LXD to Incus.
- deps: add gorilla/websocket for the exec transport.
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>