The Hidden Cost of "Works on My Machine"

Every seasoned sysadmin has lived this nightmare: a critical production server dies at 3 AM. The replacement hardware is ready—but nobody can remember exactly which packages were installed, which PPAs were added six months ago, or why that one Perl script only works on the old box.

We've long accepted Infrastructure as Code (IaC) for our servers. Terraform plans, Ansible playbooks, and Puppet manifests govern our data centers with ruthless consistency. Yet our workstations—the very machines we use to orchestrate that infrastructure—remain islands of tribal knowledge, drifting slowly into unique, unrepeatable snowflakes.

Why Package State Matters (And Why You Can't Remember It)

A Debian workstation is a living system. Over months or years, it accumulates:

  • Development toolchains installed for one-off projects
  • PPAs and third-party repositories added to get newer versions
  • Configuration files tweaked in /etc and forgotten
  • Security tools, monitoring agents, and utilities layered atop each other

dpkg --list might show 2,000+ packages, but which ones did you intentionally install? The crucial web of dependencies—libssl-dev for that Ruby gem, pkg-config for the Rust build, libpq-dev for PostgreSQL support—is invisible six months later.

Configuration Drift: The silent killer of reproducibility. Two machines that started from the same ISO diverge over time as individual needs drive unique modifications. When disaster strikes, you don't have a blueprint—you have archaeology.

The Declarative Solution

Imperative configuration means running commands: sudo apt install nginx, pip install requests. It describes how to reach a state. Declarative configuration describes the desired end state itself:

packages.toml
# This file IS the state of the system
[apt.essentials]
packages = ["git", "curl", "vim", "htop", "tmux"]

[apt.development]
packages = ["build-essential", "python3-dev", "python3-pip", "nodejs", "npm"]

[apt.security]
packages = ["ufw", "fail2ban", "lynis"]

[sources]
ppas = ["deadsnakes/ppa", "git-core/ppa"]

[flatpak]
applications = ["com.spotify.Client", "org.videolan.VLC"]

With a declarative approach, the configuration file becomes the source of truth. The tool figures out how to get there. This is the same philosophy behind Kubernetes manifests, Docker Compose files, and Terraform HCL—and it belongs on your workstation just as much.

Repro: Package Management as Infrastructure Code

Repro treats your Debian workstation as infrastructure worthy of the same rigor as your production fleet. It converts the chaos of manual package management into version-controlled, auditable, reproducible configuration.

Core Principles

  • Single Source of Truth: One TOML file describes your entire environment
  • Idempotent Operations: Running apply multiple times produces the same result
  • Multi-Source Awareness: apt, snap, flatpak, cargo, npm, pip—all tracked
  • Drift Detection: Know immediately when reality diverges from intent

From Bare Metal to Battle-Ready

Here's the real power: rebuilding from scratch becomes a standardized procedure rather than an adventure into forgotten decisions.

Scenario 1: New Developer Onboarding

Your company hires a new backend developer. Traditionally, they'd spend days installing tools, hunting for the right PostgreSQL version, and discovering that the team uses nvim with a specific plugin setup. With version-controlled package lists:

terminal
# On a fresh Debian install
$ sudo apt update && sudo apt install git

$ git clone https://github.com/acmecorp/workstation-configs.git
$ cd workstation-configs/backend-team

$ cat environment.toml
[apt]
base = ["curl", "wget", "jq", "httpie", "postgresql-client", "redis-tools"]
devtools = ["docker.io", "docker-compose", "kubectx", "helm", "tilt"]

[docker]
images = ["postgres:15", "redis:7-alpine"]

[npm.global]
packages = ["@angular/cli", "typescript", "nodemon"]

$ repro apply
[INFO] Parsing environment.toml...
[INFO] Found 16 packages to install
[INFO] Configuring Docker daemon...
[INFO] Pulling container images...
[INFO] Complete. Ready for development.

The new developer is productive in minutes, not days. The environment matches every other team member's exactly.

Scenario 2: The Failed SSD Recovery

Your laptop's SSD dies catastrophically. No backup (because you're that person). But your packages.toml was pushed to Git last week. On the replacement machine:

rebuild-workstation.sh
#!/bin/bash
# Emergency workstation rebuild script

set -e

# Base system
sudo apt update && sudo apt upgrade -y

# Fetch configuration
git clone https://github.com/youruser/dotfiles.git ~/dotfiles
cd ~/dotfiles

# Install Repro
curl -fsSL https://repro-cli.dev/install.sh | bash

# Restore EVERYTHING
repro apply --config ./packages.toml

