Go for docker instead, cause php sucks

This commit is contained in:
kalle 2025-04-11 23:59:26 +02:00
parent 248a0fd69c
commit 80c91e6b23
9 changed files with 80 additions and 66 deletions

18
dockerImages.nix Normal file
View file

@ -0,0 +1,18 @@
{
freshrss = {
imageName = "docker.io/freshrss/freshrss";
imageDigest = "sha256:bca4407f1f3ecb2e02bd57f704593c64f89bbf3fad53f03ebcf4baecb0122de6"; # 1.26.1
sha256 = "699413e5b0637eb007f77cf7615ff6d372eb01dac8b48d213c8fbf766bef3995";
};
authentik-redis = {
imageName = "docker.io/library/redis";
imageDigest = "sha256:5c30ac9c59d8fcddc368d0dd98f544b8b5ab3a981c633db59da7eff9d76b97cc"; # 7.4.2-alpine
sha256 = "8a4937f259307fa724fb1a9eac9862b5a9bfba555eba2a43e816cd40104e1692";
};
authentik-server = {
imageName = "ghcr.io/goauthentik/server";
imageDigest = "sha256:7464a70c0d84df0816858106116a3306a80359b4300aa656c3a5ab790a38c229"; # 2024.12.3
sha256 = "fadbb55b7ae1d84d7322538101e933caa021582e5120828040c3883a18b1b3d5";
};
}

View file

@ -1,22 +1,23 @@
# FreshRSS role # FreshRSS role
## Notes ## Notes
- Requires the postgres role to be enabled on the same host. - Requires the postgres and podman roles to be enabled on the same host.
- By default no SSO is configured. - Requires you to manually follow the installer
- Set database type to postgres
- Set database host to `host.containers.internal`
- Set database username to `freshrss`
- Set database password to the same value as `postgres/freshrss`
- Set database to `freshrss`
- Set username of the default user to the OIDC identity (username) of the desired admin user.
- Set authentication method to HTTP.
## Options ## Options
### `freshrss.domain` ### `freshrss.domain`
The domain used by freshrss. The domain used by freshrss.
### `freshrss.adminUser`
The administrator user for freshrss. This users password is controlled by the
`freshrss/admin_pass` secret.
## Secrets ## Secrets
### `freshrss/db_pass` ## `freshrss/client_id`
The password for the freshrss postgres database. This should be the same as Client id for OIDC. Obtainable from the auth provider.
`postgres/freshrss` on the same host.
### `freshrss/admin_pass`
The password for the administrator user.
## `freshrss/client_secret`
Client secret for OIDC. Obtainable from the auth provider.

View file

@ -16,6 +16,7 @@
lib = nixpkgs.lib; lib = nixpkgs.lib;
outputs = self.outputs; outputs = self.outputs;
dockerImages = import ./dockerImages.nix;
homelabConfig = import ./config.nix; homelabConfig = import ./config.nix;
utils = import ./utils.nix { inherit inputs homelabConfig; }; utils = import ./utils.nix { inherit inputs homelabConfig; };
@ -48,6 +49,7 @@
inputs inputs
outputs outputs
hosts hosts
dockerImages
; ;
}; };
nodeSpecialArgs = builtins.mapAttrs (_: cfg: { host = cfg; }) hosts; nodeSpecialArgs = builtins.mapAttrs (_: cfg: { host = cfg; }) hosts;

View file

@ -9,12 +9,12 @@
roles = with roles; [ roles = with roles; [
postgres postgres
podman
freshrss freshrss
]; ];
config = { config = {
freshrss.domain = "rss.${hlConfig.domain}"; freshrss.domain = "rss.${hlConfig.domain}";
freshrss.adminUser = "kalle";
}; };
stateVersion = "24.05"; stateVersion = "24.05";
} }

View file

