1{ lib, config, hostname, helpers, ... }:
2
3with lib;
4let
5 cfg = config.modules.server;
6
7 domain = config.networking.domain;
8 knotEnabled = cfg.tangled.enable;
9 tailscaleEnabled = cfg.tailscale.enable;
10 vaultwardenEnabled = cfg.vaultwarden.enable;
11 jellyfinEnabled = cfg.jellyfin.enable;
12 hassEnabled = cfg.home-assistant.enable;
13
14 vaultwardenHandlerConfig = if vaultwardenEnabled then ''
15 handle_path /vault {
16 redir * /vault/
17 }
18
19 handle_path /vault/* {
20 reverse_proxy /notifications/hub/negotiate 127.0.0.1:8000
21 reverse_proxy /notifications/hub 127.0.0.1:8001
22 reverse_proxy localhost:8000 {
23 header_up X-Real-IP {remote_host}
24 }
25 }
26 '' else "";
27
28 jellyfinHandlerConfig = if jellyfinEnabled then ''
29 handle_path /media {
30 redir * /media/
31 }
32
33 reverse_proxy /media/* localhost:8096 {
34 header_up X-Real-IP {remote_host}
35 }
36 '' else "";
37
38 hassHandlerConfig = if hassEnabled && tailscaleEnabled then ''
39 handle_path /home {
40 redir * https://${hostname}.${domain}:8123
41 }
42 '' else "";
43
44 tailscaleConfig = if tailscaleEnabled then ''
45 ${hostname}.${domain} {
46 import network_paths
47 }
48 '' else "";
49
50 knotConfig = if knotEnabled then ''
51 ${cfg.tangled.hostname} {
52 reverse_proxy ${config.services.tangled.knot.server.listenAddr}
53 }
54 '' else "";
55
56 exposeConfig = let
57 configs = attrsets.mapAttrsToList (name: root: ''
58 handle_path /${name} {
59 redir * /${name}/
60 }
61
62 handle_path /${name}/* {
63 file_server {
64 browse
65 root ${root}
66 hide .*
67 }
68
69 @file path *.*
70
71 handle_path /* {
72 header @file +Content-Disposition attachment
73 }
74 }
75 '') cfg.caddy.exposeFolders;
76 in strings.concatStringsSep "\n\n" configs;
77in helpers.linuxAttrs {
78 options.modules.server.caddy = {
79 enable = mkOption {
80 default = false;
81 example = true;
82 description = "Whether to enable Caddy.";
83 type = types.bool;
84 };
85
86 exposeFolders = mkOption {
87 default = {};
88 description = "Folders to expose via Cadddy.";
89 example = { files = "/share/files"; };
90 type = types.attrsOf types.str;
91 };
92 };
93
94 config = mkIf (cfg.enable && cfg.caddy.enable) {
95 services.tailscale = mkIf tailscaleEnabled {
96 permitCertUid = config.services.caddy.user;
97 };
98
99 services.caddy = {
100 enable = true;
101 email = "phil@kitten.sh";
102 extraConfig = ''
103 (network_paths) {
104 ${vaultwardenHandlerConfig}
105 ${jellyfinHandlerConfig}
106 ${hassHandlerConfig}
107 ${exposeConfig}
108 }
109
110 ${tailscaleConfig}
111 ${knotConfig}
112
113 :80 {
114 import network_paths
115 }
116
117 :443 {
118 import network_paths
119 }
120 '';
121 };
122
123 networking.firewall.allowedTCPPorts = [ 80 443 ];
124 networking.firewall.allowedUDPPorts = [ 443 ];
125 };
126}