# Restore dotfiles
stow vim starship git tmux

echo "Workstation rebuilt. Welcome back."

The script is the same whether you're restoring yesterday's configuration or last year's. The version-controlled package list guarantees consistency across time.

Preventing Drift with Continuous Reconciliation

Infrastructure teams run configuration management continuously because systems drift. Your workstation is no different. Repro's sync command acts as a reconciliation loop:

terminal
$ repro sync --dry-run
[DRIFT DETECTED] 3 packages installed but not in config:
  - ansible (manually installed last Tuesday)
  - k9s (kubectl replacement you tried)
  - cargo-watch (for that Rust project)

[DRIFT DETECTED] 1 configured package removed:
  - flameshot (removed during cleanup?)

Run 'repro sync' to update config or 'repro remove' to align system.

Like Prometheus alerting on metric anomalies, Repro alerts on configuration anomalies. You're not just documenting what should be installed—you're maintaining a contract between intent and reality.

Advanced: Environment Templates

Devops engineers often context-switch between projects with conflicting requirements. One needs Python 3.9, another demands 3.11. Rather than polluting your system with version managers, define project-specific environments:

environments/legacy-api.toml
# Legacy microservice stack
[apt]
runtime = ["python3.9", "python3.9-venv", "python3.9-dev"]
database = ["postgresql-13", "pgadmin3"]
cache = ["memcached", "redis-server"]

[python]
requirements = "requirements-legacy.txt"
virtualenv = ".venv-legacy"

[npm]
version = "16"
packages = ["pm2@4.5.0"]

[services]
enabled = ["postgresql", "redis", "memcached"]
environments/modern-platform.toml
# Greenfield platform project
[apt]
runtime = ["python3.11", "python3.11-full", "rustc", "cargo"]
database = ["postgresql-15", "timescaledb-postgresql-15"]
observability = ["prometheus-node-exporter", "grafana"]

[python]
requirements = "requirements-modern.txt"
virtualenv = ".venv-modern"

[rust]
components = ["clippy", "rustfmt", "rust-analyzer"]

[services]
enabled = ["postgresql", "prometheus-node-exporter"]

Switch between project contexts with repro apply --file environments/legacy-api.toml. Your workstation shape-shifts to match requirements, then returns to baseline when you switch back.

Version Control as Audit Trail

With your environment in Git, you gain superpowers:

  • Blame for Infrastructure: git log -p packages.toml reveals when vault was added and why
  • Rollback Capability: git checkout HEAD~5 -- packages.toml && repro apply undoes problematic changes
  • Code Review for Tools: New packages get reviewed just like code dependencies
  • Cross-Machine Synchronization: git pull && repro apply keeps laptop and desktop identical
terminal
$ git log --oneline -- packages.toml
7a3d2b1 Add k6 for load testing (ops-request #447)
9f1e8c4 Remove kustomize - migrated to helm
2b8c9a1 Add tailscale for VPN access
4d5f7e2 Initial workstation configuration

This is infrastructure documentation that stays current because it's executable. Nobody updates the Wiki; they update the TOML.

Integration with CI/CD Pipelines

The same package lists that configure workstations can validate build environments:

.github/workflows/environment-check.yml
name: Verify Environment Reproducibility
on: [push, pull_request]

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Install Repro
        run: curl -fsSL https://repro-cli.dev/install.sh | bash
      
      - name: Validate package lists
        run: repro validate --strict packages.toml
      
      - name: Test fresh install in container
        run: |
          docker run --rm -v "$PWD:/config" debian:12 bash -c \
            "apt update && apt install -y git && \
             curl -fsSL https://repro-cli.dev/install.sh | bash && \
             repro apply --config /config/packages.toml --noninteractive"
      
      - name: Check for drift
        run: repro sync --check-only packages.toml

Your package configuration is now tested code. Breaking changes get caught before they reach production workstations.

The Infrastructure Mindset at Your Fingertips

Managing workstations with Infrastructure as Code isn't about complexity—it's about treating your time with respect. The hours lost to "let me remember how I set this up" are hours stolen from actual work.

With Repro and version-controlled package lists, you:

  • ✅ Eliminate "snowflake" machines that nobody can reproduce
  • ✅ Onboard team members in minutes with identical environments
  • ✅ Recover from hardware failures with confidence
  • ✅ Maintain an audit trail of system changes
  • ✅ Prevent configuration drift through continuous reconciliation

Your workstation is infrastructure. Start treating it that way.

Get Started: Repro is open source at github.com/stefan-hacks/repro. Fork the repo, version control your first packages.toml, and never document your environment in a text file again.