diff --git a/hosts/caddy/default.nix b/hosts/caddy/default.nix index cff7cfd..9a4ff7e 100644 --- a/hosts/caddy/default.nix +++ b/hosts/caddy/default.nix @@ -68,6 +68,12 @@ in host = p.hosts.n8n; }; + ilpost-addict.proxy = { + enable = true; + domain = p.domains.public; + host = p.hosts.ilpost-podcast; + }; + media-mgr.proxy = { enable = true; domain = p.domains.public; diff --git a/hosts/hosts.nix b/hosts/hosts.nix index b120895..b285d84 100644 --- a/hosts/hosts.nix +++ b/hosts/hosts.nix @@ -91,6 +91,15 @@ ]; }; + ilpost-podcast = { + module = ./ilpost-podcast; + tags = [ + "lxc" + "bacco" + "secondary" + ]; + }; + immich = { module = ./immich; tags = [ @@ -115,6 +124,7 @@ "lxc" "bacco" "n8n" + "secondary" ]; }; @@ -151,6 +161,7 @@ "lxc" "bacco" "portainer" + "secondary" ]; }; @@ -160,6 +171,7 @@ "lxc" "bacco" "shadowsocks" + "secondary" ]; }; @@ -179,6 +191,7 @@ "lxc" "bacco" "zigbee2mqtt" + "secondary" ]; }; diff --git a/hosts/ilpost-podcast/default.nix b/hosts/ilpost-podcast/default.nix new file mode 100644 index 0000000..650f6e7 --- /dev/null +++ b/hosts/ilpost-podcast/default.nix @@ -0,0 +1,23 @@ +{ + config, + pkgs, + lib, + ... +}: +{ + + my = { + + services.ilpost-addict.enable = true; + + utils = { + commons.enable = true; + commons.gc.enable = true; + lxc-standard.enable = true; + }; + + virtualisation.proxmox.enable = true; + }; + + system.stateVersion = "25.11"; +} diff --git a/hosts/n8n/default.nix b/hosts/n8n/default.nix index 86c4754..6190d15 100644 --- a/hosts/n8n/default.nix +++ b/hosts/n8n/default.nix @@ -10,6 +10,8 @@ services.n8n.enable = true; + services.ilpost-addict.enable = true; + utils = { commons.enable = true; commons.gc.enable = true; diff --git a/hosts/parameters.nix b/hosts/parameters.nix index 5e36ba4..16150e0 100644 --- a/hosts/parameters.nix +++ b/hosts/parameters.nix @@ -31,6 +31,7 @@ in forgejo = "forgejo.${private-domain}"; forgejo-runner = "forgejo-runner.${private-domain}"; n8n = "n8n.${private-domain}"; + ilpost-podcast = "ilpost-podcast.${private-domain}"; }; email = "davide@${public-domain}"; } diff --git a/modules/services/default.nix b/modules/services/default.nix index 3941b66..f18ab3d 100644 --- a/modules/services/default.nix +++ b/modules/services/default.nix @@ -5,6 +5,7 @@ ./firefly-iii.nix ./forgejo.nix ./forgejo-runner.nix + ./ilpost-addict.nix ./immich.nix ./media-mgr.nix ./n8n.nix diff --git a/modules/services/ilpost-addict.nix b/modules/services/ilpost-addict.nix new file mode 100644 index 0000000..21100bb --- /dev/null +++ b/modules/services/ilpost-addict.nix @@ -0,0 +1,172 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.my.services.ilpost-addict; + + # Fetch the ilpost-addict source from GitHub + ilpostAddict = pkgs.fetchFromGitHub { + owner = "stagadet"; + repo = "ilpost-addict"; + rev = "main"; + sha256 = "sha256-kL7tVHXZunqGFztbVx850QQ1U5h5wY1ltIONWXwe7QQ="; + }; + + phpPackage = pkgs.php.withExtensions ({ enabled, all }: enabled ++ [ + all.curl + all.dom + ]); + +in +{ + options.my.services.ilpost-addict = { + enable = lib.mkEnableOption "Enable ilpost-addict podcast feed generator"; + + dataDir = lib.mkOption { + type = lib.types.str; + default = "/var/lib/ilpost-addict"; + description = "Directory where ilpost-addict stores its data (logs, cookies)"; + }; + + user = lib.mkOption { + type = lib.types.str; + default = "ilpost-addict"; + description = "User which runs the ilpost-addict service"; + }; + + group = lib.mkOption { + type = lib.types.str; + default = "ilpost-addict"; + description = "Group which runs the ilpost-addict service"; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 8095; + description = "Port on which Caddy serves ilpost-addict"; + }; + + poolSettings = lib.mkOption { + type = with lib.types; attrsOf (oneOf [ str int bool ]); + default = { + "pm" = "dynamic"; + "pm.max_children" = 8; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 1; + "pm.max_spare_servers" = 4; + "pm.max_requests" = 500; + }; + description = "PHP-FPM pool settings for ilpost-addict"; + }; + + proxy = { + enable = lib.mkEnableOption "Set the proxy entry for this service"; + + domain = lib.mkOption { + default = "example.com"; + type = lib.types.str; + description = "The domain where Caddy is reachable"; + }; + + subdomain = lib.mkOption { + default = "ilpost-podcast"; + type = lib.types.str; + description = "The subdomain where ilpost-addict is reachable"; + }; + + host = lib.mkOption { + default = "localhost"; + type = lib.types.str; + description = "Host name where the service is running"; + }; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.enable { + + users.groups.${cfg.group} = { }; + + users.users.${cfg.user} = { + home = cfg.dataDir; + group = cfg.group; + description = "ilpost-addict service user"; + isSystemUser = true; + }; + + # Add caddy user to ilpost-addict group so it can read the files + users.users.${config.services.caddy.user}.extraGroups = [ cfg.group ]; + + # Create data directories + # The PHP script uses relative paths (log/, cookies/) so we create them + # in the www directory where the script runs from + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' 0750 ${cfg.user} ${cfg.group} -" + "d '${cfg.dataDir}/log' 0750 ${cfg.user} ${cfg.group} -" + "d '${cfg.dataDir}/cookies' 0750 ${cfg.user} ${cfg.group} -" + ]; + + # Setup service to copy PHP files + systemd.services.ilpost-addict-setup = { + wantedBy = [ "multi-user.target" ]; + before = [ "phpfpm-ilpost-addict.service" ]; + serviceConfig = { + Type = "oneshot"; + User = cfg.user; + Group = cfg.group; + }; + script = '' + # Copy the PHP source to the data directory + cp ${ilpostAddict}/src/index.php ${cfg.dataDir}/index.php + chmod 644 ${cfg.dataDir}/index.php + ''; + }; + + # PHP-FPM pool configuration + # The chdir setting ensures the PHP script runs from dataDir + # so the relative paths (log/, cookies/) resolve correctly + services.phpfpm.pools.ilpost-addict = { + user = cfg.user; + group = cfg.group; + phpPackage = phpPackage; + settings = lib.mapAttrs (name: lib.mkDefault) { + "listen.owner" = config.services.caddy.user; + "listen.group" = config.services.caddy.group; + "chdir" = cfg.dataDir; + } // cfg.poolSettings; + }; + + # Caddy configuration for serving PHP + # Using :port syntax to match any hostname on this port + services.caddy = { + enable = true; + virtualHosts.":${toString cfg.port}".extraConfig = '' + root * ${cfg.dataDir} + php_fastcgi unix/${config.services.phpfpm.pools.ilpost-addict.socket} + file_server + encode gzip + + log { + output file ${config.services.caddy.logDir}/ilpost-addict.log + } + ''; + }; + + networking.firewall.allowedTCPPorts = [ cfg.port ]; + }) + + (lib.mkIf cfg.proxy.enable { + services.caddy = with cfg.proxy; { + virtualHosts."${subdomain}.${domain}".extraConfig = '' + reverse_proxy http://${host}:${toString cfg.port} + import cloudflare_${domain} + ''; + }; + }) + ]; +} +