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¶
- Error Handling Gaps: Bootstrap script and mise tasks lacked proper error handling
curlcommands missing security flags (-fsSL)- Error messages sent to stdout instead of stderr
-
Missing
set -ein doctor task -
Untested Server Path: The documented server deployment command was never validated
- No CI test for
chezmoi init --apply --exclude "run_once_*" - Sparse checkout path documented but untested
-
Server deployments could fail silently
-
Desktop Tool Bloat: All tools installed on servers regardless of necessity
- UI tools (yazi, lazygit, lazydocker) pull 50+ MB on headless servers
- Desktop-focused tools (atuin sync, glow, lolcat) serve no purpose
-
No way to install minimal footprint
-
Health Check Limitations:
mise run doctorassumed full dev environment - Failed on servers due to missing UI tools
- No server-aware validation mode
-
Couldn't validate server deployments
-
Secrets Management Unclear: Server secret injection strategy poorly documented
- Age key setup assumes interactive user
- No guidance on vault integration (HashiCorp Vault, AWS Secrets Manager)
- 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:
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:
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¶
- Production Ready: Server deployments now tested and validated in CI
- Minimal Footprint: Server profile reduces tool install size by ~50MB+
- Secure: Error handling prevents silent failures, proper vault integration
- Validated:
mise run doctorcan verify server health correctly - Documented: Clear guidance for all server deployment scenarios
Negative¶
- Maintenance Overhead: Two mise configs to maintain (mise.toml + mise-server.toml)
- Complexity: Users must choose between full vs server profile
- 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¶
- Mise Profiles: Use native
[profiles]feature -
Rejected: Less flexible, harder to customize, not widely used
-
Package Manager Filters: Conditionally install tools based on env var
-
Rejected: More complex, requires mise.toml template logic
-
Single Config with Comments: Just mark tools as optional
-
Rejected: Doesn't prevent installation, users would still pull desktop tools
-
Separate Repo for Servers: Fork dotfiles into server-specific repo
- 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 doctorverified working - ✅
MISE_CONFIG_FILE=mise-server.toml mise installdry-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¶
- Implementation PR: (this commit)
- Related ADRs: ADR-003: Mise Tool Management, ADR-004: Age Encryption
- Testing:
.github/workflows/ci.ymltest-server-deployment job - Documentation:
docs/SECRETS.mdServer Deployment section