diff --git a/modules/server/containers/apps/homepage.nix b/modules/server/containers/apps/homepage.nix index f6618f0..2429901 100644 --- a/modules/server/containers/apps/homepage.nix +++ b/modules/server/containers/apps/homepage.nix @@ -1,293 +1,350 @@ -{ config, containerCfg, pkgs, lib, builder, name,... }: +{ config, containerCfg, pkgs, lib, builder, name, ... }: let - version = "latest"; - serverCfg = config.syscfg.server; - mediaCfg = config.syscfg.media; - backgroundImage = if mediaCfg.banner.png != null then mediaCfg.banner.png else mediaCfg.bg; - backgroundFileName = builtins.baseNameOf (toString backgroundImage); - backgroundMount = "/app/public/media/${backgroundFileName}"; + version = "latest"; + serverCfg = config.syscfg.server; + mediaCfg = config.syscfg.media; + homepageExtra = containerCfg.extra or {}; + backgroundImage = if mediaCfg.banner.png != null then mediaCfg.banner.png else mediaCfg.bg; + backgroundFileName = builtins.baseNameOf (toString backgroundImage); + backgroundMount = "/app/public/media/${backgroundFileName}"; + latitude = + if homepageExtra ? latitude then homepageExtra.latitude + else if homepageExtra ? lat then homepageExtra.lat + else 47.3769; + longitude = + if homepageExtra ? longitude then homepageExtra.longitude + else if homepageExtra ? lon then homepageExtra.lon + else 8.5417; + extraBookmarks = homepageExtra.bookmarks or []; + extraServices = homepageExtra.services or []; - settings = pkgs.writers.writeYAML "settings.yaml" { - title = "Home"; - description = ""; - startUrl = "https://${containerCfg.subdomain}.${serverCfg.domain}"; - background = { - image = "/media/${backgroundFileName}"; - blur = "xs"; # "", sm, md, xl,... - # saturate = ""; - brightness = 50; - # opacity = 40; - }; - cardBlur = "md"; - # favicon = ""; - theme = "dark"; - color = "slate"; - fullWidth = true; - useEqualHeights = true; - pwa = { + settings = pkgs.writers.writeYAML "settings.yaml" { + title = "Home"; + description = ""; + startUrl = "https://${containerCfg.subdomain}.${serverCfg.domain}"; + background = { + image = "/media/${backgroundFileName}"; + brightness = 50; + }; + cardBlur = "md"; + favicon = config.syscfg.media.logo.ico; + theme = "dark"; + color = "slate"; + fullWidth = true; + useEqualHeights = true; + pwa = { }; + layout = { + Admin = { + style = "row"; + columns = 4; + }; + }; + providers = { + finnhub = "{{HOMEPAGE_VAR_FINNHUB}}"; + }; + headerStyle = "clean"; + hideVersion = true; + disableUpdateCheck = true; + showStats = false; + statusStyle = "dot"; + hideErrors = true; + }; - }; - layout = { - Admin = { - style = "row"; - columns = 4; + widgets = pkgs.writers.writeYAML "widgets.yaml" [ + { openmeteo = { + latitude = toString latitude; + longitude = toString longitude; + timezone = config.time.timeZone; + units = "metric"; + cache = "15"; + }; + } + { search = { + provider = "custom"; + focus = true; + showSearchSuggestions = true; + target = "_blank"; + } // (lib.optionalAttrs (serverCfg.containers ? searxng) { + url = "https://${serverCfg.containers.searxng.subdomain}.${serverCfg.domain}/search?q="; + suggestionUrl = "https://${serverCfg.containers.searxng.subdomain}.${serverCfg.domain}/autocompleter?q="; + }); + } + { stocks = { + provider = "finnhub"; + color = true; + cache = 15; + watchlist = homepageExtra.stocks or []; + }; + } + ]; + + bookmarks = pkgs.writers.writeYAML "bookmarks.yaml" (extraBookmarks); + + services = pkgs.writers.writeYAML "services.yaml" ([ + { Media = lib.flatten [ + (lib.optional (serverCfg.containers ? jellyfin) { + Jellyfin = { + icon = "jellyfin.png"; + href = "https://${serverCfg.containers.jellyfin.subdomain}.${serverCfg.domain}"; + widget = { + type = "jellyfin"; + url = "http://jellyfin-server:8096"; + key = "{{HOMEPAGE_VAR_JELLYFIN_API}}"; }; - }; - providers = { - finnhub = "{{HOMEPAGE_VAR_FINNHUB}}"; - }; - headerStyle = "clean"; - hideVersion = true; - disableUpdateCheck = true; - showStats = false; - statusStyle = "dot"; - hideErrors = true; - }; - widgets = pkgs.writers.writeYAML "widgets.yaml" [ - {openmeteo = { - latitude = "47.3769"; - longitude = "8.5417"; - timezone = "Europe/Zurich"; - units = "metric"; - cache = "15"; - };} - {search = { - provider = "custom"; - focus = true; - showSearchSuggestions = true; - target = "_blank"; - } // (lib.optionalAttrs (serverCfg.containers?searxng) { - url = "https://${serverCfg.containers.searxng.subdomain}.${serverCfg.domain}/search?q="; - suggestionUrl = "https://${serverCfg.containers.searxng.subdomain}.${serverCfg.domain}/autocompleter?q="; - }); - } - {stocks = { - provider = "finnhub"; - color = true; - cache = 15; - watchlist = containerCfg.extra.stocks or []; - - };} - ]; - - bookmarks = pkgs.writers.writeYAML "bookmarks.yaml" [ - - ]; - services = pkgs.writers.writeYAML "services.yaml" [ - {Media = lib.flatten [ - (lib.optional (serverCfg.containers?jellyfin) { - Jellyfin={ - icon = "jellyfin.png"; - href = "https://${serverCfg.containers.jellyfin.subdomain}.${serverCfg.domain}"; - widget = { - type="jellyfin"; - url = "http://jellyfin-server:8096"; - key = "{{HOMEPAGE_VAR_JELLYFIN_API}}"; - }; - }; - }) - (lib.optional (serverCfg.containers?invidious) { - Invidious={ - icon = "invidious.png"; - href = "https://${serverCfg.containers.invidious.subdomain}.${serverCfg.domain}"; - }; - }) - (lib.optional (serverCfg.containers?miniflux) { - Miniflux={ - icon = "miniflux.png"; - href = "https://${serverCfg.containers.miniflux.subdomain}.${serverCfg.domain}"; - widget = { - type="miniflux"; - url = "http://miniflux-server"; - key = "{{HOMEPAGE_VAR_MINIFLUX_API}}"; - }; - }; - }) - ];} - {Cloud = lib.flatten [ - (lib.optional (serverCfg.containers?nextcloud) { - Nextcloud={ - icon = "nextcloud.png"; - href = "https://${serverCfg.containers.nextcloud.subdomain}.${serverCfg.domain}"; - widget = { - type="nextcloud"; - url = "http://nextcloud-server:80"; - key = "{{HOMEPAGE_VAR_NEXTCLOUD_API}}"; - }; - }; - }) - (lib.optional (serverCfg.containers?ethercalc) { - Ethercalc={ - icon = "ethercalc.png"; - href = "https://${serverCfg.containers.ethercalc.subdomain}.${serverCfg.domain}"; - }; - }) - (lib.optional (serverCfg.containers?etherpad) { - Etherpad={ - icon = "etherpad.png"; - href = "https://${serverCfg.containers.etherpad.subdomain}.${serverCfg.domain}"; - }; - }) - (lib.optional (serverCfg.containers?immich) { - immich={ - icon = "immich.png"; - href = "https://${serverCfg.containers.immich.subdomain}.${serverCfg.domain}"; - widget = { - type="immich"; - url = "http://immich-server:80"; - key = "{{HOMEPAGE_VAR_IMMICH_API}}"; - version = "2"; - }; - }; - }) - ];} - {Dev = lib.flatten [ - (lib.optional (serverCfg.containers?gitea) { - Gitea={ - icon = "gitea.png"; - href = "https://${serverCfg.containers.gitea.subdomain}.${serverCfg.domain}"; - # widget = { - # type="gitea"; - # url = "http://gitea-server:8080"; - # key = "{{HOMEPAGE_VAR_GITEA_API}}"; - # }; - }; - }) - ];} - {Admin = #lib.flatten [ - #({permissions.groups = ["admin"];}) - #({services = - lib.flatten [ - (lib.optional (serverCfg.containers?traefik) { - Traefik={ - icon = "traefik.png"; - href = "https://${serverCfg.containers.traefik.subdomain}.${serverCfg.domain}"; - widget = { - type = "traefik"; - url = "http://traefik-server:8080"; - }; - }; - }) - (lib.optional (serverCfg.containers?authentik) { - Authentik={ - icon = "authentik.png"; - href = "https://${serverCfg.containers.authentik.subdomain}.${serverCfg.domain}"; - widget = { - type = "authentik"; - url = "http://authentik-server:9000"; - key = "{{HOMEPAGE_VAR_AUTHENTIK_API}}"; - version = "2"; - }; - }; - }) - (lib.optional (serverCfg.containers?umami) { - Umami={ - icon = "umami.png"; - href = "https://${serverCfg.containers.umami.subdomain}.${serverCfg.domain}"; - }; - }) - (lib.optional (serverCfg.containers?influx) { - Influx={ - icon = "grafana.png"; - href = "https://${serverCfg.containers.influx.subdomain}.${serverCfg.domain}"; - }; - }) - (lib.optional (serverCfg.containers?handbrake) { - Handbrake={ - icon = "handbrake.png"; - href = "https://${serverCfg.containers.handbrake.subdomain}.${serverCfg.domain}"; - }; - }) - (lib.optional (serverCfg.containers?transmission) { - Transmission={ - icon = "transmission.png"; - href = "https://${serverCfg.containers.transmission.subdomain}.${serverCfg.domain}/transmission"; - widget = { - type = "transmission"; - url = "http://transmission-server:9091"; - rpcUrl = "/transmission/"; - }; - }; - }) - (lib.optional (serverCfg.containers?servarr) ( - let - modules = serverCfg.containers.servarr.extra.modules or ["prowlarr" "sonarr" "radarr" "flaresolverr" ]; - in + }; + }) + (lib.optional (serverCfg.containers ? invidious) { + Invidious = { + icon = "invidious.png"; + href = "https://${serverCfg.containers.invidious.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? calibre) { + Calibre = { + icon = "calibre.png"; + href = "https://${serverCfg.containers.calibre.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? freshrss) { + FreshRSS = { + icon = "freshrss.png"; + href = "https://${serverCfg.containers.freshrss.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? miniflux) { + Miniflux = { + icon = "miniflux.png"; + href = "https://${serverCfg.containers.miniflux.subdomain}.${serverCfg.domain}"; + widget = { + type = "miniflux"; + url = "http://miniflux-server"; + key = "{{HOMEPAGE_VAR_MINIFLUX_API}}"; + }; + }; + }) + (lib.optional (serverCfg.containers ? suwayomi) { + Suwayomi = { + icon = "suwayomi.png"; + href = "https://${serverCfg.containers.suwayomi.subdomain}.${serverCfg.domain}"; + }; + }) + ]; + } + { Cloud = lib.flatten [ + (lib.optional (serverCfg.containers ? nextcloud) { + Nextcloud = { + icon = "nextcloud.png"; + href = "https://${serverCfg.containers.nextcloud.subdomain}.${serverCfg.domain}"; + widget = { + type = "nextcloud"; + url = "http://nextcloud-server:80"; + key = "{{HOMEPAGE_VAR_NEXTCLOUD_API}}"; + }; + }; + }) + (lib.optional (serverCfg.containers ? ethercalc) { + Ethercalc = { + icon = "ethercalc.png"; + href = "https://${serverCfg.containers.ethercalc.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? etherpad) { + Etherpad = { + icon = "etherpad.png"; + href = "https://${serverCfg.containers.etherpad.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? collabora && false) { + Collabora = { + icon = "microsoft-office.png"; + href = "https://${serverCfg.containers.collabora.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? immich) { + Immich = { + icon = "immich.png"; + href = "https://${serverCfg.containers.immich.subdomain}.${serverCfg.domain}"; + widget = { + type = "immich"; + url = "http://immich-server:80"; + key = "{{HOMEPAGE_VAR_IMMICH_API}}"; + version = "2"; + }; + }; + }) + ]; + } + { Home = lib.flatten [ + (lib.optional (serverCfg.containers ? homeassistant) { + "Home Assistant" = { + icon = "home-assistant.png"; + href = "https://${serverCfg.containers.homeassistant.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? openhab) { + openHAB = { + icon = "openhab.png"; + href = "https://${serverCfg.containers.openhab.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? frigate) { + Frigate = { + icon = "frigate.png"; + href = "https://${serverCfg.containers.frigate.subdomain}.${serverCfg.domain}"; + }; + }) + ]; + } + { Dev = lib.flatten [ + (lib.optional (serverCfg.containers ? gitea) { + Gitea = { + icon = "gitea.png"; + href = "https://${serverCfg.containers.gitea.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? trmnl) { + TRMNL = { + icon = "terminal.png"; + href = "https://${serverCfg.containers.trmnl.subdomain}.${serverCfg.domain}"; + }; + }) + ]; + } + { Admin = lib.flatten [ + (lib.optional (serverCfg.containers ? traefik) { + Traefik = { + icon = "traefik.png"; + href = "https://${serverCfg.containers.traefik.subdomain}.${serverCfg.domain}"; + widget = { + type = "traefik"; + url = "http://traefik-server:8080"; + }; + }; + }) + (lib.optional (serverCfg.containers ? authentik) { + Authentik = { + icon = "authentik.png"; + href = "https://${serverCfg.containers.authentik.subdomain}.${serverCfg.domain}"; + widget = { + type = "authentik"; + url = "http://authentik-server:9000"; + key = "{{HOMEPAGE_VAR_AUTHENTIK_API}}"; + version = "2"; + }; + }; + }) + (lib.optional (serverCfg.containers ? umami) { + Umami = { + icon = "umami.png"; + href = "https://${serverCfg.containers.umami.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? influx) { + Influx = { + icon = "grafana.png"; + href = "https://${serverCfg.containers.influx.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? handbrake) { + Handbrake = { + icon = "handbrake.png"; + href = "https://${serverCfg.containers.handbrake.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? transmission) { + Transmission = { + icon = "transmission.png"; + href = "https://${serverCfg.containers.transmission.subdomain}.${serverCfg.domain}/transmission"; + widget = { + type = "transmission"; + url = "http://transmission-server:9091"; + rpcUrl = "/transmission/"; + }; + }; + }) + (lib.optional (serverCfg.containers ? selfmark) { + Selfmark = { + icon = "link.png"; + href = "https://${serverCfg.containers.selfmark.subdomain}.${serverCfg.domain}"; + }; + }) + (lib.optional (serverCfg.containers ? servarr) ( + let + modules = serverCfg.containers.servarr.extra.modules or [ "prowlarr" "sonarr" "radarr" "flaresolverr" ]; + in (lib.optional (builtins.elem "sonarr" modules) { - Sonarr={ - icon = "sonarr.png"; - href = "https://${serverCfg.containers.servarr.subdomain}.${serverCfg.domain}/sonarr"; - widget = { - type = "sonarr"; - url = "http://servarr-sonarr:8989"; - key = "{{HOMEPAGE_VAR_SONARR_API}}"; - - }; - }; - }) ++ (lib.optional (builtins.elem "radarr" modules) { - Radarr={ - icon = "radarr.png"; - href = "https://${serverCfg.containers.servarr.subdomain}.${serverCfg.domain}/radarr"; - widget = { - type = "radarr"; - url = "http://servarr-radarr:8989"; - key = "{{HOMEPAGE_VAR_RADARR_API}}"; - - }; - }; - }) ++ (lib.optional (builtins.elem "lidarr" modules) { - Lidarr={ - icon = "lidarr.png"; - href = "https://${serverCfg.containers.servarr.subdomain}.${serverCfg.domain}/lidarr"; - widget = { - type = "lidarr"; - url = "http://servarr-lidarr:8989"; - key = "{{HOMEPAGE_VAR_LIDARR_API}}"; - - }; - }; - }) ++ (lib.optional (builtins.elem "prowlarr" modules) { - Prowlarr={ - icon = "prowlarr.png"; - href = "https://${serverCfg.containers.servarr.subdomain}.${serverCfg.domain}/prowlarr"; - widget = { - type = "prowlarr"; - url = "http://servarr-prowlarr:8989"; - key = "{{HOMEPAGE_VAR_PROWLARR_API}}"; - - }; + Sonarr = { + icon = "sonarr.png"; + href = "https://${serverCfg.containers.servarr.subdomain}.${serverCfg.domain}/sonarr"; + widget = { + type = "sonarr"; + url = "http://servarr-sonarr:8989"; + key = "{{HOMEPAGE_VAR_SONARR_API}}"; }; + }; }) - # Bazarr - - )) - ];}#)];} - ]; + ++ (lib.optional (builtins.elem "radarr" modules) { + Radarr = { + icon = "radarr.png"; + href = "https://${serverCfg.containers.servarr.subdomain}.${serverCfg.domain}/radarr"; + widget = { + type = "radarr"; + url = "http://servarr-radarr:8989"; + key = "{{HOMEPAGE_VAR_RADARR_API}}"; + }; + }; + }) + ++ (lib.optional (builtins.elem "lidarr" modules) { + Lidarr = { + icon = "lidarr.png"; + href = "https://${serverCfg.containers.servarr.subdomain}.${serverCfg.domain}/lidarr"; + widget = { + type = "lidarr"; + url = "http://servarr-lidarr:8989"; + key = "{{HOMEPAGE_VAR_LIDARR_API}}"; + }; + }; + }) + ++ (lib.optional (builtins.elem "prowlarr" modules) { + Prowlarr = { + icon = "prowlarr.png"; + href = "https://${serverCfg.containers.servarr.subdomain}.${serverCfg.domain}/prowlarr"; + widget = { + type = "prowlarr"; + url = "http://servarr-prowlarr:8989"; + key = "{{HOMEPAGE_VAR_PROWLARR_API}}"; + }; + }; + }) + )) + ]; + } + ] ++ extraServices); in { - runtime = { - containers = { - server = builder.mkContainer { - subdomain = containerCfg.subdomain; - image = "ghcr.io/gethomepage/homepage:${version}"; - port = 3000; - extraEnv = { - HOMEPAGE_VAR_TITLE="${serverCfg.domain}"; - HOMEPAGE_ALLOWED_HOSTS = "${containerCfg.subdomain}.${serverCfg.domain},${builder.host}"; - }; - extraLabels = { + runtime = { + containers = { + server = builder.mkContainer { + subdomain = containerCfg.subdomain; + image = "ghcr.io/gethomepage/homepage:${version}"; + port = 3000; + extraEnv = { + HOMEPAGE_VAR_TITLE = "${serverCfg.domain}"; + HOMEPAGE_ALLOWED_HOSTS = "${containerCfg.subdomain}.${serverCfg.domain},${builder.host}"; + }; + extraLabels = { "traefik.http.routers.${containerCfg.subdomain}.service" = "${containerCfg.subdomain}"; - }; - overrides = { - environmentFiles = [ config.sops.secrets."CUSTOM".path ]; - volumes = [ - "${settings}:/app/config/settings.yaml:ro" - "${services}:/app/config/services.yaml:ro" - "${widgets}:/app/config/widgets.yaml:ro" - "${bookmarks}:/app/config/bookmarks.yaml:ro" - "${backgroundImage}:${backgroundMount}:ro" - ]; - }; - }; + }; + overrides = { + environmentFiles = [ config.sops.secrets."CUSTOM".path ]; + volumes = [ + "${settings}:/app/config/settings.yaml:ro" + "${services}:/app/config/services.yaml:ro" + "${widgets}:/app/config/widgets.yaml:ro" + "${bookmarks}:/app/config/bookmarks.yaml:ro" + "${backgroundImage}:${backgroundMount}:ro" + ]; + }; }; }; + }; }