Skip to content

Commit ee57352

Browse files
authored
Merge pull request #1 from thrix/host-config-module
Extract host config materialization into a reusable Home Manager module
2 parents ea9fec6 + f50ee95 commit ee57352

9 files changed

Lines changed: 313 additions & 65 deletions

File tree

.github/dependabot.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
version: 2
3+
updates:
4+
- package-ecosystem: github-actions
5+
directory: /
6+
schedule:
7+
interval: weekly

.github/workflows/check.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
name: Check
3+
4+
on:
5+
push:
6+
branches: [main]
7+
pull_request:
8+
9+
jobs:
10+
pre-commit:
11+
name: Pre-commit
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: cachix/install-nix-action@v31
16+
- run: nix profile install nixpkgs#alejandra nixpkgs#deadnix
17+
- uses: pre-commit/action@v3.0.1
18+
19+
nix-build:
20+
name: Nix build
21+
runs-on: ubuntu-latest
22+
steps:
23+
- uses: actions/checkout@v4
24+
- uses: cachix/install-nix-action@v31
25+
- run: make check/nix
26+
27+
bats:
28+
name: Bats tests
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v4
32+
- uses: cachix/install-nix-action@v31
33+
- run: nix shell nixpkgs#bats --command make check/bats

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ Usage:
1515

1616
endef
1717

18+
##@ Check
19+
20+
check/nix: ## Build Nix config for all users without creating result links
21+
nix build .#homeConfigurations.thrix.activationPackage --no-link
22+
nix build .#homeConfigurations.mvadkert.activationPackage --no-link
23+
24+
check/bats: ## Run bats unit tests
25+
bats tests/
26+
27+
check: check/nix check/bats ## Run all checks
28+
1829
##@ Home Manager
1930

2031
switch: ## Run home-manager switch

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,50 @@
33
Nix configurations of thrix.
44

