Skip to content

rwaltr/dotfiles

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

1,582 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿš€ rwaltr's dotfiles

rwaltr logo

Container-first, multi-shell dotfiles for Linux power users with a Kubernetes & container workflow focus

Chezmoi mise Fish Shell License

๐Ÿ“‹ Table of Contents

๐ŸŽฏ Overview

This is my personal dotfiles repository, designed to provide a consistent development environment across:

  • Linux workstations (Fedora/Universal Blue)
  • Container environments (Distrobox, Podman, Docker)
  • Future: Kubernetes debug pods (coming soon!)

Target Audience: Linux power users who work with containers, Kubernetes, and need a portable, consistent shell environment anywhere.

๐Ÿ’ก Philosophy

Container-First Design

Everything is designed to run in userspace and work seamlessly in containerized environments:

  • โœ… No system-level configuration - Works on immutable OSes (Fedora Atomic, etc.)
  • โœ… Portable - Same environment in Distrobox, Podman, or bare metal
  • โœ… Self-contained - All tools managed via mise, no root required
  • โœ… Future-proof - Ready for Kubernetes debug containers

Multi-Shell by Purpose

Different shells for different tasks, not just preference:

  • ๐Ÿš Fish - Primary interactive shell (user-friendly, modern)
  • ๐Ÿ“œ Bash - Scripting and automation (universal, POSIX)
  • ๐Ÿ“Š Nushell - Data processing (structured pipelines)

User-Space Only

This repo does not manage:

  • โŒ Host NetworkManager configurations
  • โŒ Host-level systemd services (system units)
  • โŒ Server/system administration
  • โŒ Host package installation (no pacman/apt/dnf)

This keeps configs portable and safe for immutable operating systems.

โœจ Features

๐Ÿ”ง Development Tools

  • Editor: Neovim (Lua-based configuration)
  • Terminal: Wezterm with sessionizer
  • Shell Tools: Starship prompt, Carapace completions, eza, bat, fzf
  • Version Management: mise (formerly rtx)
  • Git Hooks: hk (high-performance, mise-integrated)

โ˜ธ๏ธ Kubernetes & Containers

  • Container Runtime: Podman + Distrobox

  • K8s Tools: kubectl, krew plugins

  • Custom kubeconfig manager (Fish shell)

    # Automatically merges configs from ~/.kube/clusters/
    set-kubeconfig          # Load all configs
    isolate-kubeconfig path # Use single config
    append-kubeconfig path  # Add to current context
    store-kubeconfig path   # Save to clusters dir

๐Ÿ” Secrets Management

  • 1Password CLI integration via Chezmoi templates
  • Personal use only (not for team/shared secrets)

๐Ÿ“ฆ Package Management

  • CLI Tools: Homebrew (general use), mise (project-specific versions)
  • GUI Apps: Flatpak (Linux only)
  • Containers: Podman + Distrobox exported apps
  • Language Tools: Managed by mise per-project (Python, Node, Go, Rust, etc.)

๐Ÿค– Bootstrap Automation

chezmoi apply on a fresh ublue/immutable Linux system automatically:

  1. Installs Homebrew (run_once_before_10) โ€” Linuxbrew in /home/linuxbrew
  2. Installs Tailscale (run_once_before_20) โ€” via official install script, skipped if present or ephemeral
  3. Runs brew bundle (run_always_after_30) โ€” CLI tools, fonts; rendered from Brewfile template
  4. Installs Flatpaks (run_always_after_35) โ€” system-wide from flatpaks.txt template; additive only
  5. Installs OrcaSlicer (run_always_after_36) โ€” personal machines; version-checked, flatpak bundle
  6. Runs mise install (run_onchange_after_50) โ€” installs all tools in ~/.config/mise/config.toml
  7. Reloads systemd (run_always_after_99) โ€” picks up new/changed user units

All scripts are idempotent and additive โ€” safe to re-run on every chezmoi apply.

๐ŸŽจ Desktop Environments

  • Niri (Wayland tiling compositor)
  • KDE Plasma (full desktop)

๐Ÿš€ Quick Start

