Managing Multiple NixOS Machines with Claude Code via SSH
TL;DR
I’m using Claude Code (Anthropic’s AI CLI) running in a dedicated LXC container to manage multiple NixOS machines via SSH over Tailscale. Instead of writing scripts or using deployment tools, I have a conversational interface that can sync configurations, fix issues, and maintain consistency across machines in real-time.
The Setup
Architecture
Tailscale Mesh Network
|
+------------------+------------------+
| | |
+---------+ +-----------+ +-----------+
|claude-cli| | nixx1 | | nuc-nix |
| (LXC) |--SSH->| (laptop) | | (desktop) |
| Claude | | NixOS | | NixOS |
| Code |--SSH->| | | |
+---------+ +-----------+ +-----------+
- claude-cli: Debian LXC container on Proxmox running Claude Code
- nixx1: ThinkPad X1 Carbon laptop running NixOS
- nuc-nix: ASUS NUC desktop running NixOS
- Network: Tailscale mesh for secure connectivity
Why This Approach?
- Conversational Configuration: Instead of writing deployment scripts, I describe what I want in natural language
- Cross-Machine Context: Claude maintains context about both systems in a single session
- Real-Time Troubleshooting: Fix deprecation warnings, sync packages, update configs interactively
- No Custom Tooling: Just Claude Code + SSH + Tailscale
Example Session
Here’s what a typical session looks like:
Me: "The nixx1 laptop should have the same setup as nuc-nix.
Can you sync their NixOS configs?"
Claude: *SSHs into both machines*
*Compares configuration.nix, home.nix, flake.nix*
*Identifies differences*
*Proposes changes*
*Applies updates*
*Rebuilds both systems*
Me: "There are deprecation warnings, fix them"
Claude: *Identifies the warnings*
*Updates initExtra -> initContent*
*Renames plugins.surround -> plugins.vim-surround*
*Adds web-devicons.enable*
*Rebuilds - no more warnings*
The NixOS Configuration
Both machines run nearly identical configs:
flake.nix inputs:
- nixpkgs (unstable)
- home-manager
- nixvim
- zen-browser
Key features:
- Cosmic Desktop with system76-scheduler
- Nixvim (LazyVim-style) with LSP, telescope, treesitter
- Zsh with Powerlevel10k, vi-mode
- Tmux with resurrect/continuum
- Tailscale with trusted firewall
Machine-specific:
- nixx1: Intel laptop graphics (VA-API)
- nuc-nix: YubiKey/FIDO2 for LUKS unlock
Security Considerations
Since Claude Code has SSH access with sudo privileges, security is important:
# SSH hardening - keys only, no passwords
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false; # Key-only access
};
};
# Tailscale provides the network boundary
networking.firewall = {
enable = true;
trustedInterfaces = [ "tailscale0" ];
allowedUDPPorts = [ config.services.tailscale.port ];
};
Security model:
- SSH key authentication only (no password brute-forcing)
- Tailscale mesh = not exposed to public internet
- YubiKey for SSH keys where possible
- Passwordless sudo is a trade-off for automation (acceptable for homelab)
Context Management with CLAUDE.md
Claude Code reads a CLAUDE.md file for session context. I use a topic-based system:
# CLAUDE.md
## Session Start - ASK FIRST
At the start of each session, ask the user what the topic is:
- notes - Obsidian vault management
- nuc-nix - NixOS desktop setup
- nixx1 - NixOS laptop setup
- email - Email agent system
- new - Fresh topic
Based on answer, read the relevant context file:
- nixx1 -> @topics/nixx1.md
- nuc-nix -> @topics/nuc-nix.md
Each topic file contains:
- System info and IPs
- Current configuration state
- Common commands
- Known issues
What Works Well
- Declarative + Conversational: NixOS’s declarative nature combines perfectly with AI assistance
- Error Recovery: Claude can read error messages and fix them iteratively
- Knowledge Synthesis: Combines NixOS docs, nixpkgs, home-manager knowledge
- Consistency: Easy to keep multiple machines in sync
Limitations
- Context Window: Very long sessions may lose earlier context
- Trust: You’re giving an AI sudo access to your machines
- Debugging: Complex Nix errors sometimes need human understanding
- Cost: Claude API usage for heavy sessions
Try It Yourself
- Install Claude Code:
npm install -g @anthropic-ai/claude-code - Set up Tailscale between your machines
- Configure SSH key access
- Create a
CLAUDE.mdwith your machine details - Start a session:
claude
Questions?
Happy to share more details about the configurationo or answer questions about this approach.
Related tools that complement this approach: