diff --git a/agent/app/service/agents.go b/agent/app/service/agents.go index a95eccc13203..038e500a5e5a 100644 --- a/agent/app/service/agents.go +++ b/agent/app/service/agents.go @@ -26,6 +26,7 @@ import ( "github.com/1Panel-dev/1Panel/agent/utils/cmd" "github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/files" + openclawutil "github.com/1Panel-dev/1Panel/agent/utils/openclaw" "github.com/1Panel-dev/1Panel/agent/utils/req_helper" "github.com/1Panel-dev/1Panel/agent/utils/xpack" ) @@ -77,9 +78,6 @@ const ( maxCommunityAIAgents = int64(5) openclawPluginBaseDir = "/home/node/.openclaw/extensions" openclawGatewayPort = 18789 - openclawCaddyPort = 8443 - openclawCaddyDataPerm = 0777 - openclawCaddyLoopbackAddress = "https://127.0.0.1:8443" openclawAllowedOriginHost = "127.0.0.1" openclawHTTPSVersion = "2026.3.13" openclawTrustedProxyLoopback = "127.0.0.1/32" @@ -901,9 +899,6 @@ func (a AgentService) UpdateSecurityConfig(req dto.AgentSecurityConfigUpdateReq) if err := writeOpenclawConfigRaw(agent.ConfigPath, conf); err != nil { return err } - if err := writeOpenclawCaddyfile(agent.ConfigPath, allowedOrigins); err != nil { - return err - } if err := syncOpenclawAllowedOriginEnv(install, allowedOrigins); err != nil { return err } @@ -1640,6 +1635,9 @@ func migrateOpenclawHTTPSUpgradeWithSystemIP(install *model.AppInstall, fromVers return nil } migrateOpenclawInstallPorts(install) + if err := openclawutil.WriteCatchAllCaddyfile(install.GetPath()); err != nil { + return err + } configPath := path.Join(install.GetPath(), "data", "conf", "openclaw.json") var allowedOrigins []string if conf, err := readOpenclawConfig(configPath); err == nil { @@ -1661,9 +1659,6 @@ func migrateOpenclawHTTPSUpgradeWithSystemIP(install *model.AppInstall, fromVers if err := writeOpenclawConfigRaw(configPath, conf); err != nil { return err } - if err := writeOpenclawCaddyfile(configPath, allowedOrigins); err != nil { - return err - } } } return migrateOpenclawInstallEnv(install, allowedOrigins) @@ -1750,82 +1745,6 @@ func buildOpenclawAllowedOrigin(host string, port int) (string, error) { return normalizeAllowedOrigin(fmt.Sprintf("https://%s:%d", host, port)) } -func writeOpenclawCaddyfile(configPath string, allowedOrigins []string) error { - content, err := buildOpenclawCaddyfile(allowedOrigins) - if err != nil { - return err - } - dataDir := path.Dir(path.Dir(configPath)) - caddyDir := path.Join(dataDir, "caddy") - fileOp := files.NewFileOp() - if !fileOp.Stat(caddyDir) { - if err := fileOp.CreateDir(caddyDir, constant.DirPerm); err != nil { - return err - } - } - caddyDataDir := path.Join(caddyDir, "data") - if !fileOp.Stat(caddyDataDir) { - if err := fileOp.CreateDir(caddyDataDir, constant.DirPerm); err != nil { - return err - } - } - if err := fileOp.ChmodR(caddyDataDir, openclawCaddyDataPerm, false); err != nil { - return err - } - return fileOp.SaveFile(path.Join(caddyDir, "Caddyfile"), content, 0644) -} - -func buildOpenclawCaddyfile(allowedOrigins []string) (string, error) { - if len(allowedOrigins) == 0 { - return "", fmt.Errorf("allowed origins is required") - } - addresses := make([]string, 0, len(allowedOrigins)) - seen := make(map[string]struct{}, len(allowedOrigins)) - for _, origin := range allowedOrigins { - normalized, err := normalizeAllowedOrigin(origin) - if err != nil { - return "", err - } - parsed, err := url.Parse(normalized) - if err != nil { - return "", err - } - host := parsed.Hostname() - if strings.Contains(host, ":") { - host = "[" + host + "]" - } - address := fmt.Sprintf("https://%s:%d", host, openclawCaddyPort) - if _, ok := seen[address]; ok { - continue - } - seen[address] = struct{}{} - addresses = append(addresses, address) - } - if len(addresses) == 0 { - return "", fmt.Errorf("allowed origins is required") - } - if _, ok := seen[openclawCaddyLoopbackAddress]; !ok { - addresses = append(addresses, openclawCaddyLoopbackAddress) - } - content := `{ - admin off - auto_https disable_redirects - default_sni 127.0.0.1 - skip_install_trust - storage file_system { - root /data/caddy - } -} - -` + strings.Join(addresses, ", ") + ` { - bind 0.0.0.0 - tls internal - reverse_proxy 127.0.0.1:` + strconv.Itoa(openclawGatewayPort) + ` -} -` - return content, nil -} - func checkAgentUpgradable(install model.AppInstall) bool { if install.ID == 0 || install.Version == "" || install.Version == "latest" { return false @@ -2145,12 +2064,6 @@ func writeOpenclawConfig(confDir, provider, modelName, apiType string, maxTokens if err := writeOpenclawConfigRaw(configPath, conf); err != nil { return err } - if allowedOrigins != nil { - if err := writeOpenclawCaddyfile(configPath, allowedOrigins); err != nil { - return err - } - } - envPath := path.Join(confDir, ".env") lines := []string{fmt.Sprintf("OPENCLAW_GATEWAY_TOKEN=%s", token)} if envKey := providerEnvKey(provider); envKey != "" && strings.TrimSpace(apiKey) != "" { diff --git a/agent/init/migration/migrate.go b/agent/init/migration/migrate.go index 16b763bcc864..2a6ffd852c36 100644 --- a/agent/init/migration/migrate.go +++ b/agent/init/migration/migrate.go @@ -73,6 +73,7 @@ func InitAgentDB() { migrations.AddAgentTypeForAgents, migrations.NormalizeAgentAccountVerifiedStatus, migrations.NormalizeOllamaAccountAPIType, + migrations.RewriteOpenclawBundledCaddyfile, }) if err := m.Migrate(); err != nil { global.LOG.Error(err) diff --git a/agent/init/migration/migrations/init.go b/agent/init/migration/migrations/init.go index ea83ad1e5710..ca33beb50036 100644 --- a/agent/init/migration/migrations/init.go +++ b/agent/init/migration/migrations/init.go @@ -1095,3 +1095,10 @@ var NormalizeOllamaAccountAPIType = &gormigrate.Migration{ Update("api_type", "openai-responses").Error }, } + +var RewriteOpenclawBundledCaddyfile = &gormigrate.Migration{ + ID: "20260318-rewrite-openclaw-bundled-caddyfile", + Migrate: func(tx *gorm.DB) error { + return migrationutils.RewriteOpenclawBundledCaddyfile(tx) + }, +} diff --git a/agent/init/migration/migrations/utils/openclaw_caddyfile.go b/agent/init/migration/migrations/utils/openclaw_caddyfile.go new file mode 100644 index 000000000000..75079a678063 --- /dev/null +++ b/agent/init/migration/migrations/utils/openclaw_caddyfile.go @@ -0,0 +1,42 @@ +package utils + +import ( + "strings" + + "github.com/1Panel-dev/1Panel/agent/app/model" + "github.com/1Panel-dev/1Panel/agent/constant" + openclawutil "github.com/1Panel-dev/1Panel/agent/utils/openclaw" + + "gorm.io/gorm" +) + +const ( + openclawVersionWithBundledCaddyMigration = "2026.3.13" +) + +func RewriteOpenclawCaddyfileForVersion(tx *gorm.DB, version string) error { + targetVersion := strings.TrimSpace(version) + if targetVersion == "" { + return nil + } + var installs []model.AppInstall + if err := tx.Preload("App").Find(&installs).Error; err != nil { + return err + } + for _, install := range installs { + if install.App.Key != constant.AppOpenclaw { + continue + } + if strings.TrimSpace(install.Version) != targetVersion { + continue + } + if err := openclawutil.WriteCatchAllCaddyfile(install.GetPath()); err != nil { + return err + } + } + return nil +} + +func RewriteOpenclawBundledCaddyfile(tx *gorm.DB) error { + return RewriteOpenclawCaddyfileForVersion(tx, openclawVersionWithBundledCaddyMigration) +} diff --git a/agent/utils/openclaw/caddyfile.go b/agent/utils/openclaw/caddyfile.go new file mode 100644 index 000000000000..3342c03cbf43 --- /dev/null +++ b/agent/utils/openclaw/caddyfile.go @@ -0,0 +1,47 @@ +package openclaw + +import ( + "fmt" + "os" + "path" + + "github.com/1Panel-dev/1Panel/agent/constant" +) + +const ( + gatewayPort = 18789 + caddyPort = 8443 + caddyDataPerm = 0o777 +) + +func BuildCatchAllCaddyfile() string { + return fmt.Sprintf(`{ + admin off + auto_https disable_redirects + skip_install_trust + storage file_system { + root /data/caddy + } +} + +https://:%d { + bind 0.0.0.0 + tls internal { + on_demand + } + reverse_proxy 127.0.0.1:%d +} +`, caddyPort, gatewayPort) +} + +func WriteCatchAllCaddyfile(installPath string) error { + caddyDir := path.Join(installPath, "data", "caddy") + caddyDataDir := path.Join(caddyDir, "data") + if err := os.MkdirAll(caddyDataDir, constant.DirPerm); err != nil { + return err + } + if err := os.Chmod(caddyDataDir, caddyDataPerm); err != nil { + return err + } + return os.WriteFile(path.Join(caddyDir, "Caddyfile"), []byte(BuildCatchAllCaddyfile()), constant.FilePerm) +}