diff --git a/hosts/freun-dev/glance.nix b/hosts/freun-dev/glance.nix
new file mode 100644
index 0000000..24ff43a
--- /dev/null
+++ b/hosts/freun-dev/glance.nix
@@ -0,0 +1,339 @@
+{ config, ... }:
+let
+ secrets = config.age.secrets;
+in
+{
+ services.tailscaledGlance = {
+ enable = true;
+ subdomain = "glance";
+ settings = {
+ server.port = 4114;
+ pages = [
+ {
+ name = "Home";
+ columns = [
+ {
+ size = "small";
+ widgets = [
+ {
+ type = "clock";
+ hour-format = "24h";
+ timezones = [
+ {
+ timezone = "Europe/Zurich";
+ label = "Zürich";
+ }
+ ];
+ }
+ {
+ type = "group";
+ title = "Weather";
+ widgets =
+ let
+ buildWeatherWidget =
+ { location, title }:
+ {
+ type = "weather";
+ hide-location = true;
+ hour-format = "24h";
+ units = "metric";
+ inherit location title;
+ };
+ in
+ builtins.map buildWeatherWidget [
+ {
+ title = "Espoo";
+ location = "Espoo, Finland";
+ }
+ {
+ title = "Mökki";
+ location = "Pellosniemi, Finland";
+ }
+ {
+ title = "Frankfurt";
+ location = "Frankfurt, Germany";
+ }
+ ];
+ }
+ {
+ type = "markets";
+ markets = [
+ {
+ symbol = "KOZ0.F";
+ name = "Kongsberg Gruppen";
+ }
+ {
+ symbol = "AMD";
+ name = "AMD";
+ }
+ ];
+ }
+ {
+ type = "group";
+ widgets = [
+ {
+ type = "rss";
+ title = "News";
+ limit = 10;
+ collapse-after = 3;
+ cache = "12h";
+ feeds = [
+ {
+ url = "https://yle.fi/rss/uutiset/paauutiset";
+ title = "Yle";
+ }
+ ];
+ }
+ {
+ type = "rss";
+ title = "Tech";
+ limit = 10;
+ collapse-after = 3;
+ cache = "12h";
+ feeds = [
+ {
+ url = "https://nixos.org/blog/announcements-rss.xml";
+ title = "NixOS";
+ }
+ {
+ url = "https://selfh.st/rss";
+ title = "selfh.st";
+ }
+ ];
+ }
+ {
+ type = "rss";
+ title = "Blogs";
+ limit = 10;
+ collapse-after = 3;
+ cache = "12h";
+ feeds = [
+ {
+ url = "https://samharris.substack.com/feed";
+ title = "Sam Harris";
+ }
+ ];
+ }
+ ];
+ }
+ {
+ type = "custom-api";
+ title = "Steam Specials";
+ cache = "12h";
+ url = "https://store.steampowered.com/api/featuredcategories?cc=fi";
+ template = ''
+
+ {{ range .JSON.Array "specials.items" }}
+ -
+ {{ .String "name" }}
+
+ - {{ div (.Int "final_price" | toFloat) 100 | printf "$%.2f" }}
+ {{ $discount := .Int "discount_percent" }}
+ - {{ $discount }}% off
+
+
+ {{ end }}
+
+ '';
+ }
+ ];
+ }
+ {
+ size = "full";
+ widgets = [
+ {
+ type = "group";
+ widgets = [
+ { type = "hacker-news"; }
+ { type = "lobsters"; }
+ ];
+ }
+ {
+ type = "videos";
+ channels = [
+ "UCXuqSBlHAE6Xw-yeJA0Tunw" # Linus Tech Tips
+ "UCshObcm-nLhbu8MY50EZ5Ng" # Benn Jordan
+ ];
+ }
+ {
+ type = "group";
+ widgets =
+ let
+ type = "reddit";
+ show-thumbnails = true;
+ app-auth = {
+ name = "Glance";
+ id = {
+ _secret = secrets."glance/reddit/app-id".path;
+ };
+ secret = {
+ _secret = secrets."glance/reddit/app-secret".path;
+ };
+ };
+ in
+ [
+ {
+ inherit type app-auth show-thumbnails;
+ subreddit = "nixos";
+ }
+ {
+ inherit type app-auth show-thumbnails;
+ subreddit = "technology";
+ }
+ {
+ inherit type app-auth show-thumbnails;
+ subreddit = "selfhosted";
+ }
+ ];
+ }
+ ];
+ }
+ {
+ size = "small";
+ widgets = [
+ {
+ type = "server-stats";
+ servers = [
+ {
+ type = "local";
+ name = "freun.dev";
+ }
+ ];
+ }
+ {
+ type = "group";
+ title = "Services";
+ widgets =
+ let
+ buildSite =
+ domain:
+ {
+ subdomain,
+ title,
+ alt-status-codes ? [ ],
+ }:
+ {
+ inherit title alt-status-codes;
+ url = "https://${subdomain}.${domain}";
+ };
+ buildMonitor =
+ { domain, sites }:
+ {
+ type = "monitor";
+ cache = "1m";
+ title = domain;
+ style = "compact";
+ sites = builtins.map (buildSite domain) sites;
+ };
+ in
+ builtins.map buildMonitor [
+ {
+ domain = "freun.dev";
+ sites = [
+ {
+ subdomain = "img";
+ title = "Immich";
+ }
+ {
+ subdomain = "pw";
+ title = "Vaultwarden";
+ }
+ {
+ subdomain = "social";
+ title = "Gotosocial";
+ }
+ {
+ subdomain = "graph";
+ title = "Grafana";
+ }
+ {
+ subdomain = "home";
+ title = "Home Assistant";
+ }
+ {
+ subdomain = "cook";
+ title = "Mealie";
+ }
+ {
+ subdomain = "sync";
+ title = "Syncthing";
+ }
+ {
+ subdomain = "bin";
+ title = "Hastebin";
+ alt-status-codes = [ 404 ];
+ }
+ {
+ subdomain = "ledger";
+ title = "Ledger";
+ }
+ {
+ subdomain = "note";
+ title = "Dnote";
+ }
+ {
+ subdomain = "trackmap";
+ title = "Trackmap";
+ }
+ {
+ subdomain = "fit";
+ title = "Workout Tracker";
+ }
+ {
+ subdomain = "stream";
+ title = "Owncast";
+ }
+ {
+ subdomain = "read";
+ title = "Readeck";
+ }
+ ];
+ }
+ {
+ domain = "alderaan.space";
+ sites = [
+ {
+ subdomain = "jelly";
+ title = "Jellyfin";
+ }
+ {
+ subdomain = "radarr";
+ title = "Radarr";
+ }
+ {
+ subdomain = "sonarr";
+ title = "Sonarr";
+ }
+ {
+ subdomain = "deluge";
+ title = "qBittorrent";
+ }
+ {
+ subdomain = "lidarr";
+ title = "Lidarr";
+ }
+ {
+ subdomain = "bazarr";
+ title = "Bazarr";
+ }
+ {
+ subdomain = "req";
+ title = "Jellyseer";
+ }
+ ];
+ }
+ ];
+ }
+ {
+ type = "dns-stats";
+ service = "adguard";
+ url = "http://localhost:3006";
+ }
+ ];
+ }
+ ];
+ }
+ ];
+ };
+ };
+}
diff --git a/hosts/freun-dev/secrets.nix b/hosts/freun-dev/secrets.nix
index 1874cc4..b1a3019 100644
--- a/hosts/freun-dev/secrets.nix
+++ b/hosts/freun-dev/secrets.nix
@@ -25,6 +25,8 @@
"mosquitto/mokkimaatti"
"gitlab-runner/default"
"gitlab-runner/docker"
+ "glance/reddit/app-id"
+ "glance/reddit/app-secret"
"hetzner"
]
)
diff --git a/hosts/freun-dev/services.nix b/hosts/freun-dev/services.nix
index d0f87d0..c5fc6cf 100644
--- a/hosts/freun-dev/services.nix
+++ b/hosts/freun-dev/services.nix
@@ -18,6 +18,9 @@ let
secrets = config.age.secrets;
in
{
+ imports = [
+ ./glance.nix
+ ];
virtualisation.podman.enable = true;
virtualisation.oci-containers.backend = "podman";
security.acme.defaults.environmentFile = secrets.hetzner.path;
diff --git a/modules/services/default.nix b/modules/services/default.nix
index 16ddd5d..ae41162 100644
--- a/modules/services/default.nix
+++ b/modules/services/default.nix
@@ -25,5 +25,6 @@
./home-assistant.nix
./weechat.nix
./hledger-web.nix
+ ./glance.nix
];
}
diff --git a/modules/services/glance.nix b/modules/services/glance.nix
new file mode 100644
index 0000000..4d0ee95
--- /dev/null
+++ b/modules/services/glance.nix
@@ -0,0 +1,45 @@
+{ config, lib, ... }:
+let
+ cfg = config.services.tailscaledGlance;
+ fqdn = "${cfg.subdomain}.${config.networking.domain}";
+ acme = config.security.acme;
+in
+{
+ imports = [
+ (lib.mkAliasOptionModule
+ [ "services" "tailscaledGlance" "settings" ]
+ [ "services" "glance" "settings" ]
+ )
+ ];
+
+ options.services.tailscaledGlance = {
+ enable = lib.mkEnableOption "Enable tailscaled glance";
+ subdomain = lib.mkOption {
+ type = lib.types.str;
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ services.tailscale.enable = true;
+ modules.firewall.interfaces.${config.services.tailscale.interfaceName} = [ "dns" ];
+
+ systemd.services.glance.serviceConfig.LoadCredential = [
+ "fullchain.pem:${acme.certs.${fqdn}.directory}/fullchain.pem"
+ "key.pem:${acme.certs.${fqdn}.directory}/key.pem"
+ ];
+
+ services.glance = {
+ enable = cfg.enable;
+ };
+
+ systemd.services.glance = {
+ requires = [ "tailscaled.service" ];
+ after = [ "tailscaled.service" ];
+ };
+
+ services.webserver.vHosts.${fqdn} = {
+ tailscaleAuth = true;
+ locations."/".proxyPort = cfg.settings.server.port;
+ };
+ };
+}
diff --git a/secrets/glance/reddit/app-id.age b/secrets/glance/reddit/app-id.age
new file mode 100644
index 0000000..3e9608b
--- /dev/null
+++ b/secrets/glance/reddit/app-id.age
@@ -0,0 +1,9 @@
+age-encryption.org/v1
+-> ssh-ed25519 osOCZA Y7ieflWxf67Jik747FnOu5aKcDjh6hd8OWE88oX7gWc
+aQavFEvcW30cer2DutpkfSkKk1NqGzPiP2bYL2MCv+Q
+-> ssh-ed25519 DFiohQ J5HO9n4KTQ6cSBGHxrBHORvmYp4WYJZiATekbZvhuEU
+QGAhwn6P5ByiNY8bMUI07hHvnA8diVI56Vg+6kVEJb0
+-> ssh-ed25519 PT7ffg RpcpdzFtX5VyodX3lXKvjMRxMlpasRqqpjqCacXDcy4
+VJQuB8YfhB0DQ4TjwzBhdtl35eyFVLLW8O87mCuH828
+--- qJnfQgOyw0CTBhXNSyIw3O33av2cjPxTntLsOW/bevA
+-
8^$-I4EJ5R ssh-ed25519 osOCZA y1DrZWN4jrO6xg7TkFqrjTT/k4L49IAZVf/NLw3jMiM
+BB+Aq/80SFQpLJfZxRKFPBw9ylHb+Y6LLuZQAqG3WdQ
+-> ssh-ed25519 DFiohQ jPPM8ATBvlXn0F/9pDCsZB15yW+af0b2FQqV2gI8YyQ
+8yJjKEvEGKDwtvBWP/yjiDql+HA6l5q+RfEgP8cAIGM
+-> ssh-ed25519 PT7ffg +R5KlrnH2gGW2Qc3V+RgYKtAXerbRB5j898+b41/VAU
+7Lq3GE9CMGeXAmsf9WgSiJf/o+HyssF4xz94JNjbEgM
+--- k2xNMbWr5tntlbOOYLbt6DsWsW2mT/P3pg3IgXYcM58
+|Ѱm7yzRY+q1>Y?hH֞|7̃
+Nz
\ No newline at end of file
diff --git a/secrets/secrets.nix b/secrets/secrets.nix
index bada010..d18d5c6 100644
--- a/secrets/secrets.nix
+++ b/secrets/secrets.nix
@@ -37,4 +37,6 @@ in
];
"hledger-basic-auth.age".publicKeys = users ++ [ freun-dev ];
"wpa_supplicant.age".publicKeys = users ++ [ turny ];
+ "glance/reddit/app-id.age".publicKeys = users ++ [ freun-dev ];
+ "glance/reddit/app-secret.age".publicKeys = users ++ [ freun-dev ];
}