diff --git a/app/src/views/system/SelfCheck/tasks/backend/index.ts b/app/src/views/system/SelfCheck/tasks/backend/index.ts index 01afe14b..a8881ea1 100644 --- a/app/src/views/system/SelfCheck/tasks/backend/index.ts +++ b/app/src/views/system/SelfCheck/tasks/backend/index.ts @@ -21,6 +21,11 @@ const backendTasks: Record = { description: () => $gettext('Check if the nginx.conf includes the streams-enabled directory.'), type: 'backend', }, + 'NginxConf-ConfD': { + name: () => $gettext('Nginx Conf Include Conf.d'), + description: () => $gettext('Check if the nginx.conf includes the conf.d directory.'), + type: 'backend', + }, } export default backendTasks diff --git a/internal/self_check/errors.go b/internal/self_check/errors.go index 202857ba..e745a245 100644 --- a/internal/self_check/errors.go +++ b/internal/self_check/errors.go @@ -16,4 +16,5 @@ var ( ErrSitesEnabledNotExist = e.New(4047, "Sites-enabled directory not exist") ErrStreamAvailableNotExist = e.New(4048, "Streams-available directory not exist") ErrStreamEnabledNotExist = e.New(4049, "Streams-enabled directory not exist") + ErrNginxConfNotIncludeConfD = e.New(4050, "Nginx conf not include conf.d directory") ) diff --git a/internal/self_check/nginx_conf.go b/internal/self_check/nginx_conf.go index 1d7e2778..49c617c8 100644 --- a/internal/self_check/nginx_conf.go +++ b/internal/self_check/nginx_conf.go @@ -3,6 +3,7 @@ package self_check import ( "fmt" "os" + "strings" "time" "github.com/0xJacky/Nginx-UI/internal/nginx" @@ -118,7 +119,7 @@ func FixNginxConfIncludeSites() error { } // 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/*")))...) + content = append(content, fmt.Appendf(nil, "\nhttp {\n\tinclude %s;\n}\n", nginx.GetConfPath("sites-enabled/*"))...) return os.WriteFile(path, content, 0644) } @@ -162,6 +163,84 @@ func FixNginxConfIncludeStreams() error { } // 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/*")))...) + content = append(content, fmt.Appendf(nil, "\nstream {\n\tinclude %s;\n}\n", nginx.GetConfPath("streams-enabled/*"))...) + return os.WriteFile(path, content, 0644) +} + +// CheckNginxConfIncludeConfD checks if nginx.conf includes conf.d directory +func CheckNginxConfIncludeConfD() 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 conf.d + for _, directive := range v.GetBlock().GetDirectives() { + if directive.GetName() == "include" && len(directive.GetParameters()) > 0 && + strings.HasPrefix(directive.GetParameters()[0].Value, nginx.GetConfPath("conf.d")) { + return nil + } + } + return ErrNginxConfNotIncludeConfD + } + } + + return ErrNginxConfNoHttpBlock +} + +// FixNginxConfIncludeConfD attempts to fix nginx.conf to include conf.d directory +func FixNginxConfIncludeConfD() error { + path := nginx.GetConfEntryPath() + + content, err := os.ReadFile(path) + if err != nil { + return ErrFailedToReadNginxConf + } + + // create a backup file (+.bak.timestamp) + backupPath := fmt.Sprintf("%s.bak.%d", path, 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 conf.d/*.conf to http block + includeDirective := &config.Directive{ + Name: "include", + Parameters: []config.Parameter{{Value: nginx.GetConfPath("conf.d/*.conf")}}, + } + + 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 conf.d/*.conf + content = append(content, fmt.Appendf(nil, "\nhttp {\n\tinclude %s;\n}\n", nginx.GetConfPath("conf.d/*.conf"))...) return os.WriteFile(path, content, 0644) } diff --git a/internal/self_check/self_check.go b/internal/self_check/self_check.go index bef72d49..5f2325a0 100644 --- a/internal/self_check/self_check.go +++ b/internal/self_check/self_check.go @@ -40,6 +40,11 @@ var selfCheckTasks = []*Task{ CheckFunc: CheckNginxConfIncludeStreams, FixFunc: FixNginxConfIncludeStreams, }, + { + Name: "NginxConf-ConfD", + CheckFunc: CheckNginxConfIncludeConfD, + FixFunc: FixNginxConfIncludeConfD, + }, } var selfCheckTaskMap = make(map[string]*Task)