diff --git a/modules/default.nix b/modules/default.nix index a2e7ae3..4f48cda 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -22,6 +22,7 @@ ./services/data-share ./services/docker ./services/docker-mailserver + ./services/freshrss ./services/gitea ./services/grav ./services/haproxy @@ -48,7 +49,6 @@ ./services/syslog ./services/telegram-notifications ./services/tlp - ./services/ttrss-postgres ./services/virtualbox-guest ]; } diff --git a/modules/services/freshrss/default.nix b/modules/services/freshrss/default.nix new file mode 100644 index 0000000..469081e --- /dev/null +++ b/modules/services/freshrss/default.nix @@ -0,0 +1,108 @@ +{ config, inputs, lib, pkgs, ... }: +let + cfg = config.services.az-freshrss; +in +{ + options = { + services.az-freshrss.enable = lib.mkEnableOption "Enable FreshRSS."; + }; + + config = lib.mkIf cfg.enable { + + age.secrets.freshrss_db_pass = { + file = "${inputs.self}/scrts/freshrss_db_pass.age"; + mode = "600"; + owner = config.services.freshrss.user; + group = config.services.freshrss.user; + }; + age.secrets.freshrss_user_pass = { + file = "${inputs.self}/scrts/freshrss_user_pass.age"; + mode = "600"; + owner = config.services.freshrss.user; + group = config.services.freshrss.user; + }; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + security.acme = { + acceptTerms = true; + defaults.email = "admin+acme@zweili.ch"; + }; + + services = { + az-data-share.enable = true; + freshrss = { + enable = true; + baseUrl = "https://rss.zweili.org"; + database = { + passFile = config.age.secrets.freshrss_db_pass.path; + port = 3306; + type = "mysql"; + }; + defaultUser = "thedoctor"; + passwordFile = config.age.secrets.freshrss_user_pass.path; + virtualHost = "rss.zweili.org"; + }; + mysql = { + enable = true; + package = pkgs.mariadb; + ensureUsers = [ + { + name = "freshrss"; + ensurePermissions = { + "freshrss.*" = "ALL PRIVILEGES"; + }; + } + ]; + initialDatabases = [{ name = "freshrss"; }]; + settings = { + mysqld = { + innodb_file_per_table = 1; + innodb_buffer_pool_size = "2G"; + read_rnd_buffer_size = "4M"; + sort_buffer_size = "4M"; + }; + }; + }; + nginx = { + appendHttpConfig = '' + # Disable embedding as a frame + add_header X-Frame-Options DENY; + ''; + commonHttpConfig = '' + # Add HSTS header with preloading to HTTPS requests. + # Adding this header to HTTP requests is discouraged + map $scheme $hsts_header { + https "max-age=63072000; includeSubdomains; preload"; + } + add_header Strict-Transport-Security $hsts_header; + + # Enable CSP for your services. + #add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always; + + # Minimize information leaked to other domains + add_header 'Referrer-Policy' 'origin-when-cross-origin'; + + # Prevent injection of code in other mime types (XSS Attacks) + add_header X-Content-Type-Options nosniff; + + # Enable XSS protection of the browser. + # May be unnecessary when CSP is configured properly (see above) + add_header X-XSS-Protection "1; mode=block"; + + # This might create errors + proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict"; + ''; + recommendedOptimisation = true; + recommendedTlsSettings = true; + virtualHosts."rss.zweili.org" = { + enableACME = true; + forceSSL = true; + }; + }; + }; + }; +} + diff --git a/modules/services/haproxy/default.nix b/modules/services/haproxy/default.nix index e6a46b9..0924332 100644 --- a/modules/services/haproxy/default.nix +++ b/modules/services/haproxy/default.nix @@ -38,9 +38,8 @@ in redirect scheme https code 301 if { hdr(host) -i git.2li.ch } !{ ssl_fc } redirect scheme https code 301 if { hdr(host) -i heimdall.2li.ch } !{ ssl_fc } redirect scheme https code 301 if { hdr(host) -i nextcloud.2li.ch } !{ ssl_fc } - redirect scheme https code 301 if { hdr(host) -i ttrss.2li.ch } !{ ssl_fc } - redirect scheme https code 301 if { hdr(host) -i webmail.2li.ch } !{ ssl_fc } - redirect scheme https code 301 if { hdr(host) -i rss-bridge.2li.ch } !{ ssl_fc } + redirect scheme https code 301 if { hdr(host) -i rss.zweili.org } !{ ssl_fc } + redirect scheme https code 301 if { hdr(host) -i rss-bridge.zweili.org } !{ ssl_fc } redirect scheme https code 301 if { hdr(host) -i www.2li.ch } !{ ssl_fc } redirect scheme https code 301 if { hdr_dom(host) -i 2li.ch } !{ ssl_fc } @@ -57,8 +56,8 @@ in use_backend proxy if { req_ssl_sni -i heimdall.2li.ch } use_backend mail_server if { req_ssl_sni -i mail.zweili.org } use_backend nextcloud_server if { req_ssl_sni -i nextcloud.2li.ch } - use_backend ttrss_server if { req_ssl_sni -i ttrss.2li.ch } - use_backend ttrss_server if { req_ssl_sni -i rss-bridge.2li.ch } + use_backend rss_server if { req_ssl_sni -i rss.zweili.org } + use_backend rss_server if { req_ssl_sni -i rss-bridge.zweili.org } use_backend proxy if { req_ssl_sni -i www.2li.ch } use_backend proxy if { req_ssl_sni -i 2li.ch } @@ -71,7 +70,7 @@ in backend nextcloud_server mode tcp server server1 10.7.89.103:443 check - backend ttrss_server + backend rss_server mode tcp server server1 10.7.89.115:443 check backend mail_server diff --git a/modules/services/ttrss-postgres/default.nix b/modules/services/ttrss-postgres/default.nix deleted file mode 100644 index e0fa362..0000000 --- a/modules/services/ttrss-postgres/default.nix +++ /dev/null @@ -1,123 +0,0 @@ -{ config, inputs, lib, ... }: -let - cfg = config.services.az-ttrss-postgres; - ttrssEnvironment = { - TZ = "Europe/Zurich"; - TTRSS_DB_USER = "ttrss"; - TTRSS_DB_NAME = "ttrssdb"; - TTRSS_DB_HOST = "host.docker.internal"; - TTRSS_SELF_URL_PATH = "https://${cfg.domain}/tt-rss"; - TTRSS_SESSION_COOKIE_LIFETIME = "604800"; - TTRSS_PLUGINS = "af_comics, af_readability, auth_internal, hotkeys_swap_jk, nginx_xaccel"; - }; - # https://github.com/Nebucatnetzer/tt-rss-aarch64/pkgs/container/tt-rss-aarch64%2Fttrss-fpm-pgsql-static/versions - ttrssImage = "ghcr.io/nebucatnetzer/tt-rss-aarch64/ttrss-fpm-pgsql-static@sha256:917984de936a1b2d734d6b8a05ecbd741a46a05d5220c45ea0929da67c8738df"; - ttrssService = "${config.virtualisation.oci-containers.backend}-ttrss"; -in -{ - options = { - services.az-ttrss-postgres = { - enable = lib.mkEnableOption "Enable TTRSS"; - domain = lib.mkOption { - type = lib.types.str; - description = "The domain TTRSS is being run from."; - }; - }; - }; - - config = lib.mkIf cfg.enable { - age.secrets.ttrssEnv.file = "${inputs.self}/scrts/ttrss_env.age"; - - services = { - az-docker.enable = true; - az-nginx-fpm = { - enable = true; - dataDir = "/var/lib/ttrss/html"; - domain = cfg.domain; - }; - az-postgresql.enable = true; - nginx.virtualHosts."${cfg.domain}".locations = { - "/".extraConfig = '' - try_files $uri $uri/ = 404; - ''; - "/tt-rss/cache".extraConfig = '' - aio threads; - internal; - ''; - "/tt-rss/backups".extraConfig = '' - internal; - ''; - }; - postgresql = { - authentication = "host ttrssdb ttrss 172.16.0.0/12 scram-sha-256"; - ensureDatabases = [ "ttrssdb" ]; - ensureUsers = [{ - name = "ttrss"; - ensurePermissions = { - "DATABASE ttrssdb " = "ALL PRIVILEGES"; - }; - }]; - }; - }; - - virtualisation.oci-containers = { - backend = "docker"; - containers."ttrss" = { - image = ttrssImage; - autoStart = true; - environment = ttrssEnvironment; - environmentFiles = [ config.age.secrets.ttrssEnv.path ]; - ports = [ - "9000:9000" - ]; - volumes = [ - "/var/lib/ttrss/html:/var/www/html" - "/etc/localtime:/etc/localtime:ro" - ]; - extraOptions = [ - "--add-host=host.docker.internal:host-gateway" - "--log-opt=tag='ttrss'" - ]; - }; - containers."backup" = { - image = ttrssImage; - autoStart = true; - environment = ttrssEnvironment; - environmentFiles = [ config.age.secrets.ttrssEnv.path ]; - volumes = [ - "/var/lib/ttrss/html:/var/www/html" - "/var/lib/ttrss/backup:/backup" - "/etc/localtime:/etc/localtime:ro" - ]; - cmd = [ "/opt/tt-rss/dcron.sh" "-f" ]; - extraOptions = [ - "--add-host=host.docker.internal:host-gateway" - "--log-opt=tag='ttrss-backup'" - ]; - }; - containers."updater" = { - image = ttrssImage; - autoStart = true; - environment = ttrssEnvironment; - environmentFiles = [ config.age.secrets.ttrssEnv.path ]; - volumes = [ - "/var/lib/ttrss/html:/var/www/html" - "/etc/localtime:/etc/localtime:ro" - ]; - cmd = [ "/opt/tt-rss/updater.sh" ]; - dependsOn = [ "ttrss" ]; - extraOptions = [ - "--add-host=host.docker.internal:host-gateway" - "--log-opt=tag='ttrss-updater'" - ]; - }; - }; - - systemd.services.${ttrssService}.after = [ "nginx.service" ]; - systemd.services.postgresql.after = [ "${ttrssService}.service" ]; - }; -} - - - - diff --git a/scrts/freshrss_db_pass.age b/scrts/freshrss_db_pass.age new file mode 100644 index 0000000..0e26c3b --- /dev/null +++ b/scrts/freshrss_db_pass.age @@ -0,0 +1,37 @@ +age-encryption.org/v1 +-> ssh-rsa 7S8lxw +Tj0HzEBICajGuM776Pi19+VktT2/QXLlJKGwhPK7uUIIjXSB1C/DvOv6A1pltxjB +hQPkkvBdt6zCUbPBoqCF0obKm+PJxvYXspWlbUraY1i3H9mmq128SBnn1hn8O3nl +xMW3hBSxt64Hy1JqJQ9pg+hzvuNMYXXtaKeXmp7vkuqguL/6Cb4TcoZAWMkyp2Vg +iyhhkguHbCQ5AhS9parNRCvlCPWndI9ZfZ0UJwrsJrMVoScyzffEI+/ch8ghTv5L +WZLbTnyrtFwXpFeRUsDy5OH8xLsZ+SJbVd4ugJQqg1SJp88vDj9PhCjhnM4ymYfQ +wnCj795dv/mK393oBDRB7f6HBEfkvpqP1HUVgrnohftcMNsrGr3GCCnR6YoJENsF +4dhFDkUzoZO7ZV6g1P5S8FE3NA1MUOiAS4EevtFfWUEwazwVbOR7cTpeluLN6GhB +cFFrTLCoSgyR8//RkwXbfHg38nlJ6QZZCVoMMcFyLvUIImHjFTsFGaSpZVbtHhH+ + +-> ssh-rsa Ws+JZA +RjOZ8aZVXzZ2X7Xj5GkgZPoBInvV87zZ5j5P/RpZb0CdDWY33Pn48NCANPfJ+/Kj +EUAQktF8Is9RTMx9jlD3eitHS6Ef4RWdm0R4HEMPP9OtsFgKSj7vwedDUPhQo6rA +XR1ZB7K5Qj2c2F04IABAh2mXFr17EzicNLPao6bhh6QykHMaOibFbuomTdCT3I8E +bEtWVxr+KreiPMO2hph2dBQpcsGKteTn2bjfiXZF08FCar85zIwb9+TQM7anWFhJ +umEqFIqgc9J+nIS/KW4dyjNMm5t4s+DwL3/oyG6u7lEGpOCl+skrOmm/N9CNdpyr +MDEMpH8A660evBKgUYDdmS4zsIzs3jEYxZodF5MwZQIZbbZsnKK/gJFJBZzZlBU+ +XhB4p5HCnSVG6vxM9utUac0VOYHbd7+8zDHpld0rp7UEH3nS2E/1Vevbe6uiteSj +xVC9k+yvPPd/hF3qTkKmlq1W5xlNZYUadr50LrGJneC75HxT08yZ9euKv7vAUsc8 + +-> ssh-ed25519 skmU/w OiQbxJUvx2S/8RXREeiC/qa7XaKy8kDuHCV2WWBtQBQ +MYaPQRNRFUkPcYEkmoQRJiZEiqFJiADs066WbzHccN0 +-> ssh-ed25519 IjdJGQ 3bIQASlVHoNmor1rekf8NRgo4fJ7WvIqMw1zgiqZNQM +jNSi6IRovlg5tCnHnOIA3LQbHi8VO+9kbEhNSpewdIQ +-> ssh-ed25519 KXqA9w a0kw2i+TIqrL83h0NLEwVNZRlsLLufx++d51jHPHJC4 +tGzwEIiZo/290lT6E5If6VZP1cFaQJErU2fAWFFcU0U +-> ssh-ed25519 O6+Deg pOlPH/k7bDElSWFPwNUBNAbAj73oHkzMg4W534HVg1A +NvOUColy0xshhJ0L/5y8h3gyhTOqP4ifLNlaFTZE8nw +-> ssh-ed25519 NNd1zQ y7VAwdFlqUcQIkyUfE2GAHiQngEumFwyxHuglYVVYSg +8BuelHXeEVxn97BbgNsUBM7cwBfrpG10dQnSMLjR36w +-> a+hD-grease 8i{c;z; G _CI^; +0e6ZcLxVrqKcAA9N6pLRwVaZMbr5k6S09oz62js47dw +--- 2N/hOA3Vln9Y1hu/5YghOZSB+DccQtPedDC1MWeJLfY +GC~e' + &6 +P}(8(+)N' Ԑ͟+(LG[rE" \ No newline at end of file diff --git a/scrts/freshrss_user_pass.age b/scrts/freshrss_user_pass.age new file mode 100644 index 0000000..227493b --- /dev/null +++ b/scrts/freshrss_user_pass.age @@ -0,0 +1,35 @@ +age-encryption.org/v1 +-> ssh-rsa 7S8lxw +hzXk5l07rI7WEV1ntXuNUrp5w46rpoSV4OsKrE8uZ2LlK7Kf5QRcRk11uNTOQWI3 +fiuoJdQAH6Z2jdl3qmUHG1kidnRaT7wYfGVtXkBWihRV8uy6GZVd2D1cd2qIAGzp +FC1RnhQMoqBhLqormRVMqH63otwYYv0J+RrxS1pwyYaOyXWH7VnXpoxHgvkx54tp +MpZWKHEAgYPhgnSQCxGofK3WChMfhkpsATkExFCJflv8BYjXUUhFIUCK6wtFJQar +MoOTOzl6+v0n3i1+1YSychu+CEtqBbB9jBYd1t6MzKapoSTRPFcMGUEy2sYEcOKc +CaGxHFqxRDNBgHS11YFxy+H7H55CbaI2ILMY9Gg+cByVEHEB9v4HiPSfhozsPi04 +i/Rk5Xl7BVAH/YvMvsfFnoYjEXO4mNqQiIAZ/IfiryxOqaB+2MJdCHSezuOHa78h +Cjhn6r232fBbX/mr6ZsH4AeoxZB+cIFjqVVkZbxtsYZd1Olu/rCnKJ7AH/arpEfT + +-> ssh-rsa Ws+JZA +sbny3J/0ZtHRqXQ75NGKmdSayFm9+6uh+RiIzS/DxL56HV39QyQQwnfMEL5fPTy6 +XbQzQ0zi9SlgKPikVc3hVYU4wJXPOx0UF5fQUR5EDfMzRmEeBtmDgOZUXEyD02EL +IJUl+x58GpeHEQrLJhysg2QrEXpGDUwKqSPb/wkMPwxeqyv1o/ROTBSlvv2KtOZU +PKoc3fUWmVEUKnjGk3U6GfU96Um8DqE/625MbqrxB1rKXaufAYqJEHORqVUSJJGt +Ir9M7cXXF5NtGl9AfxDUkJOStEq9tIM70PKOZCsTd3yzhbEx1pRgZ3yUd7hrI+FG +RzpK004Bp88VETh1K89AiIPfl3Qsbr4EQpUoovSIA4uye/nBiv7fWcd16WHuzStq +u4T+G7KO79M3BtVh4+GtFSRJHUwoXpxpL1R1Ip/g3lk8tOdDBe/3N6TW/h/2PPbK +leBCnog5OseqfiFvE4yrP2J+a7bW/QMpoz23KNQJuUhlsB5bDe7ZEdFiSrdBhY8y + +-> ssh-ed25519 skmU/w vkFWaSxEAyY15OFlHRUCl9gD3zcioHhCtZU4Zt1ScxE +IfSElDAsWZ1I+KCP3aGpqlvngjoVMdr8KwY5wYa/AM4 +-> ssh-ed25519 IjdJGQ 7JCqyuBuHOEWP+BMHhkV+xILx1jCibkT3mK5+En/VHM +et1E8yWRltlFhQSZ9dNZTol6auGNDVFQnM8zRk8WX78 +-> ssh-ed25519 KXqA9w X7SbzoO3VoVKrLlxpLDRn6WOhYEqUT5BhsfCs2xL0h0 +j2eS8jfR4p4gEjoZISZ79j9p7O+nukQghv217G369qM +-> ssh-ed25519 O6+Deg MxP6gjy49oxPmCkQ3q/8HDJu9Jdvw6sZlw+yuP8S0GQ +SMRI5W8CpYSv36z9F5N50m0kQx6F1ymCIXp4efjBRaY +-> ssh-ed25519 NNd1zQ Eq/TBtKBZeUAu+rcyagW71v5UxvdiODRZiZKC08vCjw +jwp23eWcIH9AzpKx88iDW2OK+3FLo5jYwxtH7xbtjAM +-> f-grease +XqArEpZJ +--- otuHrontDMhvdXryLukT2JXB9man78BJeGZxAjpmdWw +k!`=J>DsM4.VbBkG?w`L \ No newline at end of file diff --git a/scrts/secrets.nix b/scrts/secrets.nix index a3ec732..3c87dcd 100644 --- a/scrts/secrets.nix +++ b/scrts/secrets.nix @@ -35,6 +35,8 @@ in { "dkim_2li.ch.age".publicKeys = defaultKeys ++ [ mail ]; "dkim_zweili.ch.age".publicKeys = defaultKeys ++ [ mail ]; + "freshrss_db_pass.age".publicKeys = defaultKeys ++ [ ttrss ]; + "freshrss_user_pass.age".publicKeys = defaultKeys ++ [ ttrss ]; "gitea_env.age".publicKeys = defaultKeys ++ [ git ]; "infomaniak_env.age".publicKeys = all; "nextcloud_env.age".publicKeys = defaultKeys ++ [ nextcloud ]; @@ -42,7 +44,6 @@ in "plex_claim.age".publicKeys = defaultKeys ++ [ plex ]; "restic.key.age".publicKeys = all; "telegram_notify_env.age".publicKeys = all; - "ttrss_env.age".publicKeys = defaultKeys ++ [ ttrss ]; "webdav_andreas.age".publicKeys = defaultKeys; } diff --git a/scrts/ttrss_env.age b/scrts/ttrss_env.age deleted file mode 100644 index 37d6d91..0000000 Binary files a/scrts/ttrss_env.age and /dev/null differ diff --git a/systems/ttrss/default.nix b/systems/ttrss/default.nix index 7b2fb85..f61fec3 100644 --- a/systems/ttrss/default.nix +++ b/systems/ttrss/default.nix @@ -1,4 +1,4 @@ -{ hostname }: { inputs, pkgs, ... }: +{ hostname }: { config, inputs, pkgs, ... }: { hardware = { az-raspi4-ethernet = { @@ -11,19 +11,15 @@ services = { az-nginx-proxy = { enable = true; - domain = "rss-bridge.2li.ch"; + domain = "rss-bridge.zweili.org"; port = 8082; }; - az-restic-client-server-postgres = { + az-restic-client-server-mysql = { enable = true; - path = "/var/lib/ttrss"; - tag = "tt-rss"; + path = config.services.freshrss.dataDir; time = "23:00"; }; az-rss-bridge.enable = true; - az-ttrss-postgres = { - enable = true; - domain = "ttrss.2li.ch"; - }; + az-freshrss.enable = true; }; }