Browse Source

fix: log container is empty after failing to obtain cert #281

Jacky 1 year ago
parent
commit
a095c88fd2

+ 3 - 3
app/package.json

@@ -16,7 +16,7 @@
     "@vue/reactivity": "^3.4.13",
     "@vue/shared": "^3.4.13",
     "@vueuse/core": "^10.7.2",
-    "ant-design-vue": "4.1.0",
+    "ant-design-vue": "4.1.2",
     "apexcharts": "^3.45.1",
     "axios": "^1.6.5",
     "dayjs": "^1.11.10",
@@ -29,7 +29,7 @@
     "reconnecting-websocket": "^4.4.0",
     "sortablejs": "^1.15.0",
     "vite-plugin-build-id": "^0.2.8",
-    "vue": "^3.4.16",
+    "vue": "^3.4.18",
     "vue-github-button": "https://github.com/0xJacky/vue-github-button",
     "vue-router": "^4.2.5",
     "vue3-ace-editor": "2.2.4",
@@ -67,7 +67,7 @@
     "unplugin-auto-import": "^0.17.3",
     "unplugin-vue-components": "^0.26.0",
     "unplugin-vue-define-options": "^1.4.1",
-    "vite": "^5.1.0",
+    "vite": "^5.1.1",
     "vite-svg-loader": "^5.1.0",
     "vue-tsc": "^1.8.27"
   }

+ 116 - 116
app/pnpm-lock.yaml

@@ -7,7 +7,7 @@ settings:
 dependencies:
   '@ant-design/icons-vue':
     specifier: ^7.0.1
-    version: 7.0.1(vue@3.4.16)
+    version: 7.0.1(vue@3.4.18)
   '@formkit/auto-animate':
     specifier: ^0.8.0
     version: 0.8.1
@@ -19,10 +19,10 @@ dependencies:
     version: 3.4.13
   '@vueuse/core':
     specifier: ^10.7.2
-    version: 10.7.2(vue@3.4.16)
+    version: 10.7.2(vue@3.4.18)
   ant-design-vue:
-    specifier: 4.1.0
-    version: 4.1.0(vue@3.4.16)
+    specifier: 4.1.2
+    version: 4.1.2(vue@3.4.18)
   apexcharts:
     specifier: ^3.45.1
     version: 3.45.1
@@ -46,7 +46,7 @@ dependencies:
     version: 0.2.0
   pinia:
     specifier: ^2.1.7
-    version: 2.1.7(typescript@5.3.3)(vue@3.4.16)
+    version: 2.1.7(typescript@5.3.3)(vue@3.4.18)
   pinia-plugin-persistedstate:
     specifier: ^3.0.2
     version: 3.2.0(pinia@2.1.7)
@@ -60,26 +60,26 @@ dependencies:
     specifier: ^0.2.8
     version: 0.2.8(less@4.2.0)
   vue:
-    specifier: ^3.4.16
-    version: 3.4.16(typescript@5.3.3)
+    specifier: ^3.4.18
+    version: 3.4.18(typescript@5.3.3)
   vue-github-button:
     specifier: https://github.com/0xJacky/vue-github-button
     version: github.com/0xJacky/vue-github-button/fc3c93355a790d3249de6610de3ebe35949ee314
   vue-router:
     specifier: ^4.2.5
-    version: 4.2.5(vue@3.4.16)
+    version: 4.2.5(vue@3.4.18)
   vue3-ace-editor:
     specifier: 2.2.4
-    version: 2.2.4(ace-builds@1.32.3)(vue@3.4.16)
+    version: 2.2.4(ace-builds@1.32.3)(vue@3.4.18)
   vue3-apexcharts:
     specifier: ^1.4.4
-    version: 1.4.4(apexcharts@3.45.1)(vue@3.4.16)
+    version: 1.4.4(apexcharts@3.45.1)(vue@3.4.18)
   vue3-gettext:
     specifier: ^3.0.0-beta.3
-    version: 3.0.0-beta.3(@vue/compiler-sfc@3.4.13)(vue@3.4.16)
+    version: 3.0.0-beta.3(@vue/compiler-sfc@3.4.13)(vue@3.4.18)
   vuedraggable:
     specifier: ^4.1.0
-    version: 4.1.0(vue@3.4.16)
+    version: 4.1.0(vue@3.4.18)
   xterm:
     specifier: ^5.3.0
     version: 5.3.0
@@ -111,10 +111,10 @@ devDependencies:
     version: 6.18.1(eslint@8.56.0)(typescript@5.3.3)
   '@vitejs/plugin-vue':
     specifier: ^5.0.3
-    version: 5.0.3(vite@5.1.0)(vue@3.4.16)
+    version: 5.0.3(vite@5.1.1)(vue@3.4.18)
   '@vitejs/plugin-vue-jsx':
     specifier: ^3.1.0
-    version: 3.1.0(vite@5.1.0)(vue@3.4.16)
+    version: 3.1.0(vite@5.1.1)(vue@3.4.18)
   '@vue/compiler-sfc':
     specifier: ^3.4.13
     version: 3.4.13
@@ -165,16 +165,16 @@ devDependencies:
     version: 0.17.3(@vueuse/core@10.7.2)
   unplugin-vue-components:
     specifier: ^0.26.0
-    version: 0.26.0(vue@3.4.16)
+    version: 0.26.0(vue@3.4.18)
   unplugin-vue-define-options:
     specifier: ^1.4.1
-    version: 1.4.1(vue@3.4.16)
+    version: 1.4.1(vue@3.4.18)
   vite:
-    specifier: ^5.1.0
-    version: 5.1.0(@types/node@20.10.2)(less@4.2.0)
+    specifier: ^5.1.1
+    version: 5.1.1(@types/node@20.10.2)(less@4.2.0)
   vite-svg-loader:
     specifier: ^5.1.0
-    version: 5.1.0(vue@3.4.16)
+    version: 5.1.0(vue@3.4.18)
   vue-tsc:
     specifier: ^1.8.27
     version: 1.8.27(typescript@5.3.3)
@@ -209,14 +209,14 @@ packages:
     resolution: {integrity: sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g==}
     dev: false
 
-  /@ant-design/icons-vue@7.0.1(vue@3.4.16):
+  /@ant-design/icons-vue@7.0.1(vue@3.4.18):
     resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==}
     peerDependencies:
       vue: '>=3.0.3'
     dependencies:
       '@ant-design/colors': 6.0.0
       '@ant-design/icons-svg': 4.3.1
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
     dev: false
 
   /@antfu/eslint-config-basic@0.43.1(@typescript-eslint/eslint-plugin@6.18.1)(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)(typescript@5.3.3):
@@ -1415,7 +1415,7 @@ packages:
     resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
     dev: true
 
