Using GNU Stow for Dotfiles in a DevContainer

GNU Stow turns a dotfiles directory into a tidy symlink farm, and its idempotence makes it a natural fit for a devcontainer's re-running bootstrap. This page uses Stow to link dotfiles into $HOME, so re-runs converge and there's nothing to duplicate.

Prerequisites

You need a Stow-structured dotfiles repo and Stow in the container.

  • A dotfiles repo laid out as Stow packages.
  • stow installed in the image.
  • The dotfiles keys pointing at your repo.

Stow prerequisitesYou need a Stow layout, an apply step, idempotence, and a link check.Stow layoutpackages/stow applysymlink into $HOMEIdempotentre-runs convergeVerifylinks exist

Step-by-Step Implementation

  1. Lay out dotfiles as Stow packages.
dotfiles/zsh/.zshrc
dotfiles/git/.gitconfig
  1. Install Stow and apply in the bootstrap.
#!/usr/bin/env bash
set -e
command -v stow >/dev/null || sudo apt-get install -y stow
cd "$HOME/.dotfiles" && stow zsh git
  1. Point the dotfiles keys at the repo.
{ "dotfiles": { "repository": "https://github.com/you/dotfiles", "installCommand": "install.sh" }, "remoteUser": "vscode" }
  1. Verify the symlinks exist.
readlink ~/.zshrc   # -> .dotfiles/zsh/.zshrc

Stow modelStow symlinks package directories into home idempotently, so re-runs converge.Stow packagesone dir per toolstow <pkg>symlinks into $HOMEIdempotentre-apply is a no-opResulttidy, reversible dotfiles

Common Pitfalls

Stow issues are conflicts with existing files or a wrong layout.

Stow triageA triage path from a Stow conflict to a clean, idempotent symlink farm.Does stow report a conflict?YESAdopt or remove the existing fileIs the package layout correct?YESRe-apply is idempotentClean symlinked dotfiles

SymptomRoot CauseRemediation
stow: conflict on existing fileA real file blocks the symlinkRemove/adopt it, then re-stow
Nothing gets linkedWrong package directory layoutStructure as package/relative-path
Re-run duplicates nothing but errorsAlready-linked treated as conflictUse --restow to refresh
stow not foundNot installed in the imageInstall stow in the bootstrap or image

Conclusion

GNU Stow makes dotfiles a reversible symlink farm: each package directory maps into $HOME, and re-applying is idempotent, so a devcontainer's re-running bootstrap converges cleanly. Structure your repo as Stow packages and the bootstrap stays trivially correct.

Stow summaryStow gives idempotent, reversible dotfiles given a package layout.Stow givesIdempotent linkingReversible setupClear structureNeedsPackage layoutStow installedConflict-free $HOME

FAQ

Why use Stow over a hand-written symlink script? Stow is idempotent and reversible by design: re-applying converges, and stow -D cleanly removes links. A devcontainer re-runs the bootstrap on every create, so Stow's convergence means no duplicated links or accumulated state, without hand-guarding every ln.

How should I lay out a Stow dotfiles repo? One package directory per tool, mirroring the path relative to $HOME. For example zsh/.zshrc and git/.gitconfig; running stow zsh git links ~/.zshrc and ~/.gitconfig. The structure makes what-links-where obvious.

What if a real file already exists where Stow wants a link? Stow reports a conflict rather than clobbering it. Remove or adopt the existing file (Stow's --adopt can absorb it into the package), then re-stow. This safety is why Stow is predictable in a shared bootstrap.