1outer@{
2 lib,
3 stdenv,
4 fetchurl,
5 fetchpatch,
6 openssl,
7 zlib-ng,
8 pcre2,
9 libxml2,
10 libxslt,
11 nginx-doc,
12
13 nixosTests,
14 installShellFiles,
15 replaceVars,
16 removeReferencesTo,
17 gd,
18 geoip,
19 perl,
20 withDebug ? false,
21 withGeoIP ? false,
22 withImageFilter ? false,
23 withKTLS ? true,
24 withStream ? true,
25 withMail ? false,
26 withPerl ? true,
27 withSlice ? false,
28 modules ? [ ],
29 ...
30}:
31
32{
33 pname ? "nginx",
34 version,
35 nginxVersion ? version,
36 src ? null, # defaults to upstream nginx ${version}
37 hash ? null, # when not specifying src
38 configureFlags ? [ ],
39 nativeBuildInputs ? [ ],
40 buildInputs ? [ ],
41 extraPatches ? [ ],
42 fixPatch ? p: p,
43 postPatch ? null,
44 preConfigure ? "",
45 preInstall ? "",
46 postInstall ? "",
47 meta ? null,
48 nginx-doc ? outer.nginx-doc,
49 passthru ? {
50 tests = { };
51 },
52}:
53
54let
55
56 moduleNames = map (
57 mod:
58 mod.name
59 or (throw "The nginx module with source ${toString mod.src} does not have a `name` attribute. This prevents duplicate module detection and is no longer supported.")
60 ) modules;
61
62 mapModules =
63 attrPath:
64 lib.flip lib.concatMap modules (
65 mod:
66 let
67 supports = mod.supports or (_: true);
68 in
69 if supports nginxVersion then
70 mod.${attrPath} or [ ]
71 else
72 throw "Module at ${toString mod.src} does not support nginx version ${nginxVersion}!"
73 );
74
75in
76
77assert lib.assertMsg (lib.unique moduleNames == moduleNames)
78 "nginx: duplicate modules: ${lib.concatStringsSep ", " moduleNames}. A common cause for this is that services.nginx.additionalModules adds a module which the nixos module itself already adds.";
79
80stdenv.mkDerivation {
81 inherit pname version nginxVersion;
82
83 outputs = [
84 "out"
85 "doc"
86 ];
87
88 src =
89 if src != null then
90 src
91 else
92 fetchurl {
93 url = "https://nginx.org/download/nginx-${version}.tar.gz";
94 inherit hash;
95 };
96
97 nativeBuildInputs = [
98 installShellFiles
99 removeReferencesTo
100 ]
101 ++ nativeBuildInputs;
102
103 buildInputs = [
104 openssl
105 zlib-ng
106 pcre2
107 libxml2
108 libxslt
109 perl
110 ]
111 ++ buildInputs
112 ++ mapModules "inputs"
113 ++ lib.optional withGeoIP geoip
114 ++ lib.optional withImageFilter gd;
115
116 configureFlags = [
117 "--sbin-path=bin/nginx"
118 "--with-http_ssl_module"
119 "--with-http_v2_module"
120 "--with-http_realip_module"
121 "--with-http_addition_module"
122 "--with-http_xslt_module"
123 "--with-http_sub_module"
124 "--with-http_dav_module"
125 "--with-http_flv_module"
126 "--with-http_mp4_module"
127 "--with-http_gunzip_module"
128 "--with-http_gzip_static_module"
129 "--with-http_auth_request_module"
130 "--with-http_random_index_module"
131 "--with-http_secure_link_module"
132 "--with-http_degradation_module"
133 "--with-http_stub_status_module"
134 "--with-threads"
135 "--with-pcre-jit"
136 "--http-log-path=/var/log/nginx/access.log"
137 "--error-log-path=/var/log/nginx/error.log"
138 "--pid-path=/var/log/nginx/nginx.pid"
139 "--http-client-body-temp-path=/tmp/nginx_client_body"
140 "--http-proxy-temp-path=/tmp/nginx_proxy"
141 "--http-fastcgi-temp-path=/tmp/nginx_fastcgi"
142 "--http-uwsgi-temp-path=/tmp/nginx_uwsgi"
143 "--http-scgi-temp-path=/tmp/nginx_scgi"
144 ]
145 ++ lib.optionals withDebug [
146 "--with-debug"
147 ]
148 ++ lib.optionals withKTLS [
149 "--with-openssl-opt=enable-ktls"
150 ]
151 ++ lib.optionals withStream [
152 "--with-stream"
153 "--with-stream_realip_module"
154 "--with-stream_ssl_module"
155 "--with-stream_ssl_preread_module"
156 ]
157 ++ lib.optionals withMail [
158 "--with-mail"
159 "--with-mail_ssl_module"
160 ]
161 ++ lib.optionals withPerl [
162 "--with-http_perl_module"
163 "--with-perl=${perl}/bin/perl"
164 "--with-perl_modules_path=lib/perl5"
165 ]
166 ++ lib.optional withImageFilter "--with-http_image_filter_module"
167 ++ lib.optional withSlice "--with-http_slice_module"
168 ++ lib.optionals withGeoIP (
169 [ "--with-http_geoip_module" ] ++ lib.optional withStream "--with-stream_geoip_module"
170 )
171 ++ lib.optional (with stdenv.hostPlatform; isLinux || isFreeBSD) "--with-file-aio"
172 ++ lib.optional (
173 stdenv.buildPlatform != stdenv.hostPlatform
174 ) "--crossbuild=${stdenv.hostPlatform.uname.system}::${stdenv.hostPlatform.uname.processor}"
175 ++ configureFlags
176 ++ map (mod: "--add-module=${mod.src}") modules;
177
178 env.NIX_CFLAGS_COMPILE = toString (
179 [
180 "-I${libxml2.dev}/include/libxml2"
181 "-Wno-error=implicit-fallthrough"
182 (
183 # zlig-ng patch needs this
184 if stdenv.cc.isGNU then
185 "-Wno-error=discarded-qualifiers"
186 else
187 "-Wno-error=incompatible-pointer-types-discards-qualifiers"
188 )
189 ]
190 ++ lib.optionals (stdenv.cc.isGNU && lib.versionAtLeast stdenv.cc.version "11") [
191 # fix build vts module on gcc11
192 "-Wno-error=stringop-overread"
193 ]
194 ++ lib.optionals stdenv.cc.isClang [
195 "-Wno-error=deprecated-declarations"
196 "-Wno-error=gnu-folding-constant"
197 "-Wno-error=unused-but-set-variable"
198 ]
199 ++ lib.optionals stdenv.hostPlatform.isMusl [
200 # fix sys/cdefs.h is deprecated
201 "-Wno-error=cpp"
202 ]
203 );
204
205 configurePlatforms = [ ];
206
207 # Disable _multioutConfig hook which adds --bindir=$out/bin into configureFlags,
208 # which breaks build, since nginx does not actually use autoconf.
209 preConfigure = ''
210 setOutputFlags=
211 ''
212 + preConfigure
213 + lib.concatMapStringsSep "\n" (mod: mod.preConfigure or "") modules;
214
215 patches =
216 map fixPatch (
217 [
218 ./nix-etag-1.15.4.patch
219 ./nix-skip-check-logs-path.patch
220 ]
221 ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
222 (fetchpatch {
223 url = "https://raw.githubusercontent.com/openwrt/packages/c057dfb09c7027287c7862afab965a4cd95293a3/net/nginx/patches/102-sizeof_test_fix.patch";
224 sha256 = "0i2k30ac8d7inj9l6bl0684kjglam2f68z8lf3xggcc2i5wzhh8a";
225 })
226 (fetchpatch {
227 url = "https://raw.githubusercontent.com/openwrt/packages/c057dfb09c7027287c7862afab965a4cd95293a3/net/nginx/patches/101-feature_test_fix.patch";
228 sha256 = "0v6890a85aqmw60pgj3mm7g8nkaphgq65dj4v9c6h58wdsrc6f0y";
229 })
230 (fetchpatch {
231 url = "https://raw.githubusercontent.com/openwrt/packages/c057dfb09c7027287c7862afab965a4cd95293a3/net/nginx/patches/103-sys_nerr.patch";
232 sha256 = "0s497x6mkz947aw29wdy073k8dyjq8j99lax1a1mzpikzr4rxlmd";
233 })
234 ]
235 ++ mapModules "patches"
236 )
237 ++ extraPatches;
238
239 postPatch = lib.defaultTo ''
240 substituteInPlace src/http/ngx_http_core_module.c \
241 --replace-fail '@nixStoreDir@' "$NIX_STORE" \
242 --replace-fail '@nixStoreDirLen@' "''${#NIX_STORE}"
243 '' postPatch;
244
245 hardeningEnable = lib.optional (!stdenv.hostPlatform.isDarwin) "pie";
246
247 enableParallelBuilding = true;
248
249 preInstall = ''
250 mkdir -p $doc
251 cp -r ${nginx-doc}/* $doc
252
253 # TODO: make it unconditional when `openresty` and `nginx` are not
254 # sharing this code.
255 if [[ -e man/nginx.8 ]]; then
256 installManPage man/nginx.8
257 fi
258 ''
259 + preInstall;
260
261 disallowedReferences = map (m: m.src) modules;
262
263 postInstall =
264 let
265 noSourceRefs = lib.concatMapStrings (
266 m: "remove-references-to -t ${m.src} $(readlink -fn $out/bin/nginx)\n"
267 ) modules;
268 in
269 postInstall + noSourceRefs;
270
271 passthru = {
272 inherit modules;
273 tests = {
274 inherit (nixosTests)
275 nginx
276 nginx-auth
277 nginx-etag
278 nginx-etag-compression
279 nginx-globalredirect
280 nginx-http3
281 nginx-proxyprotocol
282 nginx-pubhtml
283 nginx-sso
284 nginx-status-page
285 nginx-unix-socket
286 ;
287 variants = lib.recurseIntoAttrs nixosTests.nginx-variants;
288 acme-integration = nixosTests.acme.nginx;
289 }
290 // passthru.tests;
291 };
292
293 meta =
294 if meta != null then
295 meta
296 else
297 with lib;
298 {
299 description = "Reverse proxy and lightweight webserver";
300 mainProgram = "nginx";
301 homepage = "http://nginx.org";
302 license = [ licenses.bsd2 ] ++ concatMap (m: m.meta.license) modules;
303 broken = lib.any (m: m.meta.broken or false) modules;
304 platforms = platforms.all;
305 maintainers = with maintainers; [
306 fpletz
307 raitobezarius
308 ];
309 teams = with teams; [
310 helsinki-systems
311 stridtech
312 ];
313 };
314}