Port to NixOS: replace Helm chart with flake-based NixOS config

Replaces the Helm/k3s setup with a declarative NixOS configuration targeting
a Raspberry Pi 4. Services run as podman containers under systemd, with data
on an external HD at /mnt/data. Key components:

- flake.nix: multi-host flake with pi-main (aarch64) and a placeholder for a
  second machine
- modules/common.nix: shared system config (nix, podman, sops, SSH)
- modules/storage.nix: external HD mount with per-service subdirs
- modules/caddy.nix: Caddy with cloudflare DNS-01 ACME + authelia forward_auth
- modules/cloudflared.nix: Cloudflare tunnel for remote access
- modules/backup.nix: restic daily backups with NC maintenance mode pre-hook
- modules/services/{openldap,authelia,gitea,nextcloud,phpldapadmin}.nix: core services
- modules/services/{jellyfin,transmission}.nix: media services (disabled by default)
- secrets/: sops-nix scaffold with .sops.yaml age key config
- hosts/pi-main/: hardware config + service selection for the Pi
- PORTING.md: step-by-step migration guide (SD card → data restore → verify)
This commit is contained in:
Aner Zakobar
2026-04-15 17:18:12 +03:00
parent d1948df47e
commit 2f0d0b5e4c
59 changed files with 2173 additions and 4666 deletions
+77
View File
@@ -0,0 +1,77 @@
{ config, lib, pkgs, homeyConfig, ... }:
# Cloudflare Tunnel (cloudflared) — remote access without open inbound ports.
#
# Architecture:
# Internet → Cloudflare edge → cloudflared tunnel (outbound from Pi)
# → Caddy on localhost → service containers
#
# The tunnel is configured to route each hostname to Caddy's HTTPS listener.
# Caddy handles TLS and forward_auth; cloudflared just carries the traffic.
#
# Setup steps (one-time, done from the Cloudflare dashboard):
# 1. Go to Zero Trust → Networks → Tunnels → Create a tunnel
# 2. Name it (e.g. "pi-main")
# 3. Copy the tunnel token — add it to secrets.yaml as cloudflare/tunnel_token
# 4. In the tunnel's "Public Hostnames" config, add routes:
# auth.home.zakobar.com → http://localhost:80 (or https://localhost:443)
# git.home.zakobar.com → https://localhost:443
# nextcloud.home.zakobar.com → https://localhost:443
# ldapadmin.home.zakobar.com → https://localhost:443
# jellyfin.home.zakobar.com → https://localhost:443
# torrent.home.zakobar.com → https://localhost:443
# Set "No TLS Verify" = true (Caddy's cert is from Let's Encrypt but
# the hostname seen by cloudflared is localhost, so hostname verification
# would fail without this flag).
#
# The tunnel_token approach (--token) is the simplest: one secret, no config
# file needed on the Pi.
#
# Secrets consumed from sops:
# cloudflare/tunnel_token
let
cfg = config.homey.cloudflared;
in
{
options.homey.cloudflared = {
enable = lib.mkEnableOption "Cloudflare Tunnel for remote access";
};
config = lib.mkIf cfg.enable {
# -----------------------------------------------------------------------
# Secrets
# -----------------------------------------------------------------------
sops.secrets."cloudflare/tunnel_token" = { owner = "cloudflared"; };
# -----------------------------------------------------------------------
# cloudflared service
# NixOS 24.11 ships services.cloudflared natively.
# -----------------------------------------------------------------------
services.cloudflared = {
enable = true;
tunnels = {
"pi-main" = {
# credentialsFile is not used with token-based auth;
# the token is passed via environment variable instead.
# We override the systemd unit below to inject it.
default = "http_status:404";
};
};
};
# Inject the tunnel token from the sops secret file
systemd.services."cloudflared-tunnel-pi-main" = {
serviceConfig = {
ExecStart = lib.mkForce (pkgs.writeShellScript "cloudflared-start" ''
exec ${pkgs.cloudflared}/bin/cloudflared tunnel \
--no-autoupdate \
run \
--token "$(cat ${config.sops.secrets."cloudflare/tunnel_token".path})"
'');
};
after = lib.mkAfter [ "caddy.service" ];
wants = lib.mkAfter [ "caddy.service" ];
};
};
}