diff options
| author | schererleander <leander@schererleander.de> | 2025-12-25 23:33:25 +0000 |
|---|---|---|
| committer | schererleander <leander@schererleander.de> | 2025-12-25 23:33:25 +0000 |
| commit | d82fb3b552d20a279efdd9408042183cfa02fb48 (patch) | |
| tree | 4ffe818e591e54da71f7592506c873abf0d9d481 /flake.nix | |
| parent | d7edbf05ab0e90eedcb99e4462e3a61793b2eff9 (diff) | |
initial commit
Diffstat (limited to 'flake.nix')
| -rw-r--r-- | flake.nix | 86 |
1 files changed, 47 insertions, 39 deletions
@@ -32,14 +32,23 @@ installPhase = '' runHook preInstall + mkdir -p $out/share/web - cp -r dist/* $out/share/web/ + + cp -r .next/standalone/* $out/share/web/ + + mkdir -p $out/share/web/.next + cp -r .next/static $out/share/web/.next/ + cp -r public $out/share/web/ + runHook postInstall ''; }; in { - packages.default = site; + packages = { + default = site; + }; } ) // { @@ -61,64 +70,63 @@ in { options.services.site = { - enable = mkEnableOption "Serve the built Vite site via nginx"; + enable = mkEnableOption "Serve the built Next.js site using systemd"; domain = mkOption { type = types.str; description = "Domain to serve."; }; - default = lib.mkOption { - type = types.bool; - default = false; - description = "Make this vhost the default for nginx."; + port = mkOption { + type = types.port; + default = 3000; + description = "Port to expose on the host."; }; package = mkOption { type = types.package; - description = "Package whose /share/web contains the built site."; + description = "The site package to run."; default = self.packages.${pkgs.system}.default; }; - - sslCertificate = mkOption { - type = types.nullOr types.path; - default = null; - description = "Path to TLS certificate (PEM)."; - }; - sslCertificateKey = mkOption { - type = types.nullOr types.path; - default = null; - description = "Path to TLS private key (PEM)."; - }; }; config = mkIf cfg.enable { + systemd.services.site = { + description = "Next.js site service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; - assertions = [ - { - assertion = (cfg.sslCertificate == null) == (cfg.sslCertificateKey == null); - message = "services.site: sslCertificate and sslCertificateKey must be set together."; - } - ]; - - services.nginx.enable = true; + serviceConfig = { + ExecStart = "${pkgs.nodejs}/bin/node ${cfg.package}/share/web/server.js"; + WorkingDirectory = "${cfg.package}/share/web"; + User = "nextjs"; + Group = "nextjs"; + Restart = "always"; + + # Hardening + DynamicUser = true; + PrivateTmp = true; + ProtectSystem = "strict"; + ProtectHome = true; + NoNewPrivileges = true; - services.nginx.virtualHosts.${cfg.domain} = - let - useTLS = (cfg.sslCertificate != null) && (cfg.sslCertificateKey != null); - in - { - root = "${cfg.package}/share/web"; - default = cfg.default; + Environment = [ + "NODE_ENV=production" + "PORT=${toString cfg.port}" + "HOSTNAME=127.0.0.1" + ]; + }; + }; + services.nginx = { + enable = true; + virtualHosts.${cfg.domain} = { locations."/" = { - tryFiles = "$uri $uri/ /index.html"; + proxyPass = "http://127.0.0.1:${toString cfg.port}"; + proxyWebsockets = true; }; - - forceSSL = useTLS; - sslCertificate = mkIf useTLS cfg.sslCertificate; - sslCertificateKey = mkIf useTLS cfg.sslCertificateKey; }; + }; }; }; }; |
