feat: add LogDirWhiteList option

This commit is contained in:
Jacky 2024-10-08 12:32:57 +08:00
parent 27f751671b
commit 6d09ff5919
No known key found for this signature in database
GPG key ID: 215C21B10DF38B4D
10 changed files with 185 additions and 63 deletions

1
.gitignore vendored
View file

@ -11,3 +11,4 @@ nginx-ui
resources/development/nginx resources/development/nginx
app/.env app/.env
app/.status_hash app/.status_hash
casdoor.pub

View file

@ -2,9 +2,13 @@ package nginx
import ( import (
"encoding/json" "encoding/json"
"fmt"
"github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/api"
"github.com/0xJacky/Nginx-UI/internal/cache"
"github.com/0xJacky/Nginx-UI/internal/helper"
"github.com/0xJacky/Nginx-UI/internal/logger" "github.com/0xJacky/Nginx-UI/internal/logger"
"github.com/0xJacky/Nginx-UI/internal/nginx" "github.com/0xJacky/Nginx-UI/internal/nginx"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/hpcloud/tail" "github.com/hpcloud/tail"
@ -30,6 +34,7 @@ type controlStruct struct {
type nginxLogPageResp struct { type nginxLogPageResp struct {
Content string `json:"content"` Content string `json:"content"`
Page int64 `json:"page"` Page int64 `json:"page"`
Error string `json:"error,omitempty"`
} }
func GetNginxLogPage(c *gin.Context) { func GetNginxLogPage(c *gin.Context) {
@ -46,6 +51,9 @@ func GetNginxLogPage(c *gin.Context) {
logPath, err := getLogPath(&control) logPath, err := getLogPath(&control)
if err != nil { if err != nil {
c.JSON(http.StatusInternalServerError, nginxLogPageResp{
Error: err.Error(),
})
logger.Error(err) logger.Error(err)
return return
} }
@ -53,13 +61,17 @@ func GetNginxLogPage(c *gin.Context) {
logFileStat, err := os.Stat(logPath) logFileStat, err := os.Stat(logPath)
if err != nil { if err != nil {
c.JSON(http.StatusOK, nginxLogPageResp{}) c.JSON(http.StatusInternalServerError, nginxLogPageResp{
Error: err.Error(),
})
logger.Error(err) logger.Error(err)
return return
} }
if !logFileStat.Mode().IsRegular() { if !logFileStat.Mode().IsRegular() {
c.JSON(http.StatusOK, nginxLogPageResp{}) c.JSON(http.StatusInternalServerError, nginxLogPageResp{
Error: "log file is not regular file",
})
logger.Error("log file is not regular file:", logPath) logger.Error("log file is not regular file:", logPath)
return return
} }
@ -67,7 +79,9 @@ func GetNginxLogPage(c *gin.Context) {
f, err := os.Open(logPath) f, err := os.Open(logPath)
if err != nil { if err != nil {
c.JSON(http.StatusOK, nginxLogPageResp{}) c.JSON(http.StatusInternalServerError, nginxLogPageResp{
Error: err.Error(),
})
logger.Error(err) logger.Error(err)
return return
} }
@ -90,7 +104,9 @@ func GetNginxLogPage(c *gin.Context) {
// seek // seek
_, err = f.Seek(offset, io.SeekStart) _, err = f.Seek(offset, io.SeekStart)
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
c.JSON(http.StatusOK, nginxLogPageResp{}) c.JSON(http.StatusInternalServerError, nginxLogPageResp{
Error: err.Error(),
})
logger.Error(err) logger.Error(err)
return return
} }
@ -98,7 +114,9 @@ func GetNginxLogPage(c *gin.Context) {
n, err := f.Read(buf) n, err := f.Read(buf)
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
c.JSON(http.StatusOK, nginxLogPageResp{}) c.JSON(http.StatusInternalServerError, nginxLogPageResp{
Error: err.Error(),
})
logger.Error(err) logger.Error(err)
return return
} }
@ -109,7 +127,30 @@ func GetNginxLogPage(c *gin.Context) {
}) })
} }
// isLogPathUnderWhiteList checks if the log path is under one of the paths in LogDirWhiteList
func isLogPathUnderWhiteList(path string) bool {
cacheKey := fmt.Sprintf("isLogPathUnderWhiteList:%s", path)
res, ok := cache.Get(cacheKey)
// no cache, check it
if !ok {
for _, whitePath := range settings.NginxSettings.LogDirWhiteList {
if helper.IsUnderDirectory(path, whitePath) {
cache.Set(cacheKey, true, 0)
return true
}
}
return false
}
return res.(bool)
}
func getLogPath(control *controlStruct) (logPath string, err error) { func getLogPath(control *controlStruct) (logPath string, err error) {
if len(settings.NginxSettings.LogDirWhiteList) == 0 {
err = errors.New("The settings.NginxSettings.LogDirWhiteList has not been configured. " +
"For security reasons, please configure a whitelist of log directories. " +
"Please visit https://nginxui.com/guide/config-nginx.html for more information.")
return
}
switch control.Type { switch control.Type {
case "site": case "site":
var config *nginx.NgxConfig var config *nginx.NgxConfig
@ -172,6 +213,11 @@ func getLogPath(control *controlStruct) (logPath string, err error) {
logPath = path logPath = path
} }
// check if logPath is under one of the paths in LogDirWhiteList
if !isLogPathUnderWhiteList(logPath) {
err = errors.New("The log path is not under the paths in LogDirWhiteList.")
return "", err
}
return return
} }

View file

@ -59,6 +59,9 @@ function init() {
nginx_log.page(0, control).then(r => { nginx_log.page(0, control).then(r => {
page.value = r.page - 1 page.value = r.page - 1
addLog(r.content) addLog(r.content)
openWs()
}).catch(e => {
addLog(e.error)
}) })
} }
@ -68,11 +71,10 @@ function clearLog() {
onMounted(() => { onMounted(() => {
init() init()
openWs()
}) })
onUnmounted(() => { onUnmounted(() => {
websocket.close() websocket?.close()
}) })
watch(auto_refresh, value => { watch(auto_refresh, value => {

29
casdoor.pub Normal file
View file

@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE3TCCAsWgAwIBAgIDAeJAMA0GCSqGSIb3DQEBCwUAMCgxDjAMBgNVBAoTBWFk
bWluMRYwFAYDVQQDEw1jZXJ0LWJ1aWx0LWluMB4XDTI0MDcyOTAzMDUzM1oXDTQ0
MDcyOTAzMDUzM1owKDEOMAwGA1UEChMFYWRtaW4xFjAUBgNVBAMTDWNlcnQtYnVp
bHQtaW4wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh0c2zvM21NDNi
xZmSQVPOtckiH/K80mHQ99e+xzdGrZugaw00tyTOMVRot+Bv1cggcJXmFcVaa9Da
siIcIQ6jT3w7mINsrErYu4nz9tELd4BZUM6tytN+khVqo73p/NbRsnmX8ykMyrgx
YCBknNoSxh7glLSmKcj4uQ12dYakRPr0QNnDwU7fpPfB7N4O88yXWpbqWaABwqBx
S6+tYUp9Wx74mH8c917w5xXx8EI5eC+dJOAeVXrbzqD7OdC+uo8m7f06HAX1vRE/
MQS0BDx8tDGtqOvdJbVxdnS6MQ2E3vmuusFseDcKVgqTF/7b76y5uNyBBux5zfpt
G1O3bquMlQ8mSedK8BBcbI79gXYJRWazMBXvAdacaV93dF1s0EEjYXiBManAci2d
lH8zzs4TNpE0t3adYiPbGPW1F6Q+HaV52MDVpFwG9Ld0kJmKhkvoWiSXl58Db3VN
Ef8Jjo2xF+5o9685CQ2o9L0RalcHxMxy1+6wdKMSp7PReYpIiEgmkAhUsKePOVmr
JwL46/4EulcXrh+ASjobmknHzdBQEK+MHapb/XWewX4mzq777gPmP8RdILTHsc1m
/hbR8uW9iTfo9LQFvXwnIPVfX0wzFXSZzSg/zLb2tN5D7VlDenUAdCDT1zNOfz5m
9vLYwfo5GzXIkp2py0G40vrZlv7C9wIDAQABoxAwDjAMBgNVHRMBAf8EAjAAMA0G
CSqGSIb3DQEBCwUAA4ICAQBp1Bx+mShpumQiVb2hv0amSzAKADyYIX3Xcef68rPu
Eb+7HSCmQf4yyI9eU1TyvQCLbjum3U3OhDWwAiRvxOwj0oO/Q+dOUEZxTjbL9UF3
4LIrUUBMRhRgy3wK73qy3o8hAcRtQyexUW7eoFS+7L++6XQOvMkYAtLO0DQCHeKG
loiQa5RuWbzQDdP7810DLvNF8IMA8t9KKaKGybYze9WTzRUMTDbXby8pVs8DG7JI
zIW6neEmtsVbxufk/nthG1b83/yZxe0StL42xI7f4xgguhkfd68E4lpf/gp91EAM
K6MbTmCqkB68c0wOSXpWYkte7EvXTTmMSKf6FnMgOtqdxqYYMknLk4ZdI7tMqS31
rpb9XxjBgXFbB18oOSDbW64KPMjE7vuOx+o32BTHKsUWxOiDc8+0ELrbhG2Bm1Gj
CYkx9bq5iTLDwtZZlPoA8O/T0TJzBTtC/tlEdpHSkkLoEaWsx0nT9ipRWck1Kj59
NGJkArbrpq9Ee8tWJKqTN/pv0X8r+MxowIY2dKvwweokXb7R6k9nfXyGw8ji22Hv
H4iibv9FEyVFQ16HPR6fIKg9yE9u0223UhJZEwohA4DylCxpmI/YSXbUmzQJwjBP
27qvT4Y07xsdNqIbkwhb5yEQB5huivITD+SBwI5NwDfUeY6eF/BEHpRq+Uy3itx0
SA==
-----END CERTIFICATE-----

View file

@ -33,6 +33,20 @@ In Nginx UI v2, we parse the output of the `nginx -V` command to get the default
If you need to set a different path, you can use this option. If you need to set a different path, you can use this option.
::: :::
### LogDirWhiteList
- Type: `[]string`
- Version`>= v2.0.0-beta.36`
- Example: `/var/log/nginx,/var/log/sites`
This option is used to set the whitelist of directories for the Nginx logs viewer in Nginx UI.
::: warning Warning
For security reasons, you must specify the directories where the logs are stored.
Only logs within these directories can be viewed online.
:::
## Service Monitoring and Control ## Service Monitoring and Control
In this section, we will introduce configuration options in Nginx UI for monitoring and controlling Nginx services. In this section, we will introduce configuration options in Nginx UI for monitoring and controlling Nginx services.

View file

@ -7,11 +7,11 @@
"docs:preview": "vitepress preview" "docs:preview": "vitepress preview"
}, },
"dependencies": { "dependencies": {
"vitepress": "^1.3.4", "vitepress": "^1.4.0",
"vue": "^3.5.11" "vue": "^3.5.11"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.7.4", "@types/node": "^22.7.5",
"less": "^4.2.0" "less": "^4.2.0"
}, },
"license": "AGPL-3.0", "license": "AGPL-3.0",

95
docs/pnpm-lock.yaml generated
View file

@ -9,15 +9,15 @@ importers:
.: .:
dependencies: dependencies:
vitepress: vitepress:
specifier: ^1.3.4 specifier: ^1.4.0
version: 1.3.4(@algolia/client-search@4.24.0)(@types/node@22.7.4)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0) version: 1.4.0(@algolia/client-search@4.24.0)(@types/node@22.7.5)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0)
vue: vue:
specifier: ^3.5.11 specifier: ^3.5.11
version: 3.5.11 version: 3.5.11
devDependencies: devDependencies:
'@types/node': '@types/node':
specifier: ^22.7.4 specifier: ^22.7.5
version: 22.7.4 version: 22.7.5
less: less:
specifier: ^4.2.0 specifier: ^4.2.0
version: 4.2.0 version: 4.2.0
@ -350,20 +350,20 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@shikijs/core@1.21.1': '@shikijs/core@1.22.0':
resolution: {integrity: sha512-scBQo4V4O4WZLEDg11e75UPmXoCMq4Ya2A16U6efi/aTiR4o7T/GMNWZs2rq1U8dEvFKGxJZxiUy+tXgmr/4vw==} resolution: {integrity: sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==}
'@shikijs/engine-javascript@1.21.1': '@shikijs/engine-javascript@1.22.0':
resolution: {integrity: sha512-29EG4KYKlAona8yikEx8uoKbK7N2YoXUO26LS1GOIxpMMIAlQS9UFONg95lkGmIfp1rRcvCvSpYYIJ/blsQxvg==} resolution: {integrity: sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==}
'@shikijs/engine-oniguruma@1.21.1': '@shikijs/engine-oniguruma@1.22.0':
resolution: {integrity: sha512-PvfEtXCDbQZc9ud0SC0bPiuMbul44Cv0Ky2go4SsvVkYAAKYJsMe/Hx7nxThW8yS0r+w8USa0WfOtQKsD9DU9A==} resolution: {integrity: sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==}
'@shikijs/transformers@1.21.1': '@shikijs/transformers@1.22.0':
resolution: {integrity: sha512-97csTb0Gv8eLbglPDhNZTuAI9eCXOujNqD4qK6H0cjFNK+NBhkRIU02RgmYHZ7yNyLary6cEzY6WmUWb+al3MQ==} resolution: {integrity: sha512-k7iMOYuGQA62KwAuJOQBgH2IQb5vP8uiB3lMvAMGUgAMMurePOx3Z7oNqJdcpxqZP6I9cc7nc4DNqSKduCxmdg==}
'@shikijs/types@1.21.1': '@shikijs/types@1.22.0':
resolution: {integrity: sha512-yLuTJTCHmYznerJ0nxF+f2rBKHQf2FMAd08QL/3du2xNBy/7yQ8CjuKN4Zc+Pk0vfIFzdBoxdzvEXE4JtXoR4Q==} resolution: {integrity: sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==}
'@shikijs/vscode-textmate@9.3.0': '@shikijs/vscode-textmate@9.3.0':
resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==}
@ -386,8 +386,8 @@ packages:
'@types/mdurl@2.0.0': '@types/mdurl@2.0.0':
resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
'@types/node@22.7.4': '@types/node@22.7.5':
resolution: {integrity: sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==} resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==}
'@types/unist@3.0.3': '@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
@ -691,8 +691,8 @@ packages:
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
hasBin: true hasBin: true
shiki@1.21.1: shiki@1.22.0:
resolution: {integrity: sha512-jSOKRHyQJxGOW3kJflmwzHJbp/kjg6hP8LYuVbCPw5oyX+fSNNoCywvcCD3w9eHbj2rvNljt7YMa5BP5Xi+nHg==} resolution: {integrity: sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==}
source-map-js@1.2.1: source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
@ -784,8 +784,8 @@ packages:
terser: terser:
optional: true optional: true
vitepress@1.3.4: vitepress@1.4.0:
resolution: {integrity: sha512-I1/F6OW1xl3kW4PaIMC6snxjWgf3qfziq2aqsDoFc/Gt41WbcRv++z8zjw8qGRIJ+I4bUW7ZcKFDHHN/jkH9DQ==} resolution: {integrity: sha512-JXCv4EsKTDyAFb6C/UjZr7nsGAzZ6mafVk2rx7rG5o8N+B/4QstIk+iEOe/9dKoU6V624UIC6g1pZ+K63rxhlw==}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
markdown-it-mathjax3: ^4 markdown-it-mathjax3: ^4
@ -1081,31 +1081,31 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.24.0': '@rollup/rollup-win32-x64-msvc@4.24.0':
optional: true optional: true
'@shikijs/core@1.21.1': '@shikijs/core@1.22.0':
dependencies: dependencies:
'@shikijs/engine-javascript': 1.21.1 '@shikijs/engine-javascript': 1.22.0
'@shikijs/engine-oniguruma': 1.21.1 '@shikijs/engine-oniguruma': 1.22.0
'@shikijs/types': 1.21.1 '@shikijs/types': 1.22.0
'@shikijs/vscode-textmate': 9.3.0 '@shikijs/vscode-textmate': 9.3.0
'@types/hast': 3.0.4 '@types/hast': 3.0.4
hast-util-to-html: 9.0.3 hast-util-to-html: 9.0.3
'@shikijs/engine-javascript@1.21.1': '@shikijs/engine-javascript@1.22.0':
dependencies: dependencies:
'@shikijs/types': 1.21.1 '@shikijs/types': 1.22.0
'@shikijs/vscode-textmate': 9.3.0 '@shikijs/vscode-textmate': 9.3.0
oniguruma-to-js: 0.4.3 oniguruma-to-js: 0.4.3
'@shikijs/engine-oniguruma@1.21.1': '@shikijs/engine-oniguruma@1.22.0':
dependencies: dependencies:
'@shikijs/types': 1.21.1 '@shikijs/types': 1.22.0
'@shikijs/vscode-textmate': 9.3.0 '@shikijs/vscode-textmate': 9.3.0
'@shikijs/transformers@1.21.1': '@shikijs/transformers@1.22.0':
dependencies: dependencies:
shiki: 1.21.1 shiki: 1.22.0
'@shikijs/types@1.21.1': '@shikijs/types@1.22.0':
dependencies: dependencies:
'@shikijs/vscode-textmate': 9.3.0 '@shikijs/vscode-textmate': 9.3.0
'@types/hast': 3.0.4 '@types/hast': 3.0.4
@ -1131,7 +1131,7 @@ snapshots:
'@types/mdurl@2.0.0': {} '@types/mdurl@2.0.0': {}
'@types/node@22.7.4': '@types/node@22.7.5':
dependencies: dependencies:
undici-types: 6.19.8 undici-types: 6.19.8
@ -1141,9 +1141,9 @@ snapshots:
'@ungap/structured-clone@1.2.0': {} '@ungap/structured-clone@1.2.0': {}
'@vitejs/plugin-vue@5.1.4(vite@5.4.8(@types/node@22.7.4)(less@4.2.0))(vue@3.5.11)': '@vitejs/plugin-vue@5.1.4(vite@5.4.8(@types/node@22.7.5)(less@4.2.0))(vue@3.5.11)':
dependencies: dependencies:
vite: 5.4.8(@types/node@22.7.4)(less@4.2.0) vite: 5.4.8(@types/node@22.7.5)(less@4.2.0)
vue: 3.5.11 vue: 3.5.11
'@vue/compiler-core@3.5.11': '@vue/compiler-core@3.5.11':
@ -1504,12 +1504,12 @@ snapshots:
semver@5.7.2: semver@5.7.2:
optional: true optional: true
shiki@1.21.1: shiki@1.22.0:
dependencies: dependencies:
'@shikijs/core': 1.21.1 '@shikijs/core': 1.22.0
'@shikijs/engine-javascript': 1.21.1 '@shikijs/engine-javascript': 1.22.0
'@shikijs/engine-oniguruma': 1.21.1 '@shikijs/engine-oniguruma': 1.22.0
'@shikijs/types': 1.21.1 '@shikijs/types': 1.22.0
'@shikijs/vscode-textmate': 9.3.0 '@shikijs/vscode-textmate': 9.3.0
'@types/hast': 3.0.4 '@types/hast': 3.0.4
@ -1574,24 +1574,25 @@ snapshots:
'@types/unist': 3.0.3 '@types/unist': 3.0.3
vfile-message: 4.0.2 vfile-message: 4.0.2
vite@5.4.8(@types/node@22.7.4)(less@4.2.0): vite@5.4.8(@types/node@22.7.5)(less@4.2.0):
dependencies: dependencies:
esbuild: 0.21.5 esbuild: 0.21.5
postcss: 8.4.47 postcss: 8.4.47
rollup: 4.24.0 rollup: 4.24.0
optionalDependencies: optionalDependencies:
'@types/node': 22.7.4 '@types/node': 22.7.5
fsevents: 2.3.3 fsevents: 2.3.3
less: 4.2.0 less: 4.2.0
vitepress@1.3.4(@algolia/client-search@4.24.0)(@types/node@22.7.4)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0): vitepress@1.4.0(@algolia/client-search@4.24.0)(@types/node@22.7.5)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0):
dependencies: dependencies:
'@docsearch/css': 3.6.2 '@docsearch/css': 3.6.2
'@docsearch/js': 3.6.2(@algolia/client-search@4.24.0)(search-insights@2.13.0) '@docsearch/js': 3.6.2(@algolia/client-search@4.24.0)(search-insights@2.13.0)
'@shikijs/core': 1.21.1 '@shikijs/core': 1.22.0
'@shikijs/transformers': 1.21.1 '@shikijs/transformers': 1.22.0
'@shikijs/types': 1.22.0
'@types/markdown-it': 14.1.2 '@types/markdown-it': 14.1.2
'@vitejs/plugin-vue': 5.1.4(vite@5.4.8(@types/node@22.7.4)(less@4.2.0))(vue@3.5.11) '@vitejs/plugin-vue': 5.1.4(vite@5.4.8(@types/node@22.7.5)(less@4.2.0))(vue@3.5.11)
'@vue/devtools-api': 7.4.6 '@vue/devtools-api': 7.4.6
'@vue/shared': 3.5.11 '@vue/shared': 3.5.11
'@vueuse/core': 11.1.0(vue@3.5.11) '@vueuse/core': 11.1.0(vue@3.5.11)
@ -1599,8 +1600,8 @@ snapshots:
focus-trap: 7.6.0 focus-trap: 7.6.0
mark.js: 8.11.1 mark.js: 8.11.1
minisearch: 7.1.0 minisearch: 7.1.0
shiki: 1.21.1 shiki: 1.22.0
vite: 5.4.8(@types/node@22.7.4)(less@4.2.0) vite: 5.4.8(@types/node@22.7.5)(less@4.2.0)
vue: 3.5.11 vue: 3.5.11
optionalDependencies: optionalDependencies:
postcss: 8.4.47 postcss: 8.4.47

