mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-30 08:05:43 +00:00
feat: Modify the OpenClaw upgrade logic. (#12175)
This commit is contained in:
+103
-2
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/xpack/xglobal"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
@@ -28,6 +27,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/req_helper"
|
||||
"github.com/1Panel-dev/1Panel/agent/xpack/xglobal"
|
||||
)
|
||||
|
||||
type AgentService struct{}
|
||||
@@ -80,6 +80,7 @@ const (
|
||||
openclawCaddyPort = 8443
|
||||
openclawCaddyDataPerm = 0777
|
||||
openclawCaddyLoopbackAddress = "https://127.0.0.1:8443"
|
||||
openclawHTTPSVersion = "2026.3.13"
|
||||
openclawTrustedProxyLoopback = "127.0.0.1/32"
|
||||
)
|
||||
|
||||
@@ -1576,7 +1577,11 @@ func buildAgentItem(agent *model.Agent, appInstall *model.AppInstall, envMap map
|
||||
item.Container = appInstall.ContainerName
|
||||
item.AppVersion = appInstall.Version
|
||||
if agentType == constant.AppOpenclaw {
|
||||
item.WebUIPort = appInstall.HttpsPort
|
||||
if isOpenclawHTTPSVersion(appInstall.Version) {
|
||||
item.WebUIPort = appInstall.HttpsPort
|
||||
} else {
|
||||
item.WebUIPort = appInstall.HttpPort
|
||||
}
|
||||
} else {
|
||||
item.WebUIPort = appInstall.HttpPort
|
||||
}
|
||||
@@ -1592,6 +1597,102 @@ func buildAgentItem(agent *model.Agent, appInstall *model.AppInstall, envMap map
|
||||
return item
|
||||
}
|
||||
|
||||
func isOpenclawHTTPSVersion(version string) bool {
|
||||
target := strings.TrimSpace(strings.ToLower(version))
|
||||
if target == "" || target == "latest" {
|
||||
return true
|
||||
}
|
||||
if !strings.ContainsAny(target, "0123456789") {
|
||||
return true
|
||||
}
|
||||
return common.CompareAppVersion(target, openclawHTTPSVersion)
|
||||
}
|
||||
|
||||
func shouldMigrateOpenclawHTTPSUpgrade(install *model.AppInstall, fromVersion, toVersion string) bool {
|
||||
if install == nil || install.App.Key != constant.AppOpenclaw {
|
||||
return false
|
||||
}
|
||||
return !isOpenclawHTTPSVersion(fromVersion) && isOpenclawHTTPSVersion(toVersion)
|
||||
}
|
||||
|
||||
func migrateOpenclawHTTPSUpgrade(install *model.AppInstall, fromVersion, toVersion string) error {
|
||||
systemIP, _ := settingRepo.GetValueByKey("SystemIP")
|
||||
return migrateOpenclawHTTPSUpgradeWithSystemIP(install, fromVersion, toVersion, systemIP)
|
||||
}
|
||||
|
||||
func migrateOpenclawHTTPSUpgradeWithSystemIP(install *model.AppInstall, fromVersion, toVersion, systemIP string) error {
|
||||
if !shouldMigrateOpenclawHTTPSUpgrade(install, fromVersion, toVersion) {
|
||||
return nil
|
||||
}
|
||||
migrateOpenclawInstallPorts(install)
|
||||
if err := migrateOpenclawInstallEnv(install); err != nil {
|
||||
return err
|
||||
}
|
||||
systemIP = strings.TrimSpace(systemIP)
|
||||
if systemIP == "" || install.HttpsPort <= 0 {
|
||||
return nil
|
||||
}
|
||||
allowedOrigin, err := buildOpenclawAllowedOrigin(systemIP, install.HttpsPort)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
configPath := path.Join(install.GetPath(), "data", "conf", "openclaw.json")
|
||||
conf, err := readOpenclawConfig(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
setSecurityConfig(conf, dto.AgentSecurityConfig{AllowedOrigins: []string{allowedOrigin}})
|
||||
if err := writeOpenclawConfigRaw(configPath, conf); err != nil {
|
||||
return err
|
||||
}
|
||||
return writeOpenclawCaddyfile(configPath, []string{allowedOrigin})
|
||||
}
|
||||
|
||||
func migrateOpenclawInstallPorts(install *model.AppInstall) {
|
||||
if install == nil {
|
||||
return
|
||||
}
|
||||
if install.HttpsPort == 0 && install.HttpPort > 0 {
|
||||
install.HttpsPort = install.HttpPort
|
||||
}
|
||||
if install.HttpPort > 0 {
|
||||
install.HttpPort = 0
|
||||
}
|
||||
}
|
||||
|
||||
func migrateOpenclawInstallEnv(install *model.AppInstall) error {
|
||||
if install == nil {
|
||||
return nil
|
||||
}
|
||||
envMap := make(map[string]interface{})
|
||||
if strings.TrimSpace(install.Env) != "" {
|
||||
if err := json.Unmarshal([]byte(install.Env), &envMap); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if install.HttpsPort > 0 {
|
||||
envMap["PANEL_APP_PORT_HTTPS"] = install.HttpsPort
|
||||
}
|
||||
delete(envMap, "PANEL_APP_PORT_HTTP")
|
||||
payload, err := json.Marshal(envMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
install.Env = string(payload)
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildOpenclawAllowedOrigin(host string, port int) (string, error) {
|
||||
host = strings.TrimSpace(host)
|
||||
if host == "" || port <= 0 {
|
||||
return "", fmt.Errorf("invalid openclaw allowed origin")
|
||||
}
|
||||
if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") && strings.Count(host, ":") > 1 {
|
||||
host = "[" + host + "]"
|
||||
}
|
||||
return normalizeAllowedOrigin(fmt.Sprintf("https://%s:%d", host, port))
|
||||
}
|
||||
|
||||
func writeOpenclawCaddyfile(configPath string, allowedOrigins []string) error {
|
||||
content, err := buildOpenclawCaddyfile(allowedOrigins)
|
||||
if err != nil {
|
||||
|
||||
@@ -675,6 +675,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldVersion := install.Version
|
||||
detail, err := appDetailRepo.GetFirst(repo.WithByID(req.DetailID))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -801,6 +802,9 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
}
|
||||
|
||||
var newCompose string
|
||||
if err = migrateOpenclawHTTPSUpgrade(&install, oldVersion, detail.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
if req.DockerCompose == "" {
|
||||
newCompose, err = getUpgradeCompose(install, detail)
|
||||
if err != nil {
|
||||
|
||||
@@ -2419,6 +2419,12 @@ const message = {
|
||||
reload: 'Reload',
|
||||
upgradeWarn:
|
||||
'Upgrading the application will replace the docker-compose.yml file. If there are any changes, you can click to view the file comparison',
|
||||
openclawHttpsUpgradeNoticeTitle:
|
||||
'Note: The following instructions only apply to users upgrading OpenClaw from versions earlier than 2026.3.13:',
|
||||
openclawHttpsUpgradeNoticeItem1:
|
||||
'After the deployed agent is upgraded, go to Configuration -> Settings -> Security and manually add the access address.',
|
||||
openclawHttpsUpgradeNoticeItem2:
|
||||
'The new version now requires HTTPS to access the agent. If you previously used a reverse proxy website, change the proxy target to https://IP:Port.',
|
||||
newVersion: 'New version',
|
||||
oldVersion: 'Current version',
|
||||
composeDiff: 'File comparison',
|
||||
|
||||
@@ -2464,6 +2464,12 @@ const message = {
|
||||
showLocal: 'Mostrar apps locales',
|
||||
reload: 'Recargar',
|
||||
upgradeWarn: 'Actualizar reemplazará docker-compose.yml. Si hay cambios, puede ver la comparación.',
|
||||
openclawHttpsUpgradeNoticeTitle:
|
||||
'Nota: Las siguientes instrucciones solo se aplican a los usuarios que actualizan OpenClaw desde versiones anteriores a 2026.3.13:',
|
||||
openclawHttpsUpgradeNoticeItem1:
|
||||
'Después de actualizar el agente desplegado, vaya a Configuración -> Ajustes -> Seguridad y agregue manualmente la dirección de acceso.',
|
||||
openclawHttpsUpgradeNoticeItem2:
|
||||
'La nueva versión exige HTTPS para acceder al agente. Si antes usaba un sitio con proxy inverso, cambie el destino del proxy a https://IP:Port.',
|
||||
newVersion: 'Nueva versión',
|
||||
oldVersion: 'Versión actual',
|
||||
composeDiff: 'Comparación de archivos',
|
||||
|
||||
@@ -2439,6 +2439,12 @@ const message = {
|
||||
reload: 'リロード',
|
||||
upgradeWarn:
|
||||
'アプリケーションのアップグレードは、docker-compose.ymlファイルを置き換えます。変更がある場合は、クリックしてファイルの比較を表示できます',
|
||||
openclawHttpsUpgradeNoticeTitle:
|
||||
'注意: 以下の説明は、2026.3.13 より前のバージョンから OpenClaw をアップグレードするユーザーにのみ適用されます:',
|
||||
openclawHttpsUpgradeNoticeItem1:
|
||||
'デプロイ済みエージェントのアップグレード完了後、設定 -> 設定 -> セキュリティ に入り、アクセスアドレスを手動で追加してください。',
|
||||
openclawHttpsUpgradeNoticeItem2:
|
||||
'新バージョンではエージェントへのアクセスに HTTPS が必須です。以前リバースプロキシサイト経由でアクセスしていた場合は、プロキシ先を https://IP:Port に変更してください。',
|
||||
newVersion: '新しいバージョン',
|
||||
oldVersion: '現在のバージョン',
|
||||
composeDiff: 'ファイルの比較',
|
||||
|
||||
@@ -2382,6 +2382,12 @@ const message = {
|
||||
reload: '새로고침',
|
||||
upgradeWarn:
|
||||
'애플리케이션 업그레이드는 docker-compose.yml 파일을 교체합니다. 변경 사항이 있으면 파일 비교를 클릭하여 확인할 수 있습니다.',
|
||||
openclawHttpsUpgradeNoticeTitle:
|
||||
'주의: 다음 안내는 2026.3.13 이전 버전에서 OpenClaw 를 업그레이드하는 사용자에게만 적용됩니다:',
|
||||
openclawHttpsUpgradeNoticeItem1:
|
||||
'배포된 에이전트 업그레이드가 완료되면 구성 -> 설정 -> 보안 페이지로 이동해 접근 주소를 수동으로 추가해야 합니다.',
|
||||
openclawHttpsUpgradeNoticeItem2:
|
||||
'새 버전은 에이전트 접근에 HTTPS 를 강제합니다. 이전에 리버스 프록시 사이트로 접근했다면 프록시 대상 주소를 https://IP:Port 로 변경하세요.',
|
||||
newVersion: '새 버전',
|
||||
oldVersion: '현재 버전',
|
||||
composeDiff: '파일 비교',
|
||||
|
||||
@@ -2469,6 +2469,12 @@ const message = {
|
||||
showLocal: 'Papar aplikasi tempatan',
|
||||
reload: 'Muat Semula',
|
||||
upgradeWarn: 'Meningkatkan aplikasi akan menggantikan fail docker-compose.yml.',
|
||||
openclawHttpsUpgradeNoticeTitle:
|
||||
'Nota: Arahan berikut hanya terpakai kepada pengguna yang menaik taraf OpenClaw daripada versi lebih awal daripada 2026.3.13:',
|
||||
openclawHttpsUpgradeNoticeItem1:
|
||||
'Selepas ejen yang telah dipasang selesai dinaik taraf, pergi ke Konfigurasi -> Tetapan -> Keselamatan dan tambah alamat akses secara manual.',
|
||||
openclawHttpsUpgradeNoticeItem2:
|
||||
'Versi baharu kini mewajibkan HTTPS untuk mengakses ejen. Jika anda sebelum ini menggunakan laman reverse proxy, tukar alamat sasaran proksi kepada https://IP:Port.',
|
||||
newVersion: 'Versi baru',
|
||||
oldVersion: 'Versi semasa',
|
||||
composeDiff: 'Perbandingan fail',
|
||||
|
||||
@@ -2600,6 +2600,12 @@ const message = {
|
||||
reload: 'Recarregar',
|
||||
upgradeWarn:
|
||||
'Atualizar o aplicativo substituirá o arquivo docker-compose.yml. Se houver alterações, você pode clicar para visualizar a comparação do arquivo',
|
||||
openclawHttpsUpgradeNoticeTitle:
|
||||
'Nota: As instruções a seguir se aplicam apenas a usuários que estão atualizando o OpenClaw de versões anteriores à 2026.3.13:',
|
||||
openclawHttpsUpgradeNoticeItem1:
|
||||
'Depois que o agente implantado for atualizado, vá para Configuração -> Ajustes -> Segurança e adicione manualmente o endereço de acesso.',
|
||||
openclawHttpsUpgradeNoticeItem2:
|
||||
'A nova versão agora exige HTTPS para acessar o agente. Se você usava um site com proxy reverso, altere o destino do proxy para https://IP:Port.',
|
||||
newVersion: 'Nova versão',
|
||||
oldVersion: 'Versão atual',
|
||||
composeDiff: 'Comparação de arquivo',
|
||||
|
||||
@@ -2464,6 +2464,12 @@ const message = {
|
||||
reload: 'Перезагрузить',
|
||||
upgradeWarn:
|
||||
'Обновление приложения заменит файл docker-compose.yml. Если есть изменения, вы можете нажать для просмотра сравнения файлов',
|
||||
openclawHttpsUpgradeNoticeTitle:
|
||||
'Примечание: Следующие инструкции применяются только к пользователям, обновляющим OpenClaw с версий ниже 2026.3.13:',
|
||||
openclawHttpsUpgradeNoticeItem1:
|
||||
'После завершения обновления развернутого агента перейдите в Конфигурация -> Настройки -> Безопасность и вручную добавьте адрес доступа.',
|
||||
openclawHttpsUpgradeNoticeItem2:
|
||||
'Новая версия теперь требует HTTPS для доступа к агенту. Если раньше использовался сайт с обратным прокси, измените адрес назначения прокси на https://IP:Port.',
|
||||
newVersion: 'Новая версия',
|
||||
oldVersion: 'Текущая версия',
|
||||
composeDiff: 'Сравнение файлов',
|
||||
|
||||
@@ -2464,6 +2464,12 @@ const message = {
|
||||
reload: 'Yeniden yükle',
|
||||
upgradeWarn:
|
||||
'Uygulamanın yükseltilmesi docker-compose.yml dosyasını değiştirecektir. Herhangi bir değişiklik varsa, dosya karşılaştırmasını görüntülemek için tıklayabilirsiniz',
|
||||
openclawHttpsUpgradeNoticeTitle:
|
||||
"Not: Aşağıdaki talimatlar yalnızca OpenClaw'ı 2026.3.13 öncesi sürümlerden yükselten kullanıcılar için geçerlidir:",
|
||||
openclawHttpsUpgradeNoticeItem1:
|
||||
'Dağıtılmış ajan yükseltmesi tamamlandıktan sonra Yapılandırma -> Ayarlar -> Güvenlik sayfasına gidip erişim adresini manuel olarak ekleyin.',
|
||||
openclawHttpsUpgradeNoticeItem2:
|
||||
'Yeni sürüm artık ajana erişim için HTTPS zorunlu kılıyor. Daha önce ters proxy sitesi kullanıyorsanız proxy hedef adresini https://IP:Port olarak değiştirin.',
|
||||
newVersion: 'Yeni sürüm',
|
||||
oldVersion: 'Mevcut sürüm',
|
||||
composeDiff: 'Dosya karşılaştırması',
|
||||
|
||||
@@ -2246,6 +2246,10 @@ const message = {
|
||||
showLocal: '顯示本機應用程式',
|
||||
reload: '重載',
|
||||
upgradeWarn: '升級應用程式會取代 docker-compose.yml 檔案,如有更改,可以點選檢視檔案對比',
|
||||
openclawHttpsUpgradeNoticeTitle: '注意:以下說明僅適用於 OpenClaw 從 2026.3.13 之前版本升級的使用者:',
|
||||
openclawHttpsUpgradeNoticeItem1: '已部署的智慧體升級完成後,需要進入 配置 → 設定 → 安全 頁面手動新增存取地址。',
|
||||
openclawHttpsUpgradeNoticeItem2:
|
||||
'新版本已強制使用 HTTPS 存取智慧體。如果之前透過反向代理網站存取,請將代理目標地址修改為 https://IP:Port。',
|
||||
newVersion: '新版本',
|
||||
oldVersion: '當前版本',
|
||||
composeDiff: '檔案對比',
|
||||
|
||||
@@ -2250,6 +2250,10 @@ const message = {
|
||||
showLocal: '本地应用',
|
||||
reload: '重载',
|
||||
upgradeWarn: '升级应用会替换 docker-compose.yml 文件,如有更改,可以点击查看文件对比',
|
||||
openclawHttpsUpgradeNoticeTitle: '注意:以下说明仅适用于 OpenClaw 从 2026.3.13 之前版本升级的用户:',
|
||||
openclawHttpsUpgradeNoticeItem1: '已部署的智能体升级完成后,需要进入 配置 → 设置 → 安全 页面手动添加访问地址。',
|
||||
openclawHttpsUpgradeNoticeItem2:
|
||||
'新版本已强制使用 HTTPS 访问智能体。如果之前通过反向代理网站访问,请将代理目标地址修改为 https://IP:Port。',
|
||||
newVersion: '新版本',
|
||||
oldVersion: '当前版本',
|
||||
composeDiff: '文件对比',
|
||||
|
||||
@@ -327,7 +327,7 @@ const isOpenClawHttpsVersion = (version: string) => {
|
||||
if (!/\d/.test(target)) {
|
||||
return true;
|
||||
}
|
||||
return compareVersion(target, '2026.3.12');
|
||||
return compareVersion(target, '2026.3.13');
|
||||
};
|
||||
|
||||
const jumpWebUI = (row: AI.AgentItem) => {
|
||||
|
||||
@@ -42,6 +42,19 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-alert
|
||||
v-if="showOpenclawHttpsUpgradeNotice"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="upgrade-notice"
|
||||
>
|
||||
<template #title>{{ $t('app.openclawHttpsUpgradeNoticeTitle') }}</template>
|
||||
<div class="upgrade-notice-content">
|
||||
<div>1. {{ $t('app.openclawHttpsUpgradeNoticeItem1') }}</div>
|
||||
<div>2. {{ $t('app.openclawHttpsUpgradeNoticeItem2') }}</div>
|
||||
</div>
|
||||
</el-alert>
|
||||
<el-form-item prop="backup" v-if="operateReq.operate === 'upgrade'">
|
||||
<el-checkbox v-model="operateReq.backup" :label="$t('app.backupApp')" />
|
||||
<span class="input-help">
|
||||
@@ -86,15 +99,17 @@ import CodemirrorPro from '@/components/codemirror-pro/index.vue';
|
||||
import { App } from '@/api/interface/app';
|
||||
import { getAppUpdateVersions, ignoreUpgrade, installedOp } from '@/api/modules/app';
|
||||
import { getAppStoreConfig } from '@/api/modules/setting';
|
||||
import { compareVersion } from '@/utils/version';
|
||||
import i18n from '@/lang';
|
||||
import { ElMessageBox, FormInstance } from 'element-plus';
|
||||
import { reactive, ref, onBeforeUnmount } from 'vue';
|
||||
import { computed, onBeforeUnmount, reactive, ref } from 'vue';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import bus from '@/global/bus';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
const { currentNode } = useGlobalStore();
|
||||
const openclawHttpsVersion = '2026.3.13';
|
||||
|
||||
const composeDiffRef = ref();
|
||||
const updateRef = ref<FormInstance>();
|
||||
@@ -135,6 +150,40 @@ const ignoreAppReq = reactive({
|
||||
});
|
||||
const isEdit = ref(false);
|
||||
const node = ref('');
|
||||
const currentVersion = ref('');
|
||||
const currentAppKey = ref('');
|
||||
|
||||
const isOpenclawHttpsVersion = (version: string) => {
|
||||
const target = String(version || '')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
if (!target || target === 'latest') {
|
||||
return true;
|
||||
}
|
||||
if (!/\d/.test(target)) {
|
||||
return false;
|
||||
}
|
||||
return compareVersion(target, openclawHttpsVersion);
|
||||
};
|
||||
|
||||
const isLegacyOpenclawVersion = (version: string) => {
|
||||
const target = String(version || '')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
if (!target || target === 'latest' || !/\d/.test(target)) {
|
||||
return false;
|
||||
}
|
||||
return !compareVersion(target, openclawHttpsVersion);
|
||||
};
|
||||
|
||||
const showOpenclawHttpsUpgradeNotice = computed(() => {
|
||||
return (
|
||||
operateReq.operate === 'upgrade' &&
|
||||
currentAppKey.value === 'openclaw' &&
|
||||
isLegacyOpenclawVersion(currentVersion.value) &&
|
||||
isOpenclawHttpsVersion(operateReq.version)
|
||||
);
|
||||
});
|
||||
|
||||
const toLink = (link: string) => {
|
||||
window.open(link, '_blank');
|
||||
@@ -174,6 +223,8 @@ const acceptParams = (appInstall: App.AppInstallDto, op: string, opNode?: string
|
||||
node.value = currentNode.value;
|
||||
}
|
||||
isEdit.value = appInstall.isEdit;
|
||||
currentVersion.value = appInstall.version;
|
||||
currentAppKey.value = appInstall.appKey;
|
||||
operateReq.installId = appInstall.id;
|
||||
operateReq.operate = op;
|
||||
resourceName.value = appInstall.name;
|
||||
@@ -268,3 +319,13 @@ defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.upgrade-notice {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.upgrade-notice-content {
|
||||
line-height: 1.8;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user