Quellcode durchsuchen

feat(wip): self check

Jacky vor 3 Monaten
Ursprung
Commit
ded74bbe0a
40 geänderte Dateien mit 1418 neuen und 69 gelöschten Zeilen
  1. 1 0
      README-es.md
  2. 1 0
      README-vi_VN.md
  3. 1 0
      README-zh_CN.md
  4. 1 0
      README-zh_TW.md
  5. 1 0
      README.md
  6. 2 0
      api/system/router.go
  7. 18 0
      api/system/self_check.go
  8. 18 0
      app/src/api/self_check.ts
  9. 57 6
      app/src/language/ar/app.po
  10. 56 6
      app/src/language/en/app.po
  11. 57 6
      app/src/language/es/app.po
  12. 56 6
      app/src/language/fr_FR/app.po
  13. 57 6
      app/src/language/ko_KR/app.po
  14. 51 5
      app/src/language/messages.pot
  15. 57 6
      app/src/language/ru_RU/app.po
  16. 57 6
      app/src/language/tr_TR/app.po
  17. 56 6
      app/src/language/vi_VN/app.po
  18. 57 6
      app/src/language/zh_CN/app.po
  19. 57 6
      app/src/language/zh_TW/app.po
  20. 60 1
      app/src/lib/http/index.ts
  21. 7 0
      app/src/routes/index.ts
  22. 77 0
      app/src/views/system/SelfCheck/SelfCheck.vue
  23. 20 0
      app/src/views/system/SelfCheck/tasks.ts
  24. 1 0
      docs/guide/about.md
  25. 1 0
      docs/zh_CN/guide/about.md
  26. 1 0
      docs/zh_TW/guide/about.md
  27. 20 3
      internal/nginx/config_args.go
  28. 67 0
      internal/self_check/directory.go
  29. 19 0
      internal/self_check/errors.go
  30. 168 0
      internal/self_check/nginx_conf.go
  31. 123 0
      internal/self_check/nginx_conf_test.go
  32. 74 0
      internal/self_check/self_check.go
  33. 1 0
      internal/self_check/test_cases/5001.conf
  34. 14 0
      internal/self_check/test_cases/no-http-block-fixed.conf
  35. 10 0
      internal/self_check/test_cases/no-http-block.conf
  36. 23 0
      internal/self_check/test_cases/no-http-sites-enabled-fixed.conf
  37. 34 0
      internal/self_check/test_cases/no-http-sites-enabled.conf
  38. 35 0
      internal/self_check/test_cases/ok.conf
  39. 1 0
      internal/self_check/websocket.go
  40. 1 0
      settings/nginx.go

+ 1 - 0
README-es.md

