12 Commits

Author SHA1 Message Date
finn.markwitz ff34fe762e Merge pull request 'Feat/mibook boot desktop choice' (#4) from feat/mibook-boot-desktop-choice into main
Reviewed-on: #4
2026-07-27 09:55:47 +02:00
finn.markwitz 7e4407a1f8 feat(mibook): boot to terminal, launch KDE on demand
Add my.profiles.kde-desktop.startOnBoot (default true, no change for
existing consumers). When false, boot to multi-user.target, keep SDDM
out of any boot target's wants, and provide a 'desktop' command that
starts the display manager on demand. Enable this on mibook.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CfozKLQdUh5TzqyjSigLUx
2026-07-27 09:48:13 +02:00
finn.markwitz 539fb26791 docs: spec for mibook boot-time terminal/desktop choice
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CfozKLQdUh5TzqyjSigLUx
2026-07-27 09:27:37 +02:00
finn.markwitz 79b26ddfda chore: Flake Update 2026-07-24 12:01:15 +02:00
finn.markwitz b8961fb47d Merge pull request 'feat(mibook): do nothing on lid close while on AC power' (#2) from feat/mibook-lid-close-ac into main
Reviewed-on: #2
2026-07-24 11:56:02 +02:00
finn.markwitz 4851f745d8 feat(mibook): do nothing on lid close while on AC power
Ship a system-wide PowerDevil default (/etc/xdg/powerdevilrc) setting the
AC lid-close action to "do nothing" (LidAction=0). Battery behavior is left
at the default (suspend).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbZoyXq6J8v2eqC9yn5Vcy
2026-07-21 17:42:47 +02:00
finn.markwitz 59b5cfb47c chore: Flake update 2026-07-20 11:08:47 +02:00
finn.markwitz a8364f21ca chore: Flake update 2026-07-14 17:33:45 +02:00
finn.markwitz f135c1646f Merge pull request 'feat(home-assistant): add Apple TV and Tuya integrations' (#1) from feat/ha-appletv-tuya-irrigation into main
Reviewed-on: #1
2026-07-05 12:15:22 +02:00
marthsincemelee 7a1b0541c2 feat(home-assistant): add Apple TV and Tuya integrations
Enable the apple_tv (pyatv) and tuya (SmartLife cloud) components on
jupiter. Tuya covers the Unistyle WLAN irrigation computer; both are
config-flow integrations paired through the HA web UI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 17:19:53 +02:00
marthsincemelee 6c5f61997d fix: Homepage Domain 2026-06-27 15:45:06 +02:00
finn.markwitz 763253693c chore: Flake Update 2026-06-27 15:28:11 +02:00
10 changed files with 142 additions and 54 deletions
@@ -0,0 +1,61 @@
# mibook: choose terminal-only vs desktop at boot
## Goal
Let mibook boot to a text console by default, with KDE fully installed and
launchable on demand. The user decides after boot whether they need the
graphical desktop, without rebuilding the system.
## Behavior
- mibook boots to a text console (`multi-user.target`). SDDM and Plasma do
**not** start automatically.
- KDE (SDDM + Plasma 6) remains fully installed.
- Running `desktop` in the terminal starts the SDDM display manager, which
presents the graphical login screen; logging in there enters a Plasma 6
session.
- No reverse command. To return to a text console, stop the display manager
(`sudo systemctl stop display-manager`) or reboot.
- Other machines that enable the `kde-desktop` profile are unaffected; their
desktop still starts on boot.
## Implementation
### `modules/environments/kde-desktop/default.nix`
Add an opt-out option to the existing profile:
- New option `my.profiles.kde-desktop.startOnBoot`, a boolean defaulting to
`true`. The default preserves the current behavior for every consumer.
- The existing `config` block (SDDM, Plasma 6, user packages) stays enabled
whenever the profile is enabled, regardless of `startOnBoot`.
- When `startOnBoot = false`, additionally apply:
- `systemd.services.display-manager.wantedBy = lib.mkForce [ ];` so SDDM is
defined but not pulled in by any boot target.
- `systemd.defaultUnit = "multi-user.target";` so the boot target is the
text console.
- A `desktop` command provided via
`pkgs.writeShellScriptBin "desktop" "exec sudo systemctl start display-manager.service"`,
added to `environment.systemPackages`.
### `machines/mibook/environments.nix`
Set `kde-desktop.startOnBoot = false;` alongside the existing
`kde-desktop.enable = true;`.
## Testing / verification
- `nix build '.#nixosConfigurations.mibook.config.system.build.toplevel'`
builds without error.
- After `nixos-rebuild switch` on mibook: system boots to a TTY, no SDDM;
running `desktop` brings up the SDDM login and a working Plasma session.
- Confirm jupiter (or any non-mibook consumer) is unchanged: its evaluated
`systemd.defaultUnit` / display-manager wantedBy are not altered.
## Trade-offs
- `desktop` relies on `sudo`; the user has sudo access, so no extra
configuration is required.
- Chose "boot to terminal, launch on demand" over a GRUB boot-menu entry
because it is more robust across NixOS generations and needs no fragile
static kernel entries.
Generated
+32 -37
View File
@@ -21,11 +21,11 @@
"nixpkgs-lib": "nixpkgs-lib" "nixpkgs-lib": "nixpkgs-lib"
}, },
"locked": { "locked": {
"lastModified": 1778716662, "lastModified": 1782949081,
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=", "narHash": "sha256-vp6Y/Grm98ESt6ceOkWiHWyZRDV3J1RID4w+6NWK9yA=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb", "rev": "17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -42,11 +42,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1778716662, "lastModified": 1782949081,
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=", "narHash": "sha256-vp6Y/Grm98ESt6ceOkWiHWyZRDV3J1RID4w+6NWK9yA=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb", "rev": "17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -60,20 +60,17 @@
"flake-compat": [ "flake-compat": [
"nix" "nix"
], ],
"gitignore": [
"nix"
],
"nixpkgs": [ "nixpkgs": [
"nix", "nix",
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1781733627, "lastModified": 1783008725,
"narHash": "sha256-U3yTuGBnmXvXoQI3qkpfEDsn9RovQPAjN7ndRco+3u0=", "narHash": "sha256-jGiy6+sxjNWXSjp25uoJuNfyH9zBK1PEDY0lVoL4ibQ=",
"owner": "cachix", "owner": "cachix",
"repo": "git-hooks.nix", "repo": "git-hooks.nix",
"rev": "3bbec39bc90eadfa031e6f3b77272f3f60803e39", "rev": "bca82caa46d5ec0f5d422c61fb1e30bc51313cbe",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -92,11 +89,11 @@
"nixpkgs-regression": "nixpkgs-regression" "nixpkgs-regression": "nixpkgs-regression"
}, },
"locked": { "locked": {
"lastModified": 1782211048, "lastModified": 1784762557,
"narHash": "sha256-WKITtytZtfU6m24eK/WVI0QHZpHv4VtTpDCR3414Q70=", "narHash": "sha256-R/r6jRnANV50c8F5Fz5+1Q1moab0IGWRk+cg5ME2nMY=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nix", "repo": "nix",
"rev": "cdf3b417b272ce2c1de41445378c17f4bebf6fb6", "rev": "d10c84cd0cc0efdcb29cf2611caf5fbcd10fa071",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -146,11 +143,11 @@
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
"lastModified": 1782166108, "lastModified": 1784723954,
"narHash": "sha256-/EtnQBcKbsaCAGQ5VRcplrHRkR4ryqyLMpBfkVuG9Xw=", "narHash": "sha256-1CfD8ZUjCkTgjsneLZ/lxCHhgDfqxxE7/GX0MmsgiqA=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "875776f0252fcb8618bb948640a0d1f7a5b362be", "rev": "a017f5b72210026af5b3ac5949f08d94380a6fbd",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -161,11 +158,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1780902259, "lastModified": 1783148766,
"narHash": "sha256-YMnBf9lk/LYgvqfmSSJuOGigtRs5Lsy26pJHVlR9yMY=", "narHash": "sha256-H9+N+GFtsbVC8ZniHliChM7ndizxtqVZs6bnGOLM3WQ=",
"rev": "bd0ff2d3eac24699c3664d5966b9ef36f388e2ca", "rev": "a50de1b7d8a586adc18d2395c19de7d6058e6030",
"type": "tarball", "type": "tarball",
"url": "https://releases.nixos.org/nixos/26.05/nixos-26.05.1550.bd0ff2d3eac2/nixexprs.tar.xz" "url": "https://releases.nixos.org/nixos/26.05/nixos-26.05.4193.a50de1b7d8a5/nixexprs.tar.xz"
}, },
"original": { "original": {
"type": "tarball", "type": "tarball",
@@ -190,11 +187,11 @@
}, },
"nixpkgs-lib": { "nixpkgs-lib": {
"locked": { "locked": {
"lastModified": 1777168982, "lastModified": 1782614948,
"narHash": "sha256-GOkGPcboWE9BmGCRMLX3worL4EMnsnG8MyKmXNeYuhQ=", "narHash": "sha256-ePjCwr1sNm9NYUqywL7QfK3JnlS015msC+eBu2zKlp8=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nixpkgs.lib", "repo": "nixpkgs.lib",
"rev": "f5901329dade4a6ea039af1433fb087bd9c1fe14", "rev": "db3f255737b94216eb71cce308e2912cf6bc2d7c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -221,12 +218,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1781577229, "lastModified": 1784796856,
"narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=", "narHash": "sha256-vwxWgF+Gj276WznzGb1LxGsK/39HaQwgQXiU3EkC844=",
"owner": "NixOS", "rev": "e2587caef70cea85dd97d7daab492899902dbf5d",
"repo": "nixpkgs", "type": "tarball",
"rev": "567a49d1913ce81ac6e9582e3553dd90a955875f", "url": "https://releases.nixos.org/nixos/unstable/nixos-26.11pre1040357.e2587caef70c/nixexprs.tar.xz"
"type": "github"
}, },
"original": { "original": {
"id": "nixpkgs", "id": "nixpkgs",
@@ -249,12 +245,11 @@
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1782116945, "lastModified": 1784707089,
"narHash": "sha256-G3tw/IXmaH6IQ2upZvhuN9sG8CkuX+BLuJDpE8hz0Ds=", "narHash": "sha256-DUedXhD2Rg8q4Xyd07Sb90eZGy4gg6W+Vl/WbLNwAZo=",
"owner": "NixOS", "rev": "b3fe9581c9061c749abef42b6d4ee7b7c05c33fa",
"repo": "nixpkgs", "type": "tarball",
"rev": "34268251cf5547d39063f2c5ea9a196246f7f3a6", "url": "https://releases.nixos.org/nixos/26.05/nixos-26.05.5845.b3fe9581c906/nixexprs.tar.xz"
"type": "github"
}, },
"original": { "original": {
"id": "nixpkgs", "id": "nixpkgs",
+2 -2
View File
@@ -10,7 +10,7 @@
./disks.nix ./disks.nix
./hardware-configuration.nix ./hardware-configuration.nix
./environments.nix ./environments.nix
# ./network.nix ./network.nix
]; ];
networking.hostName = "jupiter"; networking.hostName = "jupiter";
@@ -48,7 +48,7 @@
# Try fix wifi disconnect # Try fix wifi disconnect
networking.networkmanager.wifi.powersave = false; networking.networkmanager.wifi.powersave = false;
# Disable hibernate completely # Disable hibernate completely
powerManagement.enable = true; powerManagement.enable = true;
systemd.targets."hibernate".enable = false; systemd.targets."hibernate".enable = false;
+1 -1
View File
@@ -7,4 +7,4 @@ _: {
domain = "jupiter.solar.internal"; domain = "jupiter.solar.internal";
search = [ "jupiter.solar.internal" ]; search = [ "jupiter.solar.internal" ];
}; };
} }
+8
View File
@@ -44,6 +44,14 @@
services.openssh.enable = true; services.openssh.enable = true;
# KDE (PowerDevil) power settings: do nothing on lid close while on AC power.
# Shipped as a system-wide default; KConfig cascades so a user's own
# ~/.config/powerdevilrc will override this if present.
environment.etc."xdg/powerdevilrc".text = ''
[AC][SuspendAndShutdown]
LidAction=0
'';
system = { system = {
stateVersion = "23.05"; stateVersion = "23.05";
autoUpgrade.enable = true; autoUpgrade.enable = true;
+1
View File
@@ -6,6 +6,7 @@ in
{ {
my.profiles = { my.profiles = {
kde-desktop.enable = true; kde-desktop.enable = true;
kde-desktop.startOnBoot = false;
zsh.enable = true; zsh.enable = true;
apps = { apps = {
desktop_apps = true; desktop_apps = true;
@@ -8,6 +8,7 @@
let let
cfg = config.my.profiles.audiobookshelf; cfg = config.my.profiles.audiobookshelf;
hostName = config.networking.hostName; hostName = config.networking.hostName;
domain = config.networking.domain;
in in
{ {
options.my.profiles.audiobookshelf = with lib; { options.my.profiles.audiobookshelf = with lib; {
@@ -32,7 +33,7 @@ in
group = "Media"; group = "Media";
name = "Audiobookshelf"; name = "Audiobookshelf";
description = "Audiobooks and podcasts"; description = "Audiobooks and podcasts";
href = "http://${hostName}:63834"; href = "http://${domain}:63834";
icon = "audiobookshelf.png"; icon = "audiobookshelf.png";
} }
]; ];
@@ -29,6 +29,8 @@ in
"otbr" "otbr"
"thread" "thread"
"xiaomi_miio" "xiaomi_miio"
"apple_tv" # Apple TV (pyatv); pair via UI PIN flow
"tuya" # Tuya/SmartLife cloud; Unistyle WLAN irrigation computer
]; ];
}; };
services.home-assistant.config = { services.home-assistant.config = {
@@ -38,7 +40,7 @@ in
internal_url = "http://${hostName}:8123"; internal_url = "http://${hostName}:8123";
external_url = "http://jupiter.solar.internal:8123"; external_url = "http://jupiter.solar.internal:8123";
}; };
mobile_app = {}; mobile_app = { };
automation = "!include automations.yaml"; automation = "!include automations.yaml";
script = "!include scripts.yaml"; script = "!include scripts.yaml";
scene = "!include scenes.yaml"; scene = "!include scenes.yaml";
+1 -1
View File
@@ -7,7 +7,7 @@
let let
cfg = config.my.profiles.homepage; cfg = config.my.profiles.homepage;
dashboardPort = 8082; dashboardPort = 8082;
dashboardHost = config.networking.hostName; dashboardHost = config.networking.domain;
dashboardUrl = "http://${dashboardHost}:${toString dashboardPort}"; dashboardUrl = "http://${dashboardHost}:${toString dashboardPort}";
manualServices = import ./manual-services.nix; manualServices = import ./manual-services.nix;
manualWidgets = import ./manual-widgets.nix; manualWidgets = import ./manual-widgets.nix;
+31 -11
View File
@@ -11,17 +11,37 @@ in
{ {
options.my.profiles.kde-desktop = with lib; { options.my.profiles.kde-desktop = with lib; {
enable = mkEnableOption "KDE Desktop Environment"; enable = mkEnableOption "KDE Desktop Environment";
startOnBoot = mkOption {
type = types.bool;
default = true;
description = ''
Whether the display manager (SDDM) starts automatically at boot.
When false, the system boots to a text console and KDE can be
launched on demand with the `desktop` command.
'';
};
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable (lib.mkMerge [
services = { {
displayManager.sddm.enable = true; services = {
displayManager.sddm.wayland.enable = true; displayManager.sddm.enable = true;
desktopManager.plasma6.enable = true; displayManager.sddm.wayland.enable = true;
}; desktopManager.plasma6.enable = true;
users.users.finn.packages = with pkgs; [ };
# Programms can be added here... users.users.finn.packages = with pkgs; [
numix-icon-theme # Programms can be added here...
]; numix-icon-theme
}; ];
}
(lib.mkIf (!cfg.startOnBoot) {
# Boot to a text console; SDDM stays installed but is not pulled in
# by any boot target. Launch KDE on demand with `desktop`.
systemd.services.display-manager.wantedBy = lib.mkForce [ ];
systemd.defaultUnit = lib.mkForce "multi-user.target";
environment.systemPackages = [
(pkgs.writeShellScriptBin "desktop" "exec sudo systemctl start display-manager.service")
];
})
]);
} }