{ pkgs, ... }: let errorHandlers = '' handle_errors { @unauthorized expression {http.error.status_code} == 401 handle @unauthorized { rewrite * /401.html root * /var/static/error header Hey "Are you Hacker??? 😠" file_server } @notFound expression {http.error.status_code} == 404 handle @notFound { rewrite * /404.html root * /var/static/error file_server } @gone expression {http.error.status_code} == 410 handle @gone { rewrite * /410.html root * /var/static/error file_server } @serverError expression {http.error.status_code} in [500, 502, 504, 505] handle @serverError { rewrite * /5xx.html root * /var/static/error file_server } @clientError expression {http.error.status_code} in [403, 405, 411, 497] handle @clientError { rewrite * /client.html root * /var/static/error file_server } } ''; withErrors = config: '' ${config} ${errorHandlers} ''; reverseProxy = upstream: withErrors '' reverse_proxy ${upstream} ''; reverseProxyWithHeaders = upstream: withErrors '' reverse_proxy ${upstream} { header_up Host {host} header_up X-Real-IP {remote_host} header_up X-Forwarded-For {remote_host} header_up X-Forwarded-Proto {scheme} header_up Upgrade {>Upgrade} header_up Connection {>Connection} } ''; staticHost = host: { extraConfig = withErrors '' root * /var/static/${host} @notExist { not file not file {path}/ } handle @notExist { rewrite * /410.html root * /var/static/error file_server } file_server @txt path *.txt header @txt Content-Type "text/plain; charset=utf-8" header { Access-Control-Allow-Origin * Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" Access-Control-Allow-Headers "Content-Type, Authorization" Access-Control-Max-Age 3600 } ''; }; # Keep these explicit hosts for their existing per-host content. The # wildcard host below handles any other one-level subdomain. staticHosts = [ "26layer7beginner.imnya.ng" "alt.imnya.ng" "dday.imnya.ng" "download.imnya.ng" "f.imnya.ng" "hako.imnya.ng" "ilovecloudflare.imnya.ng" "img.imnya.ng" "jongyeol.imnya.ng" "letters.imnya.ng" "log.imnya.ng" "nixos.imnya.ng" "pack.imnya.ng" "pf.imnya.ng" "potato.imnya.ng" "sometesting.imnya.ng" "spam.imnya.ng" "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 = { enable = true; email = "imnyang@pm.me"; openFirewall = true; package = pkgs.caddy.withPlugins { plugins = [ "github.com/caddy-dns/cloudflare@v0.2.4" "github.com/aksdb/caddy-cgi/v2@v2.2.6" "github.com/shift72/caddy-geo-ip@v0.6.0" "github.com/lolPants/caddy-requestid@v1.1.2" "github.com/WeidiDeng/caddy-cloudflare-ip@v0.0.0-20231130002422-f53b62aa13cb" "github.com/caddyserver/ntlm-transport@v0.1.2" "github.com/ueffel/caddy-brotli@v1.6.0" "github.com/RussellLuo/caddy-ext/ratelimit@v0.3.0" "github.com/neodyme-labs/user_agent_parse@v0.0.1" ]; hash = "sha256-r4MgRk8HpKYx7f8FmA3PKgD/5ZNTIHpQvlE+zRbP0lw="; }; 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: { name = host; value = staticHost host; }) staticHosts ) // { "*.imnya.ng".extraConfig = withErrors '' tls { dns cloudflare {env.CLOUDFLARE_API_TOKEN} } root * /var/static/{host} file_server ''; "api.imnya.ng".extraConfig = reverseProxyWithHeaders "127.0.0.1:10118"; "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 file_server } root * /var/static/imnya.ng file_server { index index.html } redir /testtesttest "https://docs.google.com/forms/d/e/1FAIpQLScFDIU151s-CwKZccCET0kfdPigluiGb8BY7vL2US85dAgmhw/viewform?entry.2088744905=test" 302 redir /discord https://api.imnya.ng/discord_invite 302 redir /al https://f.imnya.ng/archlinux/install 302 redir /a https://cloud.hrts.kr/s/ZSHcpHgb9jdtaMR 302 redir /당신은김치찌개의무구한역사를자의적으로이해할수있습니까 https://www.figma.com/deck/LtnSWN6FHhHhTMIPECkdKT 302 redir /tree https://colormytree.me/2025/01KB8E3N0YS1X4EQZDZQ855HAG 302 redir /memos https://discord.gg/CrSjzppDed 302 redir /ctf/29hackcampwriteup "https://imneko.notion.site/29-CTF-31ca3fe0643b809291d2c7c3a1a818b6?source=copy_link" 302 redir /ctf/2025logcon "https://imneko.notion.site/2025-LOGCON-Write-UP-17fa3fe0643b80c0833adf1bd85f46fa?source=copy_link" 302 redir /ctf/2024layer7 "https://imneko.notion.site/2024-Layer7-CTF-177a3fe0643b802d96d9e255f32bf034?pvs=74" 302 ''; "cdn-wiki.tpr.kr".extraConfig = withErrors '' handle_path /i/* { rewrite * /thetree/i{uri} reverse_proxy 127.0.0.1:9000 } ''; "tts.imnya.ng".extraConfig = '' reverse_proxy 10.11.8.30:8080 ''; "vw.imnya.ng".extraConfig = reverseProxy "127.0.0.1:30505"; "jongyeoliswebscale.imnya.ng".extraConfig = withErrors '' basic_auth { jongyeol $2a$10$I00t8tJJLrcl4jZznO/XmOtd84uGAeJxL71wbN/sYksFrAvZ08n0q } reverse_proxy 10.20.31.48:3001 { header_up Host {host} header_up X-Real-IP {remote_host} header_up X-Forwarded-For {remote_host} header_up X-Forwarded-Proto {scheme} header_up Upgrade {>Upgrade} header_up Connection {>Connection} } ''; "auth.imnyang.dev".extraConfig = reverseProxy "10.11.8.25:3000"; "imnyang.dev".extraConfig = reverseProxy "82.21.82.30:3000"; "wiki.imnyang.dev".extraConfig = reverseProxy "10.11.8.150:51337"; "adofai.gay".extraConfig = withErrors '' handle_path /.well-known/discord { respond "dh=81062ffb49f63e8b7310905aee38aada33a68edb" 200 header Content-Type text/plain } redir https://7thbe.at/#adofai 302 ''; "wiki.tpr.kr".extraConfig = reverseProxy "127.0.0.1:51337"; "imlo.li".extraConfig = withErrors '' handle /rpmfusion.sh { root * /var/static/scripts file_server } handle { reverse_proxy 127.0.0.1:4000 } ''; "http://117.110.40.206".extraConfig = ""; "event.dazzle.st".extraConfig = '' reverse_proxy 127.0.0.1:9794 ''; "plutos.dazzle.st".extraConfig = '' reverse_proxy 10.11.8.200:3000 ''; "multiplay.rpc.dazzle.st".extraConfig = '' @preflight method OPTIONS header { Access-Control-Allow-Origin * Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS" Access-Control-Allow-Headers * } respond @preflight "" 204 reverse_proxy 10.20.30.101:6769 ''; "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"; "http://hikari.icn.hrts.kr".extraConfig = withErrors '' respond "우응" 200 ''; "pve.hrts.kr".extraConfig = withErrors '' reverse_proxy https://10.11.8.100:8006 { header_up X-Real-Ip {remote_host} header_up X-Http-Version {http.request.proto} transport http { tls_insecure_skip_verify } } ''; "auth.hrts.kr".extraConfig = reverseProxy "10.11.8.32:1411"; "git.hrts.kr".extraConfig = reverseProxy "127.0.0.1:3000"; "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"; "hrts.kr".extraConfig = withErrors '' redir / https://imnya.ng 302 redir /whyididmakethis.md "https://md.imnya.ng/?c=唣𣏫𧆘𡚴唿𢓬𧆬𣺯𢓬𧊈𣪖㸿堊𧈠𠪕𢷬𧆁𠪏𧈠𣪝𣣪喌𢓬𧆬𣺯𢓬𧊈𣪖㸿" 302 ''; "cloud.hrts.kr".extraConfig = '' redir https://cloud.mizuki.guru{uri} ''; "i.mizuki.guru".extraConfig = reverseProxy "127.0.0.1:10040"; "git.mizuki.guru".extraConfig = reverseProxy "127.0.0.1:3000"; "cloud.mizuki.guru".extraConfig = reverseProxy "10.11.8.100:60300"; "mizuki.guru".extraConfig = withErrors '' redir / https://akiyama.mizuki.guru 302 reverse_proxy /_matrix* 127.0.0.1:6167 ''; "api.kanade.mizuki.guru".extraConfig = reverseProxy "10.20.31.41:3000"; "akiyama.mizuki.guru".extraConfig = withErrors '' handle /api { reverse_proxy 10.11.8.121:1108 } handle /api/* { reverse_proxy 10.11.8.121:1108 } handle { reverse_proxy 10.11.8.121:3000 } ''; "phrygiacomo.mizuki.guru".extraConfig = withErrors '' basic_auth { imnyang $2a$10$zA83XKt84pcXiwfkuvNmKOpQ5Cw0IP6m/.1AX0ahkVQaPOzrmFlxm } reverse_proxy 10.20.31.103:3000 ''; "http://hikari.icn.mizuki.guru".extraConfig = withErrors '' respond "우응" 200 ''; "fs.mizuki.guru".extraConfig = reverseProxy "10.11.8.121:9000"; "broadcast.epc.mizuki.guru".extraConfig = '' reverse_proxy 10.20.30.101:1234 ''; "apijongyeoltts.mizuki.guru".extraConfig = reverseProxy "10.20.30.103:9880"; "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 = { # Keep the manually provisioned token outside NixOS-managed /etc. # /var/lib/caddy is persistent across system generations. EnvironmentFile = "/var/lib/caddy/cloudflare.env"; RuntimeDirectory = "caddy"; RuntimeDirectoryMode = "0755"; }; }; }