Nix configurations for my homelab

Split up caddy config

+22 -5
dandelion/config.nix
···
imports = [
./hardware.nix
./packages.nix
-
./services/caddy.nix
../modules/basic.nix
+
../modules/caddy.nix
../modules/development/nix.nix
../modules/development/sh.nix
../modules/editor.nix
···
../modules/remoteBuildMachines.nix
../modules/sss.nix
-
../modules/services/caddy.nix
+
../modules/services/caddy
+
# ../modules/services/caddy/cp-certs.nix
+
../modules/services/caddy/matrix.nix
+
../modules/services/caddy/nextcloud.nix
+
../modules/services/caddy/pds.nix
+
../modules/services/caddy/soju.nix
+
../modules/services/caddy/tangled-knot.nix
+
../modules/services/caddy/websites/org-butwho.nix
+
# ../modules/services/caddy/xmpp.nix
../modules/services/openssh.nix
../modules/services/soju.nix
];
···
networking.hostName = "dandelion";
nix.settings.max-jobs = 0;
-
garden.info.host = {
-
sss-mount = true;
-
vps = true;
+
garden = {
+
caddy.package = {
+
plugins = [
+
"github.com/mholt/caddy-events-exec@v0.0.0-20231121214933-055bfd2e8b82"
+
"github.com/mholt/caddy-l4@v0.0.0-20250124234235-87e3e5e2c7f9"
+
];
+
hash = "sha256-ydan4Lqeh4eMCpuWryXSdcqQ3CBVCxVwPqUcVPedZy0=";
+
};
+
info.host = {
+
sss-mount = true;
+
vps = true;
+
};
};
# This option defines the first version of NixOS you have installed on this particular machine,
-183
dandelion/services/caddy.nix
···
-
# TODO: Put the sss import in this directory since it makes direct use of it
-
# TODO: Separate caddy config into separate files
-
{ config, pkgs, ... }:
-
let
-
lily = config.garden.info.network.lily.netbird-ip;
-
cpCerts = pkgs.writeShellApplication {
-
name = "cpCerts";
-
runtimeInputs = with pkgs; [ coreutils ];
-
text = ''
-
prog_name=''${0##*/}
-
-
case $1 in
-
"proxy.butwho.org" | "conference.butwho.org" | "pubsub.butwho.org" | \
-
"upload.butwho.org" | "butwho.org" )
-
caddy_path="/var/lib/caddy/.local/share/caddy"
-
printf '%s\n' "$prog_name: Copying certs for '$1' to /sss/certs/$1"
-
-
mkdir -p "/sss/certs/$1"
-
cp -f "$caddy_path/$2" "/sss/certs/$1"
-
cp -f "$caddy_path/$3" "/sss/certs/$1"
-
-
# Read both the .crt file and the .key file to make a .pem
-
crt=$(cat "$caddy_path/$2")
-
key=$(cat "$caddy_path/$3")
-
printf '%s\n\n%s\n' "$crt" "$key" > "/sss/certs/$1/$1.pem"
-
-
printf '%s\n' "$prog_name: Copied certs for '$1'"
-
;;
-
* ) printf '%s\n' "$prog_name: Skipping $1" ;;
-
esac
-
'';
-
};
-
cpCertsCommand = "${cpCerts}/bin/cpCerts {event.data.identifier} {event.data.certificate_path} {event.data.private_key_path}";
-
in
-
{
-
environment.persistence."/data/persistent".directories = [
-
{
-
directory = "/var/www/org.butwho";
-
user = "mou";
-
group = "caddy";
-
mode = "0750";
-
}
-
];
-
-
networking.firewall.interfaces."enp1s0".allowedTCPPorts = [
-
22
-
6697
-
];
-
-
services.caddy = {
-
package = pkgs.caddy.withPlugins {
-
plugins = [
-
"github.com/mholt/caddy-events-exec@v0.0.0-20231121214933-055bfd2e8b82"
-
"github.com/mholt/caddy-l4@v0.0.0-20250124234235-87e3e5e2c7f9"
-
];
-
hash = "sha256-ydan4Lqeh4eMCpuWryXSdcqQ3CBVCxVwPqUcVPedZy0=";
-
};
-
globalConfig = ''
-
events {
-
on cert_obtained exec ${cpCertsCommand}
-
}
-
-
on_demand_tls {
-
ask http://${lily}:3000/tls-check
-
}
-
-
layer4 {
-
[::]:6697 {
-
route {
-
tls {
-
connection_policy {
-
alpn irc
-
default_sni soju.y6d.boo
-
}
-
}
-
proxy [::1]:6667
-
}
-
}
-
[::]:22 {
-
route {
-
proxy ${lily}:2222
-
}
-
}
-
}
-
'';
-
virtualHosts = {
-
"butwho.org".extraConfig = ''
-
encode zstd gzip
-
-
# Should I set this for all .well-known files?
-
# header /.well-known/* Access-Control-Allow-Origin *
-
-
# Unsure if this works without
-
# header /.well-known/host-meta* Access-Control-Allow-Origin *
-
-
# header /.well-known/host-meta Content-Type text/xml
-
# respond /.well-known/host-meta <<XML
-
# <?xml version='1.0' encoding='utf-8'?>
-
# <XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>
-
# <Link rel="urn:xmpp:alt-connections:xbosh" href="https://butwho.org:5443/bosh" />
-
# <Link rel="urn:xmpp:alt-connections:websocket" href="wss://butwho.org:5443/ws" />
-
# </XRD>
-
# XML
-
-
# header /.well-known/host-meta.json Content-Type application/json
-
# respond /.well-known/host-meta.json <<JSON
-
# {
-
# "links": [
-
# { "rel": "urn:xmpp:alt-connections:xbosh", "href": "https://butwho.org:5443/bosh" },
-
# { "rel": "urn:xmpp:alt-connections:websocket", "href": "wss://butwho.org:5443/ws" }
-
# ]
-
# }
-
# JSON
-
-
header /.well-known/matrix/* Access-Control-Allow-Origin *
-
header /.well-known/matrix/* Content-Type application/json
-
respond /.well-known/matrix/client <<JSON
-
{
-
"m.homeserver": { "base_url": "https://matrix.butwho.org" }
-
}
-
JSON
-
respond /.well-known/matrix/server `{"m.server": "matrix.butwho.org:443"}`
-
-
root * /var/www/org.butwho
-
file_server {
-
hide .git readme.md license
-
}
-
-
handle_errors {
-
respond "{err.status_code} {err.status_text}"
-
}
-
'';
-
# "conference.butwho.org".extraConfig = ''
-
# redir https://butwho.org{uri}
-
# '';
-
"matrix.butwho.org".extraConfig = ''
-
encode zstd gzip
-
reverse_proxy ${lily}:8008
-
'';
-
"pds.butwho.org".extraConfig = ''
-
encode zstd gzip
-
tls {
-
on_demand
-
}
-
reverse_proxy ${lily}:3000
-
'';
-
"*.pds.butwho.org".extraConfig = ''
-
encode zstd gzip
-
tls {
-
on_demand
-
}
-
reverse_proxy ${lily}:3000
-
'';
-
"knot.butwho.org".extraConfig = ''
-
encode zstd gzip
-
reverse_proxy ${lily}:5555
-
'';
-
# "proxy.butwho.org".extraConfig = ''
-
# redir https://butwho.org{uri}
-
# '';
-
# "pubsub.butwho.org".extraConfig = ''
-
# redir https://butwho.org{uri}
-
# '';
-
# "upload.butwho.org".extraConfig = ''
-
# redir https://butwho.org{uri}
-
# '';
-
"cloud.lilac.pink".extraConfig = ''
-
encode zstd gzip
-
reverse_proxy ${lily}:80 {
-
# NixOS uses nginx as a webserver for NextCloud by default and nginx will send 301 redirects to the client
-
# using http as the protocol instead of https since it doesn't have SSL certs of its own.
-
# Because the redirect isn't also https, this can cause a Content-Security-Policy error on the client.
-
# In practice this prevents us from enabling apps on NextCloud without this line.
-
header_down Location http:// https://
-
}
-
'';
-
"soju.y6d.boo".extraConfig = ''
-
encode zstd gzip
-
reverse_proxy [::1]:8080
-
'';
-
};
-
};
-
}
+10 -10
flake.lock
···
]
},
"locked": {
-
"lastModified": 1744360457,
-
"narHash": "sha256-Rcd9KYFRYPkMfOsz6vzWosEfggJMGjb1/j9mnxC7q9s=",
+
"lastModified": 1744380363,
+
"narHash": "sha256-cXjAUuAfQDPSLSsckZuTioQ986iqSPTzx8D7dLAcC+Q=",
"owner": "nix-community",
"repo": "home-manager",
-
"rev": "da624eaad0fefd4dac002e1f09d300d150c20483",
+
"rev": "e43c6bcb101ba3301522439c459288c4a248f624",
"type": "github"
},
"original": {
···
},
"nixpkgs": {
"locked": {
-
"lastModified": 1744348691,
-
"narHash": "sha256-dIPrBepej1ebT1IaWEFLI5mpQO65+oM+SArkrNI9gjo=",
+
"lastModified": 1744371553,
+
"narHash": "sha256-KjvhD+DkQsOAggIFyuxSAZIs84UahDb/O9ojpvyFNe0=",
"owner": "NixOS",
"repo": "nixpkgs",
-
"rev": "6b93024f590b15b1f3888fcc6e56a0866e0c26c2",
+
"rev": "6f061f35682410185d9a1582601e9241bfa6ad96",
"type": "github"
},
"original": {
···
"yemou-dotfiles": {
"flake": false,
"locked": {
-
"lastModified": 1744136969,
-
"narHash": "sha256-Pv4OUJbopgHxW64DwFA/9RF69WicSLsA+Vfqd61ufBY=",
+
"lastModified": 1744381009,
+
"narHash": "sha256-N6FmFNELNT6bR6VyM7W2nU6PjKn011/uZsxRG65mXrY=",
"ref": "refs/heads/main",
-
"rev": "ed4446edcbe0787bdc43fff8fe4c9606698d47ce",
-
"revCount": 89,
+
"rev": "169fceb54947dfb8ed9a9e8bcdfa1638dd8806c0",
+
"revCount": 90,
"type": "git",
"url": "https://tangled.sh/@yemou.pink/dotfiles"
},
+41
modules/caddy.nix
···
+
{
+
config,
+
lib,
+
pkgs,
+
...
+
}:
+
{
+
options.garden.caddy = {
+
package = {
+
plugins = lib.mkOption {
+
type = lib.types.listOf lib.types.str;
+
default = [ ];
+
description = "Caddy plugins to install";
+
};
+
hash = lib.mkOption {
+
type = lib.types.str;
+
default = lib.fakeSha256;
+
description = "Hash for Caddy plugins";
+
};
+
};
+
layer4 = lib.mkOption {
+
type = lib.types.lines;
+
default = "";
+
description = "Caddy-L4 configurations";
+
};
+
};
+
+
config = {
+
services.caddy = {
+
package = pkgs.caddy.withPlugins {
+
plugins = config.garden.caddy.package.plugins;
+
hash = config.garden.caddy.package.hash;
+
};
+
globalConfig = lib.mkIf (config.garden.caddy.layer4 != "") ''
+
layer4 {
+
${config.garden.caddy.layer4}
+
}
+
'';
+
};
+
};
+
}
+1 -1
modules/services/caddy.nix modules/services/caddy/default.nix
···
services.caddy = {
enable = true;
-
email = "acme@lilac.pink";
+
email = "acme@mou.pink";
};
}
+38
modules/services/caddy/cp-certs.nix
···
+
{ pkgs, ... }:
+
let
+
cpCerts = pkgs.writeShellApplication {
+
name = "cpCerts";
+
runtimeInputs = with pkgs; [ coreutils ];
+
text = ''
+
prog_name=''${0##*/}
+
+
case $1 in
+
"proxy.butwho.org" | "conference.butwho.org" | "pubsub.butwho.org" | \
+
"upload.butwho.org" | "butwho.org" )
+
caddy_path="/var/lib/caddy/.local/share/caddy"
+
printf '%s\n' "$prog_name: Copying certs for '$1' to /sss/certs/$1"
+
+
mkdir -p "/sss/certs/$1"
+
cp -f "$caddy_path/$2" "/sss/certs/$1"
+
cp -f "$caddy_path/$3" "/sss/certs/$1"
+
+
# Read both the .crt file and the .key file to make a .pem
+
crt=$(cat "$caddy_path/$2")
+
key=$(cat "$caddy_path/$3")
+
printf '%s\n\n%s\n' "$crt" "$key" > "/sss/certs/$1/$1.pem"
+
+
printf '%s\n' "$prog_name: Copied certs for '$1'"
+
;;
+
* ) printf '%s\n' "$prog_name: Skipping $1" ;;
+
esac
+
'';
+
};
+
cpCertsCommand = "${cpCerts}/bin/cpCerts {event.data.identifier} {event.data.certificate_path} {event.data.private_key_path}";
+
in
+
{
+
services.caddy.globalConfig = ''
+
events {
+
on cert_obtained exec ${cpCertsCommand}
+
}
+
'';
+
}
+19
modules/services/caddy/matrix.nix
···
+
{ config, ... }:
+
{
+
services.caddy.virtualHosts = {
+
"butwho.org".extraConfig = ''
+
header /.well-known/matrix/* Access-Control-Allow-Origin *
+
header /.well-known/matrix/* Content-Type application/json
+
respond /.well-known/matrix/client <<JSON
+
{
+
"m.homeserver": { "base_url": "https://matrix.butwho.org" }
+
}
+
JSON
+
respond /.well-known/matrix/server `{"m.server": "matrix.butwho.org:443"}`
+
'';
+
"matrix.butwho.org".extraConfig = ''
+
encode
+
reverse_proxy ${config.garden.info.network.lily.netbird-ip}:8008
+
'';
+
};
+
}
+13
modules/services/caddy/nextcloud.nix
···
+
{ config, ... }:
+
{
+
services.caddy.virtualHosts."cloud.lilac.pink".extraConfig = ''
+
encode
+
reverse_proxy ${config.garden.info.network.lily.netbird-ip}:80 {
+
# NixOS uses nginx as a webserver for NextCloud by default and nginx will send 301 redirects to the client
+
# using http as the protocol instead of https since it doesn't have SSL certs of its own.
+
# Because the redirect isn't also https, this can cause a Content-Security-Policy error on the client.
+
# In practice this prevents us from enabling apps on NextCloud without this line.
+
header_down Location http:// https://
+
}
+
'';
+
}
+26
modules/services/caddy/pds.nix
···
+
{ config, ... }:
+
{
+
services.caddy = {
+
globalConfig = ''
+
on_demand_tls {
+
ask http://${config.garden.info.network.lily.netbird-ip}:3000/tls-check
+
}
+
'';
+
virtualHosts = {
+
"pds.butwho.org".extraConfig = ''
+
tls {
+
on_demand
+
}
+
encode
+
reverse_proxy ${config.garden.info.network.lily.netbird-ip}:3000
+
'';
+
"*.pds.butwho.org".extraConfig = ''
+
tls {
+
on_demand
+
}
+
encode
+
reverse_proxy ${config.garden.info.network.lily.netbird-ip}:3000
+
'';
+
};
+
};
+
}
+23
modules/services/caddy/soju.nix
···
+
{ ... }:
+
{
+
networking.firewall.interfaces."enp1s0".allowedTCPPorts = [ 6697 ];
+
+
services.caddy.virtualHosts."soju.y6d.boo".extraConfig = ''
+
encode
+
reverse_proxy [::1]:8080
+
'';
+
+
garden.caddy.layer4 = ''
+
[::]:6697 {
+
route {
+
tls {
+
connection_policy {
+
alpn irc
+
default_sni soju.y6d.boo
+
}
+
}
+
proxy [::1]:6667
+
}
+
}
+
'';
+
}
+17
modules/services/caddy/tangled-knot.nix
···
+
{ config, ... }:
+
{
+
networking.firewall.interfaces."enp1s0".allowedTCPPorts = [ 22 ];
+
+
services.caddy.virtualHosts."knot.butwho.org".extraConfig = ''
+
encode
+
reverse_proxy ${config.garden.info.network.lily.netbird-ip}:5555
+
'';
+
+
garden.caddy.layer4 = ''
+
[::]:22 {
+
route {
+
proxy ${config.garden.info.network.lily.netbird-ip}:2222
+
}
+
}
+
'';
+
}
+23
modules/services/caddy/websites/org-butwho.nix
···
+
{ ... }:
+
{
+
environment.persistence."/data/persistent".directories = [
+
{
+
directory = "/var/www/org.butwho";
+
user = "mou";
+
group = "caddy";
+
mode = "0750";
+
}
+
];
+
+
services.caddy.virtualHosts."butwho.org".extraConfig = ''
+
encode
+
root * /var/www/org.butwho
+
file_server {
+
hide .git license
+
}
+
+
handle_errors {
+
respond "{err.status_code} {err.status_text}"
+
}
+
'';
+
}
+41
modules/services/caddy/xmpp.nix
···
+
{ ... }:
+
{
+
services.caddy.virtualHosts = {
+
"butwho.org".extraConfig = ''
+
header /.well-known/host-meta Content-Type text/xml
+
respond /.well-known/host-meta <<XML
+
<?xml version='1.0' encoding='utf-8'?>
+
<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>
+
<Link rel="urn:xmpp:alt-connections:xbosh" href="https://butwho.org:5443/bosh" />
+
<Link rel="urn:xmpp:alt-connections:websocket" href="wss://butwho.org:5443/ws" />
+
</XRD>
+
XML
+
+
header /.well-known/host-meta.json Content-Type application/json
+
respond /.well-known/host-meta.json <<JSON
+
{
+
"links": [
+
{ "rel": "urn:xmpp:alt-connections:xbosh", "href": "https://butwho.org:5443/bosh" },
+
{ "rel": "urn:xmpp:alt-connections:websocket", "href": "wss://butwho.org:5443/ws" }
+
]
+
}
+
JSON
+
'';
+
"conference.butwho.org".extraConfig = ''
+
encode
+
redir https://butwho.org{uri}
+
'';
+
"proxy.butwho.org".extraConfig = ''
+
encode
+
redir https://butwho.org{uri}
+
'';
+
"pubsub.butwho.org".extraConfig = ''
+
encode
+
redir https://butwho.org{uri}
+
'';
+
"upload.butwho.org".extraConfig = ''
+
encode
+
redir https://butwho.org{uri}
+
'';
+
};
+
}