Renix

Inspiration

Renix began while I was using Time Machine backups but preparing to move back to Linux. Time Machine provided a convenient recovery path on macOS, but I wanted something portable across operating systems and focused on rebuilding my environment rather than restoring one machine image.

I wanted to make my system as declarative as possible. Applications, development tools, shell configuration, desktop preferences, services, and other settings should be defined as code instead of reconstructed from memory.

At the same time, I still wanted to maintain a macOS build. When I switched back to a Mac, I did not want to discover that my development environment, tools, and configuration had drifted out of sync. Renix lets Linux and macOS share a common foundation while retaining the settings each platform needs.

I kept coming back to one question: What would happen if my laptop were lost, damaged, or stolen?

The vision was simple. I could walk into a store, buy a replacement laptop, run a few commands, and restore a nearly identical environment with my tools, preferences, and system configuration ready to use.

Renix is not just another bootstrap script that installs a list of packages and then gets forgotten. Bootstrapping is only the starting point. Renix continues to manage the system after setup by rebuilding configuration, synchronizing changes, discovering updates, cleaning old generations, and providing a safe path to roll back. It is intended to support the entire lifecycle of a machine, from its first installation to its eventual replacement.

What it does

Renix provides a unified command for managing Nix-based Linux and macOS systems. It can:

  • Bootstrap a new machine from a reproducible configuration
  • Keep development environments consistent across Linux and macOS
  • Rebuild and apply the correct host configuration
  • Restore applications, tools, preferences, and dotfiles
  • Preview flake and package updates
  • Discover and update custom packages
  • Synchronize configuration through Git
  • Show system and storage information
  • Clean old generations
  • Roll back safely

How I built it

Renix combines Nix flakes, shell scripting, Python, Git, NixOS, nix-darwin, and Home Manager.

Nix defines each machine and its packages. Shared modules keep the core development environment aligned across platforms, while host-specific modules handle differences between machines. Home Manager restores the user environment and dotfiles. Shell code coordinates system operations, while Python performs structured, concurrent package-version discovery.

Custom package updates are described through a declarative manifest. This separates package-specific metadata from the update engine and makes additional update sources easier to support.

Challenges

The biggest challenge was producing one consistent experience across Linux and macOS while respecting their different configuration and rebuild systems. The shared configuration needed to prevent drift without pretending the two platforms were identical.

Custom packages introduced another challenge. Releases can come from GitHub, npm, PyPI, crates.io, redirects, and static downloads. Renix needed to discover versions, update hashes, support architecture-specific assets, and avoid unsafe changes.

I also had to balance automation with safety. Renix previews changes, validates the selected host, asks before mutations, and preserves previous Nix generations for rollback.

What I learned

I learned that backups and declarative configuration solve different parts of recovery. Backups preserve personal data, while declarative configuration describes how to reconstruct the system that uses it. Together, they create a more complete recovery strategy.

I also learned that cross-platform consistency does not require identical systems. A shared declarative foundation can keep development tools and workflows synchronized while allowing Linux and macOS to retain their platform-specific behavior.

What’s next

The long-term vision is to make a computer replaceable without making its environment disposable. If an incident occurs, a replacement machine should be only a few commands away from feeling like the previous one.

I plan to add more update sources, stronger validation, improved reporting, and an even smoother bootstrap process for new machines.

Built With

  • automation
  • bash
  • configuration-management
  • cross-platform
  • declarative-configuration
  • developer-tools
  • devops
  • disaster-recovery
  • dotfiles
  • git
  • github
  • home-manager
  • infrastructure-as-code
  • linux
  • macos
  • nix
  • nix-darwin
  • nix-flakes
  • nixos
  • package-management
  • python
  • reproducible-builds
  • shell-scripting
  • system-automation
Share this project:

Updates