Option 1: With Chezmoi Installed

# Initialize and apply dotfiles
chezmoi init rwaltr
chezmoi apply

On first apply, chezmoi will automatically install Homebrew, Tailscale, brew bundle (CLI tools + fonts), Flatpaks, and mise tools.

For 1Password on immutable/rpm-ostree hosts, use rwaltrctl-init to layer the native 1password and 1password-cli packages, then reboot before continuing setup. The init flow installs the 1Password repo key into /etc/pki/rpm-gpg/ and uses a file:/// repo key reference so it works on immutable hosts without rpm --import. Flatpak 1Password is no longer part of this setup.

Option 2: Bootstrap Without Chezmoi

# Self-contained installer (downloads chezmoi)
sh -c "$(curl -fsLS https://raw.githubusercontent.com/rwaltr/dotfiles/master/install.sh)"

Option 3: In a Container

# Quick ephemeral environment (Docker/Podman)
podman run -it --rm fedora:latest bash -c "
  dnf install -y git curl &&
  sh -c \"\$(curl -fsLS https://raw.githubusercontent.com/rwaltr/dotfiles/master/install.sh)\"
"

# Persistent Distrobox environment (Linux only)
distrobox create --image ghcr.io/ublue-os/bluefin-cli:latest --name dev
distrobox enter dev
chezmoi init rwaltr && chezmoi apply

๐Ÿš Shell Strategy

Why Multiple Shells?

Each shell serves a specific purpose based on its strengths:

Fish (Primary Interactive)

Use for: Daily interactive work, command exploration, quick tasks

Strengths:

  • Modern, intuitive syntax
  • Excellent tab completion
  • Syntax highlighting out-of-the-box
  • User-friendly interactive features

Example Config:

# ~/.config/fish/config.fish
# Modular configuration via conf.d/*.fish
# Custom functions in functions/*.fish

Bash (Universal Scripting)

Use for: Scripts, automation, CI/CD, compatibility

Strengths:

  • Available everywhere (including containers, minimal systems)
  • POSIX compatible
  • Industry standard for scripting

Example Structure:

# Modular configuration in ~/.config/bashrc.d/
# Loaded alphabetically:
# - 0.*.sh (core setup)
# - *.sh (tool configs)

Nushell (Data Processing)

Use for: Log analysis, data transformation, structured pipelines

Strengths:

  • Structured data (tables, records)
  • Type-aware commands
  • SQL-like queries

Example Use Case:

# Parse JSON logs with structured queries
cat logs.json | from json | where status == 500 | length

๐Ÿ“ Project Structure