@ -26,6 +26,7 @@
lib, lib,
config, config,
pkgs, pkgs,
dockerImages,
host, host,
... ...
}: }:
@ -115,14 +116,14 @@
podman.containers = { podman.containers = {
# TODO: Does using system redis make sense here? # TODO: Does using system redis make sense here?
"authentik-redis" = { "authentik-redis" = {
imageMetadata = import ./images/redis.nix; imageMetadata = dockerImages.authentik-redis;
autoStart = true; autoStart = true;
volumes = [ volumes = [
"/appdata/authentik/redis:/data" "/appdata/authentik/redis:/data"
]; ];
}; };
"authentik-server" = { "authentik-server" = {
imageMetadata = import ./images/server.nix; imageMetadata = dockerImages.authentik-server;
autoStart = true; autoStart = true;
cmd = [ "server" ]; cmd = [ "server" ];
environment = { environment = {

View file

@ -1,5 +0,0 @@
{
imageName = "docker.io/library/redis";
imageDigest = "sha256:5c30ac9c59d8fcddc368d0dd98f544b8b5ab3a981c633db59da7eff9d76b97cc"; # 7.4.2-alpine
sha256 = "8a4937f259307fa724fb1a9eac9862b5a9bfba555eba2a43e816cd40104e1692";
}

View file

@ -1,5 +0,0 @@
{
imageName = "ghcr.io/goauthentik/server";
imageDigest = "sha256:7464a70c0d84df0816858106116a3306a80359b4300aa656c3a5ab790a38c229"; # 2024.12.3
sha256 = "fadbb55b7ae1d84d7322538101e933caa021582e5120828040c3883a18b1b3d5";
}

View file

@ -17,12 +17,18 @@
{ {
name = "${hostname}-freshrss"; name = "${hostname}-freshrss";
rule = "Host(`${config.domain}`)"; rule = "Host(`${config.domain}`)";
target = "http://${host.ip}:80"; target = "http://${host.ip}:1342";
} }
]; ];
nixosModule = nixosModule =
{ lib, config, ... }: {
lib,
config,
pkgs,
dockerImages,
...
}:
{ {
options.freshrss = { options.freshrss = {
domain = lib.mkOption { domain = lib.mkOption {
@ -35,18 +41,15 @@
config = config =
let let
cfg = config.freshrss; appDir = "/cephfs/appdata/freshrss";
secrets = config.sops.secrets; dataDir = "${appDir}/data";
in in
{ {
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [
80 # Nginx running freshrss 1342 # Freshrss
]; ];
sops.secrets = { sops.secrets = {
"freshrss/db_pass" = {
owner = "freshrss";
};
"freshrss/client_id" = { "freshrss/client_id" = {
owner = "freshrss"; owner = "freshrss";
}; };
@ -63,43 +66,43 @@
''; '';
}; };
# Set up user to run freshrss
users.users."freshrss" = {
isSystemUser = true;
group = "freshrss";
};
users.groups."freshrss" = { };
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d '${config.services.freshrss.dataDir}/cache' 0750 ${config.services.freshrss.user} ${config.services.freshrss.user} - -" "d '${appDir}' 0750 freshrss freshrss - -"
"d '${config.services.freshrss.dataDir}/users' 0750 ${config.services.freshrss.user} ${config.services.freshrss.user} - -" "d '${dataDir}' 0750 freshrss freshrss - -"
"d '${config.services.freshrss.dataDir}/favicons' 0750 ${config.services.freshrss.user} ${config.services.freshrss.user} - -" "d '${appDir}/extensions' 0750 freshrss freshrss - -"
]; ];
# Create the database # Create the database
postgres.databases = [ "freshrss" ]; postgres.databases = [ "freshrss" ];
# Only run freshrss after ceph has been mounted podman.containers = {
systemd.services.freshrss-config = { "freshrss" = {
after = [ "cephfs.mount" ]; imageMetadata = dockerImages.freshrss;
autoStart = true;
environment = {
TZ = "Europe/Amsterdam";
CRON_MIN = "3,33";
OIDC_ENABLED = "1";
OIDC_PROVIDER_METADATA_URL = "https://auth.kallestruik.nl/application/o/freshrss/.well-known/openid-configuration";
OIDC_X_FORWARDED_HEADERS = "X-Forwarded-Port X-Forwarded-Proto X-Forwarded-Host";
OIDC_SCOPES = "openid email profile";
}; };
systemd.services.nginx = { environmentFiles = [
after = [ "cephfs.mount" ]; config.sops.templates."freshrss-secret.env".path
serviceConfig = { ];
Environment = [ volumes = [
"OIDC_ENABLED=1" "${dataDir}:/var/www/FreshRSS/data"
"OIDC_PROVIDER_METADATA_URL=https://auth.kallestruik.nl/application/o/freshrss/.well-known/openid-configuration" "${appDir}/extensions:/var/www/FreshRSS/extensions"
"OIDC_X_FORWARDED_HEADERS=\"X-Forwarded-Port X-Forwarded-Proto X-Forwarded-Host\"" ];
"OIDC_SCOPES=\"openid email profile\"" ports = [
"1342:80"
]; ];
EnvironmentFile = config.sops.templates."freshrss-secret.env".path;
};
};
# Enable and configure the service
services.freshrss = {
enable = true;
baseUrl = "https://${cfg.domain}";
virtualHost = cfg.domain;
dataDir = "/cephfs/appdata/freshrss";
authType = "http_auth";
database = {
type = "pgsql";
passFile = secrets."freshrss/db_pass".path;
}; };
}; };
}; };

View file

@ -1,5 +1,4 @@
freshrss: freshrss:
db_pass: ENC[AES256_GCM,data:6/DOnp9vzUUdibx1FdEMucgXzxsyae7UHwDMC7byaQ8YrQmkGCCDi3Q4ZqE=,iv:LS/IMe97HifOq5uoP5n0++vMLfaiJC6FOQ7tKmR5438=,tag:XLhYQ5N+HbrUOPY6VVB8qA==,type:str]
client_id: ENC[AES256_GCM,data:pn/rhQ4AOngFUAk+Ty0Ms0Vrq2/ZwJj6O1dVKBxNloZnW5i6cEQWvQ==,iv:plsNXFQLNyYlb5EIZZM3AmF2BqGbHDftq6X54w5kBhc=,tag:3FZpwjWQ8O2sIfbaGhsl8Q==,type:str] client_id: ENC[AES256_GCM,data:pn/rhQ4AOngFUAk+Ty0Ms0Vrq2/ZwJj6O1dVKBxNloZnW5i6cEQWvQ==,iv:plsNXFQLNyYlb5EIZZM3AmF2BqGbHDftq6X54w5kBhc=,tag:3FZpwjWQ8O2sIfbaGhsl8Q==,type:str]
client_secret: ENC[AES256_GCM,data:86taBVM/JdN0cfLC7Yfl5OPuK55jLDedzYyv+iRZTViZSBfUCoQKLqiZOznHXEH07qJCGSJ9QjmaGy6DbtXjZ1OHAX/9egr8yx0GNdtaoDbzNxYEY0hhzxmMJHdVa5qRaiw+yZNLUzXFBXYjRCltKncAk2h2O+PRnjvgWeYqnzQ=,iv:vlkWwBLcxDGZRWyVRpm8DBQ0ZAPRsB6J/0j+Ucg1p9s=,tag:r/lXsVBncl3d+6kS389GoQ==,type:str] client_secret: ENC[AES256_GCM,data:86taBVM/JdN0cfLC7Yfl5OPuK55jLDedzYyv+iRZTViZSBfUCoQKLqiZOznHXEH07qJCGSJ9QjmaGy6DbtXjZ1OHAX/9egr8yx0GNdtaoDbzNxYEY0hhzxmMJHdVa5qRaiw+yZNLUzXFBXYjRCltKncAk2h2O+PRnjvgWeYqnzQ=,iv:vlkWwBLcxDGZRWyVRpm8DBQ0ZAPRsB6J/0j+Ucg1p9s=,tag:r/lXsVBncl3d+6kS389GoQ==,type:str]
postgres: postgres:
@ -37,8 +36,8 @@ sops:
aWxTNjVPTmZGMUJFK2ZCMTg1eHlEeTAK7EPDDmFXMGSe96L6vv7ZCrebLxITYHQ/ aWxTNjVPTmZGMUJFK2ZCMTg1eHlEeTAK7EPDDmFXMGSe96L6vv7ZCrebLxITYHQ/
TmMTLj6YN+PsdVv3AgKnOytgJll5/GFsmvR5HnDuHaEqDI71q+8nIQ== TmMTLj6YN+PsdVv3AgKnOytgJll5/GFsmvR5HnDuHaEqDI71q+8nIQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-04-11T21:12:13Z" lastmodified: "2025-04-11T22:28:55Z"
mac: ENC[AES256_GCM,data:4UJQIwojeJJ+OP2GQfvQUcYG89YeaxHsIvGy3NyTM7W0EhJXPOMfn3laXaiFARcXcenEvchnAoX3DcfNMWouXkzrlWJkESj9OTXBLYQxr0BR1VrrgLyG6L4fXE/+Nse35v8OT3KfdGP46QC3SGCHCValS26mWClBy49MnUj/vQ4=,iv:jIp9+oaYtfoGtuMIed1L9uNg6ShXspx4G3wTMJvZS/4=,tag:XhztQl7NP9rk57nFKlRGVg==,type:str] mac: ENC[AES256_GCM,data:ke+0iinfPZYw1oPucyLnVqUtCxO+0ft+eTyL/Vr/5ir7DiFR4dIcCxyIqlrZDIFYqUNLVjyqdKFIG40PzB19EC0fAYARCT7ndKX3EfrLIo/+gZtSM8a8ErggxxI7T7tpjofyAqfeFdUvg2DclPWSCWrdTnffXt4L3rEgIy9TWzE=,iv:53zyVCr9yOHVw8d/n0AVUHX257Xz1PNvu8+Ag4/h0m4=,tag:fTS8cYIw9fMPHrOun3S1Pg==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.9.4 version: 3.9.4