update lockfile and add pgweb, fixes to cloudflare caddy

This commit is contained in:
Noah Masur 2025-05-03 19:25:32 +00:00
parent 54a073b946
commit bfbacbe93e
6 changed files with 168 additions and 52 deletions

60
flake.lock generated
View File

@ -22,11 +22,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1743221873, "lastModified": 1746254942,
"narHash": "sha256-i8VPNm4UBsC3Ni6VwjojVJvCpS9GZ4vPrpFRtCGJzBs=", "narHash": "sha256-Y062AuRx6l+TJNX8wxZcT59SSLsqD9EedAY0mqgTtQE=",
"owner": "lnl7", "owner": "lnl7",
"repo": "nix-darwin", "repo": "nix-darwin",
"rev": "53d0f0ed11487a4476741fde757d0feabef4cc4e", "rev": "760a11c87009155afa0140d55c40e7c336d62d7a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -43,11 +43,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1741786315, "lastModified": 1745812220,
"narHash": "sha256-VT65AE2syHVj6v/DGB496bqBnu1PXrrzwlw07/Zpllc=", "narHash": "sha256-hotBG0EJ9VmAHJYF0yhWuTVZpENHvwcJ2SxvIPrXm+g=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "0d8c6ad4a43906d14abd5c60e0ffe7b587b213de", "rev": "d0c543d740fad42fe2c035b43c9d41127e073c78",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -193,11 +193,11 @@
"rust-overlay": "rust-overlay" "rust-overlay": "rust-overlay"
}, },
"locked": { "locked": {
"lastModified": 1743346877, "lastModified": 1746193606,
"narHash": "sha256-WczB9koq4xvdBZoMLW8VFT16RGaDrJXyA0rDTg2GFVU=", "narHash": "sha256-LD3ce/SlIY8Wr8XG52EI5t9bNa/peBCXykIJBvcGmO8=",
"owner": "helix-editor", "owner": "helix-editor",
"repo": "helix", "repo": "helix",
"rev": "e148d8b3110ace99505c0871714cd64391cc4ba3", "rev": "12139a4c30ad20d9a1b181de69532a57601cf96f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -213,11 +213,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1743346616, "lastModified": 1746243165,
"narHash": "sha256-AB/ve2el1TB7k4iyogHGCVlWVkrhp3+4FKKMr1W5iKQ=", "narHash": "sha256-DQycVmlyLQNLjLJ/FzpokVmbxGQ8HjQQ4zN4nyq2vII=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "1d2ed9c503cf41ca7f3db091edc8519dcdcd8b41", "rev": "c0962eeeabfb8127713f859ec8a5f0e86dead0f2",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -259,11 +259,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1740943170, "lastModified": 1745846717,
"narHash": "sha256-A0F7T/euSMen004cVQN/ZkMpLkgLXDs+mq/merhd+0Y=", "narHash": "sha256-GjwZEjCrI1/tQYylAQ+hU5JYD2hJI+rZmfICCIniWuE=",
"owner": "gytis-ivaskevicius", "owner": "gytis-ivaskevicius",
"repo": "nix2vim", "repo": "nix2vim",
"rev": "a562f32ff2393d0ed198103c65a3035bcdf83d4d", "rev": "0cd899a39b56d665115f72ffc7c37e0f4cf41dbe",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -310,11 +310,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1743095683, "lastModified": 1746141548,
"narHash": "sha256-gWd4urRoLRe8GLVC/3rYRae1h+xfQzt09xOfb0PaHSk=", "narHash": "sha256-IgBWhX7A2oJmZFIrpRuMnw5RAufVnfvOgHWgIdds+hc=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "5e5402ecbcb27af32284d4a62553c019a3a49ea6", "rev": "f02fddb8acef29a8b32f10a335d44828d7825b78",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -365,11 +365,11 @@
"treefmt-nix": "treefmt-nix" "treefmt-nix": "treefmt-nix"
}, },
"locked": { "locked": {
"lastModified": 1743335104, "lastModified": 1746282980,
"narHash": "sha256-wEEHpF+h+9m2QvjYtIx11EMi+sXG3wS9f/QSE6KPpJs=", "narHash": "sha256-KOkO6aDwI8FOmMMv3MdO2WL95lMOJR4qDMUHPOoFtyM=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nur", "repo": "nur",
"rev": "374adb7fb2c751f679519f8db532f726488293a0", "rev": "e4be6680a4b231e712fef9c1cd5714f08a1ce51b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -425,11 +425,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737080704, "lastModified": 1745116541,
"narHash": "sha256-n+J2h9GM9ZpFOQUmtZoCr1+DFF/iO5UlmLJeHIxbZGY=", "narHash": "sha256-5xzA6dTfqCfTTDCo3ipPZzrg3wp01xmcr73y4cTNMP8=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "f9953fe89f8b65401fc4d4a288940bc2cb072949", "rev": "e2142ef330a61c02f274ac9a9cb6f8487a5d0080",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -560,11 +560,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1743125458, "lastModified": 1744290088,
"narHash": "sha256-0z+5AMacL2Eqo92fAd0eCWeKVecWrxPJwd5/BIfcdJ8=", "narHash": "sha256-/X9XVEl0EiyisNbF5srrxXRSVoRqdwExuqyspYqqEjQ=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NixOS-WSL", "repo": "NixOS-WSL",
"rev": "394c77f61ac76399290bfc2ef9d47b1fba31b215", "rev": "60b4904a1390ac4c89e93d95f6ed928975e525ed",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -582,11 +582,11 @@
"rust-overlay": "rust-overlay_2" "rust-overlay": "rust-overlay_2"
}, },
"locked": { "locked": {
"lastModified": 1743344227, "lastModified": 1746209831,
"narHash": "sha256-Lp1JUMrhvAmCzftOSQ2Sr0+svemxSxcLeZ4HkmdLXbE=", "narHash": "sha256-1R1MRxHmTbNUASTCdJTaaIEUevx18+XpVVxEcb0q7VM=",
"owner": "sxyazi", "owner": "sxyazi",
"repo": "yazi", "repo": "yazi",
"rev": "1765aba68440f73c590cedac14ece6778fe88ff5", "rev": "a201c93419bede1f35c69a6b8b21ebbf4a752e6e",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -133,6 +133,7 @@
notifications = "ntfy.${baseName}"; notifications = "ntfy.${baseName}";
paperless = "paper.${baseName}"; paperless = "paper.${baseName}";
photos = "photos.${baseName}"; photos = "photos.${baseName}";
postgresql = "pg.${baseName}";
prometheus = "prom.${baseName}"; prometheus = "prom.${baseName}";
secrets = "vault.${baseName}"; secrets = "vault.${baseName}";
smtp = "smtp.purelymail.com"; smtp = "smtp.purelymail.com";

View File

@ -67,8 +67,8 @@ in
# Tell Caddy to use Cloudflare DNS for ACME challenge validation # Tell Caddy to use Cloudflare DNS for ACME challenge validation
services.caddy.package = pkgs.caddy.withPlugins { services.caddy.package = pkgs.caddy.withPlugins {
plugins = [ "github.com/caddy-dns/cloudflare@v0.0.0-20250228175314-1fb64108d4de" ]; plugins = [ "github.com/caddy-dns/cloudflare@v0.2.1" ];
hash = "sha256-YYpsf8HMONR1teMiSymo2y+HrKoxuJMKIea5/NEykGc="; hash = "sha256-saKJatiBZ4775IV2C5JLOmZ4BwHKFtRZan94aS5pO90=";
}; };
nmasur.presets.services.caddy.tlsPolicies = [ nmasur.presets.services.caddy.tlsPolicies = [
{ {
@ -90,11 +90,14 @@ in
]; ];
} }
]; ];
# Allow Caddy to read Cloudflare API key for DNS validation systemd.services.caddy.serviceConfig = {
systemd.services.caddy.serviceConfig.EnvironmentFile = [ # Allow Caddy to read Cloudflare API key for DNS validation
config.secrets.cloudflare-api.dest # Allow Caddy to use letsencrypt account key for TLS verification
config.secrets.letsencrypt-key.dest EnvironmentFile = [
]; config.secrets.letsencrypt-key.dest
config.secrets.cloudflare-api-prefixed.dest
];
};
# Private key is used for LetsEncrypt # Private key is used for LetsEncrypt
secrets.letsencrypt-key = { secrets.letsencrypt-key = {
@ -111,15 +114,21 @@ in
owner = "caddy"; owner = "caddy";
group = "caddy"; group = "caddy";
}; };
secrets.cloudflare-api-prefixed = {
source = ./cloudflare-api.age;
dest = "${config.secretsDirectory}/cloudflare-api-prefixed";
owner = "caddy";
group = "caddy";
prefix = "CLOUDFLARE_API_TOKEN=";
};
# Wait for secret to exist # Wait for secret to exist
systemd.services.caddy = { systemd.services.caddy = {
after = [ after = [
"cloudflare-api-secret.service" "cloudflare-api-prefixed-secret.service"
"letsencrypt-key-secret.service" "letsencrypt-key-secret.service"
]; ];
requires = [ requires = [
"cloudflare-api-secret.service" "cloudflare-api-prefixed-secret.service"
"letsencrypt-key-secret.service" "letsencrypt-key-secret.service"
]; ];
}; };
@ -150,5 +159,8 @@ in
requires = [ "cloudflare-api-secret.service" ]; requires = [ "cloudflare-api-secret.service" ];
}; };
# Enable the home-made service that we created for non-proxied records
services.cloudflare-dyndns-noproxy.enable = true;
}; };
} }

