feat(ipv6): IPv6-Support für HAProxy + Settings-Toggle

- setup.State.IPv6Enabled + Store.SetIPv6Enabled()
- GET/POST /system/ipv6 im SystemHandler; HAProxy-Reload on save
- HAProxy-Template: bind [::]:80, [::]:443, quic6@:443, [::]:3443
  werden nur emittiert wenn IPv6Enabled=true
- haproxy.View.IPv6Enabled aus SetupStore befüllt
- Settings-UI: neues IPv6-Card (zwischen Auto-Update und Passwort)
- i18n de+en ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-23 16:48:26 +02:00
parent 906c2e17a6
commit 4e01b4569c
8 changed files with 128 additions and 2 deletions

View File

@@ -85,6 +85,8 @@ func (h *SystemHandler) Register(rg *gin.RouterGroup) {
g.POST("/render-configs", h.RenderConfigs)
g.POST("/service-restart", h.ServiceRestart)
g.GET("/upgrade-status", h.UpgradeStatus)
g.GET("/ipv6", h.IPv6)
g.POST("/ipv6", h.SetIPv6)
}
// RegisterAgent mountet die read-only System-Endpoints auf der mTLS-
@@ -413,6 +415,42 @@ type dbSizeResponse struct {
Tables []dbSizeTable `json:"top_tables"`
}
func (h *SystemHandler) IPv6(c *gin.Context) {
enabled := false
if h.Setup != nil {
if st, err := h.Setup.Load(); err == nil && st != nil {
enabled = st.IPv6Enabled
}
}
response.OK(c, gin.H{"enabled": enabled})
}
func (h *SystemHandler) SetIPv6(c *gin.Context) {
if h.Setup == nil {
response.Err(c, http.StatusServiceUnavailable, simpleErr("setup not initialised"))
return
}
var req struct {
Enabled bool `json:"enabled"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, err)
return
}
if err := h.Setup.SetIPv6Enabled(req.Enabled); err != nil {
response.BadRequest(c, err)
return
}
if h.HAProxyReloader != nil {
_ = h.HAProxyReloader(c.Request.Context())
}
if h.Audit != nil {
_ = h.Audit.Log(c.Request.Context(), actorOf(c), "system.ipv6",
"", gin.H{"enabled": req.Enabled}, h.NodeID)
}
response.OK(c, gin.H{"enabled": req.Enabled})
}
func (h *SystemHandler) DBSize(c *gin.Context) {
if h.Pool == nil {
response.Err(c, http.StatusServiceUnavailable, simpleErr("db pool unavailable"))