-  /@vitejs/plugin-vue-jsx@3.1.0(vite@5.1.0)(vue@3.4.16):
+  /@vitejs/plugin-vue-jsx@3.1.0(vite@5.1.1)(vue@3.4.18):
     resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==}
     engines: {node: ^14.18.0 || >=16.0.0}
     peerDependencies:
@@ -1425,21 +1425,21 @@ packages:
       '@babel/core': 7.23.5
       '@babel/plugin-transform-typescript': 7.23.5(@babel/core@7.23.5)
       '@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.23.5)
-      vite: 5.1.0(@types/node@20.10.2)(less@4.2.0)
-      vue: 3.4.16(typescript@5.3.3)
+      vite: 5.1.1(@types/node@20.10.2)(less@4.2.0)
+      vue: 3.4.18(typescript@5.3.3)
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@vitejs/plugin-vue@5.0.3(vite@5.1.0)(vue@3.4.16):
+  /@vitejs/plugin-vue@5.0.3(vite@5.1.1)(vue@3.4.18):
     resolution: {integrity: sha512-b8S5dVS40rgHdDrw+DQi/xOM9ed+kSRZzfm1T74bMmBDCd8XO87NKlFYInzCtwvtWwXZvo1QxE2OSspTATWrbA==}
     engines: {node: ^18.0.0 || >=20.0.0}
     peerDependencies:
       vite: ^5.0.0
       vue: ^3.2.25
     dependencies:
-      vite: 5.1.0(@types/node@20.10.2)(less@4.2.0)
-      vue: 3.4.16(typescript@5.3.3)
+      vite: 5.1.1(@types/node@20.10.2)(less@4.2.0)
+      vue: 3.4.18(typescript@5.3.3)
     dev: true
 
   /@volar/language-core@1.11.1:
@@ -1461,7 +1461,7 @@ packages:
       path-browserify: 1.0.1
     dev: true
 
-  /@vue-macros/common@1.10.0(vue@3.4.16):
+  /@vue-macros/common@1.10.0(vue@3.4.18):
     resolution: {integrity: sha512-4DZsPeQA/nBQDw2RkYAmH7KrFjJVrMdAhJhO1JCl1bbbFXCGeoGjXfkg9wHPppj47s2HpAB3GrqNwqVGbi12NQ==}
     engines: {node: '>=16.14.0'}
     peerDependencies:
@@ -1472,11 +1472,11 @@ packages:
     dependencies:
       '@babel/types': 7.23.5
       '@rollup/pluginutils': 5.1.0
-      '@vue/compiler-sfc': 3.4.13
+      '@vue/compiler-sfc': 3.4.18
       ast-kit: 0.11.3
       local-pkg: 0.5.0
       magic-string-ast: 0.3.0
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
     transitivePeerDependencies:
       - rollup
     dev: true
@@ -1513,11 +1513,11 @@ packages:
       estree-walker: 2.0.2
       source-map-js: 1.0.2
 
-  /@vue/compiler-core@3.4.16:
-    resolution: {integrity: sha512-HXgyy7gen4FNJS8Hz2q/NNBEdzD3QInhDTWaP2/mS0TlmV9CnjmXip7TZ0ROYiQM4FgXZCCJvh74yDikFkPpkQ==}
+  /@vue/compiler-core@3.4.18:
+    resolution: {integrity: sha512-F7YK8lMK0iv6b9/Gdk15A67wM0KKZvxDxed0RR60C1z9tIJTKta+urs4j0RTN5XqHISzI3etN3mX0uHhjmoqjQ==}
     dependencies:
       '@babel/parser': 7.23.9
-      '@vue/shared': 3.4.16
+      '@vue/shared': 3.4.18
       entities: 4.5.0
       estree-walker: 2.0.2
       source-map-js: 1.0.2
@@ -1528,11 +1528,11 @@ packages:
       '@vue/compiler-core': 3.4.13
       '@vue/shared': 3.4.13
 
-  /@vue/compiler-dom@3.4.16:
-    resolution: {integrity: sha512-lvs9ankPzLEuIC5aB72ntLUcwVGmgY7ASkXDRvo9+lUMWOOCqnAmM/64AZPeVAZ4EnjocCE40OUN+ZboNe4ygA==}
+  /@vue/compiler-dom@3.4.18:
+    resolution: {integrity: sha512-24Eb8lcMfInefvQ6YlEVS18w5Q66f4+uXWVA+yb7praKbyjHRNuKVWGuinfSSjM0ZIiPi++QWukhkgznBaqpEA==}
     dependencies:
-      '@vue/compiler-core': 3.4.16
-      '@vue/shared': 3.4.16
+      '@vue/compiler-core': 3.4.18
+      '@vue/shared': 3.4.18
 
   /@vue/compiler-sfc@3.4.13:
     resolution: {integrity: sha512-SkpmQN8xIFBd5onT413DFSDdjxULJf6jmJg/t3w/DZ9I8ZzyNlLIBLO0qFLewVHyHCiAgpPZlWqSRZXYrawk3Q==}
@@ -1547,17 +1547,17 @@ packages:
       postcss: 8.4.33
       source-map-js: 1.0.2
 
-  /@vue/compiler-sfc@3.4.16:
-    resolution: {integrity: sha512-zVYC42Q/NmbB4nigGcQeIvsLpBlq6K9wJP5jTFCqfpXWnkodxfLFQHDu2GntZ7yKOgwAjxuvLwrPx+I6LPL2vg==}
+  /@vue/compiler-sfc@3.4.18:
+    resolution: {integrity: sha512-rG5tqtnzwrVpMqAQ7FHtvHaV70G6LLfJIWLYZB/jZ9m/hrnZmIQh+H3ewnC5onwe/ibljm9+ZupxeElzqCkTAw==}
     dependencies:
       '@babel/parser': 7.23.9
-      '@vue/compiler-core': 3.4.16
-      '@vue/compiler-dom': 3.4.16
-      '@vue/compiler-ssr': 3.4.16
-      '@vue/shared': 3.4.16
+      '@vue/compiler-core': 3.4.18
+      '@vue/compiler-dom': 3.4.18
+      '@vue/compiler-ssr': 3.4.18
+      '@vue/shared': 3.4.18
       estree-walker: 2.0.2
       magic-string: 0.30.7
-      postcss: 8.4.33
+      postcss: 8.4.35
       source-map-js: 1.0.2
 
   /@vue/compiler-ssr@3.4.13:
@@ -1566,11 +1566,11 @@ packages:
       '@vue/compiler-dom': 3.4.13
       '@vue/shared': 3.4.13
 
-  /@vue/compiler-ssr@3.4.16:
-    resolution: {integrity: sha512-1kNF+fHdEB+5aTcPZ0hh/gzi9Ezq5IBO4bl/hV4Dg4fub6t12W6VGlsERtvdUaEowL35M3pojv0hOvLaq0FbdQ==}
+  /@vue/compiler-ssr@3.4.18:
+    resolution: {integrity: sha512-hSlv20oUhPxo2UYUacHgGaxtqP0tvFo6ixxxD6JlXIkwzwoZ9eKK6PFQN4hNK/R13JlNyldwWt/fqGBKgWJ6nQ==}
     dependencies:
