diff options
| author | Maxim Cournoyer <maxim@guixotic.coop> | 2026-05-25 12:19:42 +0900 |
|---|---|---|
| committer | Maxim Cournoyer <maxim@guixotic.coop> | 2026-06-03 13:52:35 +0900 |
| commit | 2aa2bbc5fe4594daa3c782a4bfe258db77fdc01f (patch) | |
| tree | 61cf4b2a29bc6d47a1c9cbed6475a6b7a026e7ac /gnu/services | |
| parent | d2cadc2cfe4cbdfb607b84fdd0f356f14dbc5c1c (diff) | |
services: nginx: Use a fixed location for the nginx configuration file.
The motivation is twofold:
1. We can ensure the presence of the nginx default configuration fragments in
the configuration file directory;
2. 'herd reload nginx' can now be used to reload an updated configuration
file.
Before this change, 'include fastcgi_params;', for example, would fail with
error:
nginx: [emerg] open() "/gnu/store/fastcgi_params" failed
(2: No such file or directory) in /gnu/store/...-nginx.conf:50
* gnu/services/web.scm (%nginx-configuration-file): New variable.
(nginx-activation): Delay configuration file check to...
(nginx-shepherd-service): ... a new one-shot 'nginx-init' service. Adjust to
use the %nginx-configuration-file variable for the configuration file.
<actions>: Add a new 'configuration' action.
(nginx-conf-files, nginx-etc-directory): New procedures.
(nginx-service-type): Extend etc-service-type with nginx-service-type.
* gnu/tests/web.scm (%nginx-servers): Add an include directive to test config
to ensure it now works.
Merges: !8811
Change-Id: I26882ab01288ec4dd374e9f282e95ffa33dfa3cc
Diffstat (limited to 'gnu/services')
| -rw-r--r-- | gnu/services/web.scm | 157 |
1 files changed, 99 insertions, 58 deletions
diff --git a/gnu/services/web.scm b/gnu/services/web.scm index 81e6509e085..9bc1adf147a 100644 --- a/gnu/services/web.scm +++ b/gnu/services/web.scm | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | ;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu> | 18 | ;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu> |
| 19 | ;;; Copyright © 2023 Miguel Ángel Moreno <mail@migalmoreno.com> | 19 | ;;; Copyright © 2023 Miguel Ángel Moreno <mail@migalmoreno.com> |
| 20 | ;;; Copyright © 2024 Leo Nikkilä <hello@lnikki.la> | 20 | ;;; Copyright © 2024 Leo Nikkilä <hello@lnikki.la> |
| 21 | ;;; Copyright © 2025 Maxim Cournoyer <maxim.cournoyer@gmail.com> | 21 | ;;; Copyright © 2025-2026 Maxim Cournoyer <maxim@guixotic.coop> |
| 22 | ;;; Copyright © 2025 Rodion Goritskov <rodion@goritskov.com> | 22 | ;;; Copyright © 2025 Rodion Goritskov <rodion@goritskov.com> |
| 23 | ;;; Copyright © 2026 Fabio Natali <me@fabionatali.com> | 23 | ;;; Copyright © 2026 Fabio Natali <me@fabionatali.com> |
| 24 | ;;; | 24 | ;;; |
| @@ -933,6 +933,13 @@ of index files." | |||
| 933 | (home-directory "/var/empty") | 933 | (home-directory "/var/empty") |
| 934 | (shell (file-append shadow "/sbin/nologin"))))) | 934 | (shell (file-append shadow "/sbin/nologin"))))) |
| 935 | 935 | ||
| 936 | (define %nginx-configuration-file | ||
| 937 | ;; A fixed location is used for the configuration so that it can be reloaded | ||
| 938 | ;; in place. The supporting nginx default configuration files are also | ||
| 939 | ;; added to the /etc/nginx directory so that they can be included normally, | ||
| 940 | ;; e.g. via 'include fastcgi_params;'. | ||
| 941 | "/etc/nginx/nginx.conf") | ||
| 942 | |||
| 936 | (define (nginx-activation config) | 943 | (define (nginx-activation config) |
| 937 | (match-record config | 944 | (match-record config |
| 938 | <nginx-configuration> | 945 | <nginx-configuration> |
| @@ -952,73 +959,105 @@ of index files." | |||
| 952 | (mkdir-p (string-append #$run-directory "/scgi_temp")) | 959 | (mkdir-p (string-append #$run-directory "/scgi_temp")) |
| 953 | ;; Start-up logs. Once configuration is loaded, nginx switches to | 960 | ;; Start-up logs. Once configuration is loaded, nginx switches to |
| 954 | ;; log-directory. | 961 | ;; log-directory. |
| 955 | (mkdir-p (string-append #$run-directory "/logs")) | 962 | (mkdir-p (string-append #$run-directory "/logs"))))) |
| 956 | ;; Check configuration file syntax. | ||
| 957 | (system* (string-append #$nginx "/sbin/nginx") | ||
| 958 | "-c" #$(or file | ||
| 959 | (default-nginx-config config)) | ||
| 960 | "-p" #$run-directory | ||
| 961 | "-t")))) | ||
| 962 | 963 | ||
| 963 | (define (nginx-shepherd-service config) | 964 | (define (nginx-shepherd-service config) |
| 964 | (match-record config | 965 | (match-record config <nginx-configuration> |
| 965 | <nginx-configuration> | ||
| 966 | (nginx file run-directory shepherd-requirement) | 966 | (nginx file run-directory shepherd-requirement) |
| 967 | (let* ((nginx-binary (file-append nginx "/sbin/nginx")) | 967 | (let* ((nginx-binary (file-append nginx "/sbin/nginx")) |
| 968 | (pid-file (in-vicinity run-directory "pid")) | 968 | (pid-file (in-vicinity run-directory "pid")) |
| 969 | (config-file (or file (default-nginx-config config))) | 969 | (nginx-action |
| 970 | (nginx-action | 970 | (lambda args |
| 971 | (lambda args | 971 | #~(lambda _ |
| 972 | #~(lambda _ | 972 | (invoke #$nginx-binary "-c" #$%nginx-configuration-file |
| 973 | (invoke #$nginx-binary "-c" #$config-file #$@args) | 973 | #$@args) |
| 974 | (match '#$args | 974 | (match '#$args |
| 975 | (("-s" "stop") #f) | 975 | (("-s" "stop") #f) |
| 976 | (("-s" . _) #t) | 976 | (("-s" . _) #t) |
| 977 | (_ | 977 | (_ |
| 978 | ;; When FILE is true, we cannot be sure that PID-FILE will | 978 | ;; When FILE is true, we cannot be sure that PID-FILE will |
| 979 | ;; be created, so assume it won't show up. When FILE is | 979 | ;; be created, so assume it won't show up. When FILE is |
| 980 | ;; false, read PID-FILE. | 980 | ;; false, read PID-FILE. |
| 981 | #$(if file | 981 | #$(if file |
| 982 | #~#t | 982 | #~#t |
| 983 | #~(read-pid-file #$pid-file)))))))) | 983 | #~(read-pid-file #$pid-file)))))))) |
| 984 | 984 | ||
| 985 | (list (shepherd-service | 985 | (list (shepherd-service |
| 986 | (provision '(nginx)) | 986 | (documentation "Run nginx pre-start actions.") |
| 987 | (documentation "Run the nginx daemon.") | 987 | (requirement '(user-processes loopback)) |
| 988 | (requirement `(user-processes loopback ,@shepherd-requirement)) | 988 | (provision '(nginx-init)) |
| 989 | (modules `((ice-9 match) | 989 | (one-shot? #t) |
| 990 | ,@%default-modules)) | 990 | (start |
| 991 | (start (nginx-action "-p" run-directory)) | 991 | #~(lambda _ |
| 992 | (stop #~(lambda (value) | 992 | ;; Check configuration file syntax. |
| 993 | ;; When the PID is known, use 'terminate-process', which | 993 | (invoke #$nginx-binary |
| 994 | ;; waits for the main process to actually terminate. | 994 | "-c" #$%nginx-configuration-file |
| 995 | ;; When FILE is true, there's potentially no PID file | 995 | "-p" #$run-directory |
| 996 | ;; and thus the PID is not known; in that case, invoke | 996 | "-t")))) |
| 997 | ;; "nginx -s stop". | 997 | (shepherd-service |
| 998 | (if (process? value) | 998 | (provision '(nginx)) |
| 999 | (terminate-process (process-id value) SIGTERM) | 999 | (documentation "Run the nginx daemon.") |
| 1000 | (#$(nginx-action "-s" "stop"))))) | 1000 | (requirement `( user-processes loopback nginx-init |
| 1001 | ,@shepherd-requirement)) | ||
| 1002 | (modules `((ice-9 match) | ||
| 1003 | ,@%default-modules)) | ||
| 1004 | (start (nginx-action "-p" run-directory)) | ||
| 1005 | (stop #~(lambda (value) | ||
| 1006 | ;; When the PID is known, use 'terminate-process', which | ||
| 1007 | ;; waits for the main process to actually terminate. | ||
| 1008 | ;; When FILE is true, there's potentially no PID file | ||
| 1009 | ;; and thus the PID is not known; in that case, invoke | ||
| 1010 | ;; "nginx -s stop". | ||
| 1011 | (if (process? value) | ||
| 1012 | (terminate-process (process-id value) SIGTERM) | ||
| 1013 | (#$(nginx-action "-s" "stop"))))) | ||
| 1001 | 1014 | ||
| 1002 | (actions | 1015 | (actions |
| 1003 | (list | 1016 | (list |
| 1004 | (shepherd-configuration-action config-file) | 1017 | (shepherd-configuration-action %nginx-configuration-file) |
| 1005 | (shepherd-action | 1018 | (shepherd-action |
| 1006 | (name 'reload) | 1019 | (name 'reload) |
| 1007 | (documentation "Reload nginx configuration file and restart worker processes. | 1020 | (documentation "Reload the nginx configuration file and |
| 1008 | This has the effect of killing old worker processes and starting new ones, using | 1021 | restart worker processes. This has the effect of killing old worker processes |
| 1009 | the same configuration file. It is useful for situations where the same nginx | 1022 | and starting new ones, using the same configuration file. This is useful when |
| 1010 | configuration file can point to different things after a reload, such as | 1023 | either the configuration files itself, or any files it refers to or includes |
| 1011 | renewed TLS certificates, or @code{include}d files.") | 1024 | changed (for example, TLS certificates).") |
| 1012 | (procedure (nginx-action "-p" run-directory "-s" "reload"))) | 1025 | (procedure (nginx-action "-p" run-directory "-s" "reload"))) |
| 1013 | (shepherd-action | 1026 | (shepherd-action |
| 1014 | (name 'reopen) | 1027 | (name 'reopen) |
| 1015 | (documentation "Re-open log files.") | 1028 | (documentation "Re-open log files.") |
| 1016 | (procedure (nginx-action "-p" run-directory "-s" "reopen")))))))))) | 1029 | (procedure (nginx-action "-p" run-directory "-s" "reopen")))))))))) |
| 1017 | 1030 | ||
| 1018 | (define (nginx-log-files config) | 1031 | (define (nginx-log-files config) |
| 1019 | (list (nginx-access-log-file config) | 1032 | (list (nginx-access-log-file config) |
| 1020 | (nginx-error-log-file config))) | 1033 | (nginx-error-log-file config))) |
| 1021 | 1034 | ||
| 1035 | (define (nginx-conf-files config) | ||
| 1036 | ;; Nginx's conf directory files except nginx.conf and .default files. | ||
| 1037 | (match-record config <nginx-configuration> | ||
| 1038 | (nginx file) | ||
| 1039 | (computed-file | ||
| 1040 | "nginx-conf-files" | ||
| 1041 | #~(begin | ||
| 1042 | (use-modules (ice-9 ftw) | ||
| 1043 | (srfi srfi-26)) | ||
| 1044 | (mkdir #$output) | ||
| 1045 | (define nginx-conf #$(file-append nginx "/share/nginx/conf")) | ||
| 1046 | (for-each | ||
| 1047 | (lambda (x) | ||
| 1048 | (symlink x (string-append #$output "/" (basename x)))) | ||
| 1049 | (map (cut string-append nginx-conf "/" <>) | ||
| 1050 | (scandir nginx-conf | ||
| 1051 | (negate (lambda (name) | ||
| 1052 | (or (string-suffix? ".default" name) | ||
| 1053 | (member name '("." ".." | ||
| 1054 | "nginx.conf")))))))) | ||
| 1055 | (symlink #$(or file (default-nginx-config config)) | ||
| 1056 | (string-append #$output "/nginx.conf")))))) | ||
| 1057 | |||
| 1058 | (define (nginx-etc-directory config) | ||
| 1059 | `(("nginx" ,(nginx-conf-files config)))) | ||
| 1060 | |||
| 1022 | (define nginx-service-type | 1061 | (define nginx-service-type |
| 1023 | (service-type | 1062 | (service-type |
| 1024 | (name 'nginx) | 1063 | (name 'nginx) |
| @@ -1031,6 +1070,8 @@ renewed TLS certificates, or @code{include}d files.") | |||
| 1031 | nginx-activation) | 1070 | nginx-activation) |
| 1032 | (service-extension account-service-type | 1071 | (service-extension account-service-type |
| 1033 | (const %nginx-accounts)) | 1072 | (const %nginx-accounts)) |
| 1073 | (service-extension etc-service-type | ||
| 1074 | nginx-etc-directory) | ||
| 1034 | ;; Make the nginx manual page available. | 1075 | ;; Make the nginx manual page available. |
| 1035 | (service-extension profile-service-type | 1076 | (service-extension profile-service-type |
| 1036 | (compose list nginx-configuration-nginx)))) | 1077 | (compose list nginx-configuration-nginx)))) |
