- dotfiles_manager.sh: add 'deploy-to' command to SCP tracked dotfiles
and scripts directly to servers with no Gitea access
- backs up existing remote files to ~/.dotfiles_backup/remote-<host>-<timestamp>/
before overwriting anything
- flags: --scripts-only, --include-ssh, --no-backup, --dry-run
- ssh/config: reorganize into labeled sections, move work hosts to top,
fix global defaults (proper Host * block, remove deprecated Protocol/KeepAlive),
add inline comments on all port forwards
- README.md: full rewrite with directory layout, profiles, shell layering,
env vars, aliases, bootstrap flow, symlink mechanics, SSH key strategy,
two-machine sync workflow, and deploy-to docs
318 lines
11 KiB
Markdown
318 lines
11 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
|
|
│ ├── 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.
|
|
|
|
---
|
|
|
|
## 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
|
|
```
|