Skip to content

ADR 007: Server Deployment Readiness

Date: 2026-02-01 Status: Accepted Author: Jeremy Dawson

Context

The dotfiles repository was designed primarily for workstation environments (Linux desktops, WSL2 dev machines) with full interactive access. While server deployment was documented via chezmoi init --apply --exclude "run_once_*", this path had several critical gaps:

Identified Issues

  1. Error Handling Gaps: Bootstrap script and mise tasks lacked proper error handling
  2. curl commands missing security flags (-fsSL)
  3. Error messages sent to stdout instead of stderr
  4. Missing set -e in doctor task

  5. Untested Server Path: The documented server deployment command was never validated

  6. No CI test for chezmoi init --apply --exclude "run_once_*"
  7. Sparse checkout path documented but untested
  8. Server deployments could fail silently

  9. Desktop Tool Bloat: All tools installed on servers regardless of necessity

  10. UI tools (yazi, lazygit, lazydocker) pull 50+ MB on headless servers
  11. Desktop-focused tools (atuin sync, glow, lolcat) serve no purpose
  12. No way to install minimal footprint

  13. Health Check Limitations: mise run doctor assumed full dev environment

  14. Failed on servers due to missing UI tools
  15. No server-aware validation mode
  16. Couldn't validate server deployments

  17. Secrets Management Unclear: Server secret injection strategy poorly documented

  18. Age key setup assumes interactive user
  19. No guidance on vault integration (HashiCorp Vault, AWS Secrets Manager)
  20. Behavior when age key missing not explained

Decision

Implement comprehensive server deployment support across five areas:

1. Error Handling Hardening

Bootstrap Script (scripts/bootstrap): - Add -fsSL flags to all curl commands for fail-fast and security - Redirect error messages to stderr (>&2) - Add explicit error checking for critical operations (git clone)

Mise Tasks: - Add set -e to mise-tasks/doctor for fail-fast behavior - Ensure all error messages use stderr

2. CI Testing for Server Path

New CI Job (.github/workflows/ci.yml):

test-server-deployment:
  - Install only chezmoi (not mise) to simulate minimal server
  - Run: chezmoi init --apply --exclude "run_once_*"
  - Verify key configs applied (zshrc, gitconfig, config/)

Validates the documented server deployment path works correctly.

3. Server-Optimized Tool Profile

New File (mise-server.toml): - Minimal config excluding desktop/UI tools - Removes: yazi, lazygit, lazydocker, dive, lnav, atuin, glow, lolcat, tinty, gitmux, pnpm, bun, direnv - Keeps: Core utilities (bat, eza, fd, ripgrep, fzf, etc.), development tools, linters, git tools

Usage:

MISE_CONFIG_FILE=mise-server.toml mise install

Main Config Updates (mise.toml): - Added (dev-only) markers to desktop tools for clarity - Documented server profile usage in header comments

4. Server-Aware Health Checks

Doctor Command (mise-tasks/doctor): - New SERVER_MODE=1 environment variable - Skips UI tool checks: atuin, yazi, glow, lazygit - Skips TPM (Tmux Plugin Manager) check - Tools become optional warnings instead of required checks

Usage:

SERVER_MODE=1 mise run doctor  # Server validation

5. Server Secrets Documentation

Comprehensive Guide (docs/SECRETS.md):

Four Deployment Options: 1. No Secrets: Skip encrypted files (default, no errors) 2. Vault Injection: Pre-inject age key from vault before deployment 3. Environment Variables: Inject via CI/CD without persisted files 4. Manual Secrets: Create server-specific ~/.secrets manually

Vault Integration Examples: - HashiCorp Vault: vault kv get -field=key secret/dotfiles/age-key - AWS Secrets Manager: aws secretsmanager get-secret-value --secret-id dotfiles/age-key - Azure Key Vault: az keyvault secret show --vault-name my-vault - Terraform provisioning example

Best Practices: - Principle of least privilege (only deploy needed secrets) - Ephemeral keys for CI/CD (prefer env vars) - Audit logging for vault access - Key rotation after server decommissioning

Consequences

Positive

  1. Production Ready: Server deployments now tested and validated in CI
  2. Minimal Footprint: Server profile reduces tool install size by ~50MB+
  3. Secure: Error handling prevents silent failures, proper vault integration
  4. Validated: mise run doctor can verify server health correctly
  5. Documented: Clear guidance for all server deployment scenarios

Negative

  1. Maintenance Overhead: Two mise configs to maintain (mise.toml + mise-server.toml)
  2. Complexity: Users must choose between full vs server profile
  3. Documentation Sprawl: Server deployment guidance across multiple files

Mitigation

  • Maintenance: Server config is subset of main config, simple to keep in sync
  • Complexity: Defaults remain unchanged (full install), server mode is opt-in
  • Documentation: All server guidance consolidated in SECRETS.md

Alternatives Considered

  1. Mise Profiles: Use native [profiles] feature
  2. Rejected: Less flexible, harder to customize, not widely used

  3. Package Manager Filters: Conditionally install tools based on env var

  4. Rejected: More complex, requires mise.toml template logic

  5. Single Config with Comments: Just mark tools as optional

  6. Rejected: Doesn't prevent installation, users would still pull desktop tools

  7. Separate Repo for Servers: Fork dotfiles into server-specific repo

  8. Rejected: Duplication, maintenance burden, divergence risk

Validation

Tests

  • ✅ 441+ existing tests still passing
  • ✅ New CI job validates server deployment path
  • SERVER_MODE=1 mise run doctor verified working
  • MISE_CONFIG_FILE=mise-server.toml mise install dry-run validated

Linting

  • ✅ ShellCheck clean (bootstrap script)
  • ✅ YAML lint clean (CI workflow)
  • ✅ TOML lint clean (mise-server.toml auto-formatted)

Security

  • ✅ No secrets committed
  • ✅ Error messages properly use stderr
  • ✅ Bootstrap script now fail-fast on errors

Documentation

  • ✅ README.md updated with server deployment section
  • ✅ CLAUDE.md updated with server profile usage
  • ✅ SECRETS.md comprehensive server guide added
  • ✅ mise.toml annotated with dev-only markers

Implementation

Files Modified: - scripts/bootstrap - Error handling fixes - mise-tasks/doctor - SERVER_MODE support - .github/workflows/ci.yml - New server deployment test job - mise.toml - Dev-only tool markers - README.md - Server deployment documentation - CLAUDE.md - Server setup reference - docs/SECRETS.md - Server secrets strategy guide

Files Created: - mise-server.toml - Server-optimized tool configuration

References