Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The script implements a sophisticated Nix installation strategy:
1. **Detection**: Checks if `/nix` directory exists
2. **First-time Setup**: If no Nix store is found:
- Enables `nix-command` and `flakes` in `/etc/nix/nix.conf`
- Creates a bind mount from `$XDG_DATA_HOME/nix` to `/nix`
- Creates a bind mount from `$XDG_DATA_HOME/nix/root/nix/` to `/nix`
- Installs Nix in single-user mode via the official installer
3. **Runtime Mount**: Ensures `/nix` is properly mounted on each container start
4. **Environment Sourcing**: Sources the Nix environment from `~/.nix-profile/etc/profile.d/nix.sh`
Expand All @@ -53,12 +53,14 @@ The script implements a sophisticated Nix installation strategy:

Nix-toolbox uses a bind mount approach for persistent storage:

- **Host Storage**: Nix store is persisted in `$XDG_DATA_HOME/nix` on the host
- **Host Storage**: Nix store is persisted in `$XDG_DATA_HOME/nix/root/nix/` on the host, matching the path used by upstream Nix's user namespace sandboxing.
Existing installs using the legacy `$XDG_DATA_HOME/nix` path are automatically detected and preserved.
- **Container Mount**: Bind-mounted to `/nix` inside the container
- **Benefits**:
- Survives container recreation
- Shares storage between multiple nix-toolbox containers
- Keeps the Nix store outside the container filesystem
- Compatible with host Nix installations using user namespace sandboxing

### Home Manager Integration

Expand Down
98 changes: 98 additions & 0 deletions docs/host-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Host Config Module

When running Home Manager inside a nix-toolbox container on Fedora Atomic Desktops, config files managed by Home Manager are symlinks pointing to `/nix/store/...` paths.
The Nix store data lives on the host at `$XDG_DATA_HOME/nix/root/nix/` (or `$XDG_DATA_HOME/nix` for legacy installs), but the `/nix` bind mount only exists inside the container.
Host-side programs like sway, waybar, foot, or firefox cannot resolve these symlinks — the config files are effectively invisible to the host.
Comment thread
thrix marked this conversation as resolved.

The `hostConfig` Home Manager module solves this by materializing symlinks as real files after each `home-manager switch`.

## How it works

The module generates two Home Manager activation scripts:

1. **`restoreNixLinks`** (runs before `checkLinkTargets`) — restores symlink backups (`.lnk` files) so Home Manager can replace them, and cleans up leftover `.new` temp files from any previous partial run.
2. **`createHostConfig`** (runs after `linkGeneration`) — copies each symlink to a real file using an atomic copy-before-move pattern, so a failed copy never leaves you without a config file.

## Installation

The module is available as a flake output from [thrix/nix-config](https://github.com/thrix/nix-config).

Add it to your `flake.nix`:

```nix
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};

nix-config = {
url = "github:thrix/nix-config";
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
};
};

outputs = { nixpkgs, home-manager, nix-config, ... }: {
homeConfigurations."alice" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
modules = [
nix-config.homeManagerModules.hostConfig
./home.nix
];
};
};
}
```

## Usage

In your `home.nix`:

```nix
hostConfig = {
enable = true;

# Automatically materialize all xdg.desktopEntries as real files
xdgDesktopEntries = true;

# Any other Home Manager-managed files the host needs to read
files = [
".config/sway/config"
".config/waybar/config"
".config/waybar/style.css"
".config/foot/foot.ini"
];
};
```

## Options

### `hostConfig.enable`

Whether to enable host config file materialization.

**Type:** `boolean`
**Default:** `false`

### `hostConfig.files`

Home-relative paths to materialize as real files for host access.
Home Manager normally creates symlinks into the Nix store, which the host cannot follow from outside the toolbox container.
Files listed here are copied to real files after each switch.

**Type:** `list of string`
**Default:** `[]`

### `hostConfig.xdgDesktopEntries`

When `true`, automatically materialize all desktop entries declared via `xdg.desktopEntries`.
Paths are derived directly from that option — adding a new entry in `xdg.desktopEntries` is sufficient, no need to list it in `files` too.

This is useful for sharing Nix-installed desktop applications (such as 1Password, Discord, or Dropbox) with the host's application launcher.

**Type:** `boolean`
**Default:** `false`
15 changes: 12 additions & 3 deletions nix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,17 @@ export GUM_SPIN_SPINNER="points"
export GUM_SPIN_SHOW_ERROR="yes"
export GUM_SPIN_TITLE="Please wait, this might take a while"

# Determine persistent Nix root location (bind-mounted to /nix)
# New installs use upstream-compatible path: $XDG_DATA_HOME/nix/root/nix/
# Existing installs with Nix root directly in $XDG_DATA_HOME/nix/ are preserved
if [ -d "$XDG_DATA_HOME/nix/store" ]; then
NIX_ROOT_DIR="$XDG_DATA_HOME/nix"
else
NIX_ROOT_DIR="$XDG_DATA_HOME/nix/root/nix"
fi
Comment thread
thrix marked this conversation as resolved.

# Ensure /nix is bind-mounted from persistent storage
mkdir -p "$XDG_DATA_HOME/nix"
mkdir -p "$NIX_ROOT_DIR"
if [ -e "/nix" ] && [ ! -d "/nix" ]; then
echo "ERROR: /nix exists but is not a directory; cannot bind-mount persistent Nix store." >&2
exit 1
Expand All @@ -50,8 +59,8 @@ if [ ! -d "/nix" ]; then
sudo mkdir -p /nix
fi
if ! mountpoint -q /nix; then
if ! sudo mount --bind "$XDG_DATA_HOME/nix" /nix; then
echo "ERROR: Failed to bind-mount $XDG_DATA_HOME/nix to /nix." >&2
if ! sudo mount --bind "$NIX_ROOT_DIR" /nix; then
echo "ERROR: Failed to bind-mount $NIX_ROOT_DIR to /nix." >&2
exit 1
fi
fi
Expand Down
Loading