Managing Multiple NixOS Machines with Claude Code via SSH

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?

  1. Conversational Configuration: Instead of writing deployment scripts, I describe what I want in natural language
  2. Cross-Machine Context: Claude maintains context about both systems in a single session
  3. Real-Time Troubleshooting: Fix deprecation warnings, sync packages, update configs interactively
  4. 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

  1. Declarative + Conversational: NixOS’s declarative nature combines perfectly with AI assistance
  2. Error Recovery: Claude can read error messages and fix them iteratively
  3. Knowledge Synthesis: Combines NixOS docs, nixpkgs, home-manager knowledge
  4. Consistency: Easy to keep multiple machines in sync

Limitations

  1. Context Window: Very long sessions may lose earlier context
  2. Trust: You’re giving an AI sudo access to your machines
  3. Debugging: Complex Nix errors sometimes need human understanding
  4. Cost: Claude API usage for heavy sessions

Try It Yourself

  1. Install Claude Code: npm install -g @anthropic-ai/claude-code
  2. Set up Tailscale between your machines
  3. Configure SSH key access
  4. Create a CLAUDE.md with your machine details
  5. 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:

  • mcp-nixos - MCP server for NixOS package/option search
  • nixai - AI-powered NixOS CLI assistant
1 Like

effortless post, we go next

6 Likes

Neat!

NixOS works really well with the slopcoding I’ve been doing. The thing that I’m still fiddling with is making it easy to spin up truly isolated VMs and plugging them in–most of the normal approaches we use w/ Nix aren’t paranoid enough for my taste.

1 Like