feat: 优化集群部署与堡垒机接入 (#106)

支持受限网络、正向代理、私有 CA 与 SSH 堡垒机部署 Agent。

加固 Docker、systemd、Nginx、安装器、Release 校验与可信代理边界,并完善命令队列索引、前端安装向导及中英文运维文档。
This commit is contained in:
Wu Qing
2026-08-09 02:45:17 +08:00
committed by GitHub
parent 00151e466c
commit 5827074334
86 changed files with 4668 additions and 3082 deletions
+25
View File
@@ -2,6 +2,8 @@ package config
import (
"fmt"
"net"
"net/url"
"strings"
"time"
@@ -21,6 +23,9 @@ type ServerConfig struct {
Port int `mapstructure:"port"`
Mode string `mapstructure:"mode"`
ExternalURL string `mapstructure:"external_url"`
// TrustedProxies 限定可提供 X-Forwarded-For 等头部的反向代理地址。
// 默认仅信任本机代理;空列表表示不信任任何代理头。
TrustedProxies []string `mapstructure:"trusted_proxies"`
// WebRoot 指向前端构建产物目录。留空时后端会按部署惯例自动探测
// ./web、./web/dist、/opt/backupx/web 等)。探测命中后后端直接托管
// 前端 SPA,无需额外的 nginx 反向代理即可访问 Web 控制台。
@@ -91,6 +96,25 @@ func Load(configPath string) (Config, error) {
if cfg.Server.Mode == "" {
cfg.Server.Mode = "release"
}
cfg.Server.ExternalURL = strings.TrimRight(strings.TrimSpace(cfg.Server.ExternalURL), "/")
if cfg.Server.ExternalURL != "" {
externalURL, parseErr := url.Parse(cfg.Server.ExternalURL)
if parseErr != nil || (externalURL.Scheme != "http" && externalURL.Scheme != "https") || externalURL.Host == "" || externalURL.User != nil || externalURL.RawQuery != "" || externalURL.Fragment != "" {
return Config{}, fmt.Errorf("server.external_url must be an absolute http(s) URL without credentials, query or fragment")
}
}
if len(cfg.Server.TrustedProxies) == 1 && strings.Contains(cfg.Server.TrustedProxies[0], ",") {
cfg.Server.TrustedProxies = strings.Split(cfg.Server.TrustedProxies[0], ",")
}
for index := range cfg.Server.TrustedProxies {
proxy := strings.TrimSpace(cfg.Server.TrustedProxies[index])
cfg.Server.TrustedProxies[index] = proxy
if net.ParseIP(proxy) == nil {
if _, _, parseErr := net.ParseCIDR(proxy); parseErr != nil {
return Config{}, fmt.Errorf("server.trusted_proxies contains invalid IP or CIDR %q", proxy)
}
}
}
if cfg.Database.Path == "" {
cfg.Database.Path = "./data/backupx.db"
}
@@ -142,6 +166,7 @@ func applyDefaults(v *viper.Viper) {
v.SetDefault("server.port", 8340)
v.SetDefault("server.mode", "release")
v.SetDefault("server.external_url", "")
v.SetDefault("server.trusted_proxies", []string{"127.0.0.1", "::1"})
v.SetDefault("server.web_root", "")
v.SetDefault("database.path", "./data/backupx.db")
v.SetDefault("security.jwt_expire", "24h")