View File

@ -0,0 +1,82 @@
{
config,
pkgs,
lib,
...
}:
let
inherit (config.nmasur.settings) username hostnames;
cfg = config.nmasur.presets.services.pgweb;
in
{
options.nmasur.presets.services.pgweb = {
enable = lib.mkEnableOption "Postgres web UI";
port = lib.mkOption {
type = lib.types.port;
description = "Port to use for the localhost";
default = 8081;
};
};
config = lib.mkIf cfg.enable {
systemd.services.pgweb = {
description = "Postgres web UI";
after = [
"postgresql.target"
];
# requires = [ "pgweb-secret.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
DynamicUser = false;
User = "postgres";
Group = "postgres";
StateDirectory = "pgweb";
ExecStart =
let
args = [
"--url postgres:///hippocampus?host=/run/postgresql"
];
in
"${lib.getExe pkgs.pgweb} ${toString args}";
};
};
# Allow web traffic to Caddy
nmasur.presets.services.caddy.routes = [
{
match = [ { host = [ hostnames.postgresql ]; } ];
handle = [
{
handler = "authentication";
providers = {
http_basic = {
hash = {
algorithm = "bcrypt";
};
accounts = [
{
username = username;
password = "$2a$14$dtzWBh7ZDNgqFIJTJO7Rxe15Y189agBiWKZFJbs4sZz7QhqGQAwJS";
}
];
};
};
}
{
handler = "reverse_proxy";
upstreams = [ { dial = "localhost:${builtins.toString cfg.port}"; } ];
}
];
}
];
# Configure Cloudflare DNS to point to this machine
services.cloudflare-dyndns.domains = [ hostnames.postgresql ];
};
}

