diff --git a/flake.lock b/flake.lock index 6600efe..10a2b84 100644 --- a/flake.lock +++ b/flake.lock @@ -16,6 +16,22 @@ "url": "ssh://forgejo@mizuki.guru/imnyang/amia" } }, + "api": { + "flake": false, + "locked": { + "lastModified": 1787712680, + "narHash": "sha256-B6sgirbuKWUYYXXzfA/HIWqBWlQakPpXvgk0ZPelNaw=", + "ref": "refs/heads/main", + "rev": "06b713828f174dd4c649868183a82fce2919c0bc", + "revCount": 34, + "type": "git", + "url": "ssh://forgejo@mizuki.guru/imnyang/api.git" + }, + "original": { + "type": "git", + "url": "ssh://forgejo@mizuki.guru/imnyang/api.git" + } + }, "brew-src": { "flake": false, "locked": { @@ -777,6 +793,7 @@ "root": { "inputs": { "amiaBot": "amiaBot", + "api": "api", "catppuccin": "catppuccin", "cfwithoutincident": "cfwithoutincident", "codex-app": "codex-app", diff --git a/flake.nix b/flake.nix index 91f85bf..9708821 100644 --- a/flake.nix +++ b/flake.nix @@ -83,7 +83,10 @@ url = "git+ssh://forgejo@mizuki.guru/imnyang/amia"; flake = false; }; - + api = { + url = "git+ssh://forgejo@mizuki.guru/imnyang/api.git"; + flake = false; + }; cfwithoutincident = { url = "git+https://git.mizuki.guru/imnyang/cfwithoutincident.git"; flake = false; diff --git a/hosts/server/hikari/hako/configuration.nix b/hosts/server/hikari/hako/configuration.nix index 8714a24..4158120 100644 --- a/hosts/server/hikari/hako/configuration.nix +++ b/hosts/server/hikari/hako/configuration.nix @@ -44,6 +44,16 @@ networking.firewall.enable = false; + # /dev/sdd1 (ext4, UUID efdf753d-282c-4b78-9549-a124b353c6a5) + fileSystems."/mnt/static" = { + device = "/dev/disk/by-uuid/efdf753d-282c-4b78-9549-a124b353c6a5"; + fsType = "ext4"; + }; + + systemd.tmpfiles.rules = [ + "L+ /var/static - - - - /mnt/static/static" + ]; + networking.hostName = "hako"; system.stateVersion = "26.05"; } diff --git a/hosts/server/hikari/hako/default.nix b/hosts/server/hikari/hako/default.nix index eac768f..97ea8f4 100644 --- a/hosts/server/hikari/hako/default.nix +++ b/hosts/server/hikari/hako/default.nix @@ -14,6 +14,7 @@ nixpkgs.lib.nixosSystem { ./services/immich.nix ./services/attic.nix ./services/helium-services.nix + ./services/api.nix ./services/caddy.nix ./services/postgresql.nix ./services/nc.nix diff --git a/hosts/server/hikari/hako/services/api.nix b/hosts/server/hikari/hako/services/api.nix new file mode 100644 index 0000000..27d94a0 --- /dev/null +++ b/hosts/server/hikari/hako/services/api.nix @@ -0,0 +1,83 @@ +{ inputs, pkgs, ... }: + +let + apiDependencies = pkgs.stdenv.mkDerivation { + pname = "imnyang-api-dependencies"; + version = "unstable"; + src = inputs.api; + + nativeBuildInputs = [ pkgs.bun ]; + + dontConfigure = true; + + buildPhase = '' + export HOME="$TMPDIR/home" + mkdir -p "$HOME" + bun install --frozen-lockfile --no-progress + ''; + + installPhase = '' + mkdir -p "$out" + cp -a node_modules "$out/node_modules" + ''; + + outputHashMode = "recursive"; + outputHash = "sha256-ke6cG/cBON6d6giFo1RAQ4gMfIbmagJfCI1FfZl1w/8="; + }; + + apiPackage = pkgs.stdenv.mkDerivation { + pname = "imnyang-api"; + version = "unstable"; + src = inputs.api; + + nativeBuildInputs = [ pkgs.bun ]; + + dontConfigure = true; + + buildPhase = '' + cp -a ${apiDependencies}/node_modules ./node_modules + bun run build + ''; + + installPhase = '' + install -Dm755 server "$out/bin/server" + mkdir -p "$out/share/imnyang-api" + cp -r src/mitda "$out/share/imnyang-api/mitda" + ''; + }; +in +{ + systemd.services.api = { + description = "Elysia"; + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + + path = [ pkgs.dnsutils ]; + + preStart = '' + if ! test -e /var/lib/imnyang-api/nadae.hrts; then + printf '0\n' > /var/lib/imnyang-api/nadae.hrts + fi + ''; + + serviceConfig = { + Type = "simple"; + User = "imnyang"; + WorkingDirectory = "/var/lib/imnyang-api"; + StateDirectory = "imnyang-api"; + StateDirectoryMode = "0750"; + ExecStart = "${apiPackage}/bin/server"; + Restart = "always"; + RestartSec = 5; + Environment = [ + "NODE_ENV=production" + "MITDA_ASSETS_DIR=${apiPackage}/share/imnyang-api/mitda" + ]; + NoNewPrivileges = true; + PrivateTmp = true; + ProtectHome = true; + ProtectSystem = "strict"; + }; + }; +} diff --git a/hosts/server/hikari/hako/services/caddy.nix b/hosts/server/hikari/hako/services/caddy.nix index e09e4a0..0a95395 100644 --- a/hosts/server/hikari/hako/services/caddy.nix +++ b/hosts/server/hikari/hako/services/caddy.nix @@ -27,7 +27,7 @@ let @serverError expression {http.error.status_code} in [500, 502, 504, 505] handle @serverError { - rewrite * /server.html + rewrite * /5xx.html root * /var/static/error file_server } @@ -118,6 +118,31 @@ let "twohearts.imnya.ng" "whs.imnya.ng" ]; + + cloudflareIpRanges = [ + "103.21.244.0/22" + "103.22.200.0/22" + "103.31.4.0/22" + "104.16.0.0/13" + "104.24.0.0/14" + "108.162.192.0/18" + "131.0.72.0/22" + "141.101.64.0/18" + "162.158.0.0/15" + "172.64.0.0/13" + "173.245.48.0/20" + "188.114.96.0/20" + "190.93.240.0/20" + "197.234.240.0/22" + "198.41.128.0/17" + "2400:cb00::/32" + "2606:4700::/32" + "2803:f800::/32" + "2405:b500::/32" + "2405:8100::/32" + "2a06:98c0::/29" + "2c0f:f248::/32" + ]; in { services.caddy = { @@ -126,6 +151,17 @@ in openFirewall = true; package = pkgs.caddy; + globalConfig = '' + admin unix//run/caddy/admin.socket + storage file_system /var/lib/caddy + servers { + trusted_proxies static ${builtins.concatStringsSep " " cloudflareIpRanges} + client_ip_headers Cf-Connecting-Ip + } + debug + ''; + + virtualHosts = builtins.listToAttrs ( map (host: { @@ -134,12 +170,23 @@ in }) staticHosts ) // { - "api.imnya.ng".extraConfig = reverseProxyWithHeaders "10.11.8.101:1108"; - "nou.imnya.ng".extraConfig = reverseProxyWithHeaders "10.11.8.101:6974"; + "api.imnya.ng".extraConfig = reverseProxyWithHeaders "127.0.0.1:1108"; "docs.imnya.ng".extraConfig = reverseProxy "100.70.1.1:3939"; "panel.imnya.ng".extraConfig = reverseProxy "127.0.0.1:32981"; "monitorss.imnya.ng".extraConfig = reverseProxy "127.0.0.1:3132"; + "ip.imnya.ng".extraConfig = '' + header Access-Control-Allow-Origin "*" + header Access-Control-Allow-Methods "GET, OPTIONS" + header Access-Control-Allow-Headers "*" + + @options method OPTIONS + respond @options 204 + + @ip path / + respond @ip "{http.request.header.Cf-Connecting-Ip}" + ''; + "imnya.ng".extraConfig = withErrors '' handle_path /.well-known/webfinger { root * /var/www/imnya.ng @@ -240,7 +287,6 @@ in reverse_proxy 10.20.30.101:6769 ''; - "t.hrts.kr".extraConfig = reverseProxy "10.11.8.101:4041"; "wakapi.hrts.kr".extraConfig = reverseProxy "127.0.0.1:13000"; "ziit.hrts.kr".extraConfig = reverseProxy "127.0.0.1:6030"; "hikari-panel.hrts.kr".extraConfig = reverseProxy "10.11.8.104:8080"; @@ -261,7 +307,6 @@ in "auth.hrts.kr".extraConfig = reverseProxy "10.11.8.32:1411"; "git.hrts.kr".extraConfig = reverseProxy "127.0.0.1:3000"; - "api-ftp.hrts.kr".extraConfig = reverseProxy "10.11.8.101:25716"; "panel.hrts.kr".extraConfig = reverseProxy "127.0.0.1:3929"; "pgadmin.hrts.kr".extraConfig = reverseProxy "127.0.0.1:5050"; "al-1s.hrts.kr".extraConfig = reverseProxy "127.0.0.1:9120"; @@ -322,4 +367,13 @@ in "demo.mizuki.guru".extraConfig = reverseProxy "10.20.30.103:3000"; }; }; + + systemd.services.caddy = { + requires = [ "mnt-static.mount" ]; + after = [ "mnt-static.mount" "systemd-tmpfiles-setup.service" ]; + serviceConfig = { + RuntimeDirectory = "caddy"; + RuntimeDirectoryMode = "0755"; + }; + }; }