dotfiles/
โ”œโ”€โ”€ .chezmoiroot          # Points source to home/ directory
โ”œโ”€โ”€ install.sh            # Bootstrap script (no chezmoi required)
โ”œโ”€โ”€ mise.toml             # Development tools & tasks
โ”œโ”€โ”€ hk.pkl                # Git hooks configuration
โ”œโ”€โ”€ .markdownlint-cli2.jsonc  # Markdown linting rules
โ”‚
โ”œโ”€โ”€ home/                 # Chezmoi source directory (becomes ~/)
โ”‚   โ”œโ”€โ”€ .chezmoiexternal.yaml  # External assets (OrcaSlicer bundle)
โ”‚   โ”œโ”€โ”€ .chezmoiignore    # Files to skip (personal-only gating)
โ”‚   โ”œโ”€โ”€ .chezmoi.yaml.tmpl    # Machine flags: personal, work, headless, ephemeral
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ .chezmoiscripts/
โ”‚   โ”‚   โ”œโ”€โ”€ before/       # Pre-apply: homebrew, tailscale, common dirs
โ”‚   โ”‚   โ””โ”€โ”€ after/        # Post-apply: brew bundle, flatpaks, mise, systemd reload
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ .chezmoitemplates/
โ”‚   โ”‚   โ”œโ”€โ”€ Brewfile       # CLI tools + fonts (segmented by flags)
โ”‚   โ”‚   โ””โ”€โ”€ flatpaks.txt   # Flatpak app IDs (segmented by flags)
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ dot_config/
โ”‚   โ”‚   โ”œโ”€โ”€ fish/          # Fish shell (primary interactive)
โ”‚   โ”‚   โ”œโ”€โ”€ bashrc.d/      # Modular Bash configs
โ”‚   โ”‚   โ”œโ”€โ”€ nushell/       # Nushell data processing
โ”‚   โ”‚   โ”œโ”€โ”€ nvim/          # Neovim Lua config
โ”‚   โ”‚   โ”œโ”€โ”€ wezterm/       # Terminal config
โ”‚   โ”‚   โ”œโ”€โ”€ mise/          # Global mise tool config
โ”‚   โ”‚   โ”œโ”€โ”€ niri/          # Niri Wayland compositor
โ”‚   โ”‚   โ”œโ”€โ”€ bisync/        # rclone bisync profiles (LOCAL/REMOTE env pairs)
โ”‚   โ”‚   โ”œโ”€โ”€ containers/systemd/  # Podman quadlets (resticprofile)
โ”‚   โ”‚   โ”œโ”€โ”€ systemd/user/  # User systemd units + timers
โ”‚   โ”‚   โ””โ”€โ”€ resticprofile/ # Backup profiles (personal only)
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€ dot_local/
โ”‚       โ””โ”€โ”€ bin/           # Custom scripts:
โ”‚                          #   auto-bisync, bisync-now, gamingctl,
โ”‚                          #   virtcontainerctl, restic-setup-creds, ssh-multi
โ”‚
โ”œโ”€โ”€ AGENTS.md             # Comprehensive context for AI agents
โ””โ”€โ”€ README.md             # This file

Key Files

  • mise.toml - Development tools, linting/formatting tasks
  • hk.pkl - Git pre-commit/pre-push hooks (delegates to mise)
  • AGENTS.md - Deep dive for AI coding assistants (like pi!)
  • home/dot_config/bashrc.d/ - 17 modular Bash scripts
  • home/dot_config/fish/ - 15+ Fish shell modules

๐Ÿ› ๏ธ Development Workflow

Linting & Formatting

Powered by mise tasks and hk git hooks:

# Run all linters
mise run lint

# Run all formatters
mise run format

# Individual linters
mise run lint:shell      # shellcheck
mise run lint:fish       # fish --no-execute
mise run lint:lua        # stylua
mise run lint:yaml       # yamllint
mise run lint:toml       # taplo
mise run lint:markdown   # markdownlint-cli2

# Individual formatters
mise run format:shell    # shfmt
mise run format:lua      # stylua
mise run format:toml     # taplo

Git Hooks (via hk)

Automatically runs linters on commit/push:

# Install hooks (one-time)
mise run hk:install

# Manually check staged files
mise run check

# Auto-fix issues in staged files
mise run hk:fix

# Hooks run automatically
git commit -m "feat: something"  # โ† linters run here

# Skip hooks if needed (emergency only)
HK=0 git commit -m "emergency fix"

How it works: hk delegates to mise run lint, ensuring git hooks and manual checks are identical.

Testing

138 tests across unit, container image, and VM layers. Unit tests run in a containerized environment for consistency:

# Build the test container (one-time)
mise run test:build

# Run unit tests in container (recommended)
mise run test:unit

# Run unit tests locally (uses host tools, may skip tests)
mise run test:unit:local

# Full suite: lint + unit tests
mise run test

# Everything including container image tests
mise run test:all

See tests/README.md for full details.

Managing Dotfiles

# Check what would change
chezmoi diff

# Apply changes
chezmoi apply

# Edit a file (opens in $EDITOR)
chezmoi edit ~/.config/fish/config.fish

# Add a new file to management
chezmoi add ~/.config/newapp/config.toml

# Update from repository
chezmoi update

# See status
chezmoi status

Adding New Tools

# Global tools via Homebrew (available everywhere)
brew install kubectl kubectx jq fzf ripgrep

# Project-specific versions via mise
cd ~/project
mise use node@20 python@3.12

# Or add to project's .mise.toml:
# [tools]
# node = "20"
# python = "3.12"