View file

@ -34,6 +34,20 @@ Nginx 日志对于监控、排查问题和维护您的 Web 服务器至关重要
如果您需要设置不同的路径,您可以使用此选项。 如果您需要设置不同的路径,您可以使用此选项。
::: :::
### LogDirWhiteList
- 类型:`[]string`
- 版本:`>= v2.0.0-beta.36`
- 示例:`/var/log/nginx,/var/log/sites`
此选项用于为 Nginx UI 设置日志查看器的目录白名单。
::: warning 警告
出于安全原因,您必须指定存储日志的目录。
只有这些目录中的日志可以在线查看。
:::
## 服务监控与控制 ## 服务监控与控制
在本节中,我们将会介绍 Nginx UI 中关于 Nginx 服务的监控和控制命令的配置选项。 在本节中,我们将会介绍 Nginx UI 中关于 Nginx 服务的监控和控制命令的配置选项。

View file

@ -33,6 +33,20 @@ Nginx 日誌對於監控、排查問題和維護您的 Web 伺服器至關重要
如果您需要設置不同的路徑,您可以使用此選項。 如果您需要設置不同的路徑,您可以使用此選項。
::: :::
### LogDirWhiteList
- 類型:`[]string`
- 版本:`>= v2.0.0-beta.36`
- 示例:`/var/log/nginx,/var/log/sites`
此選項用於為 Nginx UI 設置日誌查看器的目錄白名單。
::: warning 警告
出於安全原因,您必須指定存儲日誌的目錄。
只有這些目錄中的日誌可以在線查看。
:::
## 服務監控與控制 ## 服務監控與控制
在本節中,我們將會介紹 Nginx UI 中關於 Nginx 服務的監控和控制命令的配置選項。 在本節中,我們將會介紹 Nginx UI 中關於 Nginx 服務的監控和控制命令的配置選項。

View file

@ -1,13 +1,14 @@
package settings package settings
type Nginx struct { type Nginx struct {
AccessLogPath string `json:"access_log_path" protected:"true"` AccessLogPath string `json:"access_log_path" protected:"true"`
ErrorLogPath string `json:"error_log_path" protected:"true"` ErrorLogPath string `json:"error_log_path" protected:"true"`
ConfigDir string `json:"config_dir" protected:"true"` LogDirWhiteList []string `json:"log_dir_white_list" protected:"true"`
PIDPath string `json:"pid_path" protected:"true"` ConfigDir string `json:"config_dir" protected:"true"`
TestConfigCmd string `json:"test_config_cmd" protected:"true"` PIDPath string `json:"pid_path" protected:"true"`
ReloadCmd string `json:"reload_cmd" protected:"true"` TestConfigCmd string `json:"test_config_cmd" protected:"true"`
RestartCmd string `json:"restart_cmd" protected:"true"` ReloadCmd string `json:"reload_cmd" protected:"true"`
RestartCmd string `json:"restart_cmd" protected:"true"`
} }
var NginxSettings = Nginx{ var NginxSettings = Nginx{