View File

@ -28,6 +28,7 @@ in
grafana.enable = lib.mkDefault true; grafana.enable = lib.mkDefault true;
influxdb2.enable = lib.mkDefault true; influxdb2.enable = lib.mkDefault true;
litestream.enable = lib.mkDefault true; litestream.enable = lib.mkDefault true;
pgweb.enable = lib.mkDefault true;
minecraft-server.enable = lib.mkDefault true; minecraft-server.enable = lib.mkDefault true;
n8n.enable = lib.mkDefault true; n8n.enable = lib.mkDefault true;
nix-autoupgrade.enable = lib.mkDefault false; # On by default for communications nix-autoupgrade.enable = lib.mkDefault false; # On by default for communications

View File

@ -6,12 +6,12 @@
}: }:
let let
cfg = config.services.cloudflare-dyndns-no-proxy; cfg = config.services.cloudflare-dyndns-noproxy;
in in
{ {
options.services.cloudflare-dyndns-no-proxy.enable = lib.mkEnableOption "Cloudflare dyndns client without proxying"; options.services.cloudflare-dyndns-noproxy.enable = lib.mkEnableOption "Cloudflare dyndns client without proxying";
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
@ -37,17 +37,37 @@ in
Type = "simple"; Type = "simple";
DynamicUser = true; DynamicUser = true;
StateDirectory = "cloudflare-dyndns-noproxy"; StateDirectory = "cloudflare-dyndns-noproxy";
EnvironmentFile = config.services.cloudflare-dyndns.apiTokenFile; Environment = [ "XDG_CACHE_HOME=%S/cloudflare-dyndns-noproxy/.cache" ];
ExecStart = LoadCredential = [
let "apiToken:${config.services.cloudflare-dyndns.apiTokenFile}"
args = ];
[ "--cache-file /var/lib/cloudflare-dyndns-noproxy/ip.cache" ]
++ (if config.services.cloudflare-dyndns.ipv4 then [ "-4" ] else [ "-no-4" ])
++ (if config.services.cloudflare-dyndns.ipv6 then [ "-6" ] else [ "-no-6" ])
++ lib.optional config.services.cloudflare-dyndns.deleteMissing "--delete-missing";
in
"${pkgs.cloudflare-dyndns}/bin/cloudflare-dyndns ${toString args}";
}; };
script =
let
args =
[ "--cache-file /var/lib/cloudflare-dyndns-noproxy/ip.cache" ]
++ (if config.services.cloudflare-dyndns.ipv4 then [ "-4" ] else [ "-no-4" ])
++ (if config.services.cloudflare-dyndns.ipv6 then [ "-6" ] else [ "-no-6" ])
++ lib.optional config.services.cloudflare-dyndns.deleteMissing "--delete-missing";
in
''
export CLOUDFLARE_API_TOKEN_FILE=''${CREDENTIALS_DIRECTORY}/apiToken
echo $CLOUDFLARE_API_TOKEN_FILE
cat $CLOUDFLARE_API_TOKEN_FILE
# Added 2025-03-10: `cfg.apiTokenFile` used to be passed as an
# `EnvironmentFile` to the service, which required it to be of
# the form "CLOUDFLARE_API_TOKEN=" rather than just the secret.
# If we detect this legacy usage, error out.
token=$(< "''${CLOUDFLARE_API_TOKEN_FILE}")
if [[ $token == CLOUDFLARE_API_TOKEN* ]]; then
echo "Error: your api token starts with 'CLOUDFLARE_API_TOKEN='. Remove that, and instead specify just the token." >&2
exit 1
fi
exec ${lib.getExe pkgs.cloudflare-dyndns} ${toString args}
'';
}; };
}; };
} }