support user-specific paths with the respective user as owner of non-persisted intermediate/parent paths - #16
Conversation
Flake lock file updates:
• Updated input 'nixpkgs':
'github:nixos/nixpkgs/9d3ae807ebd2981d593cddd0080856873139aa40' (2025-01-29)
→ 'github:nixos/nixpkgs/3016b4b15d13f3089db8a41ef937b13a9e33a8df' (2025-06-30)
|
Seems the home directory is added twice to intermediate file paths. |
Oh thanks, no idea how I managed to overlooked that |
5006055 to
ba42a25
Compare
|
Great, this now produces almost the same paths as my implementation. The only thing missing is the home directory on persistent storage, which needs its permissions set to |
ba42a25 to
3ca70b0
Compare
|
There's no differences now, it all looks good to me. Thanks! |
|
Thanks for your amazing work @WilliButz! I'm encountering a conflict problem when experimenting with this branch. I'm trying to define multiple directories with different mode under the same parent directory, but it's causing a merge conflict: Here is the relevant portion of my NixOS configuration: Details{
pkgs,
inputs,
vars,
...
}:
{
imports = [
inputs.preservation.nixosModules.default
];
preservation.enable = true;
# pverservation required initrd using systemd.
boot.initrd.systemd.enable = true;
environment.systemPackages = [
# `sudo ncdu -x /`
pkgs.ncdu
];
# There are two ways to clear the root filesystem on every boot:
## 1. use tmpfs for /
## 2. (btrfs/zfs only)take a blank snapshot of the root filesystem and revert to it on every boot via:
## boot.initrd.postDeviceCommands = ''
## mkdir -p /run/mymount
## mount -o subvol=/ /dev/disk/by-uuid/UUID /run/mymount
## btrfs subvolume delete /run/mymount
## btrfs subvolume snapshot / /run/mymount
## '';
#
# See also https://grahamc.com/blog/erase-your-darlings/
# NOTE: preservation only mounts the directory/file list below to /persistent
# If the directory/file already exists in the root filesystem you should
# move those files/directories to /persistent first!
preservation.preserveAt."/persistent" = {
directories = [
"/etc/NetworkManager/system-connections"
"/etc/ssh"
"/etc/nix/inputs"
# "/etc/nixos"
# my secrets
"/etc/agenix/"
"/var/log"
# system-core
"/var/lib/nixos"
"/var/lib/systemd"
{
directory = "/var/lib/private";
mode = "0700";
}
# lanzaboote - secure boot
"/var/lib/sbctl"
# fprintd fingerprint info
{
directory = "/var/lib/fprint/";
mode = "0700";
}
# containers
"/var/lib/docker"
"/var/lib/cni"
"/var/lib/containers"
# other data
"/var/lib/flatpak"
# virtualisation
"/var/lib/libvirt"
"/var/lib/lxc"
"/var/lib/lxd"
"/var/lib/qemu"
# "/var/lib/waydroid"
# network
"/var/lib/tailscale"
"/var/lib/bluetooth"
"/var/lib/NetworkManager"
];
files = [
# auto-generated machine ID
{
file = "/etc/machine-id";
inInitrd = true;
}
{
file = "/etc/dae/config.dae";
mode = "0600";
}
];
users."${vars.user.name}" = {
commonMountOptions = [
"x-gvfs-hide"
];
directories = [
# ======================================
# XDG Directories
# ======================================
"Downloads"
"Music"
"Pictures"
"Documents"
"Videos"
# ======================================
# Nix / Home Manager Profiles
# ======================================
".local/state/home-manager"
".local/state/nix/profiles"
".local/share/nix"
# ======================================
# IDE / Editors
# ======================================
# neovim plugins(wakatime & copilot)
".wakatime"
".config/github-copilot"
# vscode
".vscode"
".config/Code"
".vscode-insiders"
".config/Code - Insiders"
# cursor ai editor
".cursor"
".config/Cursor"
# zed editor
".config/zed"
".local/share/zed"
# nvim
".local/share/nvim"
".local/state/nvim"
# doom-emacs
# "org" # org files
# ".config/emacs"
# ".local/share/doom"
# ".local/share/emacs"
# Joplin
".config/joplin" # tui client
".config/Joplin" # joplin-desktop
# ".local/share/jupyter"
# ======================================
# Cloud Native
# ======================================
{
# pulumi - infrastructure as code
directory = ".pulumi";
mode = "0700";
}
{
directory = ".aws";
mode = "0700";
}
{
directory = ".docker";
mode = "0700";
}
# ======================================
# language package managers
# ======================================
".local/share/pnpm/store" # PNPM Store
# ".npm" # typsescript/javascript
# "go"
# ".cargo" # rust
# ".m2" # java maven
# ".gradle" # java gradle
# ".conda" # python generated by `conda-shell`
# ======================================
# Security
# ======================================
{
directory = ".gnupg";
mode = "0700";
}
{
directory = ".ssh";
mode = "0700";
}
{
directory = ".pki";
mode = "0700";
}
{
directory = ".local/share/kwalletd";
mode = "0700";
}
".local/share/password-store"
# gnmome keyrings
".local/share/keyrings"
# ======================================
# Games / Media
# ======================================
".steam"
".config/blender"
".config/LDtk"
".local/share/Steam"
".local/share/PrismLauncher"
".local/share/tiled"
".local/share/GOG.com"
".local/share/StardewValley"
".local/share/feral-interactive"
# ======================================
# Instant Messaging
# ======================================
".config/QQ"
".local/share/TelegramDesktop"
# ======================================
# Meeting / Remote Desktop
# ======================================
".config/remmina"
".config/freerdp"
".zoom"
".local/share/remmina"
# ======================================
# browsers
# ======================================
".mozilla"
".config/google-chrome"
# ======================================
# CLI data
# ======================================
".local/share/atuin"
".local/share/zoxide"
".local/share/direnv"
".local/share/k9s"
# ======================================
# Containers
# ======================================
".local/share/containers"
".local/share/flatpak"
# flatpak app's data
".var"
# ======================================
# Misc
# ======================================
# Audio
".config/pulse"
".local/state/wireplumber"
# Digital Painting
".local/share/krita"
];
files = [
{
file = ".wakatime.cfg";
how = "symlink";
}
{
file = ".local/share/fish/fish_history";
how = "symlink";
# create parent directory automatically
configureParent = true;
}
{
file = ".config/zoomus.conf";
how = "symlink";
}
{
file = ".config/zoom.conf";
how = "symlink";
}
];
};
};
# systemd-machine-id-commit.service would fail but it is not relevant
# in this specific setup for a persistent machine-id so we disable it
#
# see the firstboot example below for an alternative approach
systemd.suppressedSystemUnits = [ "systemd-machine-id-commit.service" ];
# let the service commit the transient ID to the persistent volume
systemd.services.systemd-machine-id-commit = {
unitConfig.ConditionPathIsMountPoint = [
""
"/persistent/etc/machine-id"
];
serviceConfig.ExecStart = [
""
"systemd-machine-id-setup --commit --root /persistent"
];
};
}Is this conflict expected by design? If so, what’s the recommended way to resolve conflicting permission definitions for the same target directory? Since I’m very new to NixOS, so any guidance would be appreciated. |
|
@mnixry I'll see that I look into this later today. It is definitely not expected. |
3ca70b0 to
22889ae
Compare
|
@mnixry so the issue was caused by the following part in the config: preservation.preserveAt."/persistent".users."${vars.user.name}".files = [
{
file = ".wakatime.cfg"; how = "symlink";
}
];Previously, the default value of Now this should no longer be the case. |
22889ae to
f011789
Compare
@WilliButz Thanks for pushing the fix. I can confirm the config conflict is resolved. |
|
I tried the latest
|
|
@SamLukeYes thanks for the report, I'll look into it later this week |
* still needs documentation updates * open for discussion
fails trying to use unshare
f011789 to
e9376d0
Compare
|
@SamLukeYes there was a mix up with attributes. that's now fixed and also covered by the "basic" test |
|
The mode confliction is also existing. It raises with the following config: I have to write something like this to fix it: |
(see individual commit messages)