@@ -109,6 +109,7 @@ Aceptamos traducciones a cualquier idioma.
 - [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
 - [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
 - [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
+- [lego](https://github.com/go-acme/lego)
 
 ## Cómo empezar
 

+ 1 - 0
README-vi_VN.md

@@ -121,6 +121,7 @@ Chúng tôi hoan nghênh bản dịch sang bất kỳ ngôn ngữ nào.
 - [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
 - [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
 - [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
+- [lego](https://github.com/go-acme/lego)
 
 ## Bắt đầu
 

+ 1 - 0
README-zh_CN.md

@@ -102,6 +102,7 @@ Nginx 网络管理界面,由  [0xJacky](https://jackyu.cn/) 与 [Hintay](https
 - [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
 - [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
 - [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
+- [lego](https://github.com/go-acme/lego)
 
 ## 入门指南
 

+ 1 - 0
README-zh_TW.md

@@ -105,6 +105,7 @@ Nginx 網路管理介面,由 [0xJacky](https://jackyu.cn/) 與 [Hintay](https:
 - [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
 - [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
 - [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
+- [lego](https://github.com/go-acme/lego)
 
 ## 入門指南
 

+ 1 - 0
README.md

@@ -120,6 +120,7 @@ We welcome translations into any language.
 - [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
 - [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
 - [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
+- [lego](https://github.com/go-acme/lego)
 
 ## Getting Started
 

+ 2 - 0
api/system/router.go

@@ -13,6 +13,8 @@ func InitPublicRouter(r *gin.RouterGroup) {
 func InitPrivateRouter(r *gin.RouterGroup) {
 	r.GET("upgrade/release", GetRelease)
 	r.GET("upgrade/current", GetCurrentVersion)
+	r.GET("self_check", SelfCheck)
+	r.POST("self_check/:name/fix", SelfCheckFix)
 }
 
 func InitWebSocketRouter(r *gin.RouterGroup) {

+ 18 - 0
api/system/self_check.go

@@ -0,0 +1,18 @@
+package system
+
+import (
+	"net/http"
+
+	"github.com/0xJacky/Nginx-UI/internal/self_check"
+	"github.com/gin-gonic/gin"
+)
+
+func SelfCheck(c *gin.Context) {
+	report := self_check.Run()
+	c.JSON(http.StatusOK, report)
+}
+
+func SelfCheckFix(c *gin.Context) {
+	result := self_check.AttemptFix(c.Param("name"))
+	c.JSON(http.StatusOK, result)
+}

+ 18 - 0
app/src/api/self_check.ts

@@ -0,0 +1,18 @@
+import type { CosyError } from '@/lib/http'
+import http from '@/lib/http'
+
+export interface Report {
+  name: string
+  err?: CosyError
+}
+
+const selfCheck = {
+  run(): Promise<Report[]> {
+    return http.get('/self_check')
+  },
+  fix(taskName: string) {
+    return http.post(`/self_check/${taskName}/fix`)
+  },
+}
+
+export default selfCheck

+ 57 - 6
app/src/language/ar/app.po

@@ -21,7 +21,7 @@ msgstr "المصادقة الثنائية"
 msgid "2FA Settings"
 msgstr "إعدادات المصادقة الثنائية"
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr "عن"
 
@@ -199,6 +199,11 @@ msgstr "اطلب المساعدة من ChatGPT"
 msgid "Assistant"
 msgstr "المساعد"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+#, fuzzy
+msgid "Attempt to fix"
+msgstr "محاولات"
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr "محاولات"
@@ -389,6 +394,26 @@ msgstr "قناة"
 msgid "Check again"
 msgstr "تحقق مرة أخرى"
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid ""
+"Check if the sites-available and sites-enabled directory is under the nginx "
+"configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid ""
+"Check if the streams-available and streams-enabled directory is under the "
+"nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr "تنظيف متغيرات البيئة"
@@ -1132,7 +1157,7 @@ msgstr "أدخل الرمز من التطبيق:"
 msgid "Input the recovery code:"
 msgstr "أدخل رمز الاسترداد:"
 
-#: src/routes/index.ts:305 src/views/other/Install.vue:136
+#: src/routes/index.ts:312 src/views/other/Install.vue:136
 msgid "Install"
 msgstr "تثبيت"
 
@@ -1269,7 +1294,7 @@ msgstr "أماكن"
 msgid "Log"
 msgstr "سجل"
 
-#: src/routes/index.ts:311 src/views/other/Login.vue:246
+#: src/routes/index.ts:318 src/views/other/Login.vue:246
 msgid "Login"
 msgstr "تسجيل الدخول"
 
@@ -1434,6 +1459,14 @@ msgstr "Nginx"
 msgid "Nginx Access Log Path"
 msgstr "مسار سجل الوصول لـ Nginx"
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 msgid "Nginx Configuration Parse Error"
@@ -1512,7 +1545,7 @@ msgstr "سر العقدة"
 msgid "Not After"
 msgstr "ليس بعد"
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 msgid "Not Found"
 msgstr "غير موجود"
 
@@ -1813,6 +1846,10 @@ msgstr "يقرأ"
 msgid "Receive"
 msgstr "يستقبل"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 msgid "Recover"
@@ -2102,6 +2139,10 @@ msgstr "تم نسخ السر"
 msgid "Selector"
 msgstr "المحدد"
 
+#: src/routes/index.ts:283 src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 msgid "Send"
@@ -2114,7 +2155,7 @@ msgstr "إرسال"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
-#: src/views/config/components/Mkdir.vue:38
+#: src/lib/http/index.ts:129 src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
 #: src/views/environment/BatchUpgrader.vue:59
@@ -2184,6 +2225,11 @@ msgstr "فئات الموقع"
 msgid "Site Logs"
 msgstr "سجلات الموقع"
 
+#: src/views/system/SelfCheck/tasks.ts:3
+#, fuzzy
+msgid "Sites Directory"
+msgstr "مجلد"
+
 #: src/routes/index.ts:56
 msgid "Sites List"
 msgstr "قائمة المواقع"
@@ -2230,6 +2276,11 @@ msgstr "متوقف"
 msgid "Storage"
 msgstr "تخزين"
 
+#: src/views/system/SelfCheck/tasks.ts:7
+#, fuzzy
+msgid "Streams Directory"
+msgstr "مجلد"
+
 #: src/constants/index.ts:19 src/views/notification/notificationColumns.tsx:36
 msgid "Success"
 msgstr "نجاح"
@@ -2590,7 +2641,7 @@ msgstr "محدث في"
 msgid "Updated successfully"
 msgstr "تم التحديث بنجاح"
 
-#: src/routes/index.ts:290 src/views/environment/Environment.vue:55
+#: src/routes/index.ts:297 src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145 src/views/system/Upgrade.vue:228
 msgid "Upgrade"
 msgstr "ترقية"

+ 56 - 6
app/src/language/en/app.po

@@ -17,7 +17,7 @@ msgstr ""
 msgid "2FA Settings"
 msgstr ""
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr "About"
 
@@ -209,6 +209,10 @@ msgstr ""
 msgid "Assistant"
 msgstr ""
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+msgid "Attempt to fix"
+msgstr ""
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr ""
@@ -401,6 +405,26 @@ msgstr ""
 msgid "Check again"
 msgstr ""
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid ""
+"Check if the sites-available and sites-enabled directory is under the nginx "
+"configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid ""
+"Check if the streams-available and streams-enabled directory is under the "
+"nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr ""
@@ -1175,7 +1199,7 @@ msgstr ""
 msgid "Input the recovery code:"
 msgstr ""
 
-#: src/routes/index.ts:305 src/views/other/Install.vue:136
+#: src/routes/index.ts:312 src/views/other/Install.vue:136
 msgid "Install"
 msgstr "Install"
 
@@ -1327,7 +1351,7 @@ msgstr "Locations"
 msgid "Log"
 msgstr "Login"
 
-#: src/routes/index.ts:311 src/views/other/Login.vue:246
+#: src/routes/index.ts:318 src/views/other/Login.vue:246
 msgid "Login"
 msgstr "Login"
 
@@ -1496,6 +1520,14 @@ msgstr ""
 msgid "Nginx Access Log Path"
 msgstr ""
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 #, fuzzy
@@ -1579,7 +1611,7 @@ msgstr ""
 msgid "Not After"
 msgstr ""
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 msgid "Not Found"
 msgstr "Not Found"
 
@@ -1878,6 +1910,10 @@ msgstr "Reads"
 msgid "Receive"
 msgstr "Receive"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 msgid "Recover"
@@ -2193,6 +2229,10 @@ msgstr ""
 msgid "Selector"
 msgstr ""
 
+#: src/routes/index.ts:283 src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 msgid "Send"
@@ -2205,7 +2245,7 @@ msgstr "Send"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
-#: src/views/config/components/Mkdir.vue:38
+#: src/lib/http/index.ts:129 src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
 #: src/views/environment/BatchUpgrader.vue:59
@@ -2274,6 +2314,11 @@ msgstr ""
 msgid "Site Logs"
 msgstr "Sites List"
 
+#: src/views/system/SelfCheck/tasks.ts:3
+#, fuzzy
+msgid "Sites Directory"
+msgstr "Directive"
+
 #: src/routes/index.ts:56
 msgid "Sites List"
 msgstr "Sites List"
@@ -2326,6 +2371,11 @@ msgstr ""
 msgid "Storage"
 msgstr "Storage"
 
+#: src/views/system/SelfCheck/tasks.ts:7
+#, fuzzy
+msgid "Streams Directory"
+msgstr "Directive"
+
 #: src/constants/index.ts:19 src/views/notification/notificationColumns.tsx:36
 msgid "Success"
 msgstr ""
@@ -2671,7 +2721,7 @@ msgstr "Updated at"
 msgid "Updated successfully"
 msgstr "Saved successfully"
 
-#: src/routes/index.ts:290 src/views/environment/Environment.vue:55
+#: src/routes/index.ts:297 src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145 src/views/system/Upgrade.vue:228
 msgid "Upgrade"
 msgstr ""

+ 57 - 6
app/src/language/es/app.po

@@ -24,7 +24,7 @@ msgstr "2FA"
 msgid "2FA Settings"
 msgstr "Configuración de 2FA"
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr "Acerca de"
 
@@ -204,6 +204,11 @@ msgstr "Preguntar por ayuda a ChatGPT"
 msgid "Assistant"
 msgstr "Asistente"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+#, fuzzy
+msgid "Attempt to fix"
+msgstr "Intentos"
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr "Intentos"
@@ -388,6 +393,26 @@ msgstr "Canal"
 msgid "Check again"
 msgstr "Intentar nuevamente"
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid ""
+"Check if the sites-available and sites-enabled directory is under the nginx "
+"configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid ""
+"Check if the streams-available and streams-enabled directory is under the "
+"nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr "Borrar las variables de entorno"
@@ -1139,7 +1164,7 @@ msgstr "Ingrese el código de la aplicación:"
 msgid "Input the recovery code:"
 msgstr "Ingrese el código de recuperación:"
 
-#: src/routes/index.ts:305 src/views/other/Install.vue:136
+#: src/routes/index.ts:312 src/views/other/Install.vue:136
 msgid "Install"
 msgstr "Instalar"
 
@@ -1278,7 +1303,7 @@ msgstr "Ubicaciones"
 msgid "Log"
 msgstr "Registro"
 
-#: src/routes/index.ts:311 src/views/other/Login.vue:246
+#: src/routes/index.ts:318 src/views/other/Login.vue:246
 msgid "Login"
 msgstr "Acceso"
 
@@ -1444,6 +1469,14 @@ msgstr "Nginx"
 msgid "Nginx Access Log Path"
 msgstr "Ruta de registro de acceso de Nginx"
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 msgid "Nginx Configuration Parse Error"
@@ -1526,7 +1559,7 @@ msgstr "Secreto del nodo"
 msgid "Not After"
 msgstr "No después de"
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 msgid "Not Found"
 msgstr "No encontrado"
 
@@ -1845,6 +1878,10 @@ msgstr "Lecturas"
 msgid "Receive"
 msgstr "Recibido"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 msgid "Recover"
@@ -2150,6 +2187,10 @@ msgstr "El secreto ha sido copiado"
 msgid "Selector"
 msgstr "Seleccionador"
 
+#: src/routes/index.ts:283 src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 msgid "Send"
@@ -2162,7 +2203,7 @@ msgstr "Enviado"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
-#: src/views/config/components/Mkdir.vue:38
+#: src/lib/http/index.ts:129 src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
 #: src/views/environment/BatchUpgrader.vue:59
@@ -2232,6 +2273,11 @@ msgstr "Categorías del sitio"
 msgid "Site Logs"
 msgstr "Registros del sitio"
 
+#: src/views/system/SelfCheck/tasks.ts:3
+#, fuzzy
+msgid "Sites Directory"
+msgstr "Directorio"
+
 #: src/routes/index.ts:56
 msgid "Sites List"
 msgstr "Lista de sitios"
@@ -2278,6 +2324,11 @@ msgstr "Detenido"
 msgid "Storage"
 msgstr "Almacenamiento"
 
+#: src/views/system/SelfCheck/tasks.ts:7
+#, fuzzy
+msgid "Streams Directory"
+msgstr "Directorio"
+
 #: src/constants/index.ts:19 src/views/notification/notificationColumns.tsx:36
 msgid "Success"
 msgstr "Éxito"
@@ -2658,7 +2709,7 @@ msgstr "Actualizado a"
 msgid "Updated successfully"
 msgstr "Actualización exitosa"
 
-#: src/routes/index.ts:290 src/views/environment/Environment.vue:55
+#: src/routes/index.ts:297 src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145 src/views/system/Upgrade.vue:228
 msgid "Upgrade"
 msgstr "Actualizar"

+ 56 - 6
app/src/language/fr_FR/app.po

@@ -19,7 +19,7 @@ msgstr ""
 msgid "2FA Settings"
 msgstr ""
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr "À propos"
 
@@ -212,6 +212,10 @@ msgstr "Modèle ChatGPT"
 msgid "Assistant"
 msgstr ""
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+msgid "Attempt to fix"
+msgstr ""
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr ""
@@ -404,6 +408,26 @@ msgstr ""
 msgid "Check again"
 msgstr "Revérifier"
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid ""
+"Check if the sites-available and sites-enabled directory is under the nginx "
+"configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid ""
+"Check if the streams-available and streams-enabled directory is under the "
+"nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr "Nettoyage des variables d'environnement"
@@ -1180,7 +1204,7 @@ msgstr ""
 msgid "Input the recovery code:"
 msgstr ""
 
-#: src/routes/index.ts:305 src/views/other/Install.vue:136
+#: src/routes/index.ts:312 src/views/other/Install.vue:136
 msgid "Install"
 msgstr "Installer"
 
@@ -1331,7 +1355,7 @@ msgstr "Localisations"
 msgid "Log"
 msgstr "Connexion"
 
-#: src/routes/index.ts:311 src/views/other/Login.vue:246
+#: src/routes/index.ts:318 src/views/other/Login.vue:246
 msgid "Login"
 msgstr "Connexion"
 
@@ -1499,6 +1523,14 @@ msgstr "Journal Nginx"
 msgid "Nginx Access Log Path"
 msgstr "Chemin du journal d'accès Nginx"
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 msgid "Nginx Configuration Parse Error"
@@ -1582,7 +1614,7 @@ msgstr "Secret Jwt"
 msgid "Not After"
 msgstr ""
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 msgid "Not Found"
 msgstr "Introuvable"
 
@@ -1892,6 +1924,10 @@ msgstr "Lectures"
 msgid "Receive"
 msgstr "Recevoir"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 msgid "Recover"
@@ -2208,6 +2244,10 @@ msgstr ""
 msgid "Selector"
 msgstr "Sélecteur"
 
+#: src/routes/index.ts:283 src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 msgid "Send"
@@ -2220,7 +2260,7 @@ msgstr "Envoyer"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
-#: src/views/config/components/Mkdir.vue:38
+#: src/lib/http/index.ts:129 src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
 #: src/views/environment/BatchUpgrader.vue:59
@@ -2290,6 +2330,11 @@ msgstr ""
 msgid "Site Logs"
 msgstr "Journaux du site"
 
+#: src/views/system/SelfCheck/tasks.ts:3
+#, fuzzy
+msgid "Sites Directory"
+msgstr "Directive"
+
 #: src/routes/index.ts:56
 msgid "Sites List"
 msgstr "Liste des sites"
@@ -2340,6 +2385,11 @@ msgstr "Arrêté"
 msgid "Storage"
 msgstr "Stockage"
 
+#: src/views/system/SelfCheck/tasks.ts:7
+#, fuzzy
+msgid "Streams Directory"
+msgstr "Directive"
+
 #: src/constants/index.ts:19 src/views/notification/notificationColumns.tsx:36
 msgid "Success"
 msgstr ""
@@ -2693,7 +2743,7 @@ msgstr "Mis à jour le"
 msgid "Updated successfully"
 msgstr "Mis à jour avec succés"
 
-#: src/routes/index.ts:290 src/views/environment/Environment.vue:55
+#: src/routes/index.ts:297 src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145 src/views/system/Upgrade.vue:228
 msgid "Upgrade"
 msgstr "Mettre à niveau"

+ 57 - 6
app/src/language/ko_KR/app.po

@@ -22,7 +22,7 @@ msgstr "2FA"
 msgid "2FA Settings"
 msgstr "2FA 설정"
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr "대하여"
 
@@ -201,6 +201,11 @@ msgstr "ChatGPT에게 도움 요청"
 msgid "Assistant"
 msgstr "조수"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+#, fuzzy
+msgid "Attempt to fix"
+msgstr "시도 횟수"
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr "시도 횟수"
@@ -386,6 +391,26 @@ msgstr "채널"
 msgid "Check again"
 msgstr "다시 확인"
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid ""
+"Check if the sites-available and sites-enabled directory is under the nginx "
+"configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid ""
+"Check if the streams-available and streams-enabled directory is under the "
+"nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr "환경 변수 정리"
@@ -1140,7 +1165,7 @@ msgstr ""
 msgid "Input the recovery code:"
 msgstr ""
 
-#: src/routes/index.ts:305 src/views/other/Install.vue:136
+#: src/routes/index.ts:312 src/views/other/Install.vue:136
 msgid "Install"
 msgstr "설치"
 
@@ -1292,7 +1317,7 @@ msgstr "위치들"
 msgid "Log"
 msgstr "로그인"
 
-#: src/routes/index.ts:311 src/views/other/Login.vue:246
+#: src/routes/index.ts:318 src/views/other/Login.vue:246
 msgid "Login"
 msgstr "로그인"
 
@@ -1466,6 +1491,14 @@ msgstr "Nginx"
 msgid "Nginx Access Log Path"
 msgstr "Nginx 접근 로그 경로"
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 #, fuzzy
@@ -1551,7 +1584,7 @@ msgstr "노드 시크릿"
 msgid "Not After"
 msgstr "만료일"
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 msgid "Not Found"
 msgstr "찾을 수 없음"
 
@@ -1855,6 +1888,10 @@ msgstr "읽기"
 msgid "Receive"
 msgstr "수신"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 msgid "Recover"
@@ -2174,6 +2211,10 @@ msgstr ""
 msgid "Selector"
 msgstr "선택"
 
+#: src/routes/index.ts:283 src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 msgid "Send"
@@ -2186,7 +2227,7 @@ msgstr "보내기"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
-#: src/views/config/components/Mkdir.vue:38
+#: src/lib/http/index.ts:129 src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
 #: src/views/environment/BatchUpgrader.vue:59
@@ -2255,6 +2296,11 @@ msgstr ""
 msgid "Site Logs"
 msgstr "사이트 로그"
 
+#: src/views/system/SelfCheck/tasks.ts:3
+#, fuzzy
+msgid "Sites Directory"
+msgstr "디렉토리"
+
 #: src/routes/index.ts:56
 msgid "Sites List"
 msgstr "사이트 목록"
@@ -2306,6 +2352,11 @@ msgstr "정지됨"
 msgid "Storage"
 msgstr "저장소"
 
+#: src/views/system/SelfCheck/tasks.ts:7
+#, fuzzy
+msgid "Streams Directory"
+msgstr "디렉토리"
+
 #: src/constants/index.ts:19 src/views/notification/notificationColumns.tsx:36
 msgid "Success"
 msgstr "성공"
@@ -2658,7 +2709,7 @@ msgstr "업데이트됨"
 msgid "Updated successfully"
 msgstr "성공적으로 저장되었습니다"
 
-#: src/routes/index.ts:290 src/views/environment/Environment.vue:55
+#: src/routes/index.ts:297 src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145 src/views/system/Upgrade.vue:228
 msgid "Upgrade"
 msgstr "업그레이드"

+ 51 - 5
app/src/language/messages.pot

@@ -10,7 +10,7 @@ msgstr ""
 msgid "2FA Settings"
 msgstr ""
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr ""
 
@@ -190,6 +190,10 @@ msgstr ""
 msgid "Assistant"
 msgstr ""
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+msgid "Attempt to fix"
+msgstr ""
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr ""
@@ -374,6 +378,22 @@ msgstr ""
 msgid "Check again"
 msgstr ""
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid "Check if the sites-available and sites-enabled directory is under the nginx configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid "Check if the streams-available and streams-enabled directory is under the nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr ""
@@ -1105,7 +1125,7 @@ msgstr ""
 msgid "Input the recovery code:"
 msgstr ""
 
-#: src/routes/index.ts:305
+#: src/routes/index.ts:312
 #: src/views/other/Install.vue:136
 msgid "Install"
 msgstr ""
@@ -1243,7 +1263,7 @@ msgstr ""
 msgid "Log"
 msgstr ""
 
-#: src/routes/index.ts:311
+#: src/routes/index.ts:318
 #: src/views/other/Login.vue:246
 msgid "Login"
 msgstr ""
@@ -1403,6 +1423,14 @@ msgstr ""
 msgid "Nginx Access Log Path"
 msgstr ""
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 msgid "Nginx Configuration Parse Error"
@@ -1482,7 +1510,7 @@ msgstr ""
 msgid "Not After"
 msgstr ""
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 msgid "Not Found"
 msgstr ""
 
@@ -1762,6 +1790,10 @@ msgstr ""
 msgid "Receive"
 msgstr ""
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 msgid "Recover"
@@ -2045,6 +2077,11 @@ msgstr ""
 msgid "Selector"
 msgstr ""
 
+#: src/routes/index.ts:283
+#: src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 msgid "Send"
@@ -2057,6 +2094,7 @@ msgstr ""
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
+#: src/lib/http/index.ts:129
 #: src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
@@ -2127,6 +2165,10 @@ msgstr ""
 msgid "Site Logs"
 msgstr ""
 
+#: src/views/system/SelfCheck/tasks.ts:3
+msgid "Sites Directory"
+msgstr ""
+
 #: src/routes/index.ts:56
 msgid "Sites List"
 msgstr ""
@@ -2175,6 +2217,10 @@ msgstr ""
 msgid "Storage"
 msgstr ""
 
+#: src/views/system/SelfCheck/tasks.ts:7
+msgid "Streams Directory"
+msgstr ""
+
 #: src/constants/index.ts:19
 #: src/views/notification/notificationColumns.tsx:36
 msgid "Success"
@@ -2468,7 +2514,7 @@ msgstr ""
 msgid "Updated successfully"
 msgstr ""
 
-#: src/routes/index.ts:290
+#: src/routes/index.ts:297
 #: src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145
 #: src/views/system/Upgrade.vue:228

+ 57 - 6
app/src/language/ru_RU/app.po

@@ -23,7 +23,7 @@ msgstr "2FA"
 msgid "2FA Settings"
 msgstr "Настройки 2FA"
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr "О проекте"
 
@@ -203,6 +203,11 @@ msgstr "Обратитесь за помощью к ChatGPT"
 msgid "Assistant"
 msgstr "Ассистент"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+#, fuzzy
+msgid "Attempt to fix"
+msgstr "Попытки"
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr "Попытки"
@@ -387,6 +392,26 @@ msgstr "Канал"
 msgid "Check again"
 msgstr "Проверить повторно"
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid ""
+"Check if the sites-available and sites-enabled directory is under the nginx "
+"configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid ""
+"Check if the streams-available and streams-enabled directory is under the "
+"nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr "Очистка переменных среды"
@@ -1146,7 +1171,7 @@ msgstr "Введите код из приложения:"
 msgid "Input the recovery code:"
 msgstr "Введите код восстановления:"
 
-#: src/routes/index.ts:305 src/views/other/Install.vue:136
+#: src/routes/index.ts:312 src/views/other/Install.vue:136
 msgid "Install"
 msgstr "Установить"
 
@@ -1285,7 +1310,7 @@ msgstr "Локации"
 msgid "Log"
 msgstr "Журнал"
 
-#: src/routes/index.ts:311 src/views/other/Login.vue:246
+#: src/routes/index.ts:318 src/views/other/Login.vue:246
 msgid "Login"
 msgstr "Логин"
 
@@ -1450,6 +1475,14 @@ msgstr "Nginx"
 msgid "Nginx Access Log Path"
 msgstr "Путь для Nginx Access Log"
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 msgid "Nginx Configuration Parse Error"
@@ -1532,7 +1565,7 @@ msgstr ""
 msgid "Not After"
 msgstr "Не позднее"
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 msgid "Not Found"
 msgstr "Не найден"
 
@@ -1840,6 +1873,10 @@ msgstr "Чтение"
 msgid "Receive"
 msgstr "Принято"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 msgid "Recover"
@@ -2144,6 +2181,10 @@ msgstr ""
 msgid "Selector"
 msgstr "Выбор"
 
+#: src/routes/index.ts:283 src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 msgid "Send"
@@ -2156,7 +2197,7 @@ msgstr "Отправлено"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
-#: src/views/config/components/Mkdir.vue:38
+#: src/lib/http/index.ts:129 src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
 #: src/views/environment/BatchUpgrader.vue:59
@@ -2226,6 +2267,11 @@ msgstr ""
 msgid "Site Logs"
 msgstr "Журналы сайта"
 
+#: src/views/system/SelfCheck/tasks.ts:3
+#, fuzzy
+msgid "Sites Directory"
+msgstr "Каталог"
+
 #: src/routes/index.ts:56
 msgid "Sites List"
 msgstr "Список сайтов"
@@ -2272,6 +2318,11 @@ msgstr "Остановлен"
 msgid "Storage"
 msgstr "Хранилище"
 
+#: src/views/system/SelfCheck/tasks.ts:7
+#, fuzzy
+msgid "Streams Directory"
+msgstr "Каталог"
+
 #: src/constants/index.ts:19 src/views/notification/notificationColumns.tsx:36
 msgid "Success"
 msgstr "Успех"
@@ -2642,7 +2693,7 @@ msgstr "Обновлено в"
 msgid "Updated successfully"
 msgstr "Успешно обновлено"
 
-#: src/routes/index.ts:290 src/views/environment/Environment.vue:55
+#: src/routes/index.ts:297 src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145 src/views/system/Upgrade.vue:228
 msgid "Upgrade"
 msgstr "Обновление"

+ 57 - 6
app/src/language/tr_TR/app.po

@@ -20,7 +20,7 @@ msgstr "İki aşamalı kimlik doğrulaması(2FA)"
 msgid "2FA Settings"
 msgstr "2FA Ayarları"
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr "Hakkında"
 
@@ -199,6 +199,11 @@ msgstr "ChatGPT'den Yardım İsteyin"
 msgid "Assistant"
 msgstr "Asistan"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+#, fuzzy
+msgid "Attempt to fix"
+msgstr "Girişimler"
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr "Girişimler"
@@ -381,6 +386,26 @@ msgstr "Kanal"
 msgid "Check again"
 msgstr "Tekrar kontrol et"
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid ""
+"Check if the sites-available and sites-enabled directory is under the nginx "
+"configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid ""
+"Check if the streams-available and streams-enabled directory is under the "
+"nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr "Ortam değişkenlerini temizleme"
@@ -1148,7 +1173,7 @@ msgstr "Uygulamadan kodu girin:"
 msgid "Input the recovery code:"
 msgstr "Kurtarma kodunu girin:"
 
-#: src/routes/index.ts:305 src/views/other/Install.vue:136
+#: src/routes/index.ts:312 src/views/other/Install.vue:136
 msgid "Install"
 msgstr "Yükle"
 
@@ -1286,7 +1311,7 @@ msgstr "Konumlar"
 msgid "Log"
 msgstr "Günlük"
 
-#: src/routes/index.ts:311 src/views/other/Login.vue:246
+#: src/routes/index.ts:318 src/views/other/Login.vue:246
 msgid "Login"
 msgstr "Giriş"
 
@@ -1478,6 +1503,14 @@ msgstr "Nginx"
 msgid "Nginx Access Log Path"
 msgstr "Nginx Erişim Günlüğü Yolu"
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 #, fuzzy
@@ -1570,7 +1603,7 @@ msgstr "Düğüm Sırrı"
 msgid "Not After"
 msgstr "Sonra değil"
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 #, fuzzy
 msgid "Not Found"
 msgstr "Bulunamadı"
@@ -1935,6 +1968,10 @@ msgstr "Okumalar"
 msgid "Receive"
 msgstr "Teslim almak"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 #, fuzzy
@@ -2289,6 +2326,10 @@ msgstr "Sır kopyalandı"
 msgid "Selector"
 msgstr "Selektör"
 
+#: src/routes/index.ts:283 src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 #, fuzzy
@@ -2302,7 +2343,7 @@ msgstr "Gönder"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
-#: src/views/config/components/Mkdir.vue:38
+#: src/lib/http/index.ts:129 src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
 #: src/views/environment/BatchUpgrader.vue:59
@@ -2384,6 +2425,11 @@ msgstr ""
 msgid "Site Logs"
 msgstr "Site Günlükleri"
 
+#: src/views/system/SelfCheck/tasks.ts:3
+#, fuzzy
+msgid "Sites Directory"
+msgstr "Dizin"
+
 #: src/routes/index.ts:56
 #, fuzzy
 msgid "Sites List"
@@ -2440,6 +2486,11 @@ msgstr "Durduruldu"
 msgid "Storage"
 msgstr "Depolama"
 
+#: src/views/system/SelfCheck/tasks.ts:7
+#, fuzzy
+msgid "Streams Directory"
+msgstr "Dizin"
+
 #: src/constants/index.ts:19 src/views/notification/notificationColumns.tsx:36
 #, fuzzy
 msgid "Success"
@@ -2867,7 +2918,7 @@ msgstr "Güncelleme"
 msgid "Updated successfully"
 msgstr "Başarıyla güncellendi"
 
-#: src/routes/index.ts:290 src/views/environment/Environment.vue:55
+#: src/routes/index.ts:297 src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145 src/views/system/Upgrade.vue:228
 #, fuzzy
 msgid "Upgrade"

+ 56 - 6
app/src/language/vi_VN/app.po

@@ -17,7 +17,7 @@ msgstr ""
 msgid "2FA Settings"
 msgstr ""
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr "Tác giả"
 
@@ -210,6 +210,10 @@ msgstr "Hỏi ChatGPT"
 msgid "Assistant"
 msgstr "Trợ lý"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+msgid "Attempt to fix"
+msgstr ""
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr ""
@@ -405,6 +409,26 @@ msgstr "Kênh"
 msgid "Check again"
 msgstr "Kiểm tra lại"
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid ""
+"Check if the sites-available and sites-enabled directory is under the nginx "
+"configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid ""
+"Check if the streams-available and streams-enabled directory is under the "
+"nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr "Xoá các biến môi trường"
@@ -1186,7 +1210,7 @@ msgstr ""
 msgid "Input the recovery code:"
 msgstr ""
 
-#: src/routes/index.ts:305 src/views/other/Install.vue:136
+#: src/routes/index.ts:312 src/views/other/Install.vue:136
 msgid "Install"
 msgstr "Cài đặt"
 
@@ -1339,7 +1363,7 @@ msgstr "Locations"
 msgid "Log"
 msgstr "Log"
 
-#: src/routes/index.ts:311 src/views/other/Login.vue:246
+#: src/routes/index.ts:318 src/views/other/Login.vue:246
 msgid "Login"
 msgstr "Đăng nhập"
 
@@ -1507,6 +1531,14 @@ msgstr ""
 msgid "Nginx Access Log Path"
 msgstr "Vị trí lưu log truy cập (Access log) của Nginx"
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 #, fuzzy
@@ -1591,7 +1623,7 @@ msgstr ""
 msgid "Not After"
 msgstr "Không phải sau khi"
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 msgid "Not Found"
 msgstr "Không tìm thấy"
 
@@ -1896,6 +1928,10 @@ msgstr "Đọc"
 msgid "Receive"
 msgstr "Nhận"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 msgid "Recover"
@@ -2215,6 +2251,10 @@ msgstr ""
 msgid "Selector"
 msgstr "Bộ chọn"
 
+#: src/routes/index.ts:283 src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 msgid "Send"
@@ -2227,7 +2267,7 @@ msgstr "Gửi"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
-#: src/views/config/components/Mkdir.vue:38
+#: src/lib/http/index.ts:129 src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
 #: src/views/environment/BatchUpgrader.vue:59
@@ -2297,6 +2337,11 @@ msgstr ""
 msgid "Site Logs"
 msgstr "Logs"
 
+#: src/views/system/SelfCheck/tasks.ts:3
+#, fuzzy
+msgid "Sites Directory"
+msgstr "Thư mục"
+
 #: src/routes/index.ts:56
 msgid "Sites List"
 msgstr "Danh sách Website"
@@ -2344,6 +2389,11 @@ msgstr "Đã dừng"
 msgid "Storage"
 msgstr "Storage"
 
+#: src/views/system/SelfCheck/tasks.ts:7
+#, fuzzy
+msgid "Streams Directory"
+msgstr "Thư mục"
+
 #: src/constants/index.ts:19 src/views/notification/notificationColumns.tsx:36
 msgid "Success"
 msgstr "Thành công"
@@ -2692,7 +2742,7 @@ msgstr "Ngày cập nhật"
 msgid "Updated successfully"
 msgstr "Cập nhật thành công"
 
-#: src/routes/index.ts:290 src/views/environment/Environment.vue:55
+#: src/routes/index.ts:297 src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145 src/views/system/Upgrade.vue:228
 msgid "Upgrade"
 msgstr "Cập nhật"

+ 57 - 6
app/src/language/zh_CN/app.po

@@ -21,7 +21,7 @@ msgstr "2FA"
 msgid "2FA Settings"
 msgstr "2FA 设置"
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr "关于"
 
@@ -196,6 +196,11 @@ msgstr "与ChatGPT聊天"
 msgid "Assistant"
 msgstr "助手"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+#, fuzzy
+msgid "Attempt to fix"
+msgstr "尝试次数"
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr "尝试次数"
@@ -375,6 +380,26 @@ msgstr "通道"
 msgid "Check again"
 msgstr "重新检查"
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid ""
+"Check if the sites-available and sites-enabled directory is under the nginx "
+"configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid ""
+"Check if the streams-available and streams-enabled directory is under the "
+"nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr "正在清理环境变量"
@@ -1102,7 +1127,7 @@ msgstr "输入应用程序中的代码:"
 msgid "Input the recovery code:"
 msgstr "输入恢复代码:"
 
-#: src/routes/index.ts:305 src/views/other/Install.vue:136
+#: src/routes/index.ts:312 src/views/other/Install.vue:136
 msgid "Install"
 msgstr "安装"
 
@@ -1239,7 +1264,7 @@ msgstr "Locations"
 msgid "Log"
 msgstr "日志"
 
-#: src/routes/index.ts:311 src/views/other/Login.vue:246
+#: src/routes/index.ts:318 src/views/other/Login.vue:246
 msgid "Login"
 msgstr "登录"
 
@@ -1402,6 +1427,14 @@ msgstr "Nginx"
 msgid "Nginx Access Log Path"
 msgstr "Nginx 访问日志路径"
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 msgid "Nginx Configuration Parse Error"
@@ -1480,7 +1513,7 @@ msgstr "节点密钥"
 msgid "Not After"
 msgstr "有效期"
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 msgid "Not Found"
 msgstr "找不到页面"
 
@@ -1775,6 +1808,10 @@ msgstr "读"
 msgid "Receive"
 msgstr "下载"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 msgid "Recover"
@@ -2061,6 +2098,10 @@ msgstr "密钥已复制"
 msgid "Selector"
 msgstr "选择器"
 
+#: src/routes/index.ts:283 src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 msgid "Send"
@@ -2073,7 +2114,7 @@ msgstr "上传"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
-#: src/views/config/components/Mkdir.vue:38
+#: src/lib/http/index.ts:129 src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
 #: src/views/environment/BatchUpgrader.vue:59
@@ -2141,6 +2182,11 @@ msgstr "网站分类"
 msgid "Site Logs"
 msgstr "站点列表"
 
+#: src/views/system/SelfCheck/tasks.ts:3
+#, fuzzy
+msgid "Sites Directory"
+msgstr "目录"
+
 #: src/routes/index.ts:56
 msgid "Sites List"
 msgstr "站点列表"
@@ -2187,6 +2233,11 @@ msgstr "已停止"
 msgid "Storage"
 msgstr "存储"
 
+#: src/views/system/SelfCheck/tasks.ts:7
+#, fuzzy
+msgid "Streams Directory"
+msgstr "目录"
+
 #: src/constants/index.ts:19 src/views/notification/notificationColumns.tsx:36
 msgid "Success"
 msgstr "成功"
@@ -2523,7 +2574,7 @@ msgstr "修改时间"
 msgid "Updated successfully"
 msgstr "更新成功"
 
-#: src/routes/index.ts:290 src/views/environment/Environment.vue:55
+#: src/routes/index.ts:297 src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145 src/views/system/Upgrade.vue:228
 msgid "Upgrade"
 msgstr "升级"

+ 57 - 6
app/src/language/zh_TW/app.po

@@ -25,7 +25,7 @@ msgstr "多重要素驗證"
 msgid "2FA Settings"
 msgstr "多重要素驗證設定"
 
-#: src/routes/index.ts:283
+#: src/routes/index.ts:290
 msgid "About"
 msgstr "關於"
 
@@ -204,6 +204,11 @@ msgstr "向 ChatGPT 尋求幫助"
 msgid "Assistant"
 msgstr "助理"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:50
+#, fuzzy
+msgid "Attempt to fix"
+msgstr "嘗試次數"
+
 #: src/views/preference/AuthSettings.vue:17
 msgid "Attempts"
 msgstr "嘗試次數"
@@ -385,6 +390,26 @@ msgstr "通道"
 msgid "Check again"
 msgstr "再次檢查"
 
+#: src/views/system/SelfCheck/tasks.ts:12
+msgid "Check if the nginx.conf includes the sites-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:16
+msgid "Check if the nginx.conf includes the streams-enabled directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:4
+msgid ""
+"Check if the sites-available and sites-enabled directory is under the nginx "
+"configuration directory."
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:8
+msgid ""
+"Check if the streams-available and streams-enabled directory is under the "
+"nginx configuration directory."
+msgstr ""
+
 #: src/language/constants.ts:13
 msgid "Cleaning environment variables"
 msgstr "清理環境變數"
@@ -1125,7 +1150,7 @@ msgstr "請輸入應用程式中的代碼:"
 msgid "Input the recovery code:"
 msgstr "輸入恢復碼:"
 
-#: src/routes/index.ts:305 src/views/other/Install.vue:136
+#: src/routes/index.ts:312 src/views/other/Install.vue:136
 msgid "Install"
 msgstr "安裝"
 
@@ -1265,7 +1290,7 @@ msgstr "Locations"
 msgid "Log"
 msgstr "日誌"
 
-#: src/routes/index.ts:311 src/views/other/Login.vue:246
+#: src/routes/index.ts:318 src/views/other/Login.vue:246
 msgid "Login"
 msgstr "登入"
 
@@ -1427,6 +1452,14 @@ msgstr "Nginx"
 msgid "Nginx Access Log Path"
 msgstr "Nginx 存取日誌路徑"
 
+#: src/views/system/SelfCheck/tasks.ts:11
+msgid "Nginx Conf Include Sites Enabled"
+msgstr ""
+
+#: src/views/system/SelfCheck/tasks.ts:15
+msgid "Nginx Conf Include Streams Enabled"
+msgstr ""
+
 #: src/views/site/site_edit/SiteEdit.vue:223
 #: src/views/stream/StreamEdit.vue:207
 msgid "Nginx Configuration Parse Error"
@@ -1509,7 +1542,7 @@ msgstr "Node Secret"
 msgid "Not After"
 msgstr "不晚於"
 
-#: src/routes/index.ts:317
+#: src/routes/index.ts:324
 msgid "Not Found"
 msgstr "找不到頁面"
 
@@ -1808,6 +1841,10 @@ msgstr "讀取"
 msgid "Receive"
 msgstr "接收"
 
+#: src/views/system/SelfCheck/SelfCheck.vue:42
+msgid "Recheck"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:43
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:544
 msgid "Recover"
@@ -2107,6 +2144,10 @@ msgstr ""
 msgid "Selector"
 msgstr "選擇器"
 
+#: src/routes/index.ts:283 src/views/system/SelfCheck/SelfCheck.vue:37
+msgid "Self Check"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:348
 #: src/views/dashboard/ServerAnalytic.vue:35
 msgid "Send"
@@ -2119,7 +2160,7 @@ msgstr "傳送"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:53
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:70
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:194
-#: src/views/config/components/Mkdir.vue:38
+#: src/lib/http/index.ts:129 src/views/config/components/Mkdir.vue:38
 #: src/views/config/components/Rename.vue:45
 #: src/views/config/ConfigEditor.vue:111
 #: src/views/environment/BatchUpgrader.vue:59
@@ -2187,6 +2228,11 @@ msgstr ""
 msgid "Site Logs"
 msgstr "網站日誌"
 
+#: src/views/system/SelfCheck/tasks.ts:3
+#, fuzzy
+msgid "Sites Directory"
+msgstr "目錄"
+
 #: src/routes/index.ts:56
 msgid "Sites List"
 msgstr "網站列表"
@@ -2233,6 +2279,11 @@ msgstr "已停止"
 msgid "Storage"
 msgstr "儲存空間"
 
+#: src/views/system/SelfCheck/tasks.ts:7
+#, fuzzy
+msgid "Streams Directory"
+msgstr "目錄"
+
 #: src/constants/index.ts:19 src/views/notification/notificationColumns.tsx:36
 msgid "Success"
 msgstr "成功"
@@ -2574,7 +2625,7 @@ msgstr "更新時間"
 msgid "Updated successfully"
 msgstr "更新成功"
 
-#: src/routes/index.ts:290 src/views/environment/Environment.vue:55
+#: src/routes/index.ts:297 src/views/environment/Environment.vue:55
 #: src/views/system/Upgrade.vue:145 src/views/system/Upgrade.vue:228
 msgid "Upgrade"
 msgstr "升級"

+ 60 - 1
app/src/lib/http/index.ts

@@ -3,8 +3,9 @@ import use2FAModal from '@/components/TwoFA/use2FAModal'
 import { useNProgress } from '@/lib/nprogress/nprogress'
 import { useSettingsStore, useUserStore } from '@/pinia'
 import router from '@/routes'
-import axios from 'axios'
+import { message } from 'ant-design-vue'
 
+import axios from 'axios'
 import { storeToRefs } from 'pinia'
 import 'nprogress/nprogress.css'
 
@@ -12,6 +13,23 @@ const user = useUserStore()
 const settings = useSettingsStore()
 const { token, secureSessionId } = storeToRefs(user)
 
+// server response
+export interface CosyError {
+  scope?: string
+  code: string
+  message: string
+  params?: string[]
+}
+
+// code, message translation
+export type CosyErrorRecord = Record<number, () => string>
+
+const errors: Record<string, CosyErrorRecord> = {}
+
+function registerError(scope: string, record: CosyErrorRecord) {
+  errors[scope] = record
+}
+
 const instance = axios.create({
   baseURL: import.meta.env.VITE_API_ROOT,
   timeout: 50000,
@@ -59,6 +77,7 @@ instance.interceptors.response.use(
 
     return Promise.resolve(response.data)
   },
+  // eslint-disable-next-line sonarjs/cognitive-complexity
   async error => {
     nprogress.done()
 
@@ -74,6 +93,46 @@ instance.interceptors.response.use(
         break
     }
 
+    const err = error.response.data as CosyError
+
+    if (err?.scope) {
+      // check if already register
+      if (!errors[err.scope]) {
+        try {
+          const error = await import(`@/constants/errors/${err.scope}.ts`)
+
+          registerError(err.scope, error.default)
+        }
+        catch {
+          /* empty */
+        }
+      }
+
+      const msg = errors?.[err.scope]?.[err.code]
+
+      if (msg) {
+        // if err has parmas
+        if (err?.params && err.params.length > 0) {
+          let res = msg()
+
+          err.params.forEach((param, index) => {
+            res = res.replaceAll(`{${index}}`, param)
+          })
+
+          message.error(res, 5)
+        }
+        else {
+          message.error(msg(), 5)
+        }
+      }
+      else {
+        message.error($gettext('Server error'))
+      }
+    }
+    else {
+      message.error($gettext(err?.message ?? 'Server error'))
+    }
+
     return Promise.reject(error.response.data)
   },
 )

+ 7 - 0
app/src/routes/index.ts

@@ -276,6 +276,13 @@ export const routes: RouteRecordRaw[] = [
           icon: InfoCircleOutlined,
         },
         children: [{
+          path: 'self_check',
+          name: 'Self Check',
+          component: () => import('@/views/system/SelfCheck/SelfCheck.vue'),
+          meta: {
+            name: () => $gettext('Self Check'),
+          },
+        }, {
           path: 'about',
           name: 'About',
           component: () => import('@/views/system/About.vue'),

+ 77 - 0
app/src/views/system/SelfCheck/SelfCheck.vue

@@ -0,0 +1,77 @@
+<script setup lang="ts">
+import type { Report } from '@/api/self_check'
+import selfCheck from '@/api/self_check'
+import { CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons-vue'
+import tasks from './tasks'
+
+const data = ref<Report[]>()
+
+const loading = ref(false)
+
+function check() {
+  loading.value = true
+  selfCheck.run().then(r => {
+    data.value = r
+  }).finally(() => {
+    loading.value = false
+  })
+}
+
+onMounted(() => {
+  check()
+})
+
+const fixing = reactive({})
+
+function fix(taskName: string) {
+  fixing[taskName] = true
+  selfCheck.fix(taskName).then(() => {
+    check()
+  }).finally(() => {
+    fixing[taskName] = false
+  })
+}
+</script>
+
+<template>
+  <ACard :title="$gettext('Self Check')">
+    <template #extra>
+      <AButton
+        type="link" size="small" :loading @click="check"
+      >
+        {{ $gettext('Recheck') }}
+      </AButton>
+    </template>
+    <AList :data-source="data">
+      <template #renderItem="{ item }">
+        <AListItem>
+          <template v-if="item.err" #actions>
+            <AButton type="link" size="small" :loading="fixing[item.name]" @click="fix(item.name)">
+              {{ $gettext('Attempt to fix') }}
+            </AButton>
+          </template>
+          <AListItemMeta>
+            <template #title>
+              {{ tasks?.[item.name]?.name?.() }}
+            </template>
+            <template #description>
+              {{ tasks?.[item.name]?.description?.() }}
+            </template>
+            <template #avatar>
+              <div class="text-23px">
+                <CheckCircleOutlined v-if="!item.err" class="text-green" />
+                <CloseCircleOutlined v-else class="text-red" />
+              </div>
+            </template>
+          </AListItemMeta>
+        </AListItem>
+      </template>
+    </AList>
+  </ACard>
+</template>
+
+<style scoped lang="less">
+:deep(.ant-list-item-meta) {
+  align-items: center !important;
+}
+</style>

+ 20 - 0
app/src/views/system/SelfCheck/tasks.ts

@@ -0,0 +1,20 @@
+const tasks = {
+  'Directory-Sites': {
+    name: () => $gettext('Sites Directory'),
+    description: () => $gettext('Check if the sites-available and sites-enabled directory is under the nginx configuration directory.'),
+  },
+  'Directory-Streams': {
+    name: () => $gettext('Streams Directory'),
+    description: () => $gettext('Check if the streams-available and streams-enabled directory is under the nginx configuration directory.'),
+  },
+  'NginxConf-Sites-Enabled': {
+    name: () => $gettext('Nginx Conf Include Sites Enabled'),
+    description: () => $gettext('Check if the nginx.conf includes the sites-enabled directory.'),
+  },
+  'NginxConf-Streams-Enabled': {
+    name: () => $gettext('Nginx Conf Include Streams Enabled'),
+    description: () => $gettext('Check if the nginx.conf includes the streams-enabled directory.'),
+  },
+}
+
+export default tasks

+ 1 - 0
docs/guide/about.md

@@ -92,3 +92,4 @@ We welcome translations into any language.
 - [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
 - [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
 - [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
+- [lego](https://github.com/go-acme/lego)

+ 1 - 0
docs/zh_CN/guide/about.md

@@ -89,3 +89,4 @@ Nginx UI 可在以下平台中使用:
 - [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
 - [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
 - [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
+- [lego](https://github.com/go-acme/lego)

+ 1 - 0
docs/zh_TW/guide/about.md

@@ -89,3 +89,4 @@ Nginx UI 可在以下作業系統中使用:
 - [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
 - [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
 - [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
+- [lego](https://github.com/go-acme/lego)

+ 20 - 3
internal/nginx/config_args.go

@@ -39,6 +39,23 @@ func GetConfPath(dir ...string) (confPath string) {
 	return joined
 }
 
+func GetConfEntryPath() (path string) {
+	if settings.NginxSettings.ConfigPath == "" {
+		out := getNginxV()
+		r, _ := regexp.Compile("--conf-path=(.*.conf)")
+		match := r.FindStringSubmatch(out)
+		if len(match) < 1 {
+			logger.Error("nginx.GetConfEntryPath len(match) < 1")
+			return ""
+		}
+		path = match[1]
+	} else {
+		path = settings.NginxSettings.ConfigPath
+	}
+
+	return
+}
+
 func GetPIDPath() (path string) {
 	if settings.NginxSettings.PIDPath == "" {
 		out := getNginxV()
@@ -53,7 +70,7 @@ func GetPIDPath() (path string) {
 		path = settings.NginxSettings.PIDPath
 	}
 
-	return path
+	return
 }
 
 func GetSbinPath() (path string) {
@@ -66,7 +83,7 @@ func GetSbinPath() (path string) {
 	}
 	path = match[1]
 
-	return path
+	return
 }
 
 func GetAccessLogPath() (path string) {
@@ -83,7 +100,7 @@ func GetAccessLogPath() (path string) {
 		path = settings.NginxSettings.AccessLogPath
 	}
 
-	return path
+	return
 }
 
 func GetErrorLogPath() string {

+ 67 - 0
internal/self_check/directory.go

@@ -0,0 +1,67 @@
+package self_check
+
+import (
+	"os"
+
+	"github.com/0xJacky/Nginx-UI/internal/nginx"
+)
+
+// CheckSitesDirectory checks if sites-available/sites-enabled directory exists
+func CheckSitesDirectory() error {
+	// check sites-available directory
+	if _, err := os.Stat(nginx.GetConfPath("sites-available")); os.IsNotExist(err) {
+		return ErrSitesAvailableNotExist
+	}
+
+	// check sites-enabled directory
+	if _, err := os.Stat(nginx.GetConfPath("sites-enabled")); os.IsNotExist(err) {
+		return ErrSitesEnabledNotExist
+	}
+
+	return nil
+}
+
+// CheckStreamDirectory checks if stream-available/stream-enabled directory exists
+func CheckStreamDirectory() error {
+	// check stream-available directory
+	if _, err := os.Stat(nginx.GetConfPath("streams-available")); os.IsNotExist(err) {
+		return ErrStreamAvailableNotExist
+	}
+
+	// check stream-enabled directory
+	if _, err := os.Stat(nginx.GetConfPath("streams-enabled")); os.IsNotExist(err) {
+		return ErrStreamEnabledNotExist
+	}
+
+	return nil
+}
+
+// FixSitesDirectory creates sites-available/sites-enabled directory
+func FixSitesDirectory() error {
+	// create sites-available directory
+	if err := os.MkdirAll(nginx.GetConfPath("sites-available"), 0755); err != nil {
+		return err
+	}
+
+	// create sites-enabled directory
+	if err := os.MkdirAll(nginx.GetConfPath("sites-enabled"), 0755); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// FixStreamDirectory creates stream-available/stream-enabled directory
+func FixStreamDirectory() error {
+	// create stream-available directory
+	if err := os.MkdirAll(nginx.GetConfPath("streams-available"), 0755); err != nil {
+		return err
+	}
+
+	// create stream-enabled directory
+	if err := os.MkdirAll(nginx.GetConfPath("streams-enabled"), 0755); err != nil {
+		return err
+	}
+
+	return nil
+}

+ 19 - 0
internal/self_check/errors.go

@@ -0,0 +1,19 @@
+package self_check
+
+import "github.com/uozi-tech/cosy"
+
+var (
+	e                                   = cosy.NewErrorScope("self_check")
+	ErrTaskNotFound                     = e.New(4040, "Task not found")
+	ErrFailedToReadNginxConf            = e.New(4041, "Failed to read nginx.conf")
+	ErrParseNginxConf                   = e.New(5001, "Failed to parse nginx.conf")
+	ErrNginxConfNoHttpBlock             = e.New(4042, "Nginx conf no http block")
+	ErrNginxConfNotIncludeSitesEnabled  = e.New(4043, "Nginx conf not include sites-enabled")
+	ErrorNginxConfNoStreamBlock         = e.New(4044, "Nginx conf no stream block")
+	ErrNginxConfNotIncludeStreamEnabled = e.New(4045, "Nginx conf not include stream-enabled")
+	ErrFailedToCreateBackup             = e.New(5001, "Failed to create backup")
+	ErrSitesAvailableNotExist           = e.New(4046, "Sites-available directory not exist")
+	ErrSitesEnabledNotExist             = e.New(4047, "Sites-enabled directory not exist")
+	ErrStreamAvailableNotExist          = e.New(4048, "Stream-available directory not exist")
+	ErrStreamEnabledNotExist            = e.New(4049, "Stream-enabled directory not exist")
+)

+ 168 - 0
internal/self_check/nginx_conf.go

@@ -0,0 +1,168 @@
+package self_check
+
+import (
+	"fmt"
+	"os"
+	"time"
+
+	"github.com/0xJacky/Nginx-UI/internal/nginx"
+	"github.com/spf13/cast"
+	"github.com/tufanbarisyildirim/gonginx/config"
+	"github.com/tufanbarisyildirim/gonginx/dumper"
+	"github.com/tufanbarisyildirim/gonginx/parser"
+)
+
+// CheckNginxConfIncludeSites checks if nginx.conf include sites-enabled
+func CheckNginxConfIncludeSites() error {
+	path := nginx.GetConfEntryPath()
+
+	content, err := os.ReadFile(path)
+	if err != nil {
+		return ErrFailedToReadNginxConf
+	}
+
+	// parse nginx.conf
+	p := parser.NewStringParser(string(content), parser.WithSkipValidDirectivesErr())
+	c, err := p.Parse()
+	if err != nil {
+		return ErrParseNginxConf
+	}
+
+	// find http block
+	for _, v := range c.Block.Directives {
+		if v.GetName() == "http" {
+			// find include sites-enabled
+			for _, directive := range v.GetBlock().GetDirectives() {
+				if directive.GetName() == "include" && len(directive.GetParameters()) > 0 &&
+					directive.GetParameters()[0] == nginx.GetConfPath("sites-enabled/*") {
+					return nil
+				}
+			}
+			return ErrNginxConfNotIncludeSitesEnabled
+		}
+	}
+
+	return ErrNginxConfNoHttpBlock
+}
+
+// CheckNginxConfIncludeStreams checks if nginx.conf include streams-enabled
+func CheckNginxConfIncludeStreams() error {
+	path := nginx.GetConfEntryPath()
+
+	content, err := os.ReadFile(path)
+	if err != nil {
+		return ErrFailedToReadNginxConf
+	}
+
+	// parse nginx.conf
+	p := parser.NewStringParser(string(content), parser.WithSkipValidDirectivesErr())
+	c, err := p.Parse()
+	if err != nil {
+		return ErrParseNginxConf
+	}
+
+	// find http block
+	for _, v := range c.Block.Directives {
+		if v.GetName() == "stream" {
+			// find include sites-enabled
+			for _, directive := range v.GetBlock().GetDirectives() {
+				if directive.GetName() == "include" && len(directive.GetParameters()) > 0 &&
+					directive.GetParameters()[0] == nginx.GetConfPath("streams-enabled/*") {
+					return nil
+				}
+			}
+			return ErrNginxConfNotIncludeStreamEnabled
+		}
+	}
+
+	return ErrorNginxConfNoStreamBlock
+}
+
+// FixNginxConfIncludeSites attempts to fix nginx.conf include sites-enabled
+func FixNginxConfIncludeSites() error {
+	path := nginx.GetConfEntryPath()
+
+	content, err := os.ReadFile(path)
+	if err != nil {
+		return ErrFailedToReadNginxConf
+	}
+
+	// create a backup file (+.bak.timestamp)
+	backupPath := path + ".bak." + cast.ToString(time.Now().Unix())
+	err = os.WriteFile(backupPath, content, 0644)
+	if err != nil {
+		return ErrFailedToCreateBackup
+	}
+
+	// parse nginx.conf
+	p := parser.NewStringParser(string(content), parser.WithSkipValidDirectivesErr())
+	c, err := p.Parse()
+	if err != nil {
+		return ErrParseNginxConf
+	}
+
+	// find http block
+	for _, v := range c.Block.Directives {
+		if v.GetName() == "http" {
+			// add include sites-enabled/* to http block
+			includeDirective := &config.Directive{
+				Name:       "include",
+				Parameters: []string{nginx.GetConfPath("sites-enabled/*")},
+			}
+
+			realBlock := v.GetBlock().(*config.HTTP)
+			realBlock.Directives = append(realBlock.Directives, includeDirective)
+
+			// write to file
+			return os.WriteFile(path, []byte(dumper.DumpBlock(c.Block, dumper.IndentedStyle)), 0644)
+		}
+	}
+
+	// if no http block, append http block with include sites-enabled/*
+	content = append(content, []byte(fmt.Sprintf("\nhttp {\n\tinclude %s;\n}\n", nginx.GetConfPath("sites-enabled/*")))...)
+	return os.WriteFile(path, content, 0644)
+}
+
+// FixNginxConfIncludeStreams attempts to fix nginx.conf include streams-enabled
+func FixNginxConfIncludeStreams() error {
+	path := nginx.GetConfEntryPath()
+
+	content, err := os.ReadFile(path)
+	if err != nil {
+		return ErrFailedToReadNginxConf
+	}
+
+	// create a backup file (+.bak.timestamp)
+	backupPath := path + ".bak." + cast.ToString(time.Now().Unix())
+	err = os.WriteFile(backupPath, content, 0644)
+	if err != nil {
+		return ErrFailedToCreateBackup
+	}
+
+	// parse nginx.conf
+	p := parser.NewStringParser(string(content), parser.WithSkipValidDirectivesErr())
+	c, err := p.Parse()
+	if err != nil {
+		return ErrParseNginxConf
+	}
+
+	// find stream block
+	for _, v := range c.Block.Directives {
+		if v.GetName() == "stream" {
+			// add include streams-enabled/* to stream block
+			includeDirective := &config.Directive{
+				Name:       "include",
+				Parameters: []string{nginx.GetConfPath("streams-enabled/*")},
+			}
+			realBlock := v.GetBlock().(*config.Block)
+			realBlock.Directives = append(realBlock.Directives, includeDirective)
+
+			// write to file
+			return os.WriteFile(path, []byte(dumper.DumpBlock(c.Block, dumper.IndentedStyle)), 0644)
+		}
+	}
+
+	// if no stream block, append stream block with include streams-enabled/*
+	content = append(content, []byte(fmt.Sprintf("\nstream {\n\tinclude %s;\n}\n", nginx.GetConfPath("streams-enabled/*")))...)
+	return os.WriteFile(path, content, 0644)
+}

+ 123 - 0
internal/self_check/nginx_conf_test.go

@@ -0,0 +1,123 @@
+package self_check
+
+import (
+	"errors"
+	"os"
+	"strings"
+	"testing"
+
+	"github.com/0xJacky/Nginx-UI/settings"
+	"github.com/stretchr/testify/assert"
+	"github.com/uozi-tech/cosy"
+	"github.com/uozi-tech/cosy/logger"
+)
+
+func TestCheckNginxConfIncludeSites(t *testing.T) {
+	// test ok
+	logger.Init("debug")
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+	settings.NginxSettings.ConfigPath = "./test_cases/ok.conf"
+	var result *cosy.Error
+	errors.As(CheckNginxConfIncludeSites(), &result)
+	assert.Nil(t, result)
+
+	// test 4041 nginx.conf not found
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+	settings.NginxSettings.ConfigPath = "./test_cases/4041.conf"
+	errors.As(CheckNginxConfIncludeSites(), &result)
+	assert.Equal(t, int32(4041), result.Code)
+
+	// test 5001 nginx.conf parse error
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+	settings.NginxSettings.ConfigPath = "./test_cases/5001.conf"
+	errors.As(CheckNginxConfIncludeSites(), &result)
+	assert.Equal(t, int32(5001), result.Code)
+
+	// test 4042 nginx.conf no http block
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+	settings.NginxSettings.ConfigPath = "./test_cases/no-http-block.conf"
+	errors.As(CheckNginxConfIncludeSites(), &result)
+	assert.Equal(t, int32(4042), result.Code)
+
+	// test 4043 nginx.conf not include sites-enabled
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+	settings.NginxSettings.ConfigPath = "./test_cases/no-http-sites-enabled.conf"
+	errors.As(CheckNginxConfIncludeSites(), &result)
+	assert.Equal(t, int32(4043), result.Code)
+}
+
+func TestCheckNginxConfIncludeStreams(t *testing.T) {
+	// test ok
+	logger.Init("debug")
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+	settings.NginxSettings.ConfigPath = "./test_cases/ok.conf"
+	var result *cosy.Error
+	errors.As(CheckNginxConfIncludeStreams(), &result)
+	assert.Nil(t, result)
+
+	// test 4041 nginx.conf not found
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+	settings.NginxSettings.ConfigPath = "./test_cases/4041.conf"
+	errors.As(CheckNginxConfIncludeStreams(), &result)
+	assert.Equal(t, int32(4041), result.Code)
+
+	// test 5001 nginx.conf parse error
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+	settings.NginxSettings.ConfigPath = "./test_cases/5001.conf"
+	errors.As(CheckNginxConfIncludeStreams(), &result)
+	assert.Equal(t, int32(5001), result.Code)
+
+	// test 4044 nginx.conf no stream block
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+	settings.NginxSettings.ConfigPath = "./test_cases/no-http-block.conf"
+	errors.As(CheckNginxConfIncludeStreams(), &result)
+	assert.Equal(t, int32(4044), result.Code)
+
+	// test 4045 nginx.conf not include stream-enabled
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+	settings.NginxSettings.ConfigPath = "./test_cases/no-http-sites-enabled.conf"
+	errors.As(CheckNginxConfIncludeStreams(), &result)
+	assert.Equal(t, int32(4045), result.Code)
+}
+
+func TestFixNginxConfIncludeSites(t *testing.T) {
+	logger.Init("debug")
+	settings.NginxSettings.ConfigDir = "/etc/nginx"
+
+	// copy file
+	content, err := os.ReadFile("./test_cases/no-http-block.conf")
+	assert.Nil(t, err)
+
+	err = os.WriteFile("./test_cases/no-http-block-fixed.conf", content, 0644)
+	assert.Nil(t, err)
+
+	settings.NginxSettings.ConfigPath = "./test_cases/no-http-block-fixed.conf"
+	var result *cosy.Error
+	errors.As(FixNginxConfIncludeSites(), &result)
+	assert.Nil(t, result)
+
+	// copy file
+	content, err = os.ReadFile("./test_cases/no-http-sites-enabled.conf")
+	assert.Nil(t, err)
+	err = os.WriteFile("./test_cases/no-http-sites-enabled-fixed.conf", content, 0644)
+	assert.Nil(t, err)
+
+	settings.NginxSettings.ConfigPath = "./test_cases/no-http-sites-enabled-fixed.conf"
+	errors.As(FixNginxConfIncludeSites(), &result)
+	assert.Nil(t, result)
+
+	settings.NginxSettings.ConfigPath = "./test_cases/no-http-sites-enabled-fixed.conf"
+	errors.As(FixNginxConfIncludeStreams(), &result)
+	assert.Nil(t, result)
+
+	// remove backup files (./test_cases/*.bak.*)
+	files, err := os.ReadDir("./test_cases")
+	assert.Nil(t, err)
+
+	for _, file := range files {
+		if strings.Contains(file.Name(), ".bak.") {
+			err = os.Remove("./test_cases/" + file.Name())
+			assert.Nil(t, err)
+		}
+	}
+}

+ 74 - 0
internal/self_check/self_check.go

@@ -0,0 +1,74 @@
+package self_check
+
+import (
+	"errors"
+
+	"github.com/uozi-tech/cosy"
+)
+
+type Task struct {
+	Name      string
+	CheckFunc func() error
+	FixFunc   func() error
+}
+
+type Report struct {
+	Name string      `json:"name"`
+	Err  *cosy.Error `json:"err,omitempty"`
+}
+
+type Reports []*Report
+
+var selfCheckTasks = []*Task{
+	{
+		Name:      "Directory-Sites",
+		CheckFunc: CheckSitesDirectory,
+		FixFunc:   FixSitesDirectory,
+	},
+	{
+		Name:      "Directory-Streams",
+		CheckFunc: CheckStreamDirectory,
+		FixFunc:   FixStreamDirectory,
+	},
+	{
+		Name:      "NginxConf-Sites-Enabled",
+		CheckFunc: CheckNginxConfIncludeSites,
+		FixFunc:   FixNginxConfIncludeSites,
+	},
+	{
+		Name:      "NginxConf-Streams-Enabled",
+		CheckFunc: CheckNginxConfIncludeStreams,
+		FixFunc:   FixNginxConfIncludeStreams,
+	},
+}
+
+var selfCheckTaskMap = make(map[string]*Task)
+
+func init() {
+	for _, task := range selfCheckTasks {
+		selfCheckTaskMap[task.Name] = task
+	}
+}
+
+func Run() (reports Reports) {
+	reports = make(Reports, 0)
+	for _, task := range selfCheckTasks {
+		var cErr *cosy.Error
+		if err := task.CheckFunc(); err != nil {
+			errors.As(err, &cErr)
+		}
+		reports = append(reports, &Report{
+			Name: task.Name,
+			Err:  cErr,
+		})
+	}
+	return
+}
+
+func AttemptFix(taskName string) (err error) {
+	task, ok := selfCheckTaskMap[taskName]
+	if !ok {
+		return ErrTaskNotFound
+	}
+	return task.FixFunc()
+}

+ 1 - 0
internal/self_check/test_cases/5001.conf

@@ -0,0 +1 @@
+5001.conf

+ 14 - 0
internal/self_check/test_cases/no-http-block-fixed.conf

@@ -0,0 +1,14 @@
+user  nginx;
+worker_processes  auto;
+
+error_log  /var/log/nginx/error.log notice;
+error_log  /var/log/nginx/error.local.log notice;
+pid        /var/run/nginx.pid;
+
+events {
+    worker_connections  1024;
+}
+
+http {
+	include /etc/nginx/sites-enabled/*;
+}

+ 10 - 0
internal/self_check/test_cases/no-http-block.conf

@@ -0,0 +1,10 @@
+user  nginx;
+worker_processes  auto;
+
+error_log  /var/log/nginx/error.log notice;
+error_log  /var/log/nginx/error.local.log notice;
+pid        /var/run/nginx.pid;
+
+events {
+    worker_connections  1024;
+}

+ 23 - 0
internal/self_check/test_cases/no-http-sites-enabled-fixed.conf

@@ -0,0 +1,23 @@
+user nginx;
+worker_processes auto;
+error_log /var/log/nginx/error.log notice;
+error_log /var/log/nginx/error.local.log notice;
+pid /var/run/nginx.pid;
+events {
+    worker_connections 1024;
+}
+stream {
+    include /etc/nginx/streams-enabled/*;
+}
+http {
+    include /etc/nginx/mime.types;
+    default_type application/octet-stream;
+    log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
+    access_log /var/log/nginx/access.log main;
+    sendfile on;
+    #tcp_nopush     on;
+    keepalive_timeout 65;
+    gzip on;
+    include /etc/nginx/conf.d/*.conf;
+    include /etc/nginx/sites-enabled/*;
+}

+ 34 - 0
internal/self_check/test_cases/no-http-sites-enabled.conf

@@ -0,0 +1,34 @@
+user  nginx;
+worker_processes  auto;
+
+error_log  /var/log/nginx/error.log notice;
+error_log  /var/log/nginx/error.local.log notice;
+pid        /var/run/nginx.pid;
+
+events {
+    worker_connections  1024;
+}
+
+stream {
+
+}
+
+http {
+    include       /etc/nginx/mime.types;
+    default_type  application/octet-stream;
+
+    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                      '$status $body_bytes_sent "$http_referer" '
+                      '"$http_user_agent" "$http_x_forwarded_for"';
+
+    access_log  /var/log/nginx/access.log  main;
+
+    sendfile        on;
+    #tcp_nopush     on;
+
+    keepalive_timeout  65;
+
+    gzip  on;
+
+    include /etc/nginx/conf.d/*.conf;
+}

+ 35 - 0
internal/self_check/test_cases/ok.conf

@@ -0,0 +1,35 @@
+user  nginx;
+worker_processes  auto;
+
+error_log  /var/log/nginx/error.log notice;
+error_log  /var/log/nginx/error.local.log notice;
+pid        /var/run/nginx.pid;
+
+events {
+    worker_connections  1024;
+}
+
+stream {
+    include /etc/nginx/streams-enabled/*;
+}
+
+http {
+    include       /etc/nginx/mime.types;
+    default_type  application/octet-stream;
+
+    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                      '$status $body_bytes_sent "$http_referer" '
+                      '"$http_user_agent" "$http_x_forwarded_for"';
+
+    access_log  /var/log/nginx/access.log  main;
+
+    sendfile        on;
+    #tcp_nopush     on;
+
+    keepalive_timeout  65;
+
+    gzip  on;
+
+    include /etc/nginx/conf.d/*.conf;
+    include /etc/nginx/sites-enabled/*;
+}

+ 1 - 0
internal/self_check/websocket.go

@@ -0,0 +1 @@
+package self_check

+ 1 - 0
settings/nginx.go

@@ -5,6 +5,7 @@ type Nginx struct {
 	ErrorLogPath    string   `json:"error_log_path" protected:"true"`
 	LogDirWhiteList []string `json:"log_dir_white_list" protected:"true"`
 	ConfigDir       string   `json:"config_dir" protected:"true"`
+	ConfigPath      string   `json:"config_path" protected:"true"`
 	PIDPath         string   `json:"pid_path" protected:"true"`
 	TestConfigCmd   string   `json:"test_config_cmd" protected:"true"`
 	ReloadCmd       string   `json:"reload_cmd" protected:"true"`