Build an AI homelab that works like one computer
Most AI homelab advice starts with a shopping list. Buy a rack. Buy a GPU. Install Kubernetes. That is backwards.
The useful lab is the one where you can sit at any laptop, enter one command, and reach the right code, compute, secrets, browser state, logs, and backups.
It may contain a Mac mini under a desk, a louder server in another room, and three cloud workers rented for an afternoon. From your terminal, they should feel like parts of one computer.
That is the future-ready version of a homelab: not a shrine to hardware, but a small software factory that humans and agents can operate without stepping on each other.
You do not need every tool in this guide. You need a few strong defaults, a reason for each addition, and a recovery path for the morning one of them breaks.
What you are actually building
An AI homelab has five planes.
- The network plane gives every machine a stable private identity.
- The control plane lets you enter, inspect, start, stop, and resume work.
- The work plane gives each job its own code, runtime, secrets, and permissions.
- The data plane moves source, artifacts, caches, and backups deliberately.
- The recovery plane tells you what failed and lets you rebuild without folklore.
The machines are almost incidental. A base Mac mini is a fine quiet worker. A Linux box is often a better container host. A rented GPU is sensible when it would otherwise sit idle.
The architecture matters more than the logo on the enclosure.
If control planes, data planes, and failure boundaries are new terms, Fanout's system design path builds those models from first principles.
The goal is not identical machines. The goal is identical ways to reach them, run projects on them, and understand their state.
The 80/20 stack
Start with this. Add nothing else until the omission hurts.
- Tailscale gives every machine a private network address and name.
- SSH, Mosh, and tmux make remote work fast, resilient, and resumable.
- Git worktrees give every agent or task a separate branch and folder.
- SMB handles ordinary file sharing between nearby Macs.
- 1Password CLI supplies secrets without scattering plaintext env files.
- mise and direnv load the right runtimes and environment when you enter a project.
- OrbStack runs containers and Linux machines efficiently on a Mac.
- pnpm stops fourteen worktrees from storing fourteen complete dependency trees.
- just gives every project the same small command surface.
- chezmoi makes your shell and dotfiles reproducible without pretending every host is identical.
- restic plus Backblaze B2 creates encrypted offsite backups.
- Netdata tells you what the machines are doing.
- Atuin, zoxide, and fzf make the command line feel continuous across hosts.
This stack is boring on purpose. It solves identity, access, concurrency, environment drift, secrets, recovery, and visibility before it solves orchestration theatre.
Build it in 12 steps
You need only the computer you use every day and one worker to begin. The worker can be a Mac mini, an old desktop, a Linux server, or a rented VM. Do not buy a rack or GPU first.
- Give each machine one job. Use your daily computer to edit and steer work. Use the second machine for long-running jobs, containers, builds, or storage.
- Install Tailscale on both machines. Confirm that each one can reach the other by its Tailscale name before adding anything else.
- Create a short SSH alias for the worker. The goal is to type ssh studio or ssh build instead of remembering an address, user name, and port.
- Install Mosh and tmux on the worker. Start a named tmux session, disconnect, change networks, reconnect, and confirm that the job is still running.
- Keep the repository on the worker. Use VS Code or Cursor Remote SSH when you want a graphical editor, so the code and tools stay beside the compute.
- Create one Git worktree and branch for every active task or agent. Never let two agents edit the same working folder.
- Add mise, direnv, pnpm, and a justfile to one real project. Make the same short commands start, test, and build it on every machine.
- Run risky or dependency-heavy jobs inside OrbStack or another container runtime. Mount only the project files that the job needs.
- Move reusable credentials into 1Password CLI or SOPS. Give each worker access only to the vaults and secrets required for its role.
- Choose file movement by job. Use Git for code, SMB for shared local folders, rsync for one-off copies, and Syncthing only for notes or assets.
- Keep services private with Tailscale Serve. Add Funnel, ngrok, Cloudflare Tunnel, or Caddy only when a specific service must receive public traffic.
- Back up the worker with restic, restore a sample into an empty folder, then add one machine dashboard and one uptime alert.
Stop after step four on the first evening. After step eight, the lab is useful for daily work. The last four steps turn it from a convenient remote computer into dependable infrastructure.
Everything below explains the choices and alternatives. You can read it when a step creates a real question.
Networking: make the machines disappear
The first milestone is simple: every machine can reach every other machine by a stable name, without exposing SSH to the public internet.
Tailscale
Tailscale creates an encrypted private network across machines that may be at home, in an office, or in a cloud region.
Install it everywhere. Give machines names based on roles, not temporary projects: studio, mini, build-linux, gpu-east.
Direct peer-to-peer paths are ideal, but Tailscale can relay traffic when NAT traversal fails. Measure the route before blaming the remote machine for poor performance.
Tailscale SSH can use tailnet identity and policy instead of a hand-maintained pile of authorized keys.
Thunderbolt Bridge
Two nearby Macs can communicate over IP through a Thunderbolt cable. Apple documents the setup as IP over Thunderbolt.
It can deliver tens of gigabits per second with very low latency on compatible hardware. That is useful for large model files, build artifacts, and storage mounted from the Mac beside you.
Use a real Thunderbolt cable. A USB-C connector does not guarantee Thunderbolt capability or speed.
2.5 and 10 Gigabit Ethernet
Ethernet is the less delicate answer when machines are farther apart, the connection must survive reboots, or several hosts share one storage server.
Move to 2.5GbE when ordinary gigabit transfers are visibly blocking work. Move to 10GbE when the storage, cables, switch, and disks can actually feed it.
A 10GbE link does not make a slow single disk or remote filesystem ten times faster. Test the whole path.
Cloudflare Tunnel
Cloudflare Tunnel runs an outbound-only connector from your machine to Cloudflare.
That gives a local website, API, or dashboard a public hostname without a publicly routable origin IP or an inbound router rule.
Use it for a durable public service that should pass through Cloudflare policy and edge protection. It is not a reason to skip application authentication.
ngrok
ngrok is the fast temporary option. Point it at a local port and receive a public URL in seconds.
It is excellent for webhook development, demos, and a callback that only needs to exist for an hour.
Treat the URL as public. Add authentication or provider signature verification before sending real data through it.
Remote access: work where the compute lives
Copying a repository between machines is usually the wrong default. Keep the code beside the compute and move the editor or terminal experience.
SSH config
Put stable hosts in SSH config so the network disappears behind names.
Then ssh studio, ssh build, and ssh gpu are enough. The config owns user names, host names, identity files, jump hosts, and port forwards.
Keep host aliases role-based. An IP address is plumbing, not a user interface.
ControlMaster
OpenSSH connection sharing lets later sessions reuse one authenticated connection.
With ControlMaster auto, ControlPath, and a reasonable ControlPersist value, the second terminal appears immediately instead of repeating key exchange and authentication.
Do not use a shared control socket on a machine or account you do not trust. The socket is authority.
Mosh
Mosh is for the terminal that must survive Wi-Fi changes, laptop sleep, and roaming between networks.
It is not a full SSH replacement. Use SSH for authentication and file transfer; use Mosh for the long interactive shell.
tmux
tmux keeps the program on the remote machine when your laptop disconnects.
Give long agent runs, dev servers, and log tails named sessions. Attach later from another device and the process is still there.
tmux-resurrect saves pane layouts and selected process state. tmux-continuum automates saves and restores.
They improve recovery after a reboot. They do not make every arbitrary process magically checkpointable.
Remote editors
VS Code Remote SSH keeps the interface local while the repository, terminal, extensions, debugger, and language services run on the host.
Cursor follows the same basic model. This feels local because it does not pretend a remote filesystem is a fast local disk.
code-server is useful when the client is an iPad or an unconfigured computer. The editor runs in a browser, so put it behind strong authentication and private access.
Remote desktop
macOS Screen Sharing is already on the Mac and is good enough for ordinary administration.
Sunshine plus Moonlight uses game-streaming techniques for much lower latency.
Use remote desktop only when the workload is graphical. A terminal should not depend on a video stream.
Serving: choose who is allowed to reach it
Running a service and publishing a service are different decisions.
Tailscale Serve
Tailscale Serve places HTTPS in front of a local service and keeps it inside the tailnet.
This is the default for dashboards, preview builds, model endpoints, and tools intended only for you or your team.
Tailscale Funnel
Tailscale Funnel makes a specific local service reachable from the public internet.
It is useful for webhooks and a small public demo. Funnel has port, platform, and bandwidth constraints, so check the current documentation before treating it as general ingress.
Caddy
Caddy is a calm reverse proxy for a machine that owns its public endpoint.
It can obtain and renew HTTPS certificates automatically and makes a small reverse-proxy setup genuinely small.
Automatic TLS still requires correct DNS, reachable challenge paths, and sensible application security.
Cloudflare Tunnel
Choose Cloudflare Tunnel when public traffic should enter through Cloudflare and the origin should keep outbound-only connectivity.
Choose Tailscale Serve when the service is private. Choose Funnel or ngrok for narrow temporary public reach. Choose Caddy when you own the host and ingress path.
The tool follows the trust boundary.
Files: separate source, shared data, and artifacts
The dangerous phrase in a multi-machine lab is “everything syncs.”
Code needs version history and merge semantics. Assets may need continuous sync. A model checkpoint may need one fast copy. Those are different jobs.
Git and worktrees
Git is the source of truth for code that people or agents edit.
Use one branch per task. Use Git worktrees to open those branches as separate folders without cloning the object database again.
One agent gets one worktree, one tmux session, and one branch. You can inspect its diff without opening its conversation.
Jujutsu is Git-compatible and makes undo, rebasing, and concurrent change management less ceremonial.
Try jj when branch manipulation itself becomes the bottleneck. Do not introduce it only because the name is new.
Shared folders
SMB is the easiest mounted-folder answer for Macs on one network. Turn on File Sharing, expose a narrow folder, and mount it where tools expect local paths.
NFS can perform better for some Unix-heavy workloads, but its identity and permission model deserves deliberate setup.
Use shared filesystems for datasets, artifacts, and media. Do not point several independent package managers or databases at one casual network share.
Continuous file movement
Mutagen mirrors a local project to a remote machine with rules for ignored files and conflicts.
Use it when local editing is non-negotiable but execution must happen beside remote compute.
Syncthing is excellent for notes, assets, and scratch directories shared directly between machines.
Do not use Syncthing as version control for a repository several agents edit. It moves files; it does not understand branches, commits, or semantic conflicts.
One-off and cloud copies
rsync is the default for one fast, scriptable copy over SSH.
rclone applies a similar command-line model to S3, R2, B2, Google Drive, and many other storage providers.
Use checksums for important transfers. “The command exited zero” is weaker than verifying the bytes you plan to use.
Dependency storage
pnpm stores package content once and links it into projects.
That matters when a repository has many worktrees. Each worktree still gets an independent node_modules view without duplicating every package payload.
Keep the pnpm store on a fast local disk. Sharing it casually over a network filesystem can erase the latency win.
Environment: make projects portable, not hosts identical
Reproducibility has levels. Choose the cheapest level that removes a real source of drift.
mise and direnv
mise manages project runtime versions for Node, Python, Go, Ruby, and other tools in one place.
direnv loads and unloads directory-specific environment variables as you enter and leave a project.
Together they cover most personal and small-team labs. Approve direnv files carefully because entering a directory can execute shell code.
OrbStack, Colima, and containers
OrbStack is a polished Docker Desktop replacement for macOS with containers, Linux machines, and tight host integration.
Colima is the free CLI-first option when you want a straightforward local container runtime.
Containers give a workload its own filesystem view and dependency graph. They do not become a security boundary merely because a Dockerfile exists.
Homebrew and Brewfile
Homebrew Bundle records formulae, casks, taps, and selected app-store installs in a Brewfile.
It is an inventory and bootstrap tool, not a perfect snapshot. Versions and remote packages can change between runs.
Dev containers
The Development Container Specification records the tools and settings a project needs inside a container.
It is a good bridge between a laptop, a remote host, CI, and a cloud workspace because the project carries its development environment.
Nix and devenv
Nix and devenv can reproduce environments much more precisely.
Pay the learning cost when binary inputs, system libraries, or cross-machine determinism are causing real failures. Do not begin there to feel rigorous.
Secrets: machines get access, files do not get secrets
A lab becomes dangerous when every worker accumulates copied API keys and nobody knows which process can read them.
Start with one rule: source control may contain secret references and encrypted ciphertext, never reusable plaintext credentials.
1Password CLI
1Password CLI can resolve secret references and supply values to a child process.
With op run, the values live in that process environment for its lifetime instead of being pasted into a permanent env file.
Environment variables can still leak through logs, crash reports, child processes, or careless diagnostics. Runtime injection reduces exposure; it does not abolish it.
1Password Service Accounts give a headless worker access to specific vaults without attaching it to a personal login.
Use one service account per trust boundary. A build worker does not need the vault used by a production deployment worker.
SOPS and age
SOPS encrypts secret values while keeping structured files usable in Git. age provides a small key system for offline identities.
This is a good fit when a service needs a file at startup, the encrypted form belongs in the repository, and approved machines can decrypt it.
Plan key recovery before encrypting the only copy of something important.
Tailscale SSH
Tailscale SSH authorizes access with tailnet identity and policy.
It reduces public-key distribution work, but it centralizes trust in the tailnet control plane and policy. Keep a tested break-glass path for a machine you physically own.
Terminal: one memory across every host
The terminal is the thinnest useful control plane. Make it fast before building a dashboard.
History and navigation
Atuin syncs and searches shell history across machines. Encrypt the sync and decide whether sensitive commands should ever enter history.
zoxide learns frequently used directories, so z api can replace a brittle chain of parent-directory jumps.
fzf adds fuzzy selection to history, files, branches, processes, and SSH hosts.
Everyday inspection
ripgrep searches code quickly and respects ignore rules by default.
fd is a friendlier file finder for ordinary interactive use.
bat adds syntax, line numbers, and Git context to file previews.
dust makes disk usage legible before a cache fills the drive.
lazygit gives staging, history, rebasing, cherry-picking, and conflict work a visual terminal interface.
btop shows live CPU, memory, disk, network, and process state without requiring a monitoring stack.
These tools do not make a lab sophisticated. They shorten the loop between noticing a problem and finding its cause.
Consistency: give people and agents the same verbs
The best infrastructure documentation is executable and close to the project.
just
just puts project commands behind stable names.
If just dev, just test, just backup-check, and just deploy work everywhere, a human and an agent begin from the same interface.
Keep recipes small and unsurprising. A command named test should not mutate production.
chezmoi
chezmoi keeps dotfiles in version control while allowing templates, machine-specific values, and secret-manager integrations.
Use it for shell configuration, editor defaults, aliases, SSH snippets, and bootstrap scripts. Do not force Linux and macOS to pretend they have the same paths.
The rebuild quartet
Brewfile records installed Mac tools. mise records project runtimes. chezmoi records personal configuration. just records project actions.
Together they answer four different rebuild questions without one giant installer script trying to own the world.
Rebuild one spare machine from these files before declaring the setup reproducible.
Isolation: assume an agent will make a bad decision
An AI agent with shell access is a fast junior operator with unusual persistence. Give it narrow authority and an easy-to-delete workspace.
Containers
Mount only the repository and credentials a workload needs. Run as a non-root user. Restrict network reach when the job does not need the internet.
One container per client or trust boundary is useful because files that were never mounted cannot be read accidentally.
Do not mount the Docker socket into an agent container unless you intend to grant near-host-level control.
Podman
Podman supports daemonless and rootless container workflows.
Use it when rootless operation and a Docker-compatible command model matter more than seamless Mac desktop integration.
Virtual machines
Tart manages macOS and Linux virtual machines on Apple Silicon.
UTM and Parallels provide full graphical machines for workloads that need an operating system, not only a process filesystem.
Firecracker starts small microVMs quickly on Linux. It belongs in platforms that need a machine-shaped boundary per run, not in a first-week Mac setup.
The stronger the isolation, the higher the cost in startup, storage, observability, and debugging. Match it to the blast radius.
Fanout's Timeout Architect lab is a small way to practise budgets, retries, and failure boundaries before applying them to long agent runs.
Agent orchestration: start with inspectable primitives
Do not buy a fleet manager before you have a fleet.
tmux and worktrees
tmux plus Git worktrees is the simplest useful agent control plane.
Every task gets a terminal, folder, branch, name, and log you can inspect directly. Completion is a diff, not a green light in a dashboard.
This arrangement scales surprisingly far because it preserves the two things agents make easy to lose: provenance and human visibility.
Claude Code automation
Claude Code hooks can run validation, formatting, notifications, and cleanup around tool or lifecycle events.
Claude Code subagents split focused tasks into separate contexts.
Hooks are code execution. Review them like project scripts, especially when a repository can supply its own configuration.
The Claude Agent SDK is the step from terminal practice to product code: start sessions, stream events, expose tools, and steer execution programmatically.
Build that layer only after the manual lifecycle is clear enough to encode.
Durable jobs
Inngest and Trigger.dev turn runs into durable background jobs with retries, state, and observability.
BullMQ is a direct Redis-backed queue. Graphile Worker provides a PostgreSQL-backed queue.
Use launchd on macOS and systemd on Linux to start local workers after reboot and restart failed services.
Temporal is for workflows whose steps must survive process and infrastructure failures over a long time.
Temporal is powerful. It is also unnecessary until “resume exactly here after failure” is a product requirement rather than a hypothetical virtue.
Rented compute: own the baseline, rent the spike
The home machine is good at steady, private, already-paid work. The cloud is good at bursts, special hardware, and regions near collaborators or services.
Persistent CPU workers
Hetzner dedicated servers offer substantial persistent CPU and memory for workloads that run all day.
The Hetzner Server Auction lists older dedicated hardware at lower prices. Inspect disks, location, and replacement expectations before optimizing for the headline price.
DigitalOcean, Vultr, and Akamai Connected Cloud can cost more per gigabyte, but a nearby region may make interactive SSH and remote editing feel better.
Latency is a feature when a person is in the loop.
Elastic workers and builds
Fly Machines can start small machines quickly and stop them when idle.
GitHub Actions self-hosted runners send workflow jobs to hardware you control.
Do not attach a general self-hosted runner to untrusted pull requests. Workflow code can become host access.
Depot moves container and application builds to remote builders with shared caching.
Rent faster builds when build time is the bottleneck. Do not move builds merely to add another dashboard.
GPUs and Macs
Modal, RunPod, and Lambda let you rent GPUs by the hour. Compare availability, storage, cold start, egress, and framework support, not only the GPU model.
MacStadium and Scaleway Apple Silicon provide real remote Macs.
Rent macOS only when Xcode, Apple platform testing, signing, or another real macOS dependency demands it. Linux is usually the simpler worker.
Browser automation: move sessions, not Chrome profiles
Browsers are stateful, security-sensitive workers. Treat them as disposable compute with explicitly managed identity.
Playwright
Playwright storageState saves cookies, local storage, and related login state for reuse in a browser context.
The file can impersonate the account. Keep it out of Git, encrypt it at rest, scope the account, and rotate it.
This is more portable and reviewable than syncing an entire Chrome profile, which also carries extensions, caches, locks, and unrelated personal state.
Puppeteer is a smaller Chrome-focused choice when Playwright's cross-browser features are unnecessary.
Agent control
Chrome DevTools MCP lets an agent inspect and control Chrome through developer tooling.
browser-use provides a higher-level agent interface for navigating and acting on websites.
The higher the abstraction, the more important screenshots, logs, action limits, and approval boundaries become.
Hosted browsers
Browserbase, Browserless, and Steel manage remote browser processes, concurrency, and session infrastructure.
Add one when a single local Chrome has become a queue or when browser crashes should not affect the rest of the lab.
Residential proxies route traffic through consumer networks. They carry legal, contractual, privacy, and abuse risks.
Use them only for a legitimate need after checking the target site's terms and the proxy provider's sourcing. They are not a default reliability tool.
Safety: recovery is part of the architecture
If the lab can run unattended work, it must also report failure, preserve history, and restore data.
Offsite backups
restic creates encrypted, deduplicated snapshots and supports B2 and other backends.
Backblaze currently lists B2 pay-as-you-go storage at $6.95 per terabyte per month. Pricing can change, so treat the live page as authoritative.
Run automated snapshots, retention, repository checks, and a scheduled restore into an empty temporary directory.
A backup is not real because the command succeeded.
It is real when you have restored from it successfully.
Local Mac recovery
Time Machine gives convenient local file versions and a familiar restore path. It is necessary for many Mac users and insufficient as the only copy.
Carbon Copy Cloner and SuperDuper create detailed local copies and support fast recovery workflows.
On modern macOS, do not assume a clone is automatically bootable. Apple system-volume changes make bootability conditional, and CCC does not attempt it by default.
Test the restore path that your actual Mac and macOS version support.
Visibility
Netdata installs a broad live metrics dashboard quickly.
On macOS, memory_pressure answers whether the system is under usable-memory pressure. vm_stat shows pages and paging. sysctl vm.swapusage shows swap consumption.
asitop exposes Apple Silicon CPU, GPU, power, and thermal information.
Uptime Kuma checks endpoints and alerts when they fail.
Prometheus and Grafana are worth the effort when several machines need historical metrics and shared alerts.
Do not build the observability cathedral first. Start with one dashboard, one uptime check, and one alert you will actually act on.
The rule for every tool after this
Add a tool only when you can name the failure or delay it removes.
“It is popular in homelabs” is not a reason. “Three agents keep corrupting one checkout” is a reason for worktrees. “A laptop disconnect kills overnight work” is a reason for tmux.
The strongest AI homelab is not the one with the most machines.
It is the one where compute is reachable, work is isolated, secrets are scoped, state is visible, and recovery has already been rehearsed.
Build that, and a Mac, a server, and a cloud worker stop feeling like three computers.
They become one dependable place to make software.