Skip to content

About

dotfiles (using Dotbot as an installer)

Resources

Stars

1 star

Watchers

0 watching

Forks

 
 

Latest commit

 

History

963 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dotfiles

Configuration for the machines I use: laptop (i3), remote servers, a home server and a phone (Termux). One repo, linked into $HOME with dotbot.

Workspace example

What's in it

  • Shell: zsh with zinit turbo mode (plugins load after the first prompt, so startup is ~50 ms), starship prompt, zoxide (j), fzf + fzf-tab
  • Terminal: tmux (plugins via tpm), ghostty / alacritty
  • Editor: neovim with LazyVim
  • Files / search: yazi, ranger, fd, ripgrep, bat, eza
  • Git: forgit, tig, gh with custom aliases (bin/git-alias, bin/gh-aliases)
  • Desktop: i3, i3blocks, rofi
  • Misc: cheat, lnav, taskwarrior, beets, cmus
  • Packages: zerobrew (fast, sudo-free Homebrew-compatible client), listed in Brewfile

Install

Needs git and curl. If a private repo or submodule is involved, set up your SSH key first:

eval "$(ssh-agent -s)" && ssh-add     # ~/.ssh/id_rsa

Any Linux/macOS machine, no sudo

curl -fsSL https://raw.githubusercontent.com/lbesnard/dotfiles/main/initsys.sh | bash

This installs zerobrew, makes a shallow clone of this repo into ~/github_repo/dotfiles, installs the Brewfile packages and links everything into $HOME. It is safe to re-run (it updates instead of cloning again).

Add -s -- --ansible to also run the user-level roles of Fleet-Control (miniforge, neovim, cheat):

curl -fsSL https://raw.githubusercontent.com/lbesnard/dotfiles/main/initsys.sh | bash -s -- --ansible

Laptop (full system, sudo)

System packages, i3, fonts etc. are provisioned by Fleet-Control, which also installs these dotfiles:

ansible-pull -U https://github.com/lbesnard/Fleet-Control.git \
             -d ~/ansible_pull_tmp -i ansible/hosts ansible/local.yml -K

Manual

git clone --depth 1 https://github.com/lbesnard/dotfiles.git ~/github_repo/dotfiles
cd ~/github_repo/dotfiles
./install          # fetches submodules (shallow) and links the files listed in install.conf.yaml

Re-run ./install after adding a link to install.conf.yaml.

Termux (Android)

First sync the Termux packages (a partial upgrade leaves curl/git broken with cannot locate symbol "SSL_set_quic_tls_early_data_enabled"):

pkg update -y && pkg upgrade -y

Then:

curl -fsSL https://raw.githubusercontent.com/lbesnard/dotfiles/main/termux-install.sh | sh

termux-install.sh runs pkg upgrade, installs the core tools (zsh, tmux, perl, starship, zoxide, fzf, openssh, neovim) plus Termux equivalents of the packages in Fleet-Control's homebrew_packages.yml (bat, eza, fd, ripgrep, yazi, lazygit, gh, ...) with pkg; packages missing from the Termux repo are skipped and listed. It then shallow-clones this repo into ~/dotfiles, runs ./install (dotbot, like every other machine) and sets zsh as login shell. Re-running updates.

  • It uses pkg rather than zerobrew: zerobrew's binaries are built for glibc, Termux uses bionic.
  • cannot locate symbol "SSL_set_quic_tls_early_data_enabled" from git/curl: your Termux packages are partially upgraded (new libcurl, old openssl). Run pkg update -y && pkg upgrade -y (try termux-change-repo if a mirror is stale), then re-run the installer. The script does this upgrade itself.
  • zsh/zshrc.termux is a self-contained, minimal zsh config. tmux autostarts in interactive shells (attaches to session main); set export TERMUX_NO_TMUX=1 in ~/.zshenv to disable.
  • tmux uses the same Oh my tmux! tmux.conf as the other machines, with tmux/tmux.conf.termux as its ~/.tmux.conf.local. That file sources tmux.conf.ssh (the server look, prefix C-b) and adds phone tweaks (no pane-border row, no plugin cloning, Android clipboard). Oh my tmux needs perl, which the installer adds.
  • Optional: pkg i termux-api (+ the Termux:API app) so copy-mode y reaches the Android clipboard; pkg i termux-services then sv-enable ssh-agent / sv-enable sshd to run them as services.

Secrets

This repo is public, but credentials live in it encrypted with age. Everything listed in secrets.list (aws, ssh config, tokens, taskrc, ...) exists as:

  • a plaintext file in the usual place: gitignored, so git status never shows it;
  • a <file>.age next to it: encrypted to the public key in recipients.txt, committed.