# Install tools
mise install

# Verify
mise list

๐Ÿ’พ Backups

Home directory backups are managed via resticprofile โ€” a profile-based wrapper around restic.

How it works

  • Profile config: ~/.config/resticprofile/profiles.toml (managed by chezmoi, personal machines only)
  • Repo: sftp:mouse:backups/<hostname>/home โ€” per-host repo on the mouse server over SFTP/Tailscale
  • SSH auth: 1Password SSH agent (~/.1password/agent.sock)
  • Schedule: Hourly via user systemd timer (resticprofile@home.timer), starts after tailscale0 is up
  • Retention: 24 hourly, 7 daily, 4 weekly, 12 monthly, 3 yearly snapshots
  • Credentials: Per-host password stored at ~/.config/resticprofile/password (mode 600, not in git)

Podman quadlet

resticprofile runs in a rootless Podman container via a systemd quadlet โ€” no local install required.

systemd timer โ†’ resticprofile@<profile>.service โ†’ podman run ghcr.io/creativeprojects/resticprofile

The quadlet (~/.config/containers/systemd/resticprofile@.container) mounts:

  • ~ โ€” backup source and SSH keys
  • ~/.config/resticprofile โ€” profile config and credentials
  • ~/.1password/agent.sock โ€” 1Password SSH agent for SFTP auth

What's excluded

Caches, Steam, container storage, build artifacts (node_modules, target, .cargo), ~/src (on GitHub), ~/Downloads, large disk images (*.iso, *.qcow2).

First-time setup (per host)

# 1. Set the repo password โ€” stored at ~/.config/resticprofile/password
restic-setup-creds

# 2. Initialize the restic repo on the remote
systemctl --user start resticprofile@home.service
# (resticprofile initialize = true handles this automatically on first run)

# 3. Enable the timer
systemctl --user enable --now resticprofile@home.timer

# 4. Watch logs
journalctl --user -u resticprofile@home.service -f

Adding a new backup profile

Add a new profile to profiles.toml inheriting from base:

[documents]
inherit    = "base"
repository = "sftp:mouse:backups/{{ "{{" }} .chezmoi.hostname {{ "}}" }}/documents"

[documents.backup]
source = ["~/Documents"]

Then add and enable a timer:

cp ~/.config/systemd/user/resticprofile@home.timer \
   ~/.config/systemd/user/resticprofile@documents.timer
systemctl --user enable --now resticprofile@documents.timer

Future: S3 backend

When mouse gets an S3-compatible backend, add a second profile pointing at it โ€” the base excludes and retention policy inherit automatically.

๐Ÿ”„ Bisync

Two-way file synchronization between local directories and a remote server using rclone bisync, with profile-based configuration.