-      '@vue/compiler-dom': 3.4.16
-      '@vue/shared': 3.4.16
+      '@vue/compiler-dom': 3.4.18
+      '@vue/shared': 3.4.18
 
   /@vue/devtools-api@6.5.1:
     resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==}
@@ -1586,8 +1586,8 @@ packages:
     dependencies:
       '@volar/language-core': 1.11.1
       '@volar/source-map': 1.11.1
-      '@vue/compiler-dom': 3.4.13
-      '@vue/shared': 3.4.13
+      '@vue/compiler-dom': 3.4.18
+      '@vue/shared': 3.4.18
       computeds: 0.0.1
       minimatch: 9.0.3
       muggle-string: 0.3.1
@@ -1602,50 +1602,50 @@ packages:
       '@vue/shared': 3.4.13
     dev: false
 
-  /@vue/reactivity@3.4.16:
-    resolution: {integrity: sha512-XTWRMBG10PGs4MxDoUdBEhMacS5QBUAlGeb5AmQysTQ16tXxQ0lymgbSTmR2h79v5dJDFuULuLWUbwc0uj6zqQ==}
+  /@vue/reactivity@3.4.18:
+    resolution: {integrity: sha512-7uda2/I0jpLiRygprDo5Jxs2HJkOVXcOMlyVlY54yRLxoycBpwGJRwJT9EdGB4adnoqJDXVT2BilUAYwI7qvmg==}
     dependencies:
-      '@vue/shared': 3.4.16
+      '@vue/shared': 3.4.18
 
-  /@vue/runtime-core@3.4.16:
-    resolution: {integrity: sha512-vgS25M79AOY2EsBWxBcy9yAou10x2WHJhGN0FM/Ii8yum0a+KBfg8ehzq/cuDqfOPrtVrDPW+QkH3WNJNakfRw==}
+  /@vue/runtime-core@3.4.18:
+    resolution: {integrity: sha512-7mU9diCa+4e+8/wZ7Udw5pwTH10A11sZ1nldmHOUKJnzCwvZxfJqAtw31mIf4T5H2FsLCSBQT3xgioA9vIjyDQ==}
     dependencies:
-      '@vue/reactivity': 3.4.16
-      '@vue/shared': 3.4.16
+      '@vue/reactivity': 3.4.18
+      '@vue/shared': 3.4.18
 
-  /@vue/runtime-dom@3.4.16:
-    resolution: {integrity: sha512-X+knHfhefB8tX0rJG3d14U8p1CpeZ/qZxol9rN8ZAD9UalTInIsKXlBTd/xLC8GwO2aXVXxjaSIiTU5th5wj9Q==}
+  /@vue/runtime-dom@3.4.18:
+    resolution: {integrity: sha512-2y1Mkzcw1niSfG7z3Qx+2ir9Gb4hdTkZe5p/I8x1aTIKQE0vY0tPAEUPhZm5tx6183gG3D/KwHG728UR0sIufA==}
     dependencies:
-      '@vue/runtime-core': 3.4.16
-      '@vue/shared': 3.4.16
+      '@vue/runtime-core': 3.4.18
+      '@vue/shared': 3.4.18
       csstype: 3.1.3
 
-  /@vue/server-renderer@3.4.16(vue@3.4.16):
-    resolution: {integrity: sha512-e0PZDpk/eZgICYb0DTQ+OeBlgt0FYGo+2DEcUkZxw+pDgF1qL0aYaOqmPcSbL5KK0nizvuSd7k5HZOkSwSaC2g==}
+  /@vue/server-renderer@3.4.18(vue@3.4.18):
+    resolution: {integrity: sha512-YJd1wa7mzUN3NRqLEsrwEYWyO+PUBSROIGlCc3J/cvn7Zu6CxhNLgXa8Z4zZ5ja5/nviYO79J1InoPeXgwBTZA==}
     peerDependencies:
-      vue: 3.4.16
+      vue: 3.4.18
     dependencies:
-      '@vue/compiler-ssr': 3.4.16
-      '@vue/shared': 3.4.16
-      vue: 3.4.16(typescript@5.3.3)
+      '@vue/compiler-ssr': 3.4.18
+      '@vue/shared': 3.4.18
+      vue: 3.4.18(typescript@5.3.3)
 
   /@vue/shared@3.4.13:
     resolution: {integrity: sha512-56crFKLPpzk85WXX1L1c0QzPOuoapWlPVys8eMG8kkRmqdMjWUqK8KpFdE2d7BQA4CEbXwyyHPq6MpFr8H9rcg==}
 
-  /@vue/shared@3.4.16:
-    resolution: {integrity: sha512-HKCjeaxR+R95dCw1BDaytcHdlzZj9lxj7RlFnxWtcKq670t8oSeMsbPlkzkNc2V6IUzHaMtUxdBcdREAhb+7NA==}
+  /@vue/shared@3.4.18:
+    resolution: {integrity: sha512-CxouGFxxaW5r1WbrSmWwck3No58rApXgRSBxrqgnY1K+jk20F6DrXJkHdH9n4HVT+/B6G2CAn213Uq3npWiy8Q==}
 
   /@vue/tsconfig@0.5.1:
     resolution: {integrity: sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==}
     dev: true
 
-  /@vueuse/core@10.7.2(vue@3.4.16):
+  /@vueuse/core@10.7.2(vue@3.4.18):
     resolution: {integrity: sha512-AOyAL2rK0By62Hm+iqQn6Rbu8bfmbgaIMXcE3TSr7BdQ42wnSFlwIdPjInO62onYsEMK/yDMU8C6oGfDAtZ2qQ==}
     dependencies:
       '@types/web-bluetooth': 0.0.20
       '@vueuse/metadata': 10.7.2
-      '@vueuse/shared': 10.7.2(vue@3.4.16)
-      vue-demi: 0.14.6(vue@3.4.16)
+      '@vueuse/shared': 10.7.2(vue@3.4.18)
+      vue-demi: 0.14.6(vue@3.4.18)
     transitivePeerDependencies:
       - '@vue/composition-api'
       - vue
@@ -1653,10 +1653,10 @@ packages:
   /@vueuse/metadata@10.7.2:
     resolution: {integrity: sha512-kCWPb4J2KGrwLtn1eJwaJD742u1k5h6v/St5wFe8Quih90+k2a0JP8BS4Zp34XUuJqS2AxFYMb1wjUL8HfhWsQ==}
 
-  /@vueuse/shared@10.7.2(vue@3.4.16):
+  /@vueuse/shared@10.7.2(vue@3.4.18):
     resolution: {integrity: sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==}
     dependencies:
