1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
{ config, pkgs, lib, dotfilesRoot, ... }:
# VM-only Home-Manager profile (Ubuntu 22.04 remote-dev box). Adds the
# rootless podman stack, the editor/zellij/zsh/git config symlinks
# back into the cloned dotfiles tree, and a minimal ~/.zshenv shim —
# all of which the Arch host gets from chezmoi instead.
let
dotfiles = "${builtins.getEnv "HOME"}/.local/share/dotfiles";
link = path: config.lib.file.mkOutOfStoreSymlink "${dotfiles}/${path}";
in
{
imports = [ ./common.nix ];
home.username = builtins.getEnv "USER";
home.homeDirectory = builtins.getEnv "HOME";
home.sessionVariables = {
# Ubuntu 20.04-derived hosts still default to cgroups v1; podman 5
# warns on every invocation. Flipping to v2 is a host-level reboot
# and only matters for --memory/--cpus, so silence the warning.
PODMAN_IGNORE_CGROUPSV1_WARNING = "1";
};
home.packages = with pkgs; [
# ── Rootless podman ─────────────────────────────────────────────────────
# The nix `podman` is wrapped to find these helpers via /nix/store
# paths, so we don't need to write a containers.conf for
# `helper_binaries_dir`.
podman
crun # OCI runtime (lighter than runc; default for rootless)
conmon # container monitor process
netavark # default network stack on podman 4+
aardvark-dns # DNS for netavark networks
slirp4netns # rootless user-mode networking
passt # pasta backend (slirp4netns successor; podman picks it up)
];
# ── Shared config symlinks ──────────────────────────────────────────────────
# Live symlinks back into the cloned working tree so `git pull` is enough
# to update configs — no `home-manager switch` required after every edit.
# On the Arch host the same files are deployed by chezmoi; this block
# exists because the VM doesn't run chezmoi.
xdg.configFile = {
"nvim".source = link "dot_config/nvim";
"zellij".source = link "dot_config/zellij";
"zsh/.zshrc".source = link "dot_config/zsh/dot_zshrc";
"zsh/.zprofile".source = link "dot_config/zsh/dot_zprofile";
"ghostty".source = link "dot_config/ghostty"; # for terminfo refs only
"direnv/direnvrc".source = link "dot_config/direnv/direnvrc";
"git/config".source = link "dot_config/git/config";
"git/attributes".source = link "dot_config/git/attributes";
"git/ignore".source = link "dot_config/git/ignore";
# Git hooks: source filenames carry the chezmoi `executable_` attribute
# prefix which only chezmoi strips. In nix-managed setups we use raw
# symlinks, so map each hook to its stripped name explicitly. The
# executable bit comes from the working-tree file mode (git resolves
# the symlink).
"git/hooks/pre-push".source = link "dot_config/git/hooks/executable_pre-push";
"git/hooks/pre-commit".source = link "dot_config/git/hooks/executable_pre-commit";
"git/hooks/commit-msg".source = link "dot_config/git/hooks/executable_commit-msg";
"git/hooks/post-commit".source = link "dot_config/git/hooks/executable_post-commit";
"git/hooks/_dispatch.sh".source = link "dot_config/git/hooks/_dispatch.sh";
};
# ~/.ssh/config from the dotfiles tree (read-only); keys + known_hosts
# stay machine-local. We can't symlink via home.file because
# mkOutOfStoreSymlink exposes the working-tree perms (0664 under a
# default umask 002) and OpenSSH refuses any group-writable ssh_config.
# Materialize a real 0600 file via activation instead.
home.activation.sshConfig = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
run install -D -m 600 \
"${dotfiles}/private_dot_ssh/config" "$HOME/.ssh/config"
'';
# ZDOTDIR redirect so login shells find ~/.config/zsh/.zprofile etc.
# Also source HM's session-vars — HM normally drops these into
# ~/.profile, but zsh login shells don't read .profile, and we don't
# use programs.zsh.enable.
home.file.".zshenv".text = ''
if [ -r "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" ]; then
. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
fi
export ZDOTDIR="$HOME/.config/zsh"
[[ -r "$ZDOTDIR/.zshenv" ]] && source "$ZDOTDIR/.zshenv"
'';
# ── Rootless podman config ──────────────────────────────────────────────────
# Kept inline (not in the chezmoi tree) because Arch's system-wide
# /etc/containers defaults already work there; these files exist only
# to give nix's user-installed podman sane rootless defaults.
xdg.configFile."containers/registries.conf".text = ''
unqualified-search-registries = ["docker.io", "quay.io", "ghcr.io"]
short-name-mode = "permissive"
'';
xdg.configFile."containers/storage.conf".text = ''
[storage]
# runroot/graphroot default to $XDG_RUNTIME_DIR/containers and
# $XDG_DATA_HOME/containers/storage respectively for rootless — leave unset.
driver = "overlay"
[storage.options.overlay]
# Kernel >=5.13 supports rootless overlay natively (VM is on 5.15),
# so mount_program is left unset → uses the kernel driver directly
# instead of fuse-overlayfs.
'';
xdg.configFile."containers/policy.json".text = builtins.toJSON {
default = [ { type = "insecureAcceptAnything"; } ];
transports.docker-daemon."" = [ { type = "insecureAcceptAnything"; } ];
};
}
|