Add nftables forward rules to prevent sandboxed workspaces from
reaching RFC1918 private addresses while allowing public internet
and the host gateway (for DNS/NAT).
Remove credential passing to sandboxes (didn't work well enough).
Move onboarding config init from host-side setup into base.nix so
each workspace initializes its own Claude config on first boot.
Wrap claude command in VM and Incus workspaces to always skip
permission prompts.
Creates filesystem snapshots before backup for point-in-time consistency.
Uses mount namespaces to bind mount snapshots over original paths, so
restic records correct paths while reading from frozen snapshot data.
- Auto-detects filesystem type via findmnt
- Deterministic snapshot names using path hash
- Graceful fallback for unsupported filesystems
- Add incus.nix module for fully declarative Incus/LXC containers
- Build NixOS LXC images using nixpkgs.lib.nixosSystem
- Ephemeral containers: recreated on each start, cleaned up on stop
- Use flock to serialize concurrent container operations
- Deterministic MAC addresses via lib.mkMac to prevent ARP cache issues
- Add veth* to NetworkManager unmanaged interfaces
- Update CLAUDE.md with coding conventions and shared lib docs
- Add credentials bind mount in container.nix
- Create claude-credentials-dir service to copy credentials for VMs
- Generate .claude.json with onboarding skipped and workspace trusted
- Add allowUnfree to container config
Provides isolated development environments using either VMs (microvm.nix)
or containers (systemd-nspawn) with a unified configuration interface.
Features:
- Unified options with required type field ("vm" or "container")
- Shared base configuration for networking, SSH, users, packages
- Automatic SSH host key generation and persistence
- Shell aliases for workspace management (start/stop/status/ssh)
- Automatic /etc/hosts entries for workspace hostnames
- restartIfChanged support for both VMs and containers
- Passwordless doas in workspaces
Container backend:
- Uses hostBridge for proper bridge networking with /24 subnet
- systemd-networkd for IP configuration
- systemd-resolved for DNS
VM backend:
- TAP interface with deterministic MAC addresses
- virtiofs shares for workspace directories
- vsock CID generation
Music assistant has custom modifications they made to librespot that they haven't bothered to even try to upstream.
Thus, they require a custom librespot. I tried and tried and tried and tried to just override the one already in nixpkgs
but I had trouble doing so despite copying the pattern already shown in nixpkgs for overriding the src of a cargo pkg
(See mopidy) but it just didn't work... Oh well. So I just patch nixpkgs instead with the new source. It works I guess.
This is about where I gave up...
```nix
nixpkgs.overlays = [
(final: prev: {
# Cannot use librespot upstream because music-assistant requires custom changes
# that they never bothered to even try to uptream
librespot = prev.librespot.overrideAttrs (oldAttrs: rec {
src = prev.fetchFromGitHub {
owner = "music-assistant";
repo = "librespot";
rev = "786cc46199e583f304a84c786acb0a9b37bc3fbd";
sha256 = "sha256-xaOrqC8yCjF23Tz31RD3CzqZ3xxrDM6ncW1yoovEaGQ=";
};
cargoDeps = oldAttrs.cargoDeps.overrideAttrs (oldAttrs': {
vendorStaging = oldAttrs'.vendorStaging.overrideAttrs {
outputHash = "sha256-SqvJSHkyd1IicT6c4pE96dBJNNodULhpyG14HRGVWCk=";
};
});
});
})
];
```