-      vue-demi: 0.14.6(vue@3.4.16)
+      vue-demi: 0.14.6(vue@3.4.18)
     transitivePeerDependencies:
       - '@vue/composition-api'
       - vue
@@ -1717,14 +1717,14 @@ packages:
     engines: {node: '>=12'}
     dev: false
 
-  /ant-design-vue@4.1.0(vue@3.4.16):
-    resolution: {integrity: sha512-sVQAfTCxpGRfFykM033/0ZWfNWbsL8EsqhBP9knbP4Ptc52zG57mQsCPWvq6Cj3yqmDJW6ykY05v0KB+5rAPXg==}
+  /ant-design-vue@4.1.2(vue@3.4.18):
+    resolution: {integrity: sha512-ynFkDJLlHgumeK6Hr1UZ7PvQNZ1uBcri/pmejBdS3kRqHeA5VRsxneYDwa8YxA+uYB5YfT2jpYsSHsiMiCjRGg==}
     engines: {node: '>=12.22.0'}
     peerDependencies:
       vue: '>=3.2.0'
     dependencies:
       '@ant-design/colors': 6.0.0
-      '@ant-design/icons-vue': 7.0.1(vue@3.4.16)
+      '@ant-design/icons-vue': 7.0.1(vue@3.4.18)
       '@babel/runtime': 7.23.5
       '@ctrl/tinycolor': 3.6.1
       '@emotion/hash': 0.9.1
@@ -1743,8 +1743,8 @@ packages:
       shallow-equal: 1.2.1
       stylis: 4.3.0
       throttle-debounce: 5.0.0
-      vue: 3.4.16(typescript@5.3.3)
-      vue-types: 3.0.2(vue@3.4.16)
+      vue: 3.4.18(typescript@5.3.3)
+      vue-types: 3.0.2(vue@3.4.18)
       warning: 4.0.3
     dev: false
 
@@ -1865,7 +1865,7 @@ packages:
     resolution: {integrity: sha512-qdwwKEhckRk0XE22/xDdmU3v/60E8Edu4qFhgTLIhGGDs/PAJwLw9pQn8Rj99PitlbBZbYpx0k/lbir4kg0SuA==}
     engines: {node: '>=16.14.0'}
     dependencies:
-      '@babel/parser': 7.23.6
+      '@babel/parser': 7.23.9
       '@rollup/pluginutils': 5.1.0
       pathe: 1.1.1
     transitivePeerDependencies:
@@ -3756,7 +3756,7 @@ packages:
     resolution: {integrity: sha512-0shqecEPgdFpnI3AP90epXyxZy9g6CRZ+SZ7BcqFwYmtFEnZ1jpevcV5HoyVnlDS9gCnc1UIg3Rsvp3Ci7r8OA==}
     engines: {node: '>=16.14.0'}
     dependencies:
-      magic-string: 0.30.5
+      magic-string: 0.30.7
     dev: true
 
   /magic-string@0.30.5:
@@ -4170,10 +4170,10 @@ packages:
     peerDependencies:
       pinia: ^2.0.0
     dependencies:
-      pinia: 2.1.7(typescript@5.3.3)(vue@3.4.16)
+      pinia: 2.1.7(typescript@5.3.3)(vue@3.4.18)
     dev: false
 
-  /pinia@2.1.7(typescript@5.3.3)(vue@3.4.16):
+  /pinia@2.1.7(typescript@5.3.3)(vue@3.4.18):
     resolution: {integrity: sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==}
     peerDependencies:
       '@vue/composition-api': ^1.4.0
@@ -4187,8 +4187,8 @@ packages:
     dependencies:
       '@vue/devtools-api': 6.5.1
       typescript: 5.3.3
-      vue: 3.4.16(typescript@5.3.3)
-      vue-demi: 0.14.6(vue@3.4.16)
+      vue: 3.4.18(typescript@5.3.3)
+      vue-demi: 0.14.6(vue@3.4.18)
     dev: false
 
   /pirates@4.0.6:
@@ -5010,7 +5010,7 @@ packages:
     dependencies:
       '@antfu/utils': 0.7.7
       '@rollup/pluginutils': 5.1.0
-      '@vueuse/core': 10.7.2(vue@3.4.16)
+      '@vueuse/core': 10.7.2(vue@3.4.18)
       fast-glob: 3.3.2
       local-pkg: 0.5.0
       magic-string: 0.30.5
@@ -5021,7 +5021,7 @@ packages:
       - rollup
     dev: true
 
-  /unplugin-vue-components@0.26.0(vue@3.4.16):
+  /unplugin-vue-components@0.26.0(vue@3.4.18):
     resolution: {integrity: sha512-s7IdPDlnOvPamjunVxw8kNgKNK8A5KM1YpK5j/p97jEKTjlPNrA0nZBiSfAKKlK1gWZuyWXlKL5dk3EDw874LQ==}
     engines: {node: '>=14'}
     peerDependencies:
@@ -5044,17 +5044,17 @@ packages:
       minimatch: 9.0.3
       resolve: 1.22.8
       unplugin: 1.5.1
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
     transitivePeerDependencies:
       - rollup
       - supports-color
     dev: true
 
-  /unplugin-vue-define-options@1.4.1(vue@3.4.16):
+  /unplugin-vue-define-options@1.4.1(vue@3.4.18):
     resolution: {integrity: sha512-dsI7JZvzCv6hV0Iq8cUKO70gFlsfEmASZzmebVlPzT2Knb57d4Plqjuf0wpU61G2HGSDZ8gy73Nix4FTmFVOyQ==}
     engines: {node: '>=16.14.0'}
     dependencies:
-      '@vue-macros/common': 1.10.0(vue@3.4.16)
+      '@vue-macros/common': 1.10.0(vue@3.4.18)
       ast-walker-scope: 0.5.0
       unplugin: 1.5.1
     transitivePeerDependencies:
@@ -5114,7 +5114,7 @@ packages:
       '@types/node': 20.10.2
       rimraf: 5.0.5
       typescript: 5.3.3
-      vite: 5.1.0(@types/node@20.10.2)(less@4.2.0)
+      vite: 5.1.1(@types/node@20.10.2)(less@4.2.0)
     transitivePeerDependencies:
       - less
       - lightningcss
@@ -5124,17 +5124,17 @@ packages:
       - terser
     dev: false
 
-  /vite-svg-loader@5.1.0(vue@3.4.16):
+  /vite-svg-loader@5.1.0(vue@3.4.18):
     resolution: {integrity: sha512-M/wqwtOEjgb956/+m5ZrYT/Iq6Hax0OakWbokj8+9PXOnB7b/4AxESHieEtnNEy7ZpjsjYW1/5nK8fATQMmRxw==}
     peerDependencies:
       vue: '>=3.2.13'
     dependencies:
       svgo: 3.0.5
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
     dev: true
 