The private key is ~/.config/age/key.txt. It is not in the repo; keep a copy in KeePass. Without it you get the public dotfiles only and everything else still works.

New machine

./install does it all: it offers to install zerobrew + age (and pre-commit via pip), asks you to paste the key (hidden; the AGE-SECRET-KEY-1... line is enough, it is checked against recipients.txt), decrypts, installs the git hooks and links the secret files (install.private.conf.yaml). Press Enter at the key prompt to skip.

Changing a secret

git status will not show an edited secret (it is gitignored). Check with:

cd ~/github_repo/dotfiles
./secrets status                      # "plaintext differs from .age" = you have an unencrypted change
./secrets encrypt                     # writes the .age files
git add -A && git commit -m "..." && git push

Run ./secrets encrypt yourself when the secret is the only thing you changed: the commit hook only runs once git sees something to commit, so a secret-only change would otherwise say "nothing to commit". When you commit other files too, the hook re-encrypts for you (with the pre-commit framework the first attempt stops once after staging the .age files; commit again). It also refuses to commit a plaintext secret or an *.age file that is not really age.

Pulling a change

A post-merge / post-rewrite hook runs ./secrets decrypt after git pull, so the plaintext follows. It never overwrites a local edit that was not encrypted yet: you get a CONFLICT line and your file is kept (./secrets decrypt --force to take the repo's version). It says what it did (secrets: refreshing decrypted secrets after pull..., then decrypt: N updated, M unchanged); without a key it prints a one-line note, without age it warns. git pull itself never fails because of it.

Adding a secret

  1. Add its path to secrets.list and to .gitignore (encrypt refuses a path that is not ignored).
  2. ./secrets encrypt, then commit the new .age file.
  3. If it needs a symlink, add it to install.private.conf.yaml (not install.conf.yaml).

Commands

secrets is also on your PATH (bin/secrets), so these work from any directory, with zsh tab completion.

Command
./secrets status key, hook, and the state of every secret
./secrets encrypt [--stage|--add] re-encrypt changed plaintext (only if it really changed; age output is random)
./secrets decrypt [--force] [--quiet|--hook] write plaintext from the .age files
./secrets install-hook git hooks: pre-commit framework if it runs, else plain git hooks
./secrets install-completion link the zsh completion (zsh/completions/_secrets) into your $fpath; ./install does it too
./secrets bootstrap the interactive install/paste-the-key step of ./install

Keep in mind

  • The ciphertext is public and permanent. If the key leaks, anything ever pushed can be read, and changing recipients.txt does not help for old commits: rotate the secrets themselves (new tokens, keys, passwords).
  • Never commit a secret in plaintext by accident: if you did, rewriting history is not enough on its own, see how fleet-compose rotates TLS/ACME keys.
  • The key is a random file, not a passphrase, so brute-forcing the public ciphertext is not realistic.
  • Nextcloud and Joplin keep their state in real ~/.config folders; only their config files are linked from here.

How the zsh config is organised

File Role
zsh/zshrc Detects the machine profile once (termux, server, homeserver, laptop; override with ZSH_PROFILE_NAME) and sources the right files
zsh/zshrc.common Shared config: tmux autostart (first, so the outer shell does no wasted work), zerobrew PATH, prompt, turbo-loaded plugins, fzf, completion styling
zsh/zshrc.laptop, .server, .homeserver Per-machine additions
zsh/zshrc.termux Standalone Termux config
zsh/functions/, zsh/completions/ Autoloaded functions and completions
alias, alias_forgit Aliases and helper functions (loaded last so they override plugin aliases)
config/starship.toml Prompt config

Profile startup with ZSH_PROFILE=1 zsh -i -c exit (prints a zprof report), or for i in {1..5}; do time zsh -i -c exit; done.

Adding a package

zb install <formula>
zb bundle dump -f Brewfile --force     # keep Brewfile in sync

Layout

install, install.conf.yaml   dotbot entrypoint and link map
initsys.sh, Brewfile         bootstrap for fresh machines
termux-install.sh            bootstrap for Termux (Android)
zsh/ tmux/ nvim/ config/     tool configs (config/* is linked into ~/.config)
bin/                         scripts, put on $PATH as ~/bin
secrets, secrets.list        age-encrypted secrets: tool, list of files (+ *.age, recipients.txt)
install.private.conf.yaml    links for decrypted secrets (only used when the age key is present)

About

dotfiles (using Dotbot as an installer)

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages