Compare commits

..
Author SHA1 Message Date
marthsincemelee 2f88d5567e feat: MC widget and Foundry Description 2026-10-05 14:20:07 +02:00
marthsincemeleeandClaude Opus 5.5 b725bb37c2 feat(homepage): add Gaming section with FoundryVTT servers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 14:14:00 +02:00
finn.markwitz f7196c0c86 chore: Flake Update 2026-10-04 18:39:52 +02:00
finn.markwitz 20c2b43ae5 Merge pull request 'Feat/hermes webpage port' (#17) from feat/hermes-webpage-port into main
Reviewed-on: #17
2026-10-04 18:37:36 +02:00
finn.markwitz eecb7fa2b2 Merge pull request 'Feat/jupiter seerr rename' (#16) from feat/jupiter-seerr-rename into feat/hermes-webpage-port
Reviewed-on: #16
2026-10-04 18:36:35 +02:00
finn.markwitzandClaude Sonnet 5 84ada68069 fix(mibook): disable hermes-agent's built-in self-update GitHub polling
Its self-updater was independently polling GitHub for the same repo the
flake input tracks, and stacked with a runaway crash-restart loop this
exhausted the GitHub rate limit, causing unrelated flake fetches to 429.
The Nix flake input is already the source of truth for hermes's version.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F9ge2kVMD55sLJExx3v2G3
2026-09-29 17:36:18 +02:00
finn.markwitz 07a1d8ee62 feat(mibook): open port 47823 for hermes ad-hoc webpage hosting
Distinct from the existing 9119 dashboard port — this lets the agent
serve one-off pages to devices on the local network.
2026-09-26 08:15:58 +02:00
finn.markwitzandClaude Sonnet 5 565ec2bf39 feat(jupiter): rename jellyseerr profile to seerr
Jellyseerr was rebranded upstream to Seerr (seerr-team/seerr), and
nixpkgs now aliases services.jellyseerr to services.seerr with an
identical state directory, so this is a same-data rename. Also fixes
systemd.services.jellyseerr.after, which was a silent no-op since the
underlying unit has always been named seerr.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019MLWL7mWHCV6UGfzmhnfqN
2026-09-22 11:51:02 +02:00
10 changed files with 229 additions and 36 deletions
@@ -0,0 +1,164 @@
# Homepage Widgets Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Add a `my.homepage.widgets` NixOS option so widgets can be declared in the homepage module and contributed from other modules, mirroring how `my.homepage.services` works today.
**Architecture:** Add a `my.homepage.widgets` option (typed `listOf attrs` since widget shapes vary by type) to the homepage module, import a `manual-widgets.nix` for ad-hoc definitions, merge both and pass to `services.homepage-dashboard.widgets`. Add starter widgets in `machines/jupiter/environments.nix` to confirm the wiring works end-to-end.
**Tech Stack:** Nix, NixOS module system, gethomepage.dev (`services.homepage-dashboard`)
---
## File Map
| Action | File | Responsibility |
|--------|------|----------------|
| Modify | `modules/environments/homepage/default.nix` | Add `my.homepage.widgets` option + wire to dashboard |
| Create | `modules/environments/homepage/manual-widgets.nix` | Empty list for ad-hoc widgets (parallel to `manual-services.nix`) |
| Modify | `machines/jupiter/environments.nix` | Declare starter widgets to verify the feature end-to-end |
---
### Task 1: Add `my.homepage.widgets` option to the homepage module
**Files:**
- Modify: `modules/environments/homepage/default.nix`
- Create: `modules/environments/homepage/manual-widgets.nix`
- [ ] **Step 1: Create `manual-widgets.nix`** — empty list, same pattern as `manual-services.nix`
```nix
# modules/environments/homepage/manual-widgets.nix
[ ]
```
- [ ] **Step 2: Add `manualWidgets` import in the `let` block of `default.nix`**
Current `let` block (lines 7–42) ends with `homepageServices`. Add one line after `manualServices`:
```nix
manualServices = import ./manual-services.nix;
manualWidgets = import ./manual-widgets.nix;
```
- [ ] **Step 3: Add the `my.homepage.widgets` option**
After the closing brace of `options.my.homepage.services` (line 80), add:
```nix
options.my.homepage.widgets = with lib; mkOption {
type = types.listOf types.attrs;
default = [ ];
description = "Widget definitions passed directly to services.homepage-dashboard.widgets. Each entry is an attrset like { resources = { cpu = true; memory = true; }; }.";
};
```
- [ ] **Step 4: Wire widgets to the dashboard in the `config` block**
The `config` block currently sets `services = homepageServices ++ manualServices;`. Add `widgets`:
```nix
config = lib.mkIf cfg.enable {
services.homepage-dashboard = {
enable = true;
listenPort = dashboardPort;
allowedHosts = "${dashboardHost}:${toString dashboardPort},localhost:${toString dashboardPort},127.0.0.1:${toString dashboardPort},jupiter.solar.internal:${toString dashboardPort}";
bookmarks = import ./bookmarks.nix;
services = homepageServices ++ manualServices;
widgets = config.my.homepage.widgets ++ manualWidgets;
};
# ... rest of config unchanged
};
```
- [ ] **Step 5: Build to check for eval errors (no switch yet)**
```bash
nixos-rebuild build --flake /Users/finnmarkwitz/development/nixos#jupiter 2>&1 | tail -20
```
Expected: build succeeds with no errors (widgets list is empty, so no visible change yet).
- [ ] **Step 6: Commit**
```bash
cd /Users/finnmarkwitz/development/nixos
git add modules/environments/homepage/default.nix modules/environments/homepage/manual-widgets.nix
git commit -m "feat: add my.homepage.widgets option to homepage module"
```
---
### Task 2: Add starter widgets in `environments.nix`
**Files:**
- Modify: `machines/jupiter/environments.nix`
- [ ] **Step 1: Add `my.homepage.widgets` to `environments.nix`**
Add the following after the `my.profiles` block (e.g. after line 39, before the `my.hardware` block):
```nix
my.homepage.widgets = [
{
search = {
provider = "google";
target = "_blank";
};
}
{
resources = {
cpu = true;
memory = true;
disk = "/";
cacheInterval = 5000;
};
}
{
datetime = {
text_size = "xl";
format = {
timeStyle = "short";
dateStyle = "short";
hour12 = false;
};
};
}
];
```
- [ ] **Step 2: Build to confirm eval**
```bash
nixos-rebuild build --flake /Users/finnmarkwitz/development/nixos#jupiter 2>&1 | tail -20
```
Expected: build succeeds.
- [ ] **Step 3: Switch and verify visually**
```bash
sudo nixos-rebuild switch --flake /Users/finnmarkwitz/development/nixos#jupiter
```
Open `http://jupiter.solar.internal:8082` (or `http://localhost:8082`) in a browser.
Expected: search bar, CPU/memory/disk resource monitor, and date/time widget appear at the top of the dashboard.
- [ ] **Step 4: Commit**
```bash
cd /Users/finnmarkwitz/development/nixos
git add machines/jupiter/environments.nix
git commit -m "feat: add starter homepage widgets (search, resources, datetime)"
```
---
## Verification Checklist
- [ ] `nixos-rebuild build` passes with no eval errors
- [ ] Dashboard at `:8082` shows widgets at top of page
- [ ] Existing services and bookmarks are unchanged
- [ ] Other modules can now contribute widgets via `my.homepage.widgets = [ ... ];` in their `config` block
Generated
+26 -26
View File
@@ -21,11 +21,11 @@
"nixpkgs-lib": "nixpkgs-lib" "nixpkgs-lib": "nixpkgs-lib"
}, },
"locked": { "locked": {
"lastModified": 1788450739, "lastModified": 1790898470,
"narHash": "sha256-glZLQlzIn1fXH6PazR2iUmTo7kzzyYSshrWhLS9TqCU=", "narHash": "sha256-zTwuwezD0w3hpga6a6P8emidzAZFyWqlNeRBlpWOOl8=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "31729ca8cbdb4fa927b34e5f4353e6a83f39e993", "rev": "024633cd702b10285db5cb19b40ad48d2399ba60",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -113,11 +113,11 @@
"uv2nix": "uv2nix" "uv2nix": "uv2nix"
}, },
"locked": { "locked": {
"lastModified": 1789999030, "lastModified": 1791121781,
"narHash": "sha256-oqEWD3Ih/CDejvfWNXFhbwUxvU4RwQZQ9DrI5dD+P10=", "narHash": "sha256-39vzOiYTAwECDMfJAv/b+OxpHPXHfJle0Gx5x+WjPW0=",
"owner": "NousResearch", "owner": "NousResearch",
"repo": "hermes-agent", "repo": "hermes-agent",
"rev": "8f7b3b48fc61dc411cac6ebcb0aaaf451ba9c1cb", "rev": "af90026aa09949579bd423d24def3d38f743cde0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -157,11 +157,11 @@
"nixpkgs-regression": "nixpkgs-regression" "nixpkgs-regression": "nixpkgs-regression"
}, },
"locked": { "locked": {
"lastModified": 1789933661, "lastModified": 1791067591,
"narHash": "sha256-GtfSaYgUPu91AafiBAQIVEwQiPfIOrgqwmxGtMNDtMI=", "narHash": "sha256-SGcfVVSS3DLO+ES4J+SrLxKGP11yvTWXgiAqku1L+Sk=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nix", "repo": "nix",
"rev": "5711f8fed2fcff91a52646e2e856648eca86c331", "rev": "e8280775f307a94ca82cea193cfcc14c0d56232a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -211,11 +211,11 @@
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
"lastModified": 1789978172, "lastModified": 1791128201,
"narHash": "sha256-FIRXajv1pPZ+l6On6ekkmcQ6le0Zi0ncRUoR3nB0vKA=", "narHash": "sha256-rlsYY/Dg/LhbIj51Aa6TLvRpZeb3KZgUTd7llQ5XcJE=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "9ebcb7766700d7e006d9505247bd7ce0426f4232", "rev": "31cc5f4d9b9ba601071e8b8504601b9b176e2756",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -255,11 +255,11 @@
}, },
"nixpkgs-lib": { "nixpkgs-lib": {
"locked": { "locked": {
"lastModified": 1788057806, "lastModified": 1790477367,
"narHash": "sha256-DTQSMxzDWmT0zhguthvegnVkn7CFqGCv4IHCzk5ZUpM=", "narHash": "sha256-oujbxmVKDhci2E4EM3KyAbRUgp5/IsCoiA/LfEF7OOk=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nixpkgs.lib", "repo": "nixpkgs.lib",
"rev": "596e2e3940e09b2abbeb03f75fa1828c57fcd72c", "rev": "f7cd230690d9fc982d06129f9189b101fddcfa3b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -286,11 +286,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1789921291, "lastModified": 1791048980,
"narHash": "sha256-uLLUj+TLUmBc6KrUzx76KZdPi5ZkI1ORR9A6lJUIZlo=", "narHash": "sha256-u3KCLxsnf1622GdFccg8hmkEIutOZ1h4pvia5ERjIuI=",
"rev": "44a91898084f46797b5fac650c7e8c9ac38c43d4", "rev": "a7868a727837f3c09cee2ce0ca671c76b1589fed",
"type": "tarball", "type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.11pre1077143.44a91898084f/nixexprs.tar.zst" "url": "https://releases.nixos.org/nixos/unstable/nixos-26.11pre1084968.a7868a727837/nixexprs.tar.zst"
}, },
"original": { "original": {
"id": "nixpkgs", "id": "nixpkgs",
@@ -313,11 +313,11 @@
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1789885152, "lastModified": 1791031588,
"narHash": "sha256-lIL3uDaS4Q9Ks6klLrBlDr+XS71sbjMJFSipIp2yPjs=", "narHash": "sha256-4XF6NXFWmQPM0xHuxTw+iQEA6mUtmDQNJoVd4u9GkLw=",
"rev": "6d663c0533ff269008fb84e45930151e37c99db9", "rev": "825e2028c29b702a4a5f085f08095d12099784f2",
"type": "tarball", "type": "tarball",
"url": "https://releases.nixos.org/nixos/26.05/nixos-26.05.10304.6d663c0533ff/nixexprs.tar.zst" "url": "https://releases.nixos.org/nixos/26.05/nixos-26.05.11150.825e2028c29b/nixexprs.tar.zst"
}, },
"original": { "original": {
"id": "nixpkgs", "id": "nixpkgs",
@@ -415,11 +415,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1789890976, "lastModified": 1791103873,
"narHash": "sha256-GKwH3zpy7tartuJMG0Rv/xUsdetG1QLmTVv8UKgJLmA=", "narHash": "sha256-nFxM+pKoZ8LJAEnUXARyCaOAloWgaW9kZQOSjWzKcTE=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "7214124c20c1542c90deb54af50e2f53ae02711f", "rev": "dcd241ba97088c22569d1573286e1b9daad340c0",
"type": "github" "type": "github"
}, },
"original": { "original": {
+1 -1
View File
@@ -17,7 +17,7 @@ _: {
readarr.enable = true; readarr.enable = true;
sonarr.enable = true; sonarr.enable = true;
jellyfin.enable = true; jellyfin.enable = true;
jellyseerr.enable = true; seerr.enable = true;
immich.enable = true; immich.enable = true;
development.enable = true; development.enable = true;
home-assistant.enable = true; home-assistant.enable = true;
+1
View File
@@ -4,5 +4,6 @@ _: {
# firewall otherwise blocks inbound connections from other devices. # firewall otherwise blocks inbound connections from other devices.
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [
9119 # athena hermes dashboard 9119 # athena hermes dashboard
47823 # hermes agent ad-hoc webpage server
]; ];
} }
+1 -1
View File
@@ -18,7 +18,7 @@
./readarr ./readarr
./sonarr ./sonarr
./jellyfin ./jellyfin
./jellyseerr ./seerr
./immich ./immich
./hermes-agent ./hermes-agent
]; ];
@@ -20,6 +20,9 @@ in
enable = true; enable = true;
# Deliberate pin, matches the approved design — bump on purpose, not by drift. # Deliberate pin, matches the approved design — bump on purpose, not by drift.
settings.model.default = "anthropic/claude-sonnet-4-5"; settings.model.default = "anthropic/claude-sonnet-4-5";
# The Nix flake input is the source of truth for hermes's version here; its
# built-in self-updater polling GitHub independently just burns API quota.
settings.updates.check = false;
environmentFiles = [ config.sops.secrets."hermes-env".path ]; environmentFiles = [ config.sops.secrets."hermes-env".path ];
addToSystemPackages = true; addToSystemPackages = true;
+1 -2
View File
@@ -6,7 +6,6 @@
{ {
icon = "reddit.png"; icon = "reddit.png";
href = "https://reddit.com/"; href = "https://reddit.com/";
description = "The front page of the internet";
} }
]; ];
} }
@@ -17,7 +16,7 @@
{ {
YouTube = [ YouTube = [
{ {
abbr = "YT"; icon = "youtube.png";
href = "https://youtube.com/"; href = "https://youtube.com/";
} }
]; ];
@@ -32,4 +32,29 @@
} }
]; ];
} }
{
"Gaming" = [
{
"Talon" = {
href = "https://ethraldos.online";
description = "Kunst der Täuschung";
icon = "foundry-vtt.png";
};
}
{
"Tyranny of Dragons" = {
href = "https://hotdq.smoothcloud.de";
description = "Tyranny of Dragons (D&D)";
icon = "foundry-vtt.png";
};
}
{
"Beholder D&D" = {
href = "https://beholder.ethraldos.online";
description = "Andrey FoundryVTT Server";
icon = "foundry-vtt.png";
};
}
];
}
] ]
@@ -3,4 +3,5 @@
{ resources = { cpu = true; memory = true; disk = "/"; }; } { resources = { cpu = true; memory = true; disk = "/"; }; }
{ datetime = { text_size = "xl"; format = { timeStyle = "short"; }; }; } { datetime = { text_size = "xl"; format = { timeStyle = "short"; }; }; }
{ search = {provider = "google"; focus = true; target = "_blank"; }; } { search = {provider = "google"; focus = true; target = "_blank"; }; }
{ minecraft = { url = "udp://rechberg.online:25565" }; }
] ]
@@ -1,17 +1,17 @@
# manages and downloads films # manages and downloads films
{ config, lib, ... }: { config, lib, ... }:
let let
cfg = config.my.profiles.jellyseerr; cfg = config.my.profiles.seerr;
hostName = config.networking.hostName; hostName = config.networking.hostName;
port = 5055; port = 5055;
in in
{ {
options.my.profiles.jellyseerr = with lib; { options.my.profiles.seerr = with lib; {
enable = mkEnableOption "JellySeerr Media Service"; enable = mkEnableOption "Seerr Media Service";
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.jellyseerr = { services.seerr = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
}; };
@@ -19,14 +19,14 @@ in
my.homepage.services = [ my.homepage.services = [
{ {
group = "Media"; group = "Media";
name = "Jellyseerr"; name = "Seerr";
description = "Media requests"; description = "Media requests";
href = "http://${hostName}:${toString port}"; href = "http://${hostName}:${toString port}";
icon = "mdi-television-guide"; icon = "mdi-television-guide";
} }
]; ];
systemd.services.jellyseerr = { systemd.services.seerr = {
after = [ "network-online.target" ]; after = [ "network-online.target" ];
}; };
}; };