-  /vite@5.1.0(@types/node@20.10.2)(less@4.2.0):
-    resolution: {integrity: sha512-STmSFzhY4ljuhz14bg9LkMTk3d98IO6DIArnTY6MeBwiD1Za2StcQtz7fzOUnRCqrHSD5+OS2reg4HOz1eoLnw==}
+  /vite@5.1.1(@types/node@20.10.2)(less@4.2.0):
+    resolution: {integrity: sha512-wclpAgY3F1tR7t9LL5CcHC41YPkQIpKUGeIuT8MdNwNZr6OqOTLs7JX5vIHAtzqLWXts0T+GDrh9pN2arneKqg==}
     engines: {node: ^18.0.0 || >=20.0.0}
     hasBin: true
     peerDependencies:
@@ -5169,7 +5169,7 @@ packages:
     optionalDependencies:
       fsevents: 2.3.3
 
-  /vue-demi@0.14.6(vue@3.4.16):
+  /vue-demi@0.14.6(vue@3.4.18):
     resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
     engines: {node: '>=12'}
     hasBin: true
@@ -5181,7 +5181,7 @@ packages:
       '@vue/composition-api':
         optional: true
     dependencies:
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
 
   /vue-eslint-parser@9.4.0(eslint@8.56.0):
     resolution: {integrity: sha512-7KsNBb6gHFA75BtneJsoK/dbZ281whUIwFYdQxA68QrCrGMXYzUMbPDHGcOQ0OocIVKrWSKWXZ4mL7tonCXoUw==}
@@ -5201,13 +5201,13 @@ packages:
       - supports-color
     dev: true
 
-  /vue-router@4.2.5(vue@3.4.16):
+  /vue-router@4.2.5(vue@3.4.18):
     resolution: {integrity: sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==}
     peerDependencies:
       vue: ^3.2.0
     dependencies:
       '@vue/devtools-api': 6.5.1
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
     dev: false
 
   /vue-template-compiler@2.7.15:
@@ -5229,17 +5229,17 @@ packages:
       typescript: 5.3.3
     dev: true
 
-  /vue-types@3.0.2(vue@3.4.16):
+  /vue-types@3.0.2(vue@3.4.18):
     resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==}
     engines: {node: '>=10.15.0'}
     peerDependencies:
       vue: ^3.0.0
     dependencies:
       is-plain-object: 3.0.1
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
     dev: false
 
-  /vue3-ace-editor@2.2.4(ace-builds@1.32.3)(vue@3.4.16):
+  /vue3-ace-editor@2.2.4(ace-builds@1.32.3)(vue@3.4.18):
     resolution: {integrity: sha512-FZkEyfpbH068BwjhMyNROxfEI8135Sc+x8ouxkMdCNkuj/Tuw83VP/gStFQqZHqljyX9/VfMTCdTqtOnJZGN8g==}
     peerDependencies:
       ace-builds: '*'
@@ -5247,20 +5247,20 @@ packages:
     dependencies:
       ace-builds: 1.32.3
       resize-observer-polyfill: 1.5.1
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
     dev: false
 
-  /vue3-apexcharts@1.4.4(apexcharts@3.45.1)(vue@3.4.16):
+  /vue3-apexcharts@1.4.4(apexcharts@3.45.1)(vue@3.4.18):
     resolution: {integrity: sha512-TH89uZrxGjaDvkaYAISvj8+k6Bf1rUKFillc8oJirs5XZEPiwM1ELKZQ786wz0rfPqkSHHny2lqqUCK7Rw+LcQ==}
     peerDependencies:
       apexcharts: '> 3.0.0'
       vue: '> 3.0.0'
     dependencies:
       apexcharts: 3.45.1
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
     dev: false
 
-  /vue3-gettext@3.0.0-beta.3(@vue/compiler-sfc@3.4.13)(vue@3.4.16):
+  /vue3-gettext@3.0.0-beta.3(@vue/compiler-sfc@3.4.13)(vue@3.4.18):
     resolution: {integrity: sha512-zE6qKEhzlL4R/El9Z6dSg+tmXjfLorG5/Y2o+Z+DMt7dMxeYF3FQbkHzvU7DKZMXkAkkscwspmwsYAXp5ctGdA==}
     engines: {node: '>= 12.0.0'}
     hasBin: true
@@ -5278,31 +5278,31 @@ packages:
       parse5-htmlparser2-tree-adapter: 6.0.1
       pofile: 1.1.4
       tslib: 2.6.2
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
     dev: false
 
-  /vue@3.4.16(typescript@5.3.3):
-    resolution: {integrity: sha512-l5/KcZRp3GbsFXQGeCL9ll1JfRU285K/7l8mZM+dEO+CnE1j26MvfBKJi17iCRRwstl+Jz7KSLlzj9L79fB6WA==}
+  /vue@3.4.18(typescript@5.3.3):
+    resolution: {integrity: sha512-0zLRYamFRe0wF4q2L3O24KQzLyLpL64ye1RUToOgOxuWZsb/FhaNRdGmeozdtVYLz6tl94OXLaK7/WQIrVCw1A==}
     peerDependencies:
       typescript: '*'
     peerDependenciesMeta:
       typescript:
         optional: true
     dependencies:
-      '@vue/compiler-dom': 3.4.16
-      '@vue/compiler-sfc': 3.4.16
-      '@vue/runtime-dom': 3.4.16
-      '@vue/server-renderer': 3.4.16(vue@3.4.16)
-      '@vue/shared': 3.4.16
+      '@vue/compiler-dom': 3.4.18
+      '@vue/compiler-sfc': 3.4.18
+      '@vue/runtime-dom': 3.4.18
+      '@vue/server-renderer': 3.4.18(vue@3.4.18)
+      '@vue/shared': 3.4.18
       typescript: 5.3.3
 
-  /vuedraggable@4.1.0(vue@3.4.16):
+  /vuedraggable@4.1.0(vue@3.4.18):
     resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==}
     peerDependencies:
       vue: ^3.0.1
     dependencies:
       sortablejs: 1.14.0
-      vue: 3.4.16(typescript@5.3.3)
+      vue: 3.4.18(typescript@5.3.3)
     dev: false
 
   /warning@4.0.3:

+ 5 - 0
app/src/api/cert.ts

@@ -25,6 +25,11 @@ export interface CertificateInfo {
   not_before: string
 }
 
+export interface CertificateResult {
+  ssl_certificate: string
+  ssl_certificate_key: string
+}
+
 const cert: Curd<Cert> = new Curd('/cert')
 
 export default cert

+ 1 - 1
app/src/version.json

@@ -1 +1 @@
-{"version":"2.0.0-beta.14","build_id":114,"total_build":318}
+{"version":"2.0.0-beta.14","build_id":116,"total_build":320}

