Quellcode durchsuchen

refactor(preference): show more settings

Jacky vor 6 Monaten
Ursprung
Commit
a0c005f314

+ 40 - 8
api/settings/settings.go

@@ -1,6 +1,7 @@
 package settings
 
 import (
+	"fmt"
 	"github.com/0xJacky/Nginx-UI/api"
 	"github.com/0xJacky/Nginx-UI/internal/cron"
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
@@ -19,22 +20,52 @@ func GetServerName(c *gin.Context) {
 func GetSettings(c *gin.Context) {
 	settings.NginxSettings.AccessLogPath = nginx.GetAccessLogPath()
 	settings.NginxSettings.ErrorLogPath = nginx.GetErrorLogPath()
+	settings.NginxSettings.ConfigDir = nginx.GetConfPath()
+	settings.NginxSettings.PIDPath = nginx.GetPIDPath()
+
+	if settings.NginxSettings.ReloadCmd == "" {
+		settings.NginxSettings.ReloadCmd = "nginx -s reload"
+	}
+
+	if settings.NginxSettings.RestartCmd == "" {
+		pidPath := nginx.GetPIDPath()
+		daemon := nginx.GetSbinPath()
+		if daemon == "" {
+			settings.NginxSettings.RestartCmd =
+				fmt.Sprintf("start-stop-daemon --stop --quiet --oknodo --retry=TERM/30/KILL/5"+
+					" --pidfile %s && nginx", pidPath)
+			return
+		}
+
+		settings.NginxSettings.RestartCmd =
+			fmt.Sprintf("start-stop-daemon --start --quiet --pidfile %s --exec %s", pidPath, daemon)
+	}
+
 	c.JSON(http.StatusOK, gin.H{
+		"app":       cSettings.AppSettings,
 		"server":    cSettings.ServerSettings,
+		"database":  settings.DatabaseSettings,
+		"auth":      settings.AuthSettings,
+		"casdoor":   settings.CasdoorSettings,
+		"cert":      settings.CertSettings,
+		"http":      settings.HTTPSettings,
+		"logrotate": settings.LogrotateSettings,
 		"nginx":     settings.NginxSettings,
+		"node":      settings.NodeSettings,
 		"openai":    settings.OpenAISettings,
-		"logrotate": settings.LogrotateSettings,
-		"auth":      settings.AuthSettings,
+		"terminal":  settings.TerminalSettings,
+		"webauthn":  settings.WebAuthnSettings,
 	})
 }
 
 func SaveSettings(c *gin.Context) {
 	var json struct {
-		Server    cSettings.Server   `json:"server"`
-		Nginx     settings.Nginx     `json:"nginx"`
+		Auth      settings.Auth      `json:"auth"`
+		Cert      settings.Cert      `json:"cert"`
+		Http      settings.HTTP      `json:"http"`
+		Node      settings.Node      `json:"node"`
 		Openai    settings.OpenAI    `json:"openai"`
 		Logrotate settings.Logrotate `json:"logrotate"`
-		Auth      settings.Auth      `json:"auth"`
 	}
 
 	if !api.BindAndValid(c, &json) {
@@ -46,11 +77,12 @@ func SaveSettings(c *gin.Context) {
 		go cron.RestartLogrotate()
 	}
 
-	cSettings.ProtectedFill(cSettings.ServerSettings, &json.Server)
-	cSettings.ProtectedFill(settings.NginxSettings, &json.Nginx)
+	cSettings.ProtectedFill(settings.AuthSettings, &json.Auth)
+	cSettings.ProtectedFill(settings.CertSettings, &json.Cert)
+	cSettings.ProtectedFill(settings.HTTPSettings, &json.Http)
+	cSettings.ProtectedFill(settings.NodeSettings, &json.Node)
 	cSettings.ProtectedFill(settings.OpenAISettings, &json.Openai)
 	cSettings.ProtectedFill(settings.LogrotateSettings, &json.Logrotate)
-	cSettings.ProtectedFill(settings.AuthSettings, &json.Auth)
 
 	err := settings.Save()
 	if err != nil {

+ 100 - 2
app/src/api/settings.ts

@@ -1,16 +1,114 @@
 import http from '@/lib/http'
 
+export interface AppSettings {
+  page_size: number
+  jwt_secret: string
+}
+
+export interface ServerSettings {
+  host: string
+  port: number
+  run_mode: 'debug' | 'release'
+}
+
+export interface DatabaseSettings {
+  name: string
+}
+
+export interface AuthSettings {
+  ip_white_list: string[]
+  ban_threshold_minutes: number
+  max_attempts: number
+}
+
+export interface CasdoorSettings {
+  endpoint: string
+  client_id: string
+  client_secret: string
+  certificate_path: string
+  organization: string
+  application: string
+  redirect_uri: string
+}
+
+export interface CertSettings {
+  email: string
+  ca_dir: string
+  renewal_interval: number
+  recursive_nameservers: string[]
+  http_challenge_port: string
+}
+
+export interface HTTPSettings {
+  github_proxy: string
+  insecure_skip_verify: boolean
+}
+
+export interface LogrotateSettings {
+  enabled: boolean
+  cmd: string
+  interval: number
+}
+
+export interface NginxSettings {
+  access_log_path: string
+  error_log_path: string
+  config_dir: string
+  log_dir_white_list: string[]
+  pid_path: string
+  reload_cmd: string
+  restart_cmd: string
+}
+
+export interface NodeSettings {
+  name: string
+  secret: string
+}
+
+export interface OpenaiSettings {
+  model: string
+  base_url: string
+  proxy: string
+  token: string
+}
+
+export interface TerminalSettings {
+  start_cmd: string
+}
+
+export interface WebauthnSettings {
+  rp_display_name: string
+  rpid: string
+  rp_origins: string[]
+}
+
 export interface BannedIP {
   ip: string
   attempts: number
   expired_at: string
 }
 
+export interface Settings {
+  app: AppSettings
+  server: ServerSettings
+  database: DatabaseSettings
+  auth: AuthSettings
+  casdoor: CasdoorSettings
+  cert: CertSettings
+  http: HTTPSettings
+  logrotate: LogrotateSettings
+  nginx: NginxSettings
+  node: NodeSettings
+  openai: OpenaiSettings
+  terminal: TerminalSettings
+  webauthn: WebauthnSettings
+}
+
 const settings = {
-  get<T>(): Promise<T> {
+  get(): Promise<Settings> {
     return http.get('/settings')
   },
-  save<T>(data: T) {
+  save(data: Settings) {
     return http.post('/settings', data)
   },
   get_server_name(): Promise<{ name: string }> {

+ 43 - 9
app/src/views/preference/AuthSettings.vue

@@ -3,10 +3,9 @@ import { message } from 'ant-design-vue'
 import type { Ref } from 'vue'
 import dayjs from 'dayjs'
 import PasskeyRegistration from './components/Passkey.vue'
-import type { BannedIP } from '@/api/settings'
+import type { BannedIP, Settings } from '@/api/settings'
 import setting from '@/api/settings'
 import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
-import type { Settings } from '@/views/preference/typedef'
 import TOTP from '@/views/preference/components/TOTP.vue'
 
 const data: Settings = inject('data') as Settings
@@ -62,13 +61,41 @@ function removeBannedIP(ip: string) {
       <h2>
         {{ $gettext('Authentication Settings') }}
       </h2>
-      <AAlert
+      <div
+        v-if="data.webauthn.rpid
+          && data.webauthn.rp_display_name
+          && data.webauthn.rp_origins?.length > 0"
         class="mb-4"
-        :message="$gettext('Tips')"
-        :description="$gettext('If the number of login failed attempts from a ip reach the max attempts in ban threshold minutes,'
-          + ' the ip will be banned for a period of time.')"
-        type="info"
-      />
+      >
+        <h3>
+          {{ $gettext('Webauthn') }}
+        </h3>
+        <div class="mb-4">
+          <h4>
+            {{ $gettext('RPID') }}
+          </h4>
+          <p>{{ data.webauthn.rpid }}</p>
+        </div>
+        <div class="mb-4">
+          <h4>
+            {{ $gettext('RP Display Name') }}
+          </h4>
+          <p>{{ data.webauthn.rp_display_name }}</p>
+        </div>
+        <div>
+          <h4>
+            {{ $gettext('RP Origins') }}
+          </h4>
+          <div
+            v-for="origin in data.webauthn.rp_origins"
+            :key="origin"
+            class="mb-4"
+          >
+            {{ origin }}
+          </div>
+        </div>
+      </div>
+      <h3>{{ $gettext('Throttle') }}</h3>
       <AForm
         layout="horizontal"
         style="width:90%;max-width: 500px"
@@ -86,7 +113,14 @@ function removeBannedIP(ip: string) {
           />
         </AFormItem>
       </AForm>
-      <h3>
+      <AAlert
+        class="mb-6"
+        :message="$gettext('Tips')"
+        :description="$gettext('If the number of login failed attempts from a ip reach the max attempts in ban threshold minutes,'
+          + ' the ip will be banned for a period of time.')"
+        type="info"
+      />
+      <h3 class="mb-4">
         {{ $gettext('Banned IPs') }}
       </h3>
       <div class="mb-6">

+ 15 - 90
app/src/views/preference/BasicSettings.vue

@@ -1,7 +1,5 @@
 <script setup lang="ts">
-import Draggable from 'vuedraggable'
-import { DeleteOutlined, HolderOutlined } from '@ant-design/icons-vue'
-import type { Settings } from '@/views/preference/typedef'
+import type { Settings } from '@/api/settings'
 import SensitiveString from '@/components/SensitiveString/SensitiveString.vue'
 
 const data: Settings = inject('data') as Settings
@@ -11,116 +9,43 @@ const errors: Record<string, Record<string, string>> = inject('errors') as Recor
 <template>
   <AForm layout="vertical">
     <AFormItem :label="$gettext('HTTP Host')">
-      <p>{{ data.server.http_host }}</p>
+      <p>{{ data.server.host }}</p>
     </AFormItem>
     <AFormItem :label="$gettext('HTTP Port')">
-      <p>{{ data.server.http_port }}</p>
+      <p>{{ data.server.port }}</p>
     </AFormItem>
     <AFormItem :label="$gettext('Run Mode')">
       <p>{{ data.server.run_mode }}</p>
     </AFormItem>
     <AFormItem :label="$gettext('Jwt Secret')">
-      <SensitiveString :value="data.server.jwt_secret" />
+      <SensitiveString :value="data.app.jwt_secret" />
     </AFormItem>
     <AFormItem :label="$gettext('Node Secret')">
-      <SensitiveString :value="data.server.node_secret" />
+      <SensitiveString :value="data.node.secret" />
     </AFormItem>
     <AFormItem :label="$gettext('Terminal Start Command')">
-      <p>{{ data.server.start_cmd }}</p>
-    </AFormItem>
-    <AFormItem :label="$gettext('HTTP Challenge Port')">
-      <AInputNumber v-model:value="data.server.http_challenge_port" />
+      <p>{{ data.terminal.start_cmd }}</p>
     </AFormItem>
     <AFormItem
       :label="$gettext('Github Proxy')"
-      :validate-status="errors?.server?.github_proxy ? 'error' : ''"
-      :help="errors?.server?.github_proxy === 'url'
+      :validate-status="errors?.http?.github_proxy ? 'error' : ''"
+      :help="errors?.http?.github_proxy === 'url'
         ? $gettext('The url is invalid')
         : ''"
     >
       <AInput
-        v-model:value="data.server.github_proxy"
+        v-model:value="data.http.github_proxy"
         :placeholder="$gettext('For Chinese user: https://mirror.ghproxy.com/')"
       />
     </AFormItem>
     <AFormItem
-      :label="$gettext('CADir')"
-      :validate-status="errors?.server?.ca_dir ? 'error' : ''"
-      :help="errors?.server?.ca_dir === 'url'
-        ? $gettext('The url is invalid')
-        : ''"
-    >
-      <AInput v-model:value="data.server.ca_dir" />
-    </AFormItem>
-    <AFormItem :label="$gettext('Certificate Renewal Interval')">
-      <AInputNumber
-        v-model:value="data.server.cert_renewal_interval"
-        :min="7"
-        :max="21"
-        :addon-after="$gettext('Days')"
-      />
-    </AFormItem>
-    <AFormItem
-      :help="$gettext('Set the recursive nameservers to override the systems nameservers '
-        + 'for the step of DNS challenge.')"
-    >
-      <template #label>
-        {{ $gettext('Recursive Nameservers') }}
-        <AButton
-          type="link"
-          @click="data.server.recursive_nameservers.push('')"
-        >
-          {{ $gettext('Add') }}
-        </AButton>
-      </template>
-
-      <Draggable
-        :list="data.server.recursive_nameservers"
-        item-key="name"
-        class="list-group"
-        ghost-class="ghost"
-        handle=".anticon-holder"
-      >
-        <template #item="{ index }">
-          <ARow>
-            <ACol :span="2">
-              <HolderOutlined class="p-2" />
-            </ACol>
-            <ACol :span="20">
-              <AInput
-                v-model:value="data.server.recursive_nameservers[index]"
-                :status="errors?.server?.recursive_nameservers?.[index] ? 'error' : undefined"
-                placeholder="8.8.8.8:53"
-                class="mb-4"
-              />
-            </ACol>
-            <ACol :span="2">
-              <APopconfirm
-                :title="$gettext('Are you sure you want to remove this item?')"
-                :ok-text="$gettext('Yes')"
-                :cancel-text="$gettext('No')"
-                @confirm="data.server.recursive_nameservers.splice(index, 1)"
-              >
-                <AButton
-                  type="link"
-                  danger
-                >
-                  <DeleteOutlined />
-                </AButton>
-              </APopconfirm>
-            </ACol>
-          </ARow>
-        </template>
-      </Draggable>
-    </AFormItem>
-    <AFormItem
-      :label="$gettext('Server Name')"
-      :validate-status="errors?.server?.name ? 'error' : ''"
-      :help="errors?.server?.name.includes('safety_text')
-        ? $gettext('The server name should only contain letters, unicode, numbers, hyphens, dashes, and dots.')
-        : $gettext('Customize the name of local server to be displayed in the environment indicator.')"
+      :label="$gettext('Node name')"
+      :validate-status="errors?.node?.name ? 'error' : ''"
+      :help="errors?.node?.name.includes('safety_text')
+        ? $gettext('The node name should only contain letters, unicode, numbers, hyphens, dashes, and dots.')
+        : $gettext('Customize the name of local node to be displayed in the environment indicator.')"
     >
-      <AInput v-model:value="data.server.name" />
+      <AInput v-model:value="data.node.name" />
     </AFormItem>
   </AForm>
 </template>

+ 90 - 0
app/src/views/preference/CertSettings.vue

@@ -0,0 +1,90 @@
+<script setup lang="ts">
+import Draggable from 'vuedraggable'
+import { DeleteOutlined, HolderOutlined } from '@ant-design/icons-vue'
+import type { Settings } from '@/api/settings'
+
+const data: Settings = inject('data') as Settings
+const errors: Record<string, Record<string, string>> = inject('errors') as Record<string, Record<string, string>>
+</script>
+
+<template>
+  <AForm layout="vertical">
+    <AFormItem :label="$gettext('HTTP Challenge Port')">
+      <AInputNumber v-model:value="data.cert.http_challenge_port" />
+    </AFormItem>
+    <AFormItem
+      :label="$gettext('CADir')"
+      :validate-status="errors?.cert?.ca_dir ? 'error' : ''"
+      :help="errors?.cert?.ca_dir === 'url'
+        ? $gettext('The url is invalid')
+        : ''"
+    >
+      <AInput v-model:value="data.cert.ca_dir" />
+    </AFormItem>
+    <AFormItem :label="$gettext('Certificate Renewal Interval')">
+      <AInputNumber
+        v-model:value="data.cert.renewal_interval"
+        :min="7"
+        :max="21"
+        :addon-after="$gettext('Days')"
+      />
+    </AFormItem>
+    <AFormItem
+      :help="$gettext('Set the recursive nameservers to override the systems nameservers '
+        + 'for the step of DNS challenge.')"
+    >
+      <template #label>
+        {{ $gettext('Recursive Nameservers') }}
+        <AButton
+          type="link"
+          @click="data.cert.recursive_nameservers.push('')"
+        >
+          {{ $gettext('Add') }}
+        </AButton>
+      </template>
+
+      <Draggable
+        :list="data.cert.recursive_nameservers"
+        item-key="name"
+        class="list-group"
+        ghost-class="ghost"
+        handle=".anticon-holder"
+      >
+        <template #item="{ index }">
+          <ARow>
+            <ACol :span="2">
+              <HolderOutlined class="p-2" />
+            </ACol>
+            <ACol :span="20">
+              <AInput
+                v-model:value="data.cert.recursive_nameservers[index]"
+                :status="errors?.cert?.recursive_nameservers?.[index] ? 'error' : undefined"
+                placeholder="8.8.8.8:53"
+                class="mb-4"
+              />
+            </ACol>
+            <ACol :span="2">
+              <APopconfirm
+                :title="$gettext('Are you sure you want to remove this item?')"
+                :ok-text="$gettext('Yes')"
+                :cancel-text="$gettext('No')"
+                @confirm="data.cert.recursive_nameservers.splice(index, 1)"
+              >
+                <AButton
+                  type="link"
+                  danger
+                >
+                  <DeleteOutlined />
+                </AButton>
+              </APopconfirm>
+            </ACol>
+          </ARow>
+        </template>
+      </Draggable>
+    </AFormItem>
+  </AForm>
+</template>
+
+<style lang="less" scoped>
+
+</style>

+ 1 - 1
app/src/views/preference/LogrotateSettings.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import type { Settings } from '@/views/preference/typedef'
+import type { Settings } from '@/api/settings'
 
 const data: Settings = inject('data')!
 </script>

+ 24 - 16
app/src/views/preference/NginxSettings.vue

@@ -1,30 +1,38 @@
 <script setup lang="ts">
-import type { Settings } from '@/views/preference/typedef'
+import type { Settings } from '@/api/settings'
 
 const data: Settings = inject('data')!
-const errors: Record<string, Record<string, string>> = inject('errors') as Record<string, Record<string, string>>
 </script>
 
 <template>
   <AForm layout="vertical">
-    <AFormItem
-      :label="$gettext('Nginx Access Log Path')"
-      :validate-status="errors?.nginx?.access_log_path ? 'error' : ''"
-      :help="errors?.nginx?.access_log_path === 'file'
-        ? $gettext('File not found')
-        : ''"
-    >
+    <AFormItem :label="$gettext('Nginx Access Log Path')">
       {{ data.nginx.access_log_path }}
     </AFormItem>
-    <AFormItem
-      :label="$gettext('Nginx Error Log Path')"
-      :validate-status="errors?.nginx?.error_log_path ? 'error' : ''"
-      :help="errors?.nginx?.error_log_path === 'file'
-        ? $gettext('File not found')
-        : ''"
-    >
+    <AFormItem :label="$gettext('Nginx Error Log Path')">
       {{ data.nginx.error_log_path }}
     </AFormItem>
+    <AFormItem :label="$gettext('Nginx Configurations Directory')">
+      {{ data.nginx.config_dir }}
+    </AFormItem>
+    <AFormItem :label="$gettext('Nginx Log Directory Whitelist')">
+      <div
+        v-for="dir in data.nginx.log_dir_white_list"
+        :key="dir"
+        class="mb-2"
+      >
+        {{ dir }}
+      </div>
+    </AFormItem>
+    <AFormItem :label="$gettext('Nginx PID Path')">
+      {{ data.nginx.pid_path }}
+    </AFormItem>
+    <AFormItem :label="$gettext('Nginx Reload Command')">
+      {{ data.nginx.reload_cmd }}
+    </AFormItem>
+    <AFormItem :label="$gettext('Nginx Restart Command')">
+      {{ data.nginx.restart_cmd }}
+    </AFormItem>
   </AForm>
 </template>
 

+ 1 - 1
app/src/views/preference/OpenAISettings.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import type { Settings } from '@/views/preference/typedef'
+import type { Settings } from '@/api/settings'
 
 const data: Settings = inject('data')!
 const errors: Record<string, Record<string, string>> = inject('errors') as Record<string, Record<string, string>>

+ 57 - 20
app/src/views/preference/Preference.vue

@@ -7,55 +7,86 @@ import settings from '@/api/settings'
 import BasicSettings from '@/views/preference/BasicSettings.vue'
 import OpenAISettings from '@/views/preference/OpenAISettings.vue'
 import NginxSettings from '@/views/preference/NginxSettings.vue'
-import type { Settings } from '@/views/preference/typedef'
+import type { Settings } from '@/api/settings'
 import LogrotateSettings from '@/views/preference/LogrotateSettings.vue'
 import { useSettingsStore } from '@/pinia'
 import AuthSettings from '@/views/preference/AuthSettings.vue'
 import use2FAModal from '@/components/TwoFA/use2FAModal'
+import CertSettings from '@/views/preference/CertSettings.vue'
 
 const data = ref<Settings>({
+  app: {
+    page_size: 10,
+    jwt_secret: '',
+  },
   server: {
-    http_host: '0.0.0.0',
-    http_port: '9000',
+    host: '0.0.0.0',
+    port: 9000,
     run_mode: 'debug',
-    jwt_secret: '',
-    start_cmd: '',
+  },
+  database: {
+    name: '',
+  },
+  auth: {
+    ip_white_list: [],
+    ban_threshold_minutes: 10,
+    max_attempts: 10,
+  },
+  casdoor: {
+    endpoint: '',
+    client_id: '',
+    client_secret: '',
+    certificate_path: '',
+    organization: '',
+    application: '',
+    redirect_uri: '',
+  },
+  cert: {
     email: '',
-    http_challenge_port: '9180',
-    github_proxy: '',
     ca_dir: '',
-    node_secret: '',
-    cert_renewal_interval: 7,
+    renewal_interval: 7,
     recursive_nameservers: [],
-    name: '',
+    http_challenge_port: '9180',
+  },
+  http: {
+    github_proxy: '',
+    insecure_skip_verify: false,
+  },
+  logrotate: {
+    enabled: false,
+    cmd: '',
+    interval: 1440,
   },
   nginx: {
     access_log_path: '',
     error_log_path: '',
     config_dir: '',
+    log_dir_white_list: [],
     pid_path: '',
     reload_cmd: '',
     restart_cmd: '',
   },
+  node: {
+    name: '',
+    secret: '',
+  },
   openai: {
     model: '',
     base_url: '',
     proxy: '',
     token: '',
   },
-  logrotate: {
-    enabled: false,
-    cmd: '',
-    interval: 1440,
+  terminal: {
+    start_cmd: '',
   },
-  auth: {
-    ip_white_list: [],
-    ban_threshold_minutes: 10,
-    max_attempts: 10,
+  webauthn: {
+    rp_display_name: '',
+    rpid: '',
+    rp_origins: [],
   },
 })
 
-settings.get<Settings>().then(r => {
+settings.get().then(r => {
   data.value = r
 })
 
@@ -66,7 +97,7 @@ const refAuthSettings = ref()
 
 async function save() {
   // fix type
-  data.value.server.http_challenge_port = data.value.server.http_challenge_port.toString()
+  data.value.cert.http_challenge_port = data.value.cert.http_challenge_port.toString()
 
   const otpModal = use2FAModal()
 
@@ -123,6 +154,12 @@ onMounted(() => {
         >
           <AuthSettings ref="refAuthSettings" />
         </ATabPane>
+        <ATabPane
+          key="cert"
+          :tab="$gettext('Cert')"
+        >
+          <CertSettings />
+        </ATabPane>
         <ATabPane
           key="nginx"
           :tab="$gettext('Nginx')"

+ 0 - 41
app/src/views/preference/typedef.ts

@@ -1,41 +0,0 @@
-export interface Settings {
-  server: {
-    http_host: string
-    http_port: string
-    run_mode: string
-    jwt_secret: string
-    node_secret: string
-    start_cmd: string
-    http_challenge_port: string
-    github_proxy: string
-    email: string
-    ca_dir: string
-    cert_renewal_interval: number
-    recursive_nameservers: string[]
-    name: string
-  }
-  nginx: {
-    access_log_path: string
-    error_log_path: string
-    config_dir: string
-    pid_path: string
-    reload_cmd: string
-    restart_cmd: string
-  }
-  openai: {
-    model: string
-    base_url: string
-    proxy: string
-    token: string
-  }
-  logrotate: {
-    enabled: boolean
-    cmd: string
-    interval: number
-  }
-  auth: {
-    ip_white_list: string[]
-    ban_threshold_minutes: number
-    max_attempts: number
-  }
-}

+ 17 - 13
docker-compose-demo.yml

@@ -1,17 +1,21 @@
 version: '3'
 services:
-    nginx-demo-1:
-        image: uozi/nginx-ui-demo:latest
-        restart: always
-        networks:
-            - nginx-ui-network
-        ports:
-            - "9003:80"
+  nginx-demo-1:
+    image: uozi/nginx-ui-demo:latest
+    restart: always
+    networks:
+      - nginx-ui-network
+    entrypoint:
+      - NGINX_UI_NODE_DEMO=true
+    ports:
+      - "9003:80"
 
-    nginx-demo-2:
-        image: uozi/nginx-ui-demo:latest
-        restart: always
-        networks:
-            - nginx-ui-network
+  nginx-demo-2:
+    image: uozi/nginx-ui-demo:latest
+    restart: always
+    entrypoint:
+      - NGINX_UI_NODE_DEMO=true
+    networks:
+      - nginx-ui-network
 networks:
-    nginx-ui-network:
+  nginx-ui-network:

+ 1 - 1
internal/nginx/config_args.go

@@ -2,8 +2,8 @@ package nginx
 
 import (
 	"github.com/0xJacky/Nginx-UI/internal/helper"
-	"github.com/uozi-tech/cosy/logger"
 	"github.com/0xJacky/Nginx-UI/settings"
+	"github.com/uozi-tech/cosy/logger"
 	"os/exec"
 	"path/filepath"
 	"regexp"

+ 1 - 1
settings/cert.go

@@ -5,7 +5,7 @@ import "github.com/go-acme/lego/v4/lego"
 type Cert struct {
 	Email                string   `json:"email" protected:"true"`
 	CADir                string   `json:"ca_dir" binding:"omitempty,url"`
-	RenewalInterval      int      `json:"cert_renewal_interval" binding:"min=7,max=21"`
+	RenewalInterval      int      `json:"renewal_interval" binding:"min=7,max=21"`
 	RecursiveNameservers []string `json:"recursive_nameservers" binding:"omitempty,dive,hostname_port"`
 	HTTPChallengePort    string   `json:"http_challenge_port"`
 }

+ 1 - 1
settings/cluster.go

@@ -3,7 +3,7 @@ package settings
 import "github.com/uozi-tech/cosy/settings"
 
 type Cluster struct {
-	Node []string `ini:",,allowshadow"`
+	Node []string `json:"node" ini:",,allowshadow"`
 }
 
 var ClusterSettings = &Cluster{

+ 1 - 1
settings/crypto.go

@@ -3,7 +3,7 @@ package settings
 import "crypto/md5"
 
 type Crypto struct {
-	Secret string
+	Secret string `json:"secret"`
 }
 
 var CryptoSettings = &Crypto{}

+ 1 - 1
settings/database.go

@@ -1,7 +1,7 @@
 package settings
 
 type Database struct {
-	Name string
+	Name string `json:"name"`
 }
 
 var DatabaseSettings = &Database{

+ 3 - 3
settings/webauthn.go

@@ -1,9 +1,9 @@
 package settings
 
 type WebAuthn struct {
-	RPDisplayName string
-	RPID          string
-	RPOrigins     []string
+	RPDisplayName string   `json:"rp_display_name"`
+	RPID          string   `json:"rpid"`
+	RPOrigins     []string `json:"rp_origins"`
 }
 
 var WebAuthnSettings = &WebAuthn{}