Bisync details

  • Profiles: ~/.config/bisync/*.env โ€” each file defines a LOCAL and REMOTE path pair
  • Transport: SFTP to the mouse server over Tailscale with SSH key auth
  • Tools: auto-bisync (watch mode) and bisync-now (ad-hoc sync)
  • Backups: Conflict/overwrite backups stored in ~/.local/share/bisync-backups/

Configured profiles

Profile Local Remote
books ~/Books mouse:/var/tank/home/rwaltr/Books
documents ~/Documents mouse:/var/tank/home/rwaltr/Documents
games ~/Games mouse:/var/tank/home/rwaltr/Games
music ~/Music mouse:/var/tank/home/rwaltr/Music
pictures ~/Pictures mouse:/var/tank/home/rwaltr/Pictures
videos ~/Videos mouse:/var/tank/home/rwaltr/Videos

Usage

# List available profiles
bisync-now list

# Sync a specific profile
bisync-now documents

# Sync all profiles
bisync-now all

# Watch mode โ€” auto-sync on file changes (requires inotify-tools)
auto-bisync ~/Documents :sftp,host=mouse,key_file=~/.ssh/id_ed25519:/var/tank/home/rwaltr/Documents watch

# One-shot sync (used by bisync-now internally)
auto-bisync ~/Documents :sftp,host=mouse,key_file=~/.ssh/id_ed25519:/var/tank/home/rwaltr/Documents once

# First-time resync (resolves empty tracking state)
auto-bisync ~/Documents :sftp,host=mouse,key_file=~/.ssh/id_ed25519:/var/tank/home/rwaltr/Documents resync

Systemd integration

A templated user service (bisync@.service) runs auto-bisync in watch mode for any profile. It waits for the Tailscale interface before starting.

# Enable continuous sync for a profile
systemctl --user enable --now bisync@documents.service

# Enable all profiles
for p in books documents games music pictures videos; do
  systemctl --user enable --now bisync@${p}.service
done

# Check status
systemctl --user status bisync@documents.service

# View logs
journalctl --user -u bisync@documents.service -f

Requirements

  • rclone โ€” installed via Homebrew/mise
  • inotify-tools โ€” for watch mode
  • SSH key referenced by the bisync profile (defaults to ~/.ssh/id_ed25519) with access to mouse
  • Tailscale โ€” service waits for tailscale0 interface

rwaltrctl-init will check for the configured bisync SSH key and can generate it if missing. If Tailscale is already connected, it will also try to install the generated public key on the remote host automatically. If that fails, you can still install the public key manually.

๐Ÿค” Design Choices

Why Chezmoi?

vs Nix: More complexity than needed for dotfiles alone. Chezmoi hits the sweet spot between:

  • Simplicity: Templates, not a whole OS
  • Power: Templating, external resources, secrets management
  • Portability: Works on any system with a shell

vs Stow/bare git: Need templating for:

  • Different configs per machine
  • Secret injection from 1Password
  • OS-specific sections

Why Fish as Primary Shell?

  • Interactive Focus: 90% of shell time is interactive, not scripting
  • Modern UX: Tab completion, syntax highlighting, better defaults
  • Less Configuration: Works great out-of-the-box
  • Still Use Bash: For scripts where portability matters

Why mise?

For project-specific version management:

  • โœ… Version Management: Replaces asdf, nvm, rbenv, pyenv, etc. per-project
  • โœ… Task Runner: Built-in make alternative
  • โœ… Tool Installer: Downloads and manages CLI tools
  • โœ… Environment Management: Per-project tool versions via .mise.toml

vs Homebrew: Homebrew is for global tools used everywhere (kubectl, jq, fzf, etc.), while mise handles per-project versions (Node 18 in project A, Node 20 in project B).

Why Container-First?

Goal: Run this environment anywhere:

  • ๐Ÿ–ฅ๏ธ Workstation: Full setup with GUI tools
  • ๐Ÿ“ฆ Container: Lightweight dev environment
  • โ˜ธ๏ธ K8s Debug Pod: Familiar shell in production (future)

Benefits:

  • No system pollution
  • Immutable OS friendly
  • Portable and reproducible
  • Same environment everywhere

๐Ÿ”ฎ Future Plans

In Progress

  • Distrobox Assemble: Rebuild pi AI agent environment on any machine
  • Kubernetes debug container: Run dotfiles in kubectl debug pods
  • Test suite: 138 bats tests (unit + container image), containerized runner

Ideas

  • Wezterm sessionizer integration with pi agent for long-running tasks
  • Container image: Pre-built Docker/Podman image with full setup
  • Nushell integration: Deeper data processing workflows
  • S3 backup backend: Second restic profile pointing at S3-compatible storage

๐Ÿ“š Additional Documentation

  • AGENTS.md - Comprehensive guide for AI coding assistants
    • Full project philosophy
    • File-by-file breakdown
    • Configuration patterns
    • Chezmoi workflows
    • Development tasks

๐Ÿค Contributing

This is a personal repository, but feel free to:

  • ๐Ÿ’ก Open issues with questions
  • ๐Ÿ› Report bugs or suggest improvements
  • โญ Star if you find it useful!

๐Ÿ“ License

Personal use. Feel free to use as inspiration or starting point for your own dotfiles.


Built with: Chezmoi โ€ข mise โ€ข Fish โ€ข Neovim โ€ข Wezterm

About

No description or website provided.

Topics

Resources

Stars

Watchers

Forks

Contributors