Merge branch 'master' of ssh://git.joshuabell.xyz:3032/ringofstorms/dotfiles
This commit is contained in:
commit
282208d537
6 changed files with 215 additions and 91 deletions
|
|
@ -1,64 +1,207 @@
|
||||||
{ lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.services.automatic-timezoned;
|
||||||
|
persistFile = if cfg.persistDir == null then null else "${cfg.persistDir}/timezone";
|
||||||
|
tzdata = pkgs.tzdata;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
services.dbus.enable = lib.mkDefault true;
|
options.services.automatic-timezoned.persistDir = lib.mkOption {
|
||||||
services.geoclue2.enable = true;
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Absolute runtime directory used to persist the timezone for impermanence setups.
|
||||||
|
|
||||||
time.timeZone = null;
|
Important: this must be a normal filesystem path (a string like
|
||||||
services.automatic-timezoned.enable = true;
|
"/persist/var/lib/timezone-persist"), not a Nix `path` value, otherwise it
|
||||||
|
can be coerced into a `/nix/store/...` path and become unwritable at runtime.
|
||||||
|
|
||||||
systemd.services.automatic-timezoned = {
|
When set, the timezone is saved to this directory and restored on boot,
|
||||||
after = [ "dbus.socket" "systemd-timedated.service" "geoclue.service" ];
|
allowing offline boots to use the last known timezone.
|
||||||
wants = [ "dbus.socket" "systemd-timedated.service" "geoclue.service" ];
|
Set to null to disable persistence (default).
|
||||||
serviceConfig = {
|
'';
|
||||||
ExecStartPre = "${lib.getExe' pkgs.coreutils "sleep"} 5";
|
|
||||||
Restart = "on-failure";
|
|
||||||
RestartSec = "10s";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.automatic-timezoned-geoclue-agent = {
|
config = {
|
||||||
after = [ "dbus.socket" ];
|
assertions = [
|
||||||
wants = [ "dbus.socket" ];
|
{
|
||||||
};
|
assertion = cfg.persistDir == null || lib.hasPrefix "/" cfg.persistDir;
|
||||||
|
message = "services.automatic-timezoned.persistDir must be an absolute path";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
systemd.services.fix-localtime-symlink = {
|
services.dbus.enable = lib.mkDefault true;
|
||||||
description = "Fix /etc/localtime symlink to be absolute";
|
services.geoclue2.enable = true;
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
after = [ "automatic-timezoned.service" ];
|
|
||||||
wants = [ "automatic-timezoned.service" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
time.timeZone = null;
|
||||||
Type = "oneshot";
|
services.automatic-timezoned.enable = true;
|
||||||
RemainAfterExit = true;
|
|
||||||
ExecStart = pkgs.writeShellScript "fix-localtime-symlink" ''
|
|
||||||
target=$(${pkgs.coreutils}/bin/readlink /etc/localtime 2>/dev/null || true)
|
|
||||||
if [ -z "$target" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$target" == /* ]]; then
|
systemd.services.automatic-timezoned = {
|
||||||
exit 0
|
after = [ "dbus.socket" "systemd-timedated.service" "geoclue.service" ]
|
||||||
fi
|
++ lib.optional (cfg.persistDir != null) "timezone-restore.service";
|
||||||
|
wants = [ "dbus.socket" "systemd-timedated.service" "geoclue.service" ]
|
||||||
abs_target="/etc/$target"
|
++ lib.optional (cfg.persistDir != null) "timezone-restore.service";
|
||||||
if [ -e "$abs_target" ]; then
|
serviceConfig = {
|
||||||
${pkgs.coreutils}/bin/ln -sf "$abs_target" /etc/localtime
|
ExecStartPre = "${lib.getExe' pkgs.coreutils "sleep"} 5";
|
||||||
fi
|
Restart = "on-failure";
|
||||||
'';
|
RestartSec = "10s";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
unitConfig = {
|
systemd.services.automatic-timezoned-geoclue-agent = {
|
||||||
ConditionPathIsSymbolicLink = "/etc/localtime";
|
after = [ "dbus.socket" ];
|
||||||
|
wants = [ "dbus.socket" ];
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
systemd.paths.fix-localtime-symlink = {
|
# Ensure anything using timedate1 sees restored timezone first.
|
||||||
description = "Watch /etc/localtime for changes";
|
systemd.services.systemd-timedated = lib.mkIf (cfg.persistDir != null) {
|
||||||
wantedBy = [ "multi-user.target" ];
|
after = [ "timezone-restore.service" ];
|
||||||
|
wants = [ "timezone-restore.service" ];
|
||||||
|
requires = [ "timezone-restore.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
pathConfig = {
|
# Restore timezone from persistent storage on boot (fallback for offline boots)
|
||||||
PathChanged = "/etc/localtime";
|
systemd.services.timezone-restore = lib.mkIf (cfg.persistDir != null) {
|
||||||
Unit = "fix-localtime-symlink.service";
|
description = "Restore timezone from persistent storage";
|
||||||
|
wantedBy = [ "sysinit.target" ];
|
||||||
|
|
||||||
|
# NixOS activation may recreate /etc/localtime based on config.
|
||||||
|
# Run after activation so the restored timezone "wins" on offline boots.
|
||||||
|
after = [
|
||||||
|
"local-fs.target"
|
||||||
|
"systemd-remount-fs.service"
|
||||||
|
"nixos-activation.service"
|
||||||
|
];
|
||||||
|
wants = [ "nixos-activation.service" ];
|
||||||
|
|
||||||
|
before = [
|
||||||
|
"time-sync.target"
|
||||||
|
"automatic-timezoned.service"
|
||||||
|
"systemd-timedated.service"
|
||||||
|
];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
RequiresMountsFor = [ cfg.persistDir ];
|
||||||
|
ExecStart = pkgs.writeShellScript "timezone-restore" ''
|
||||||
|
set -euo pipefail
|
||||||
|
persist_file="${persistFile}"
|
||||||
|
|
||||||
|
if [ ! -f "$persist_file" ]; then
|
||||||
|
echo "No persisted timezone found, skipping restore"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
tz=$(${pkgs.coreutils}/bin/cat "$persist_file")
|
||||||
|
if [ -z "$tz" ]; then
|
||||||
|
echo "Persisted timezone file is empty, skipping restore"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
tzfile="${tzdata}/share/zoneinfo/$tz"
|
||||||
|
if [ ! -f "$tzfile" ]; then
|
||||||
|
echo "Invalid timezone '$tz' in persist file, skipping restore"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Restoring timezone: $tz"
|
||||||
|
${pkgs.coreutils}/bin/ln -sf "$tzfile" /etc/localtime
|
||||||
|
|
||||||
|
# Some NixOS setups may generate /etc/timezone as a symlink into the store.
|
||||||
|
# Replace it so we don't fail the whole restore.
|
||||||
|
${pkgs.coreutils}/bin/rm -f /etc/timezone
|
||||||
|
${pkgs.coreutils}/bin/printf '%s\n' "$tz" > /etc/timezone
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Save timezone whenever it changes
|
||||||
|
systemd.services.timezone-persist = lib.mkIf (cfg.persistDir != null) {
|
||||||
|
description = "Persist timezone to storage";
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RequiresMountsFor = [ cfg.persistDir ];
|
||||||
|
ExecStart = pkgs.writeShellScript "timezone-persist" ''
|
||||||
|
set -euo pipefail
|
||||||
|
${pkgs.coreutils}/bin/mkdir -p "${cfg.persistDir}"
|
||||||
|
|
||||||
|
# Try to read timezone from /etc/timezone first, fall back to parsing symlink
|
||||||
|
if [ -f /etc/timezone ]; then
|
||||||
|
tz=$(${pkgs.coreutils}/bin/cat /etc/timezone | ${pkgs.coreutils}/bin/tr -d '[:space:]')
|
||||||
|
else
|
||||||
|
target=$(${pkgs.coreutils}/bin/readlink /etc/localtime 2>/dev/null || true)
|
||||||
|
if [ -z "$target" ]; then
|
||||||
|
echo "Cannot determine timezone, skipping persist"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# Extract timezone name from path like /nix/store/.../share/zoneinfo/America/Chicago
|
||||||
|
tz=$(echo "$target" | ${pkgs.gnused}/bin/sed -n 's|.*/zoneinfo/||p')
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$tz" ]; then
|
||||||
|
echo "Cannot determine timezone, skipping persist"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
persist_file="${persistFile}"
|
||||||
|
|
||||||
|
echo "Persisting timezone: $tz"
|
||||||
|
echo "$tz" > "$persist_file"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Watch /etc/localtime and /etc/timezone for changes and trigger persist
|
||||||
|
systemd.paths.timezone-persist = lib.mkIf (cfg.persistDir != null) {
|
||||||
|
description = "Watch timezone changes to persist";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
|
pathConfig = {
|
||||||
|
PathChanged = [ "/etc/localtime" "/etc/timezone" ];
|
||||||
|
Unit = "timezone-persist.service";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.fix-localtime-symlink = {
|
||||||
|
description = "Fix /etc/localtime symlink to be absolute";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "automatic-timezoned.service" ];
|
||||||
|
wants = [ "automatic-timezoned.service" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
ExecStart = pkgs.writeShellScript "fix-localtime-symlink" ''
|
||||||
|
target=$(${pkgs.coreutils}/bin/readlink /etc/localtime 2>/dev/null || true)
|
||||||
|
if [ -z "$target" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$target" == /* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
abs_target="/etc/$target"
|
||||||
|
if [ -e "$abs_target" ]; then
|
||||||
|
${pkgs.coreutils}/bin/ln -sf "$abs_target" /etc/localtime
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
unitConfig = {
|
||||||
|
ConditionPathIsSymbolicLink = "/etc/localtime";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.paths.fix-localtime-symlink = {
|
||||||
|
description = "Watch /etc/localtime for changes";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
|
pathConfig = {
|
||||||
|
PathChanged = "/etc/localtime";
|
||||||
|
Unit = "fix-localtime-symlink.service";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -209,16 +209,6 @@ in
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
|
||||||
(mkIf ((length cfg.wallpapers) > 0) {
|
|
||||||
environment.etc."xdg/plasma-org.kde.plasma.desktop-appletsrc".text =
|
|
||||||
let
|
|
||||||
wallpaperPath = builtins.head cfg.wallpapers;
|
|
||||||
in
|
|
||||||
''
|
|
||||||
[Containments][1][Wallpaper][org.kde.image][General]
|
|
||||||
Image=file://${wallpaperPath}
|
|
||||||
'';
|
|
||||||
})
|
|
||||||
|
|
||||||
# GPU blocks
|
# GPU blocks
|
||||||
(mkIf cfg.gpu.amd.enable {
|
(mkIf cfg.gpu.amd.enable {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
cfg = osConfig.ringofstorms.dePlasma;
|
cfg = osConfig.ringofstorms.dePlasma;
|
||||||
inherit (lib) mkIf;
|
inherit (lib) mkIf optionalAttrs;
|
||||||
|
# Get the first wallpaper from the list if available
|
||||||
|
wallpaper = if (builtins.length cfg.wallpapers) > 0 then builtins.head cfg.wallpapers else null;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
|
@ -294,6 +296,8 @@ in
|
||||||
lookAndFeel = "org.kde.breezedark.desktop";
|
lookAndFeel = "org.kde.breezedark.desktop";
|
||||||
theme = "breeze-dark";
|
theme = "breeze-dark";
|
||||||
cursor.theme = "breeze_cursors";
|
cursor.theme = "breeze_cursors";
|
||||||
|
} // optionalAttrs (wallpaper != null) {
|
||||||
|
wallpaper = wallpaper;
|
||||||
};
|
};
|
||||||
|
|
||||||
configFile = {
|
configFile = {
|
||||||
|
|
|
||||||
36
hosts/juni/flake.lock
generated
36
hosts/juni/flake.lock
generated
|
|
@ -38,40 +38,28 @@
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"dir": "flakes/common",
|
"path": "../../flakes/common",
|
||||||
"lastModified": 1768255305,
|
"type": "path"
|
||||||
"narHash": "sha256-XcXl5M0WNYhCCqE9qc9Aj2/2Jb/T0NHZnu2ZuVBvlHw=",
|
|
||||||
"ref": "refs/heads/master",
|
|
||||||
"rev": "15769eda748f6fcc6fdab04f79f14ed9b1ffc548",
|
|
||||||
"revCount": 1125,
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.joshuabell.xyz/ringofstorms/dotfiles"
|
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"dir": "flakes/common",
|
"path": "../../flakes/common",
|
||||||
"type": "git",
|
"type": "path"
|
||||||
"url": "https://git.joshuabell.xyz/ringofstorms/dotfiles"
|
},
|
||||||
}
|
"parent": []
|
||||||
},
|
},
|
||||||
"de_plasma": {
|
"de_plasma": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"plasma-manager": "plasma-manager"
|
"plasma-manager": "plasma-manager"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"dir": "flakes/de_plasma",
|
"path": "../../flakes/de_plasma",
|
||||||
"lastModified": 1768255305,
|
"type": "path"
|
||||||
"narHash": "sha256-XcXl5M0WNYhCCqE9qc9Aj2/2Jb/T0NHZnu2ZuVBvlHw=",
|
|
||||||
"ref": "refs/heads/master",
|
|
||||||
"rev": "15769eda748f6fcc6fdab04f79f14ed9b1ffc548",
|
|
||||||
"revCount": 1125,
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.joshuabell.xyz/ringofstorms/dotfiles"
|
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"dir": "flakes/de_plasma",
|
"path": "../../flakes/de_plasma",
|
||||||
"type": "git",
|
"type": "path"
|
||||||
"url": "https://git.joshuabell.xyz/ringofstorms/dotfiles"
|
},
|
||||||
}
|
"parent": []
|
||||||
},
|
},
|
||||||
"flatpaks": {
|
"flatpaks": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
|
|
||||||
|
|
@ -9,16 +9,16 @@
|
||||||
impermanence.url = "github:nix-community/impermanence";
|
impermanence.url = "github:nix-community/impermanence";
|
||||||
|
|
||||||
# Use relative to get current version for testin
|
# Use relative to get current version for testin
|
||||||
# common.url = "path:../../flakes/common";
|
common.url = "path:../../flakes/common";
|
||||||
common.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/common";
|
# common.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/common";
|
||||||
# secrets-bao.url = "path:../../flakes/secrets-bao";
|
# secrets-bao.url = "path:../../flakes/secrets-bao";
|
||||||
secrets-bao.url = "path:../../flakes/secrets-bao";
|
secrets-bao.url = "path:../../flakes/secrets-bao";
|
||||||
# flatpaks.url = "path:../../flakes/flatpaks";
|
# flatpaks.url = "path:../../flakes/flatpaks";
|
||||||
flatpaks.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/flatpaks";
|
flatpaks.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/flatpaks";
|
||||||
# beszel.url = "path:../../flakes/beszel";
|
# beszel.url = "path:../../flakes/beszel";
|
||||||
beszel.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/beszel";
|
beszel.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/beszel";
|
||||||
# de_plasma.url = "path:../../flakes/de_plasma";
|
de_plasma.url = "path:../../flakes/de_plasma";
|
||||||
de_plasma.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/de_plasma";
|
# de_plasma.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/de_plasma";
|
||||||
|
|
||||||
opencode.url = "github:sst/opencode";
|
opencode.url = "github:sst/opencode";
|
||||||
ros_neovim.url = "git+https://git.joshuabell.xyz/ringofstorms/nvim";
|
ros_neovim.url = "git+https://git.joshuabell.xyz/ringofstorms/nvim";
|
||||||
|
|
@ -63,8 +63,8 @@
|
||||||
gpu.intel.enable = true;
|
gpu.intel.enable = true;
|
||||||
sddm.autologinUser = "josh";
|
sddm.autologinUser = "josh";
|
||||||
wallpapers = [
|
wallpapers = [
|
||||||
../../_shared_assets/wallpapers/pixel_neon.png
|
../../hosts/_shared_assets/wallpapers/pixel_neon.png
|
||||||
../../_shared_assets/wallpapers/pixel_neon_v.png
|
../../hosts/_shared_assets/wallpapers/pixel_neon_v.png
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
@ -84,6 +84,7 @@
|
||||||
inputs.common.nixosModules.hardening
|
inputs.common.nixosModules.hardening
|
||||||
inputs.common.nixosModules.nix_options
|
inputs.common.nixosModules.nix_options
|
||||||
inputs.common.nixosModules.timezone_auto
|
inputs.common.nixosModules.timezone_auto
|
||||||
|
({ services.automatic-timezoned.persistDir = "/persist/var/lib/timezone-persist"; })
|
||||||
inputs.common.nixosModules.tty_caps_esc
|
inputs.common.nixosModules.tty_caps_esc
|
||||||
inputs.common.nixosModules.zsh
|
inputs.common.nixosModules.zsh
|
||||||
inputs.common.nixosModules.tailnet
|
inputs.common.nixosModules.tailnet
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,6 @@
|
||||||
files = [
|
files = [
|
||||||
"/machine-key.json"
|
"/machine-key.json"
|
||||||
"/etc/machine-id"
|
"/etc/machine-id"
|
||||||
"/etc/localtime"
|
|
||||||
"/etc/timezone"
|
|
||||||
"/etc/adjtime"
|
"/etc/adjtime"
|
||||||
# NOTE: if you want mutable passwords across reboots, persist these,
|
# NOTE: if you want mutable passwords across reboots, persist these,
|
||||||
# but you must do a one-time migration (see notes in chat).
|
# but you must do a one-time migration (see notes in chat).
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue