Files
2026-06-07 00:59:22 +03:00

99 lines
4.1 KiB
Nix

{ config, lib, pkgs, homeyConfig, ... }:
# Eurovision Vote — Django app for ranking Eurovision performances.
#
# Uses the NixOS module from the eurovote flake (eurovote.nixosModules.default).
# This wrapper wires it into the homey module system: enable flag, sops secret,
# and uptime monitoring.
#
# The app uses DynamicUser + StateDirectory so systemd owns /var/lib/eurovote/;
# no tmpfiles.rules entry needed.
#
# Authentication: Caddy forward_auth → Authelia; the app reads the
# X-Remote-User header set by Caddy (from Authelia's Remote-User).
# All authenticated users get app access; /admin/* is restricted to
# group:admins by Authelia's access_control rules (defined in this file).
#
# Secrets consumed from sops:
# eurovote/secret_key
let
cfg = config.homey.eurovote;
domain = homeyConfig.domain;
in
{
options.homey.eurovote = {
enable = lib.mkEnableOption "Eurovision Vote app" // { default = true; };
};
config = lib.mkIf cfg.enable {
# -----------------------------------------------------------------------
# Secrets
# -----------------------------------------------------------------------
# mode 0444: the service runs as a DynamicUser (random UID) so it cannot
# read a root-owned 0400 file. /run/secrets/ itself is not world-listable
# (mode 0751), so world-readable here is acceptable on a home server.
sops.secrets."eurovote/secret_key" = { owner = "root"; mode = "0444"; };
# -----------------------------------------------------------------------
# Service (options provided by eurovote.nixosModules.default)
# -----------------------------------------------------------------------
services.eurovote = {
enable = true;
port = 8007;
allowedHosts = "localhost 127.0.0.1 eurovision-vote.${domain}";
secretKeyFile = config.sops.secrets."eurovote/secret_key".path;
trustedOrigins = "https://eurovision-vote.${domain}";
# After SSO logout, send the user back to Authelia's logout page
logoutRedirectUrl = "https://auth.${domain}/logout";
};
# -----------------------------------------------------------------------
# Authelia access control — /admin/* requires two_factor + admins group;
# all other paths require one_factor.
# -----------------------------------------------------------------------
homey.authelia.accessControlRules = [
{ priority = 65; domain = [ "eurovision-vote.${domain}" ]; resources = [ "^/admin.*$" ]; subject = [ "group:admins" ]; policy = "two_factor"; }
{ priority = 66; domain = [ "eurovision-vote.${domain}" ]; resources = [ "^/admin.*$" ]; policy = "deny"; }
{ priority = 67; domain = [ "eurovision-vote.${domain}" ]; policy = "one_factor"; }
];
# -----------------------------------------------------------------------
# Caddy virtual host — forward_auth; X-Remote-User passed to Django's
# RemoteUserMiddleware for automatic SSO login
# -----------------------------------------------------------------------
homey.caddy.virtualHosts = [{
subdomain = "eurovision-vote";
port = 8007;
auth = true;
extraConfig = ''
reverse_proxy localhost:8007 {
header_up X-Remote-User {http.request.header.Remote-User}
}
'';
extraHttpConfig = ''
reverse_proxy localhost:8007 {
header_up X-Forwarded-Proto https
header_up X-Remote-User {http.request.header.Remote-User}
}
'';
}];
# Eurovision Vote uses DynamicUser + /var/lib/eurovote — no extraDirs needed.
# -----------------------------------------------------------------------
# Backup — /var/lib/eurovote holds the SQLite DB with votes
# -----------------------------------------------------------------------
homey.backup.extraPaths = [ "/var/lib/eurovote" ];
# -----------------------------------------------------------------------
# Uptime Kuma monitor
# -----------------------------------------------------------------------
homey.monitoring.monitors = [{
name = "Eurovision Vote";
url = "https://eurovision-vote.${domain}";
interval = 60;
}];
};
}