Files
dotfiles/README.md
Kenji Morishige a6296da5df feat: add hosts/ convention for centrally managed server .bashrc.local
- hosts/etqc-kenjim-11.bashrc.local: per-host local config for work server,
  managed from kenjim-mbp and deployed via 'dotfiles deploy-to'.
  Credentials replaced with CHANGEME placeholders — set real values on
  server after first deploy, never commit actual secrets.
- dotfiles_manager.sh: deploy-to step 5 auto-detects hosts/<hostname>.bashrc.local
  and SCPs it to ~/.bashrc.local on the remote (with backup of existing file)
- .gitignore: clarify that hosts/*.bashrc.local is intentionally tracked
  (existing .bashrc.local rule only matches the exact filename)
- README.md: document hosts/ layout, workflow, and credential placeholder strategy
2026-02-23 17:12:29 -06:00

348 lines
12 KiB
Markdown

# dotfiles
Centralized configuration and environment management for `kenjim`.
Remote: `http://172.27.0.35:3000/kenjim/dotfiles`
---
## Overview
This repo tracks shell configs, SSH settings, and editor dotfiles via a git
repo hosted on a local Gitea server. On any machine, a single command restores
the full environment: directories, environment variables, shell aliases, and
symlinked config files.
Three scripts drive the system:
| Script | Role |
|---|---|
| `scripts/setup_enterprise_ai_bash.sh` | **First-time setup** — creates the directory tree, writes shell config, initializes dotfiles repo, migrates files |
| `scripts/dotfiles_manager.sh` | **Day-to-day management** — add/remove tracked files, push/pull, SSH key handling, multi-machine bootstrap |
| `scripts/bootstrap.sh` | **Restore shortcut** — reloads shell config and runs `dotfiles sync` to pull latest changes |
| `install.sh` | **New-machine restore** — applies all symlinks after cloning; auto-generated by `dotfiles_manager.sh` |
---
## Directory Layout
`setup_enterprise_ai_bash.sh` creates the following structure under `$HOME`:
```
~/
├── workspace/
│ ├── src/
│ │ ├── personal/ # personal projects
│ │ ├── work/ # work projects
│ │ └── research/ # research / papers
│ ├── experiments/ # throwaway experiments
│ ├── notebooks/ # Jupyter / Marimo notebooks
│ ├── sandboxes/ # isolated test environments
│ └── archive/ # completed / mothballed work
├── data/
│ ├── raw/ # unmodified source data (excluded from Time Machine)
│ ├── processed/ # cleaned / transformed datasets
│ ├── embeddings/ # vector embeddings
│ └── synthetic/ # generated / synthetic data
├── models/ # excluded from Time Machine
│ ├── huggingface/ # HF_HOME cache
│ ├── ollama/ # OLLAMA_MODELS store
│ └── fine-tuned/ # locally fine-tuned checkpoints
├── infra/
│ ├── docker/ # Compose files, Dockerfiles
│ ├── terraform/ # IaC configs
│ └── scripts/ # infra automation
├── ops/ # operational runbooks, monitoring configs
├── scripts/ # local utility scripts (dotfiles_manager, bootstrap, etc.)
├── vault/ # secrets / credentials (never committed)
├── dotfiles/ # ← this repo
│ ├── .bashrc → symlinked from ~/.bashrc
│ ├── .bash_profile → symlinked from ~/.bash_profile
│ ├── .bash_aliases → symlinked from ~/.bash_aliases
│ ├── .gitconfig → symlinked from ~/.gitconfig
│ ├── .vimrc → symlinked from ~/.vimrc
│ ├── .tmux.conf → symlinked from ~/.tmux.conf
│ ├── .inputrc → symlinked from ~/.inputrc
│ ├── .ssh/
│ │ ├── config → symlinked from ~/.ssh/config
│ │ └── keys/ # .pub files + GPG-encrypted private keys
│ ├── scripts/
│ │ ├── dotfiles_manager.sh → symlinked from ~/scripts/dotfiles_manager.sh
│ │ ├── setup_enterprise_ai_bash.sh → symlinked from ~/scripts/setup_enterprise_ai_bash.sh
│ │ └── bootstrap.sh → symlinked from ~/scripts/bootstrap.sh
│ ├── .dotfiles_manifest # internal list of tracked HOME-relative paths
│ ├── hosts/
│ │ └── <hostname>.bashrc.local # per-server local configs (deployed via deploy-to)
│ ├── install.sh # portable restore script (auto-generated)
│ └── README.md # this file
└── Cloud/ # personal profile only
├── ProtonDrive/ # PROTON_ROOT
└── GoogleDrive/ # GDRIVE_ROOT
# work profile instead creates:
# ~/OneDrive → ~/Library/CloudStorage/OneDrive-*/ (symlink)
```
---
## Machine Profiles
The setup supports two profiles selected at first-run (or via `MACHINE_PROFILE=work|personal`):
| | `work` | `personal` |
|---|---|---|
| Cloud root | `~/OneDrive` (symlink to macOS mount) | `~/Cloud` |
| `CLOUD_ROOT` | `$HOME/OneDrive` | `$HOME/Cloud` |
| Extra vars | `ONEDRIVE_ROOT` | `PROTON_ROOT`, `GDRIVE_ROOT` |
| Extra aliases | `onedrive` | `cloud`, `proton`, `gdrive` |
| Committed? | No — written to `~/.bashrc.local` | No — written to `~/.bashrc.local` |
---
## Shell Config Layering
```
~/.bash_profile
└── sources ~/.bashrc
├── ### ENTERPRISE_AI_ENV ### ← shared vars (WORKSPACE, DATA_ROOT, MODEL_ROOT, …)
├── ### DOTFILES_ALIASES ### ← dotfiles / dot / dots-sync / dots-push / dots-status
└── sources ~/.bashrc.local ← machine-specific (profile, cloud paths, MACHINE_HOST)
```
| File | Committed to dotfiles? | Purpose |
|---|---|---|
| `~/.bashrc` | **Yes** | Shared env vars, aliases, loads `.bashrc.local` |
| `~/.bash_profile` | **Yes** | macOS login shell — sources `.bashrc` |
| `~/.bashrc.local` | **No** | Machine-specific overrides (profile, cloud paths) |
`~/.bashrc.local` is written by `setup_enterprise_ai_bash.sh` and regenerated when
running it again. It is listed in `.gitignore` and never pushed to the remote.
---
## Key Environment Variables
| Variable | Value | Set in |
|---|---|---|
| `WORKSPACE` | `$HOME/workspace` | `~/.bashrc` |
| `DATA_ROOT` | `$HOME/data` | `~/.bashrc` |
| `MODEL_ROOT` | `$HOME/models` | `~/.bashrc` |
| `HF_HOME` | `$MODEL_ROOT/huggingface` | `~/.bashrc` |
| `OLLAMA_MODELS` | `$MODEL_ROOT/ollama` | `~/.bashrc` |
| `DOTFILES_DIR` | `$HOME/dotfiles` | `~/.bashrc` |
| `DOTFILES_REMOTE` | `http://172.27.0.35:3000/kenjim/dotfiles` | `~/.bashrc` |
| `MACHINE_PROFILE` | `work` or `personal` | `~/.bashrc.local` |
| `MACHINE_HOST` | `hostname -s` output | `~/.bashrc.local` |
| `CLOUD_ROOT` | `~/OneDrive` or `~/Cloud` | `~/.bashrc.local` |
---
## Shell Aliases
| Alias | Expands to |
|---|---|
| `ws` | `cd $WORKSPACE` |
| `src` | `cd $WORKSPACE/src` |
| `data` | `cd $DATA_ROOT` |
| `models` | `cd $MODEL_ROOT` |
| `cloud` | `cd $CLOUD_ROOT` |
| `dotfiles` / `dot` | `bash ~/scripts/dotfiles_manager.sh` |
| `dots-sync` | `dotfiles sync` |
| `dots-push` | `dotfiles push` |
| `dots-status` | `dotfiles status` |
---
## Bootstrap Flow
### First-time setup on a new machine
```bash
# 1. Run the full setup wizard (creates dirs, shell config, dotfiles repo):
bash scripts/setup_enterprise_ai_bash.sh
# 2. Reload shell:
source ~/.bash_profile
```
The wizard will interactively:
1. Select a machine profile (`work` / `personal`)
2. Create the full directory tree
3. Write `~/.bashrc` env block and `~/.bashrc.local`
4. Initialize or clone the dotfiles repo from Gitea
5. Add dotfiles aliases to `~/.bashrc`
6. Offer to migrate shell configs, `.gitconfig`, scripts into dotfiles
7. Offer SSH config setup + GPG key export
8. Offer to push everything to `$DOTFILES_REMOTE`
9. Offer Time Machine exclusions for `~/data/raw` and `~/models`
10. Offer to bootstrap a remote machine over SSH
### Restore an existing setup on a new machine
```bash
# Clone the repo and run the portable restore script:
git clone http://172.27.0.35:3000/kenjim/dotfiles ~/dotfiles
bash ~/dotfiles/install.sh
source ~/.bash_profile
```
`install.sh` will:
- Apply all symlinks listed in `.dotfiles_manifest`
- Prompt for machine profile and run `setup_enterprise_ai_bash.sh` if no `.bashrc.local` exists
- Prompt to GPG-decrypt any SSH private keys stored in `dotfiles/.ssh/keys/*.gpg`
### Day-to-day sync
After editing on one machine, push and sync on the other:
```bash
# On the machine where you made changes:
dotfiles push "describe what changed"
# On the other machine to pick up the changes:
dotfiles sync
```
```bash
# Other useful commands:
dotfiles status # check symlink health
dotfiles sync # pull + rebase + reapply symlinks (also callable as: bash ~/scripts/bootstrap.sh)
```
### Remote machine bootstrap (from this machine)
```bash
dotfiles remote-bootstrap user@hostname
dotfiles remote-bootstrap user@hostname --profile work
```
This uploads the scripts, then runs the full setup interactively over SSH.
### Deploy to a server with no Gitea access
Linux servers at work can't clone the private Gitea repo. Use `deploy-to` to
SCP tracked dotfiles and scripts directly to their HOME paths — no git required
on the remote.
```bash
# Push everything (dotfiles + scripts):
dotfiles deploy-to user@server
# Scripts only (dotfiles_manager.sh, bootstrap.sh, setup script):
dotfiles deploy-to user@server --scripts-only
# Preview what would be transferred without doing it:
dotfiles deploy-to user@server --dry-run
# Also deploy ~/.ssh/config (skipped by default for security):
dotfiles deploy-to user@server --include-ssh
# Skip the pre-deploy backup (faster, but no safety net):
dotfiles deploy-to user@server --no-backup
```
Before overwriting any file, `deploy-to` SCPs the server's existing versions
to `~/.dotfiles_backup/remote-<host>-<timestamp>/` on your local machine.
Files are copied directly (not symlinked). Re-run `deploy-to` any time you
want to push updates. `~/.ssh/` is skipped by default to avoid accidentally
pushing private keys or your personal known_hosts to a shared server.
### Centrally managing `~/.bashrc.local` for servers
Work servers can't reach the Gitea repo, so their `~/.bashrc.local` is managed
centrally from `kenjim-mbp` using per-host files in `dotfiles/hosts/`:
```
dotfiles/hosts/
└── <hostname>.bashrc.local # deployed as ~/.bashrc.local on that server
```
`deploy-to` automatically detects and deploys the matching file:
```bash
# Edit the server's local config on kenjim-mbp:
$EDITOR ~/dotfiles/hosts/etqc-kenjim-11.bashrc.local
# Commit and push from kenjim-mbp:
dotfiles push "fix: update etqc-kenjim-11 local config"
# Deploy to the server (no git access needed on the server):
dotfiles deploy-to kenjim@etqc-kenjim-11
```
The `hosts/` files are committed to git. They may contain non-secret
machine-specific variables (`MACHINE_PROFILE`, `MACHINE_HOST`, `AWS_PROFILE`,
etc.). **Do not commit real passwords or tokens** — use `CHANGEME` placeholders
and set real values manually on the server after first deploy.
---
## Dotfiles Management — How Symlinks Work
```
~/dotfiles/.bashrc ←──────────── ~/dotfiles/ (git repo)
symlink
~/.bashrc ←── shell reads this
```
`dotfiles add <file>` moves the file into `~/dotfiles/`, creates a symlink at
the original HOME location, and records the relative path in `.dotfiles_manifest`.
`dotfiles install` re-creates all symlinks from the manifest (idempotent — safe to
re-run). Conflicts are backed up to `~/.dotfiles_backup/<timestamp>/` before being
replaced.
---
## SSH Key Strategy
| Item | Committed? | Details |
|---|---|---|
| `~/.ssh/config` | **Yes** | Shared SSH client configuration |
| `~/.ssh/*.pub` | **Yes** | Public keys are safe to store |
| `~/.ssh/id_*` (private) | **No** | Listed in `.gitignore` |
| `~/.ssh/keys/*.gpg` | **Yes** | GPG-encrypted private key backups |
```bash
# Encrypt private keys and save to dotfiles:
dotfiles ssh-export
# Decrypt on another machine after sync:
dotfiles ssh-import
```
---
## Gitea Authentication
HTTP push/pull uses a Personal Access Token saved locally (never committed):
```bash
dotfiles auth
# → Settings (avatar) → Applications → Generate Token → paste here
```
Credentials are stored at `~/.config/dotfiles/credentials` (chmod 600).
---
## Time Machine Exclusions
During setup you are offered the option to exclude large AI folders:
```
~/data/raw — large raw datasets
~/models — multi-GB model weights
```
To add manually:
```bash
sudo tmutil addexclusion ~/data/raw
sudo tmutil addexclusion ~/models
```