diff --git a/all-packages.nix b/all-packages.nix index c849a12..e08304a 100644 --- a/all-packages.nix +++ b/all-packages.nix @@ -20,6 +20,10 @@ let CaddySiteConfig = callPackage ./caddy/siteconfig.nix {inherit utils;}; mkCaddySiteConfig = callPackage ./caddy/mksiteconfig.nix {inherit CaddySiteConfig;}; + NginxService = callPackage ./nginx/unit.nix {inherit utils;}; + NginxSiteConfig = callPackage ./nginx/siteconfig.nix {inherit utils;}; + mkNginxSiteConfig = callPackage ./nginx/mksiteconfig.nix {inherit NginxSiteConfig;}; + PHPConfig = callPackage ./php/config.nix {inherit utils;}; PHPFPMConfig = callPackage ./php-fpm/config.nix {inherit utils;}; diff --git a/nginx/mksiteconfig.nix b/nginx/mksiteconfig.nix new file mode 100644 index 0000000..f95ad83 --- /dev/null +++ b/nginx/mksiteconfig.nix @@ -0,0 +1,25 @@ +{ NginxSiteConfig +}: +{ siteConfigDir +, runtimeDirectory +, name +, port +, siteName +, siteRoot +, phpFpmSiteSocket ? "" +}: +rec { + inherit name siteConfigDir; + siteConfigFile = "${siteName}.config"; + nginxSocket = "${runtimeDirectory}/${siteName}.sock"; + pkg = NginxSiteConfig rec { + inherit siteConfigDir siteConfigFile; + inherit phpFpmSiteSocket; + + portBinding = port; + bindService = siteName; + siteSocket = nginxSocket; + serviceRoot = siteRoot; + }; + type = "fileset"; +} diff --git a/nginx/siteconfig.nix b/nginx/siteconfig.nix new file mode 100644 index 0000000..ae3704f --- /dev/null +++ b/nginx/siteconfig.nix @@ -0,0 +1,172 @@ +{ stdenv +, pkgs +, utils +}: +{ siteConfigDir +, siteConfigFile +, portBinding +, bindService +, serviceRoot ? "/usr/share/webapps/${bindService}" +, siteSocket ? null +, phpFpmSiteSocket ? null +, logLevel ? "WARN" +}: + +let + listen = + if siteSocket != null then + "unix:${siteSocket}" + else + portBinding; + + fastcgi = + if phpFpmSiteSocket == null then + "" + else + '' + location ~ \.php$ { + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:${phpFpmSiteSocket}; + fastcgi_index index.php; + + fastcgi_param GATEWAY_INTERFACE CGI/1.1; + fastcgi_param SERVER_SOFTWARE nginx; + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + fastcgi_param SCRIPT_FILENAME ${serviceRoot}$fastcgi_script_name; + # fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_param REQUEST_URI $request_uri; + fastcgi_param DOCUMENT_URI $document_uri; + fastcgi_param DOCUMENT_ROOT ${serviceRoot}; + fastcgi_param SERVER_PROTOCOL $server_protocol; + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REMOTE_PORT $remote_port; + fastcgi_param SERVER_ADDR $server_addr; + fastcgi_param SERVER_PORT $server_port; + fastcgi_param SERVER_NAME $server_name; + } + ''; + +in +utils.mkConfigFile { + name = siteConfigFile; + dir = siteConfigDir; + + content = '' + error_log syslog:server=unix:/dev/log,tag=nginx${bindService},nohostname,severity=error; + + worker_processes 5; + worker_rlimit_nofile 8192; + + events { + worker_connections 4096; + } + + http { + access_log syslog:server=unix:/dev/log,tag=nginx${bindService},nohostname,severity=info combined; + + server { + listen ${listen}; + root ${serviceRoot}; + + index index.php index.html; + + location / { + try_files $uri $uri/ =404; + } + + ${fastcgi} + } + + types { + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/x-javascript js; + application/atom+xml atom; + application/rss+xml rss; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/png png; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + image/svg+xml svg svgz; + image/webp webp; + + application/java-archive jar war ear; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.ms-excel xls; + application/vnd.ms-powerpoint ppt; + application/vnd.wap.wmlc wmlc; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream eot; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; + } + + default_type application/octet-stream; + + gzip_types text/plain text/xml text/css + text/comma-separated-values + text/javascript application/x-javascript + application/atom+xml; + + } + ''; +} diff --git a/nginx/unit.nix b/nginx/unit.nix new file mode 100644 index 0000000..d6e05ce --- /dev/null +++ b/nginx/unit.nix @@ -0,0 +1,75 @@ +{ stdenv +, pkgs +, utils +}: +{ serviceSuffix +, user ? "http" +, group ? "http" +, configDir ? "/etc/nginx" +, configFile ? "nginx.conf" +, pidFile ? "/run/nginx/nginx.pid" +}: +{...}: + +utils.systemd.mkService rec { + name = "nginx-${serviceSuffix}"; + + content = '' + [Unit] + Description=Nginx webserver + + After=network.target network-online.target + Wants=network-online.target systemd-networkd-wait-online.target + + StartLimitInterval=14400 + StartLimitBurst=10 + + [Service] + Type=forking + User=${user} + Group=${group} + PIDFile=${pidFile} + ExecStart=${pkgs.nginx}/bin/nginx -c ${configDir}/${configFile} -g 'pid ${pidFile};' + ExecReload=${pkgs.nginx}/bin/nginx -s reload + KillMode=mixed + # Nginx verifies it can open a file under here even when configured + # to write elsewhere. + LogsDirectory=nginx + CacheDirectory=nginx + RuntimeDirectory=nginx + + # Restart=on-abnormal + + # KillSignal=SIGQUIT + TimeoutStopSec=5s + + LimitNOFILE=1048576 + LimitNPROC=512 + + LockPersonality=true + NoNewPrivileges=true + PrivateDevices=true + PrivateTmp=true + ProtectClock=true + ProtectControlGroups=true + ProtectHome=true + ProtectHostname=true + ProtectKernelLogs=true + ProtectKernelModules=true + ProtectKernelTunables=true + ProtectSystem=full + RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX + RestrictNamespaces=true + RestrictRealtime=true + RestrictSUIDSGID=true + + # CapabilityBoundingSet=CAP_NET_BIND_SERVICE + AmbientCapabilities=CAP_NET_BIND_SERVICE + + # ProtectSystem=strict + # ReadWritePaths=/var/lib/nginx /var/log/nginx + + [Install] + WantedBy=multi-user.target + ''; +} diff --git a/php-fpm/mksiteconfig.nix b/php-fpm/mksiteconfig.nix index de3e0a8..cd8f1cd 100644 --- a/php-fpm/mksiteconfig.nix +++ b/php-fpm/mksiteconfig.nix @@ -1,21 +1,25 @@ { PHPFPMSiteConfig }: { PHPFPMConfig -, PHPFPMService +, user +, group , name , phpConfigDir , siteName , siteRoot +, siteSocket , socketUser , socketGroup , dependsOn +, connectsTo }: rec { - inherit name dependsOn; - siteSocket = "/run/php-fpm/${siteName}.sock"; + inherit name user group siteSocket; + inherit dependsOn connectsTo; + pkg = PHPFPMSiteConfig { inherit (PHPFPMConfig) siteConfigDir; - inherit (PHPFPMService) user group; + inherit user group; inherit siteSocket phpConfigDir socketUser socketGroup; service = siteName; diff --git a/php-fpm/unit.nix b/php-fpm/unit.nix index 402fc44..7a7d852 100644 --- a/php-fpm/unit.nix +++ b/php-fpm/unit.nix @@ -2,15 +2,16 @@ , pkgs , utils }: -{ user ? "http" -, group ? "http" +{ serviceSuffix , configFile ? "/etc/php/php-fpm.conf" , phpIni ? "/etc/php/php.ini" }: {...}: +# This service runs as root, each pool runs as a user. + utils.systemd.mkService rec { - name = "php-fpm"; + name = "php-fpm-${serviceSuffix}"; content = '' [Unit] @@ -19,16 +20,15 @@ utils.systemd.mkService rec { [Service] Type=notify - # User=${user} - # Group=${group} - PIDFile=/run/php-fpm/php-fpm.pid + PIDFile=/run/${serviceSuffix}/php-fpm.pid ExecStart=${pkgs.php}/bin/php-fpm --nodaemonize --fpm-config ${configFile} --php-ini ${phpIni} ExecReload=/bin/kill -USR2 $MAINPID - RuntimeDirectory=php-fpm - # ReadWritePaths=/usr/share/webapps/nextcloud/apps - # ReadWritePaths=/usr/share/webapps/nextcloud/apps - # ReadWritePaths=/usr/share/webapps/nextcloud/config - # ReadWritePaths=/etc/webapps/nextcloud + + # Keeping this around to avoid uncommenting them. These directories + # are handled through tmpfiles.d. + # + # RuntimeDirectory=${serviceSuffix} + # StateDirectory=${serviceSuffix} LockPersonality=true NoNewPrivileges=true