55
Used to manage developer laptop based on Bootable Containers and [nix-toolbox](https://thrix.github.io/nix-toolbox).
6+
7+
## Home Manager Modules
8+
9+
### `hostConfig`
10+
11+
Materializes Home Manager symlinks as real files so the Silverblue host can read them from
12+
outside the toolbox container. Useful for any config file that a host-side program (sway,
13+
waybar, foot, firefox) needs to access directly.
14+
15+
#### Usage
16+
17+
In your `flake.nix`:
18+
19+
```nix
20+
inputs = {
21+
nix-config = {
22+
url = "github:thrix/nix-config";
23+
inputs.nixpkgs.follows = "nixpkgs";
24+
inputs.home-manager.follows = "home-manager";
25+
};
26+
};
27+
28+
homeConfigurations."alice" = home-manager.lib.homeManagerConfiguration {
29+
pkgs = nixpkgs.legacyPackages.x86_64-linux;
30+
modules = [
31+
inputs.nix-config.homeManagerModules.hostConfig
32+
./home.nix
33+
];
34+
};
35+
```
36+
37+
In your `home.nix`:
38+
39+
```nix
40+
hostConfig = {
41+
enable = true;
42+
43+
# Automatically materialize all xdg.desktopEntries as real files
44+
xdgDesktopEntries = true;
45+
46+
# Any other Home Manager-managed files the host needs to read
47+
files = [
48+
".config/sway/config"
49+
".config/waybar/config"
50+
];
51+
};
52+
```

flake.nix

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,16 @@
2727
in {
2828
formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.alejandra;
2929

30+
homeManagerModules = {
31+
hostConfig = import ./modules/host-config.nix;
32+
};
33+
3034
homeConfigurations."thrix" = home-manager.lib.homeManagerConfiguration {
3135
inherit pkgs;
3236

3337
modules = [
3438
nixvim.homeModules.nixvim
39+
./modules/host-config.nix
3540
./home.nix
3641
];
3742

@@ -46,6 +51,7 @@
4651

4752
modules = [
4853
nixvim.homeModules.nixvim
54+
./modules/host-config.nix
4955
./home.nix
5056
];
5157

home.nix

Lines changed: 15 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -111,71 +111,21 @@ in {
111111
TESTING_FARM_PUBLIC_IP_RESOLVE_TRIES = 10;
112112
};
113113

114-
# Restore host specific configuration links, before checking link targets
115-
home.activation.restoreNixLinks = lib.hm.dag.entryBefore ["checkLinkTargets"] ''
116-
files="
117-
$HOME/.config/foot/foot.ini
118-
$HOME/.config/sway/config
119-
$HOME/.config/waybar/config
120-
$HOME/.config/waybar/style.css
121-
$HOME/.local/share/applications/mimeapps.list
122-
$HOME/.mozilla/firefox/profiles.ini
123-
$HOME/.mozilla/firefox/${username}/containers.json
124-
$HOME/.mozilla/firefox/${username}/search.json.mozlz4
125-
$HOME/.mozilla/firefox/${username}/user.js
126-
"
127-
128-
for file in $files; do
129-
[ ! -L "$file".lnk ] && continue
130-
echo -e "\e[32mRestoring link '$file' from '$file.lnk'\e[0m"
131-
mv "$file".lnk "$file"
132-
done
133-
'';
134-
135-
# For host configuration we need to create copy of the files, so the host system can see them
136-
home.activation.createHostConfig = lib.hm.dag.entryAfter ["linkGeneration"] ''
137-
files="
138-
$HOME/.config/foot/foot.ini
139-
$HOME/.config/sway/config
140-
$HOME/.config/waybar/config
141-
$HOME/.config/waybar/style.css
142-
$HOME/.local/share/applications/mimeapps.list
143-
$HOME/.mozilla/firefox/profiles.ini
144-
$HOME/.mozilla/firefox/${username}/containers.json
145-
$HOME/.mozilla/firefox/${username}/search.json.mozlz4
146-
$HOME/.mozilla/firefox/${username}/user.js
147-
"
148-
149-
for file in $files; do
150-
# Ignore if the file is an ordinary file, home-manager will replace it if needed
151-
[ ! -L "$file" ] && continue
152-
153-
# Create copy of the symlinked file
154-
echo -e "\e[32mStoring link '$file.lnk'\e[0m"
155-
target=$(readlink -f "$file")
156-
mv "$file" "$file".lnk
157-
158-
echo -e "\e[32mCopying '$target' to '$file'\e[0m"
159-
cp "$target" "$file"
160-
chmod 644 "$file"
161-
done
162-
163-
# NOTE: slack disabled
164-
desktop_entries="
165-
1password
166-
discord
167-
"
168-
169-
for entry in $desktop_entries; do
170-
src="$HOME/.nix-profile/share/applications/$entry.desktop"
171-
172-
# do not break if the file does not yet exist
173-
test -e $src || continue
174-
175-
echo -e "\e[32mCreating desktop entry '$entry.desktop'\e[0m"
176-
cp -f $src $HOME/.local/share/applications
177-
done
178-
'';
114+
hostConfig = {
115+
enable = true;
116+
xdgDesktopEntries = true;
117+
files = [
118+
".config/foot/foot.ini"
119+
".config/sway/config"
120+
".config/waybar/config"
121+
".config/waybar/style.css"
122+
".local/share/applications/mimeapps.list"
123+
".mozilla/firefox/profiles.ini"
124+
".mozilla/firefox/${username}/containers.json"
125+
".mozilla/firefox/${username}/search.json.mozlz4"
126+
".mozilla/firefox/${username}/user.js"
127+
];
128+
};
179129

180130
# For various final configurations
181131
home.activation.toolboxSetup = lib.hm.dag.entryAfter ["reloadSystemd"] ''

modules/host-config-lib.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Shell helpers for host-config activation scripts.
2+
# Sourced at activation time by modules/host-config.nix.
3+
# Also sourced directly by tests/host-config.bats.
4+
5+
_hc_restore_file() {
6+
local _hc_file="$1"
7+
rm -f "$_hc_file.new"
8+
if [ -L "$_hc_file.lnk" ]; then
9+
echo -e "\e[32mRestoring link '$_hc_file' from '$_hc_file.lnk'\e[0m"
10+
mv "$_hc_file.lnk" "$_hc_file"
11+
fi
12+
}
13+
14+
_hc_create_file() {
15+
local _hc_file="$1"
16+
[ -L "$_hc_file" ] || return 0
17+
local _hc_target
18+
_hc_target=$(readlink -f "$_hc_file")
19+
echo -e "\e[32mCopying '$_hc_target' to '$_hc_file'\e[0m"
20+
cp "$_hc_target" "$_hc_file.new" || return 1
21+
mv "$_hc_file" "$_hc_file.lnk"
22+
mv "$_hc_file.new" "$_hc_file"
23+
# Make sure the configuration file is writable, Nix usually generates the files read only (444)
24+
chmod 644 "$_hc_file"
25+
}

modules/host-config.nix

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
config,
3+
lib,
4+
...
5+
}: let
6+
cfg = config.hostConfig;
7+
8+
desktopFiles =
9+
lib.optionals cfg.xdgDesktopEntries
10+
(map (name: ".local/share/applications/${name}.desktop")
11+
(lib.attrNames config.xdg.desktopEntries));
12+
13+
allFiles = cfg.files ++ desktopFiles;
14+
15+
restoreScript =
16+
"source ${./host-config-lib.sh}\n"
17+
+ lib.concatMapStrings (file: ''
18+
_hc_restore_file "$HOME/${file}"
19+
'')
20+
allFiles;
21+
22+
createScript =
23+
"source ${./host-config-lib.sh}\n"
24+
+ lib.concatMapStrings (file: ''
25+
_hc_create_file "$HOME/${file}"
26+
'')
27+
allFiles;
28+
in {
29+
options.hostConfig = {
30+
enable = lib.mkEnableOption "host config file materialization";
31+
32+
files = lib.mkOption {
33+
type = lib.types.listOf lib.types.str;
34+
default = [];
35+
example = [".config/sway/config" ".config/waybar/config"];
36+
description = ''
37+
Home-relative paths to materialize as real files for host access.
38+
Home Manager normally creates symlinks into the Nix store, which the
39+
Silverblue host cannot follow from outside the toolbox container.
40+
Files listed here are copied to real files after each switch.
41+
'';
42+
};
43+
44+
xdgDesktopEntries = lib.mkOption {
45+
type = lib.types.bool;
46+
default = false;
47+
description = ''
48+
When true, automatically materialize all desktop entries declared via
49+
xdg.desktopEntries. Paths are derived directly from that option — adding
50+
a new entry in xdg.desktopEntries is sufficient, no need to list it here too.
51+
'';
52+
};
53+
};
54+
55+
config = lib.mkIf cfg.enable {
56+
home.activation = {
57+
restoreNixLinks = lib.hm.dag.entryBefore ["checkLinkTargets"] restoreScript;
58+
createHostConfig = lib.hm.dag.entryAfter ["linkGeneration"] createScript;
59+
};
60+
};
61+
}

0 commit comments

Comments
 (0)