Refactor caddy module, add cloudflare to caddy, remove scalpel antipatterns
diff --git a/modules/caddy.nix b/modules/caddy.nix
index c152989..51efde5 100644
--- a/modules/caddy.nix
+++ b/modules/caddy.nix
@@ -1,4 +1,4 @@
-{ config, pkgs, lib, ... }: {
+{ base, config, pkgs, lib, ... }: lib.recursiveUpdate {
services.caddy.enable = true;
services.caddy.configFile = lib.pipe ./caddy/caddyfile.nix [
import
@@ -9,4 +9,34 @@
services.caddy.package = pkgs.callPackage ../packages/caddy.nix { };
services.caddy.user = "root";
systemd.services.caddy.serviceConfig.ProtectHome = lib.mkForce false;
-}
+
+ sops.secrets.cloudflare_token = {
+ mode = "0600";
+ owner = config.users.users.root.name;
+ group = config.users.users.nobody.group;
+ sopsFile = ../secrets/caddy.json;
+ format = "json";
+ };
+} (
+ let
+ isDerived = base != null;
+ in
+ if isDerived
+ then
+ let
+ caddy_json = base.config.services.caddy.configFile;
+ in
+ {
+ scalpel.trafos."caddy.json" = {
+ source = toString caddy_json;
+ matchers."cloudflare_token".secret =
+ config.sops.secrets.cloudflare_token.path;
+ owner = config.users.users.root.name;
+ group = config.users.users.nobody.group;
+ mode = "0400";
+ };
+
+ services.caddy.configFile = lib.mkForce config.scalpel.trafos."caddy.json".destination;
+ }
+ else { }
+)
diff --git a/modules/caddy/caddyfile.nix b/modules/caddy/caddyfile.nix
index a7deb60..8ebf226 100644
--- a/modules/caddy/caddyfile.nix
+++ b/modules/caddy/caddyfile.nix
@@ -75,250 +75,255 @@
in
{ pkgs, lib }: {
apps = {
- http = {
- servers = {
- srv0 = {
- listen = [ ":443" ];
- routes = [
- (HTTPReverseProxyRoute [ "signup.hopescaramels.com" ] [ "192.168.0.4:3035" ])
- (HTTPReverseProxyRoute [ "homebridge.coded.codes" ] [ "localhost:8581" ])
- {
- handle = [
- {
- handler = "subroute";
- routes = [
- {
- handle = [
- {
- error = "You can't access admin routes from outside the server. Please use SSH tunneling, cURL on the host or similar";
- handler = "error";
- status_code = "403";
- }
- ];
- match = [{ path = [ "/_dendrite/admin/*" "/_synapse/admin/*" ]; }];
- terminal = true;
- }
- {
- handle = [
- {
- handler = "reverse_proxy";
- transport = { protocol = "http"; };
- upstreams = [{ dial = "localhost:4527"; }];
- }
- ];
- }
- ];
- }
- ];
- match = [{ host = [ "matrix-backend.coded.codes" ]; }];
- terminal = true;
- }
- (HTTPReverseProxyRoute
- [
- "mail.coded.codes"
- "mail.clicks.codes"
- "mail.hopescaramels.com"
- ]
- [ "localhost:1080" ]
- )
- (HTTPReverseProxyRoute [ "logs.clicks.codes" ] [ "localhost:9052" ])
- (HTTPRedirectRoute
- [
- "hopescaramels.com"
- "www.hopescaramels.com"
- ]
- "https://etsy.com/shop/HopesCaramels"
- )
- # (HTTPReverseProxyRoute [ "omv.coded.codes" ] [ "localhost:6773" ])
- # (HTTPReverseProxyRoute [ "jellyfin.coded.codes" ] [ "localhost:8096" ])
- (HTTPReverseProxyRoute [ "codedpc.coded.codes" ] [ "192.168.0.2:3389" ])
- (HTTPReverseProxyRoute [ "testing.coded.codes" ] [ "192.168.0.2:3030" ])
- (HTTPReverseProxyRoute [ "kavita.clicks.codes" ] [ "localhost:5000" ])
- {
- handle = [
- {
- handler = "subroute";
- routes = [
- {
- handle = [
- {
- handler = "subroute";
- routes = [
- {
- handle = [
- {
- handler = "rewrite";
- strip_path_prefix = "/nucleus";
- }
- ];
- }
- {
- handle = [
- {
- handler = "reverse_proxy";
- upstreams = [{ dial = "127.0.0.1:10000"; }];
- }
- ];
- }
- ];
- }
- ];
- match = [{ path = [ "/nucleus/*" ]; }];
- }
- {
- handle = [
- {
- handler = "error";
- error = "This API route does not exist";
- status_code = 404;
- }
- ];
- }
- ];
- }
- ];
- match = [{ host = [ "api.clicks.codes" ]; }];
- terminal = true;
- }
- {
- handle = [
- {
- handler = "subroute";
- routes = [
- {
- handle = [
- {
- handler = "subroute";
- routes = [
- {
- handle = [
- {
- handler = "rewrite";
- strip_path_prefix = "/nucleus";
- }
- ];
- }
- {
- handle = [
- {
- handler = "reverse_proxy";
- upstreams = [{ dial = "192.168.0.2:10000"; }];
- }
- ];
- }
- ];
- }
- ];
- match = [{ path = [ "/nucleus/*" ]; }];
- }
- {
- handle = [
- {
- handler = "error";
- error = "This API route does not exist";
- status_code = 404;
- }
- ];
- }
- ];
- }
- ];
- match = [{ host = [ "api.coded.codes" ]; }];
- terminal = true;
- }
- (HTTPRedirectRoute
- [
- "www.clicks.codes"
- ]
- "https://clicks.codes{http.request.uri}"
- )
- (HTTPReverseProxyRoute [ "clicks.codes" ] [ "127.0.0.1:3000" ])
- {
- handle = [
- {
- handler = "subroute";
- routes = [
- {
- handle = [
- {
- handler = "static_response";
- status_code = 200;
- body = builtins.readFile ./coded.codes/.well-known/matrix;
- headers = { Access-Control-Allow-Origin = [ "*" ]; };
- }
- ];
- match = [{
- path = [
- "/.well-known/matrix/server"
- "/.well-known/matrix/client"
- ];
- }];
- terminal = true;
- }
- {
- handle = [
- {
- handler = "static_response";
- headers = { Location = [ "https://clicks.codes{http.request.uri}" ]; };
- status_code = 302;
- }
- ];
- }
- ];
- }
- ];
- match = [{ host = [ "coded.codes" ]; }];
- terminal = true;
- }
- (HTTPFileServerRoute [ "matrix.coded.codes" ] (
- pkgs.element-web.override {
- conf = {
- default_server_config = lib.pipe ./coded.codes/.well-known/matrix [
- builtins.readFile
- builtins.fromJSON
- ];
- };
+ http.servers = {
+ srv0 = {
+ listen = [ ":443" ];
+ routes = [
+ (HTTPReverseProxyRoute [ "signup.hopescaramels.com" ] [ "192.168.0.4:3035" ])
+ (HTTPReverseProxyRoute [ "homebridge.coded.codes" ] [ "localhost:8581" ])
+ {
+ handle = [
+ {
+ handler = "subroute";
+ routes = [
+ {
+ handle = [
+ {
+ error = "You can't access admin routes from outside the server. Please use SSH tunneling, cURL on the host or similar";
+ handler = "error";
+ status_code = "403";
+ }
+ ];
+ match = [{ path = [ "/_dendrite/admin/*" "/_synapse/admin/*" ]; }];
+ terminal = true;
+ }
+ {
+ handle = [
+ {
+ handler = "reverse_proxy";
+ transport = { protocol = "http"; };
+ upstreams = [{ dial = "localhost:4527"; }];
+ }
+ ];
+ }
+ ];
}
- ))
- ];
- };
- srv1 = {
- listen = [ ":80" ];
- routes = [
- (HTTPReverseProxyRoute
- [
- "mail.clicks.codes"
- "mail.coded.codes"
- "mail.hopescaramels.com"
- "autoconfig.coded.codes"
- "autoconfig.clicks.codes"
- "autoconfig.hopescaramels.com"
- "imap.coded.codes"
- "imap.clicks.codes"
- "imap.hopescaramels.com"
- "pop.coded.codes"
- "pop.clicks.codes"
- "pop.hopescaramels.com"
- "smtp.coded.codes"
- "smtp.clicks.codes"
- "smtp.hopescaramels.com"
- ]
- [ "localhost:1080" ]
- )
- ];
- };
+ ];
+ match = [{ host = [ "matrix-backend.coded.codes" ]; }];
+ terminal = true;
+ }
+ (HTTPReverseProxyRoute
+ [
+ "mail.coded.codes"
+ "mail.clicks.codes"
+ "mail.hopescaramels.com"
+ ]
+ [ "localhost:1080" ]
+ )
+ (HTTPReverseProxyRoute [ "logs.clicks.codes" ] [ "localhost:9052" ])
+ (HTTPRedirectRoute
+ [
+ "hopescaramels.com"
+ "www.hopescaramels.com"
+ ]
+ "https://etsy.com/shop/HopesCaramels"
+ )
+ # (HTTPReverseProxyRoute [ "omv.coded.codes" ] [ "localhost:6773" ])
+ # (HTTPReverseProxyRoute [ "jellyfin.coded.codes" ] [ "localhost:8096" ])
+ (HTTPReverseProxyRoute [ "codedpc.coded.codes" ] [ "192.168.0.2:3389" ])
+ (HTTPReverseProxyRoute [ "testing.coded.codes" ] [ "192.168.0.2:3030" ])
+ (HTTPReverseProxyRoute [ "kavita.coded.codes" ] [ "localhost:5000" ])
+ {
+ handle = [
+ {
+ handler = "subroute";
+ routes = [
+ {
+ handle = [
+ {
+ handler = "subroute";
+ routes = [
+ {
+ handle = [
+ {
+ handler = "rewrite";
+ strip_path_prefix = "/nucleus";
+ }
+ ];
+ }
+ {
+ handle = [
+ {
+ handler = "reverse_proxy";
+ upstreams = [{ dial = "127.0.0.1:10000"; }];
+ }
+ ];
+ }
+ ];
+ }
+ ];
+ match = [{ path = [ "/nucleus/*" ]; }];
+ }
+ {
+ handle = [
+ {
+ handler = "error";
+ error = "This API route does not exist";
+ status_code = 404;
+ }
+ ];
+ }
+ ];
+ }
+ ];
+ match = [{ host = [ "api.clicks.codes" ]; }];
+ terminal = true;
+ }
+ {
+ handle = [
+ {
+ handler = "subroute";
+ routes = [
+ {
+ handle = [
+ {
+ handler = "subroute";
+ routes = [
+ {
+ handle = [
+ {
+ handler = "rewrite";
+ strip_path_prefix = "/nucleus";
+ }
+ ];
+ }
+ {
+ handle = [
+ {
+ handler = "reverse_proxy";
+ upstreams = [{ dial = "192.168.0.2:10000"; }];
+ }
+ ];
+ }
+ ];
+ }
+ ];
+ match = [{ path = [ "/nucleus/*" ]; }];
+ }
+ {
+ handle = [
+ {
+ handler = "error";
+ error = "This API route does not exist";
+ status_code = 404;
+ }
+ ];
+ }
+ ];
+ }
+ ];
+ match = [{ host = [ "api.coded.codes" ]; }];
+ terminal = true;
+ }
+ (HTTPRedirectRoute
+ [
+ "www.clicks.codes"
+ ]
+ "https://clicks.codes{http.request.uri}"
+ )
+ (HTTPReverseProxyRoute [ "clicks.codes" ] [ "127.0.0.1:3000" ])
+ {
+ handle = [
+ {
+ handler = "subroute";
+ routes = [
+ {
+ handle = [
+ {
+ handler = "static_response";
+ status_code = 200;
+ body = builtins.readFile ./coded.codes/.well-known/matrix;
+ headers = { Access-Control-Allow-Origin = [ "*" ]; };
+ }
+ ];
+ match = [{
+ path = [
+ "/.well-known/matrix/server"
+ "/.well-known/matrix/client"
+ ];
+ }];
+ terminal = true;
+ }
+ {
+ handle = [
+ {
+ handler = "static_response";
+ headers = { Location = [ "https://clicks.codes{http.request.uri}" ]; };
+ status_code = 302;
+ }
+ ];
+ }
+ ];
+ }
+ ];
+ match = [{ host = [ "coded.codes" ]; }];
+ terminal = true;
+ }
+ (HTTPFileServerRoute [ "matrix.coded.codes" ] (
+ pkgs.element-web.override {
+ conf = {
+ default_server_config = lib.pipe ./coded.codes/.well-known/matrix [
+ builtins.readFile
+ builtins.fromJSON
+ ];
+ };
+ }
+ ))
+ ];
+ };
+ srv1 = {
+ listen = [ ":80" ];
+ routes = [
+ (HTTPReverseProxyRoute
+ [
+ "mail.clicks.codes"
+ "mail.coded.codes"
+ "mail.hopescaramels.com"
+ "autoconfig.coded.codes"
+ "autoconfig.clicks.codes"
+ "autoconfig.hopescaramels.com"
+ "imap.coded.codes"
+ "imap.clicks.codes"
+ "imap.hopescaramels.com"
+ "pop.coded.codes"
+ "pop.clicks.codes"
+ "pop.hopescaramels.com"
+ "smtp.coded.codes"
+ "smtp.clicks.codes"
+ "smtp.hopescaramels.com"
+ ]
+ [ "localhost:1080" ]
+ )
+ ];
};
};
- layer4 = {
- servers = {
- imap-143 = (TCPReverseProxyRoute [ 143 ] [ "localhost:1143" ]);
- imap-993 = (TCPReverseProxyRoute [ 993 ] [ "localhost:1993" ]);
- pop-110 = (TCPReverseProxyRoute [ 110 ] [ "localhost:1110" ]);
- pop-995 = (TCPReverseProxyRoute [ 995 ] [ "localhost:1995" ]);
- smtp-25 = (TCPReverseProxyRoute [ 25 ] [ "localhost:1025" ]);
- smtp-465 = (TCPReverseProxyRoute [ 465 ] [ "localhost:1465" ]);
- smtp-587 = (TCPReverseProxyRoute [ 587 ] [ "localhost:1587" ]);
- };
+ layer4.servers = {
+ imap-143 = (TCPReverseProxyRoute [ 143 ] [ "localhost:1143" ]);
+ imap-993 = (TCPReverseProxyRoute [ 993 ] [ "localhost:1993" ]);
+ pop-110 = (TCPReverseProxyRoute [ 110 ] [ "localhost:1110" ]);
+ pop-995 = (TCPReverseProxyRoute [ 995 ] [ "localhost:1995" ]);
+ smtp-25 = (TCPReverseProxyRoute [ 25 ] [ "localhost:1025" ]);
+ smtp-465 = (TCPReverseProxyRoute [ 465 ] [ "localhost:1465" ]);
+ smtp-587 = (TCPReverseProxyRoute [ 587 ] [ "localhost:1587" ]);
};
+ tls.automation.policies = [{
+ issuers = [{
+ module = "acme";
+ challenges.dns.provider = {
+ name = "cloudflare";
+ api_token = "!!cloudflare_token!!";
+ };
+ }];
+ }];
};
}
diff --git a/modules/matrix.nix b/modules/matrix.nix
index b83e3f4..4be396e 100644
--- a/modules/matrix.nix
+++ b/modules/matrix.nix
@@ -1,4 +1,5 @@
{ base, config, lib, pkgs, ... }:
+lib.recursiveUpdate
{
services.matrix-synapse = {
enable = true;
@@ -46,7 +47,7 @@
path = config.services.matrix-synapse.settings.signing_key_path;
};
};
-} // (
+} (
let
isDerived = base != null;
in
diff --git a/packages/caddy.nix b/packages/caddy.nix
index 6856bf2..24f2f85 100644
--- a/packages/caddy.nix
+++ b/packages/caddy.nix
@@ -5,17 +5,26 @@
with pkgs;
let
- pluginSrc = fetchFromGitHub {
+ caddySrc = fetchFromGitHub {
+ # github.com/caddyserver/caddy/v2
+ owner = "caddyserver";
+ repo = "caddy";
+ rev = "v2.6.4";
+ hash = "sha256-3a3+nFHmGONvL/TyQRqgJtrSDIn0zdGy9YwhZP17mU0=";
+ };
+ l4Src = fetchFromGitHub {
+ # github.com/mholt/caddy-l4
owner = "mholt";
repo = "caddy-l4";
rev = "aa8cf68a3b5197c45a8b4ffd99b74465f0b5a6b1";
hash = "sha256-3KcoOAB+YkOU8qKM75uQo58/dljRBmP25dionQ9K2dc=";
};
- caddySrc = fetchFromGitHub {
- owner = "caddyserver";
- repo = "caddy";
- rev = "v2.6.4";
- hash = "sha256-3a3+nFHmGONvL/TyQRqgJtrSDIn0zdGy9YwhZP17mU0=";
+ cloudflareSrc = fetchFromGitHub {
+ # github.com/caddy-dns/cloudflare
+ owner = "caddy-dns";
+ repo = "cloudflare";
+ rev = "a9d3ae2690a1d232bc9f8fc8b15bd4e0a6960eec";
+ hash = "sha256-bqnk4XkhUI7YhCv24ha8mds5EaYphnYj8wy/mFOieqI=";
};
combinedSrc = stdenv.mkDerivation {
@@ -30,29 +39,37 @@
mkdir -p "$out/ourcaddy"
cp -r ${caddySrc} "$out/caddy"
- cp -r ${pluginSrc} "$out/plugin"
+ cp -r ${l4Src} "$out/l4"
+ cp -r ${cloudflareSrc} "$out/cloudflare"
cd "$out/ourcaddy"
go mod init caddy
echo "package main" >> main.go
+
echo 'import caddycmd "github.com/caddyserver/caddy/v2/cmd"' >> main.go
+
echo 'import _ "github.com/caddyserver/caddy/v2/modules/standard"' >> main.go
echo 'import _ "github.com/mholt/caddy-l4"' >> main.go
+ echo 'import _ "github.com/caddy-dns/cloudflare"' >> main.go
+
echo "func main(){ caddycmd.Main() }" >> main.go
+
go mod edit -require=github.com/caddyserver/caddy/v2@v2.6.4
go mod edit -replace github.com/caddyserver/caddy/v2=../caddy
go mod edit -require=github.com/mholt/caddy-l4@v0.0.0
- go mod edit -replace github.com/mholt/caddy-l4=../plugin
+ go mod edit -replace github.com/mholt/caddy-l4=../l4
+ go mod edit -require=github.com/caddy-dns/cloudflare@v0.0.0
+ go mod edit -replace github.com/caddy-dns/cloudflare=../cloudflare
'';
};
in
buildGoModule {
- name = "meowdy";
+ name = "caddy-with-plugins";
src = combinedSrc;
- vendorHash = "sha256-a49J7gKBYi9mQLlg+YFGaOetvbup5yRrWzX7kicvy+o=";
+ vendorHash = "sha256-34o91x7Y7DjIHom2Tk2ARBcJ3PzBVm+ALWK9ucj1g5A=";
overrideModAttrs = _: {
postPatch = "cd ourcaddy";
diff --git a/secrets/caddy.json b/secrets/caddy.json
new file mode 100644
index 0000000..6e917f6
--- /dev/null
+++ b/secrets/caddy.json
@@ -0,0 +1,24 @@
+{
+ "cloudflare_token": "ENC[AES256_GCM,data:ZrVPHcTEED9TnK23wvtZQDEwcWC5vyh5HJkhBlC4VjLsJkVUURsNmw==,iv:oFincLWd0ESOuNQoFRoioFPupdCl76sVpZLHZL3kV38=,tag:11wCHPq3BktPPH/g77Lg/Q==,type:str]",
+ "sops": {
+ "kms": null,
+ "gcp_kms": null,
+ "azure_kv": null,
+ "hc_vault": null,
+ "age": [
+ {
+ "recipient": "age15mv77dpnh5762gk5rsw2u79uza4tg8cu6r3nlwjudlzmdqqck3ss6mg9dy",
+ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYWlBkT0NlcGtabzZPL0FG\ncjNHMEtYWCtkMFNIaDNNdjBuV3ZQQWZNN2w0CkxLa1U5SW1JbE54NnIvL2NXZktY\nNWZNSHFTKzBPYU8rbzY3c002dEZFTGMKLS0tIDBaN2I5OEMrOWgxODdhMXhwRURJ\nYm9CS0Jxb3U0THdnRzlrMWVwYXdwWFkKGqM2dWaZYXL7kFW9YCVEeKF2OwlIyI2l\nKu/X3VslSlwx+B6vAwTFTqnJc0XbiVbelP4/HRC2IQOFjp+5jEJJLQ==\n-----END AGE ENCRYPTED FILE-----\n"
+ },
+ {
+ "recipient": "age1fxxnmkeuqhhct93c43pwkzhuzzq8857s5hye6pgfpku70kjn4ecqtamfqr",
+ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsL0l4Z0NtNWwreVF0VXJr\nYlF4dEhIQ3NLWXowcGRYa1BPb2lYejdYMFdFCm9JdXVHT1JZZnpZS0hoTlpTRmh6\ncW5nMnZDdlg5SmtHQURxbWNBdnRJQjQKLS0tIEV5V2l5RW5KVUFGbW5FOFlGcHFo\nWkhrUDhGNmtDOE8zMzlhU3lKUWNKRkEKcXASv8OxPxeX9ZulhWkXl2qCVSSRFdQ5\nWqx+rHejzQhO81cT0Wf+uiYQDvX+otJQW5Akgv8zcDMQxSyGgG+B+A==\n-----END AGE ENCRYPTED FILE-----\n"
+ }
+ ],
+ "lastmodified": "2023-05-24T15:18:01Z",
+ "mac": "ENC[AES256_GCM,data:ZETpBaOW1TCYmDYflRBz4Gz8bHvXCuZS+kN54MZ59gt3xh31n+2MBYWavh6H1EPppL6WVt1gynAF3GWPuBqfo+OeOWGaL6c3VCnnnWgbTWDb2K3Qn7JYpsAMUnSXT9DF+oAtrtvuFX+K3ubR4UL+3PYIVFmwr5esCQKI0ngz34U=,iv:CNIh86JUlMvzCfJfsqRWirNtCuUKvlcwOj/8xPR/J8M=,tag:yFRV0TB8ay86U1Z1HbpCnQ==,type:str]",
+ "pgp": null,
+ "unencrypted_suffix": "_unencrypted",
+ "version": "3.7.3"
+ }
+}
\ No newline at end of file