+ 1 - 1
app/src/views/certificate/RenewCert.vue

@@ -21,7 +21,7 @@ const data = inject('data') as Ref<Cert>
 const issueCert = () => {
   modalVisible.value = true
 
-  refObtainCertLive.value.issue_cert(data.value.name, data.value.domains, () => {
+  refObtainCertLive.value.issue_cert(data.value.name, data.value.domains).then(() => {
     message.success($gettext('Renew successfully'))
     emit('renewed')
   })

+ 2 - 1
app/src/views/certificate/WildcardCertificate.vue

@@ -20,6 +20,7 @@ provide('data', data)
 provide('issuing_cert', issuing_cert)
 function open() {
   visible.value = true
+  step.value = 0
   data.value = {
     challenge_method: 'dns01',
   } as Cert
@@ -43,7 +44,7 @@ const issueCert = () => {
   step.value++
   modalVisible.value = true
 
-  refObtainCertLive.value.issue_cert(computedDomain.value, [computedDomain.value, domain.value], () => {
+  refObtainCertLive.value.issue_cert(computedDomain.value, [computedDomain.value, domain.value]).then(() => {
     message.success($gettext('Renew successfully'))
     emit('issued')
   })

+ 3 - 2
app/src/views/domain/cert/components/ObtainCert.vue

@@ -8,6 +8,7 @@ import type { NgxConfig, NgxDirective } from '@/api/ngx'
 import type { Props } from '@/views/domain/cert/IssueCert.vue'
 import type { DnsChallenge } from '@/api/auto_cert'
 import ObtainCertLive from '@/views/domain/cert/components/ObtainCertLive.vue'
+import type { CertificateResult } from '@/api/cert'
 
 const emit = defineEmits(['update:auto_cert'])
 
@@ -47,10 +48,10 @@ const name = computed(() => {
 const refObtainCertLive = ref()
 
 const issue_cert = (config_name: string, server_name: string) => {
-  refObtainCertLive.value.issue_cert(config_name, server_name.trim().split(' '), callback)
+  refObtainCertLive.value.issue_cert(config_name, server_name.trim().split(' ')).then(resolveCert)
 }
 
-async function callback(ssl_certificate: string, ssl_certificate_key: string) {
+async function resolveCert({ ssl_certificate, ssl_certificate_key }: CertificateResult) {
   directivesMap.value.ssl_certificate[0].params = ssl_certificate
   directivesMap.value.ssl_certificate_key[0].params = ssl_certificate_key
   await save_config()

+ 52 - 48
app/src/views/domain/cert/components/ObtainCertLive.vue

@@ -3,6 +3,8 @@ import type { Ref } from 'vue'
 import { useGettext } from 'vue3-gettext'
 import websocket from '@/lib/websocket'
 import type { DnsChallenge } from '@/api/auto_cert'
+import Error from '@/views/other/Error.vue'
+import type { CertificateResult } from '@/api/cert'
 
 const props = defineProps<{
   modalClosable: boolean
@@ -57,64 +59,65 @@ function log(msg: string) {
   logContainer.value?.scroll({ top: 100000, left: 0, behavior: 'smooth' })
 }
 
-const issue_cert = async (config_name: string, server_name: string[],
-  callback?: (ssl_certificate: string, ssl_certificate_key: string) => void) => {
-  progressStatus.value = 'active'
-  modalClosable.value = false
-  modalVisible.value = true
-  progressPercent.value = 0
-  logContainer.value.innerHTML = ''
+const issue_cert = async (config_name: string, server_name: string[]) => {
+  return new Promise<CertificateResult>((resolve, reject) => {
+    progressStatus.value = 'active'
+    modalClosable.value = false
+    modalVisible.value = true
+    progressPercent.value = 0
+    logContainer.value.innerHTML = ''
 
-  log($gettext('Getting the certificate, please wait...'))
+    log($gettext('Getting the certificate, please wait...'))
 
-  const ws = websocket(`/api/domain/${config_name}/cert`, false)
+    const ws = websocket(`/api/domain/${config_name}/cert`, false)
 
-  ws.onopen = () => {
-    ws.send(JSON.stringify({
-      server_name,
-      ...data.value,
-    }))
-  }
+    ws.onopen = () => {
+      ws.send(JSON.stringify({
+        server_name,
+        ...data.value,
+      }))
+    }
 
-  ws.onmessage = async m => {
-    const r = JSON.parse(m.data)
+    ws.onmessage = async m => {
+      const r = JSON.parse(m.data)
 
-    const regex = /\[Nginx UI\] (.*)/
+      const regex = /\[Nginx UI\] (.*)/
 
-    const matches = r.message.match(regex)
+      const matches = r.message.match(regex)
 
-    if (matches && matches.length > 1) {
-      const extractedText = matches[1]
+      if (matches && matches.length > 1) {
+        const extractedText = matches[1]
 
-      r.message = r.message.replaceAll(extractedText, $gettext(extractedText))
-    }
+        r.message = r.message.replaceAll(extractedText, $gettext(extractedText))
+      }
+
+      log(r.message)
 
-    log(r.message)
-
-    // eslint-disable-next-line sonarjs/no-small-switch
-    switch (r.status) {
-      case 'info':
-        // If it is a nginx ui log, increase the percent.
-        if (r.message.includes('[Nginx UI]'))
-          progressPercent.value += 5
-
-        break
-      default:
-        modalClosable.value = true
-        issuing_cert.value = false
-
-        if (r.status === 'success' && r.ssl_certificate !== undefined && r.ssl_certificate_key !== undefined) {
-          progressStatus.value = 'success'
-          progressPercent.value = 100
-          if (callback)
-            callback(r.ssl_certificate, r.ssl_certificate_key)
-        }
-        else {
-          progressStatus.value = 'exception'
-        }
-        break
+      // eslint-disable-next-line sonarjs/no-small-switch
+      switch (r.status) {
+        case 'info':
+          // If it is a nginx ui log, increase the percent.
+          if (r.message.includes('[Nginx UI]'))
+            progressPercent.value += 8
+
+          break
+        default:
+          modalClosable.value = true
+          issuing_cert.value = false
+
+          if (r.status === 'success' && r.ssl_certificate !== undefined && r.ssl_certificate_key !== undefined) {
+            progressStatus.value = 'success'
+            progressPercent.value = 100
+            resolve({ ssl_certificate: r.ssl_certificate, ssl_certificate_key: r.ssl_certificate_key })
+          }
+          else {
+            progressStatus.value = 'exception'
+            reject(new Error($gettext('Fail to obtain certificate')))
+          }
+          break
+      }
     }
-  }
+  })
 }
 
 defineExpose({
@@ -143,6 +146,7 @@ defineExpose({
     background-color: rgba(0, 0, 0, 0.84);
   }
 }
+
 .issue-cert-log-container {
   height: 320px;
   overflow: scroll;

+ 1 - 1
app/version.json

@@ -1 +1 @@
-{"version":"2.0.0-beta.14","build_id":114,"total_build":318}
+{"version":"2.0.0-beta.14","build_id":116,"total_build":320}

+ 203 - 203
internal/cert/cert.go

@@ -1,216 +1,216 @@
 package cert
 
 import (
-    "crypto/ecdsa"
-    "crypto/elliptic"
-    "crypto/rand"
-    "crypto/tls"
-    "github.com/0xJacky/Nginx-UI/internal/cert/dns"
-    "github.com/0xJacky/Nginx-UI/internal/logger"
-    "github.com/0xJacky/Nginx-UI/internal/nginx"
-    "github.com/0xJacky/Nginx-UI/query"
-    "github.com/0xJacky/Nginx-UI/settings"
-    "github.com/go-acme/lego/v4/certcrypto"
-    "github.com/go-acme/lego/v4/certificate"
-    "github.com/go-acme/lego/v4/challenge/http01"
-    "github.com/go-acme/lego/v4/lego"
-    legolog "github.com/go-acme/lego/v4/log"
-    dnsproviders "github.com/go-acme/lego/v4/providers/dns"
-    "github.com/go-acme/lego/v4/registration"
-    "github.com/pkg/errors"
-    "log"
-    "net/http"
-    "os"
-    "path/filepath"
-    "strings"
-    "time"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/tls"
+	"github.com/0xJacky/Nginx-UI/internal/cert/dns"
+	"github.com/0xJacky/Nginx-UI/internal/logger"
+	"github.com/0xJacky/Nginx-UI/internal/nginx"
+	"github.com/0xJacky/Nginx-UI/query"
+	"github.com/0xJacky/Nginx-UI/settings"
+	"github.com/go-acme/lego/v4/certcrypto"
+	"github.com/go-acme/lego/v4/certificate"
+	"github.com/go-acme/lego/v4/challenge/http01"
+	"github.com/go-acme/lego/v4/lego"
+	legolog "github.com/go-acme/lego/v4/log"
+	dnsproviders "github.com/go-acme/lego/v4/providers/dns"
+	"github.com/go-acme/lego/v4/registration"
+	"github.com/pkg/errors"
+	"log"
+	"net/http"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
 )
 
 const (
-    HTTP01 = "http01"
-    DNS01  = "dns01"
+	HTTP01 = "http01"
+	DNS01  = "dns01"
 )
 
 type ConfigPayload struct {
-    ServerName      []string `json:"server_name"`
-    ChallengeMethod string   `json:"challenge_method"`
-    DNSCredentialID int      `json:"dns_credential_id"`
+	ServerName      []string `json:"server_name"`
+	ChallengeMethod string   `json:"challenge_method"`
+	DNSCredentialID int      `json:"dns_credential_id"`
 }
 
 func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error) {
-    defer func() {
-        if err := recover(); err != nil {
-            logger.Error(err)
-        }
-    }()
-
-    // initial a channelWriter to receive logs
-    cw := NewChannelWriter()
-    defer close(errChan)
-
-    // initial a logger
-    l := log.New(os.Stderr, "", log.LstdFlags)
-    l.SetOutput(cw)
-
-    // Hijack the (logger) of lego
-    legolog.Logger = l
-
-    domain := payload.ServerName
-
-    // Create a user. New accounts need an email and private key to start.
-    l.Println("[INFO] [Nginx UI] Generating private key for registering account")
-    privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-    if err != nil {
-        errChan <- errors.Wrap(err, "issue cert generate key error")
-        return
-    }
-
-    l.Println("[INFO] [Nginx UI] Preparing lego configurations")
-    user := User{
-        Email: settings.ServerSettings.Email,
-        Key:   privateKey,
-    }
-
-    // Start a goroutine to fetch and process logs from channel
-    go func() {
-        for msg := range cw.Ch {
-            logChan <- string(msg)
-        }
-    }()
-
-    config := lego.NewConfig(&user)
-
-    if settings.ServerSettings.Demo {
-        config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
-    }
-
-    if settings.ServerSettings.CADir != "" {
-        config.CADirURL = settings.ServerSettings.CADir
-        if config.HTTPClient != nil {
-            config.HTTPClient.Transport = &http.Transport{
-                TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
-            }
-        }
-    }
-
-    config.Certificate.KeyType = certcrypto.RSA2048
-
-    l.Println("[INFO] [Nginx UI] Creating client facilitates communication with the CA server")
-    // A client facilitates communication with the CA server.
-    client, err := lego.NewClient(config)
-    if err != nil {
-        errChan <- errors.Wrap(err, "issue cert new client error")
-        return
-    }
-
-    switch payload.ChallengeMethod {
-    default:
-        fallthrough
-    case HTTP01:
-        l.Println("[INFO] [Nginx UI] Setting HTTP01 challenge provider")
-        err = client.Challenge.SetHTTP01Provider(
-            http01.NewProviderServer("",
-                settings.ServerSettings.HTTPChallengePort,
-            ),
-        )
-    case DNS01:
-        d := query.DnsCredential
-        dnsCredential, err := d.FirstByID(payload.DNSCredentialID)
-        if err != nil {
-            errChan <- errors.Wrap(err, "get dns credential error")
-            return
-        }
-
-        l.Println("[INFO] [Nginx UI] Setting DNS01 challenge provider")
-        code := dnsCredential.Config.Code
-        pConfig, ok := dns.GetProvider(code)
-
-        if !ok {
-            errChan <- errors.Wrap(err, "provider not found")
-        }
-        l.Println("[INFO] [Nginx UI] Setting environment variables")
-        if dnsCredential.Config.Configuration != nil {
-            err = pConfig.SetEnv(*dnsCredential.Config.Configuration)
-            if err != nil {
-                break
-            }
-            defer func() {
-                pConfig.CleanEnv()
-                l.Println("[INFO] [Nginx UI] Cleaned environment variables")
-            }()
-            provider, err := dnsproviders.NewDNSChallengeProviderByName(code)
-            if err != nil {
-                break
-            }
-            err = client.Challenge.SetDNS01Provider(provider)
-        } else {
-            errChan <- errors.Wrap(err, "environment configuration is empty")
-            return
-        }
-
-    }
-
-    if err != nil {
-        errChan <- errors.Wrap(err, "challenge error")
-        return
-    }
-
-    // New users will need to register
-    l.Println("[INFO] [Nginx UI] Registering user")
-    reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
-    if err != nil {
-        errChan <- errors.Wrap(err, "register error")
-        return
-    }
-    user.Registration = reg
-
-    request := certificate.ObtainRequest{
-        Domains: domain,
-        Bundle:  true,
-    }
-
-    l.Println("[INFO] [Nginx UI] Obtaining certificate")
-    certificates, err := client.Certificate.Obtain(request)
-    if err != nil {
-        errChan <- errors.Wrap(err, "obtain certificate error")
-        return
-    }
-    name := strings.Join(domain, "_")
-    saveDir := nginx.GetConfPath("ssl/" + name)
-    if _, err = os.Stat(saveDir); os.IsNotExist(err) {
-        err = os.MkdirAll(saveDir, 0755)
-        if err != nil {
-            errChan <- errors.Wrap(err, "mkdir error")
-            return
-        }
-    }
-
-    // Each certificate comes back with the cert bytes, the bytes of the client's
-    // private key, and a certificate URL. SAVE THESE TO DISK.
-    l.Println("[INFO] [Nginx UI] Writing certificate to disk")
-    err = os.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
-        certificates.Certificate, 0644)
-
-    if err != nil {
-        errChan <- errors.Wrap(err, "write fullchain.cer error")
-        return
-    }
-
-    l.Println("[INFO] [Nginx UI] Writing certificate private key to disk")
-    err = os.WriteFile(filepath.Join(saveDir, "private.key"),
-        certificates.PrivateKey, 0644)
-
-    if err != nil {
-        errChan <- errors.Wrap(err, "write private.key error")
-        return
-    }
-
-    l.Println("[INFO] [Nginx UI] Reloading nginx")
-
-    nginx.Reload()
-
-    l.Println("[INFO] [Nginx UI] Finished")
-
-    // Wait log to be written
-    time.Sleep(5 * time.Second)
+	defer func() {
+		if err := recover(); err != nil {
+			logger.Error(err)
+		}
+	}()
+
+	// initial a channelWriter to receive logs
+	cw := NewChannelWriter()
+	defer close(errChan)
+
+	// initial a logger
+	l := log.New(os.Stderr, "", log.LstdFlags)
+	l.SetOutput(cw)
+
+	// Hijack the (logger) of lego
+	legolog.Logger = l
+
+	domain := payload.ServerName
+
+	// Create a user. New accounts need an email and private key to start.
+	l.Println("[INFO] [Nginx UI] Generating private key for registering account")
+	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		errChan <- errors.Wrap(err, "issue cert generate key error")
+		return
+	}
+
+	l.Println("[INFO] [Nginx UI] Preparing lego configurations")
+	user := User{
+		Email: settings.ServerSettings.Email,
+		Key:   privateKey,
+	}
+
+	// Start a goroutine to fetch and process logs from channel
+	go func() {
+		for msg := range cw.Ch {
+			logChan <- string(msg)
+		}
+	}()
+
+	config := lego.NewConfig(&user)
+
+	if settings.ServerSettings.Demo {
+		config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
+	}
+
+	if settings.ServerSettings.CADir != "" {
+		config.CADirURL = settings.ServerSettings.CADir
+		if config.HTTPClient != nil {
+			config.HTTPClient.Transport = &http.Transport{
+				TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+			}
+		}
+	}
+
+	config.Certificate.KeyType = certcrypto.RSA2048
+
+	l.Println("[INFO] [Nginx UI] Creating client facilitates communication with the CA server")
+	// A client facilitates communication with the CA server.
+	client, err := lego.NewClient(config)
+	if err != nil {
+		errChan <- errors.Wrap(err, "issue cert new client error")
+		return
+	}
+
+	switch payload.ChallengeMethod {
+	default:
+		fallthrough
+	case HTTP01:
+		l.Println("[INFO] [Nginx UI] Setting HTTP01 challenge provider")
+		err = client.Challenge.SetHTTP01Provider(
+			http01.NewProviderServer("",
+				settings.ServerSettings.HTTPChallengePort,
+			),
+		)
+	case DNS01:
+		d := query.DnsCredential
+		dnsCredential, err := d.FirstByID(payload.DNSCredentialID)
+		if err != nil {
+			errChan <- errors.Wrap(err, "get dns credential error")
+			return
+		}
+
+		l.Println("[INFO] [Nginx UI] Setting DNS01 challenge provider")
+		code := dnsCredential.Config.Code
+		pConfig, ok := dns.GetProvider(code)
+
+		if !ok {
+			errChan <- errors.Wrap(err, "provider not found")
+		}
+		l.Println("[INFO] [Nginx UI] Setting environment variables")
+		if dnsCredential.Config.Configuration != nil {
+			err = pConfig.SetEnv(*dnsCredential.Config.Configuration)
+			if err != nil {
+				break
+			}
+			defer func() {
+				pConfig.CleanEnv()
+				l.Println("[INFO] [Nginx UI] Cleaned environment variables")
+			}()
+			provider, err := dnsproviders.NewDNSChallengeProviderByName(code)
+			if err != nil {
+				break
+			}
+			err = client.Challenge.SetDNS01Provider(provider)
+		} else {
+			errChan <- errors.Wrap(err, "environment configuration is empty")
+			return
+		}
+
+	}
+
+	if err != nil {
+		errChan <- errors.Wrap(err, "challenge error")
+		return
+	}
+
+	// New users will need to register
+	l.Println("[INFO] [Nginx UI] Registering user")
+	reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
+	if err != nil {
+		errChan <- errors.Wrap(err, "register error")
+		return
+	}
+	user.Registration = reg
+
+	request := certificate.ObtainRequest{
+		Domains: domain,
+		Bundle:  true,
+	}
+
+	l.Println("[INFO] [Nginx UI] Obtaining certificate")
+	certificates, err := client.Certificate.Obtain(request)
+	if err != nil {
+		errChan <- errors.Wrap(err, "obtain certificate error")
+		return
+	}
+	name := strings.Join(domain, "_")
+	saveDir := nginx.GetConfPath("ssl/" + name)
+	if _, err = os.Stat(saveDir); os.IsNotExist(err) {
+		err = os.MkdirAll(saveDir, 0755)
+		if err != nil {
+			errChan <- errors.Wrap(err, "mkdir error")
+			return
+		}
+	}
+
+	// Each certificate comes back with the cert bytes, the bytes of the client's
+	// private key, and a certificate URL. SAVE THESE TO DISK.
+	l.Println("[INFO] [Nginx UI] Writing certificate to disk")
+	err = os.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
+		certificates.Certificate, 0644)
+
+	if err != nil {
+		errChan <- errors.Wrap(err, "write fullchain.cer error")
+		return
+	}
+
+	l.Println("[INFO] [Nginx UI] Writing certificate private key to disk")
+	err = os.WriteFile(filepath.Join(saveDir, "private.key"),
+		certificates.PrivateKey, 0644)
+
+	if err != nil {
+		errChan <- errors.Wrap(err, "write private.key error")
+		return
+	}
+
+	l.Println("[INFO] [Nginx UI] Reloading nginx")
+
+	nginx.Reload()
+
+	l.Println("[INFO] [Nginx UI] Finished")
+
+	// Wait log to be written
+	time.Sleep(2 * time.Second)
 }