Compare commits

...

10 Commits

Author SHA1 Message Date
Kenji Morishige
28485a9be6 add ~/.local/bin to PATH and git tree alias
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 08:18:57 -05:00
Kenji Morishige
72ffe3c30d initial dotfiles migration from kenjim-mbm 2026-03-30 08:41:51 -05:00
Kenji Morishige
b23f5d7e5f latest to support taas shells 2026-02-25 15:20:07 -06:00
Kenji Morishige
d25dac1897 added taas machines as work type machines 2026-02-24 10:00:10 -06:00
Kenji Morishige
67926c37bd NFS-aware .bashrc.local and VS Code dirs for work servers
- Remove zet* from _is_work_host (local git server, not a work host)
- setup_enterprise_ai_bash.sh: detect NFS home on work servers, relocate
  .bashrc.local to /opt/kenjim/ with symlink, handle re-runs safely
- setup_enterprise_ai_bash.sh: symlink ~/.vscode-server and
  ~/.vscode-remote-containers to /opt/kenjim/ on NFS hosts
- dotfiles_manager.sh: deploy-to detects NFS on remote, deploys
  .bashrc.local to /opt/kenjim/ with symlink, backs up symlink targets
- hosts/etqc-kenjim-11.bashrc.local: add NFS note to header
2026-02-24 09:57:29 -06:00
Kenji Morishige
074ab05908 adding ollama installer 2026-02-23 19:53:49 -06:00
Kenji Morishige
0fc1b3cba0 docs: document --run-setup and --profile flags in deploy-to section 2026-02-23 17:27:21 -06:00
Kenji Morishige
3860c8a33d feat: deploy-to --run-setup flag to bootstrap directory structure on remote 2026-02-23 17:27:00 -06:00
Kenji Morishige
16cbadd016 fix: deploy-to uses scp -r for directories (fixes .bashrc.d upload) 2026-02-23 17:17:15 -06:00
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
13 changed files with 640 additions and 20 deletions

View File

@@ -32,3 +32,8 @@ fi
# Legacy aliases file (kept for compatibility)
[ -f ~/.aliases ] && source ~/.aliases
# OpenClaw Completion
#source "/Users/kenjim/.openclaw/completions/openclaw.bash"
#export OPENCLAW_MODEL=kimi-k2.5:cloud
export PATH="$HOME/.local/bin:$PATH"

View File

@@ -14,7 +14,7 @@ _is_work_host() {
[[ "${MACHINE_PROFILE:-}" == "work" ]] && return 0
# Fallback hostname pattern for work servers where .bashrc.local may not exist
case "$(hostname -s)" in
kenjim-mbp*|etqc-*|etbg-*|engtech-dev-*|zet*) return 0 ;;
kenjim-mbp*|etqc-*|etbg-*|engtech-dev-*|qnc-kenjim-toby-shell*|qtaas*|bng-kenjim-toby-shell*|btaas*|kenjim-taas*) return 0 ;;
*) return 1 ;;
esac
}

View File

@@ -20,3 +20,4 @@ email = kenjim@juniper.net
br = branch
ci = commit
unstage = reset HEAD --
tree = log --graph --oneline --all --decorate

6
.gitignore vendored
View File

@@ -33,6 +33,10 @@
*.secrets
vault/
# Machine-local overrides — never commit (written by setup_enterprise_ai_bash.sh)
# Machine-local overrides at HOME level — never commit (written by setup_enterprise_ai_bash.sh)
.bashrc.local
.bash_profile.local
# Per-host .bashrc.local files ARE committed — managed centrally in dotfiles/hosts/
# Files are named <hostname>.bashrc.local and deployed via: dotfiles deploy-to user@host
# hosts/*.bashrc.local is intentionally tracked (gitignore rules above only match exact name)

View File

@@ -84,9 +84,12 @@ Host kold
HostName etqc-kenjim-01.juniper.net
# TaaS dev machine
Host ktaas
Host qtaas
HostName kenjim-taas.qengk8.juniper.net
Host btaas
HostName kenjim-taas.bengk8.juniper.net
# Temp machine — Bangalore K8
Host ktb
HostName kenjim-temp.bengk8.juniper.net

121
README.md
View File

@@ -75,6 +75,8 @@ Three scripts drive the system:
│ │ ├── 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
@@ -230,6 +232,13 @@ on the remote.
# Push everything (dotfiles + scripts):
dotfiles deploy-to user@server
# After file transfer, also run setup_enterprise_ai_bash.sh on the remote
# to create ~/workspace, ~/data, ~/models and write shell config:
dotfiles deploy-to user@server --run-setup
# Specify a machine profile for the setup script (default: work):
dotfiles deploy-to user@server --run-setup --profile work
# Scripts only (dotfiles_manager.sh, bootstrap.sh, setup script):
dotfiles deploy-to user@server --scripts-only
@@ -249,6 +258,38 @@ 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.
> **First-time setup on a server?** Use `--run-setup` to create the full
> directory structure after file transfer, or answer `y` when prompted
> interactively at the end of a normal `deploy-to` run.
### 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
@@ -315,3 +356,83 @@ To add manually:
sudo tmutil addexclusion ~/data/raw
sudo tmutil addexclusion ~/models
```
**Ollama Bootstrap & Usage**
- **Bootstrap (macOS)**: Run the macOS installer/check + create model folders:
```bash
bash scripts/bootstrap_ollama_mac.sh
```
- **Bootstrap (Linux)**: Run the Linux helper (attempts to detect package manager and prepares model folders):
```bash
bash scripts/bootstrap_ollama_linux.sh
```
- The scripts create the model directory referenced by the setup script as `OLLAMA_MODELS` (by default `$HOME/models/ollama`).
- Start the Ollama server inside a tmux session (helper functions):
```bash
# Load helper functions (one-liner to source from dotfiles workspace)
source scripts/ollama_tmux.sh
# Start the server in a detached tmux session named 'ollama' (default command):
start_ollama_tmux
# To attach to the session:
tmux attach -t ollama
# To stop the server session:
stop_ollama_tmux
```
- Model management (two simple options):
- Pull a remote model (via the `ollama` CLI):
```bash
# example: pull a model by reference
pull_ollama_model <model-ref>
```
- Import or stage a local model into the $OLLAMA_MODELS path (creates a symlink):
```bash
import_local_model /path/to/local/model-dir-or-file
# The helper will link it into the directory created by setup_enterprise_ai_bash.sh
```
- Scripts referenced:
- [scripts/bootstrap_ollama_mac.sh](scripts/bootstrap_ollama_mac.sh)
- [scripts/bootstrap_ollama_linux.sh](scripts/bootstrap_ollama_linux.sh)
- [scripts/ollama_tmux.sh](scripts/ollama_tmux.sh)
- How to use Ollama from other AI applications:
- Run the server with `start_ollama_tmux` (above). By default the helper uses `ollama serve --host 127.0.0.1 --port 11434`.
- Many client apps can be pointed at the local Ollama HTTP API (default: `http://127.0.0.1:11434`). Check the Ollama docs for exact endpoints and payloads.
- Example using the `ollama` CLI to run a model directly from scripts or other programs:
```bash
# Run a model locally (interactive / CLI). Replace <model> with the model name.
ollama run <model> --prompt "Write a short haiku about trees"
```
- Example (generic) using HTTP from another application (replace endpoint/payload per Ollama docs):
```bash
curl -X POST "http://127.0.0.1:11434/api/generate" \
-H "Content-Type: application/json" \
-d '{"model":"<model>","prompt":"Hello from my app"}'
```
- When integrating from other AI tooling, supply the Ollama host/port (e.g. `OLLAMA_URL=http://127.0.0.1:11434`) or call the `ollama` CLI directly from the application process.
If you want, I can also:
- Make the new scripts executable (`chmod +x`) automatically in the repo
- Attempt to detect the Ollama default model storage path and auto-configure a symlink

View File

@@ -0,0 +1,41 @@
### MACHINE_LOCAL — managed centrally in dotfiles/hosts/ on kenjim-mbp
### Deployed via: dotfiles deploy-to kenjim@etqc-kenjim-11
### DO NOT edit directly on the server — edit in ~/dotfiles/hosts/ and re-deploy
### NFS NOTE: On NFS-home servers, this file lives at /opt/kenjim/.bashrc.local
### with a symlink from ~/.bashrc.local → /opt/kenjim/.bashrc.local
# Host : etqc-kenjim-11
# Profile : work (server)
# =============================================================================
export MACHINE_PROFILE="work"
export MACHINE_HOST="etqc-kenjim-11"
# Prevent shell auto-logout on idle
unset TMOUT
# =============================================================================
# ServiceNow API credentials
# =============================================================================
export SN_USERNAME='_integ-soap-read'
export SN_PASSWORD='CHANGEME' # set real value — never commit
# =============================================================================
# LDAP bind credentials
# Referenced by ldaps() and ldaps2() in ~/.bashrc.d/30_work.sh
# =============================================================================
export JNPR_LDAP_BIND_PW='CHANGEME' # was: xqYzhL%lLe!FIr!67LJX%7a^PWOWY0
export JNPR_LDAP_BIND_PW2='CHANGEME' # was: tF#w3St@nGqq36XZDym#857U)v4xKw
# =============================================================================
# Unified Hub (Artifactory) credentials
# Referenced by unified-hub-login() and unified-hub-engtech-bin-upload()
# in ~/.bashrc.d/30_work.sh
# =============================================================================
export UNIFIED_HUB_USERNAME='kenjim@juniper.net'
export UNIFIED_HUB_TOKEN='CHANGEME' # base64 API token from Artifactory
# =============================================================================
# AWS — server uses named profiles from ~/.aws/config loaded by k8configs env
# =============================================================================
export AWS_PROFILE=pgdb-qnc
export AWS_SDK_LOAD_CONFIG=1

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bash
set -euo pipefail
echo "🔧 Ollama Linux bootstrap — starting"
# Load environment (MODEL_ROOT, OLLAMA_MODELS)
# Temporarily disable "nounset" when sourcing user shell files to avoid
# failures from system /etc/bashrc referencing undefined vars like PS1.
if [ -f "$HOME/.bashrc" ]; then
set +u
# shellcheck disable=SC1091
source "$HOME/.bashrc" || true
set -u
fi
: "${OLLAMA_MODELS:=$HOME/models/ollama}"
mkdir -p "$OLLAMA_MODELS"
if command -v ollama >/dev/null 2>&1; then
echo "✅ ollama already installed: $(ollama version 2>/dev/null || echo 'unknown')"
else
echo " Attempting to install ollama on Linux"
if command -v apt-get >/dev/null 2>&1; then
echo "Using apt to install prerequisites..."
sudo apt-get update -y || true
sudo apt-get install -y ca-certificates curl gnupg lsb-release || true
echo "⚠️ Please follow the official ollama Linux install instructions if a package is not available: https://ollama.com/docs/install"
echo "If you have a .deb from Ollama, install it with: sudo dpkg -i <file.deb>"
elif command -v dnf >/dev/null 2>&1; then
echo "Using dnf; please refer to Ollama docs for distro-specific instructions: https://ollama.com/docs/install"
else
echo "⚠️ Could not detect package manager. Please install ollama manually. See: https://ollama.com/docs/install"
fi
fi
echo "📁 Ensuring model directory exists: $OLLAMA_MODELS"
mkdir -p "$OLLAMA_MODELS"
echo "✅ Linux Ollama bootstrap complete."
echo "Next steps: run scripts/ollama_tmux.sh to start the server in tmux, and place models under $OLLAMA_MODELS"

41
scripts/bootstrap_ollama_mac.sh Executable file
View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -euo pipefail
echo "🔧 Ollama macOS bootstrap — starting"
# Load environment (MODEL_ROOT, OLLAMA_MODELS)
# Temporarily disable "nounset" when sourcing user shell files to avoid
# failures from system /etc/bashrc referencing undefined vars like PS1.
if [ -f "$HOME/.bashrc" ]; then
set +u
# shellcheck disable=SC1091
source "$HOME/.bashrc" || true
set -u
fi
: "${OLLAMA_MODELS:=$HOME/models/ollama}"
mkdir -p "$OLLAMA_MODELS"
if command -v ollama >/dev/null 2>&1; then
echo "✅ ollama already installed: $(ollama version 2>/dev/null || echo 'unknown')"
else
if command -v brew >/dev/null 2>&1; then
echo "🍺 Installing ollama via Homebrew..."
brew update || true
brew install ollama || {
echo "⚠️ Homebrew install failed. See https://ollama.com/docs/install"
exit 1
}
echo "✅ ollama installed"
else
echo "⚠️ Homebrew not found. Install Homebrew first: https://brew.sh"
echo "Then re-run this script: $0"
exit 2
fi
fi
echo "📁 Ensuring model directory exists: $OLLAMA_MODELS"
mkdir -p "$OLLAMA_MODELS"
echo "✅ macOS Ollama bootstrap complete."
echo "Next steps: run scripts/ollama_tmux.sh to start the server in tmux, and place models under $OLLAMA_MODELS"

View File

@@ -883,20 +883,24 @@ cmd_remote_bootstrap() {
# COMMAND: deploy-to (push dotfiles to a server that can't reach Gitea)
# -----------------------------------------------------------------------
cmd_deploy_to() {
[ $# -ge 1 ] || die "Usage: deploy-to <user@host> [--scripts-only] [--include-ssh] [--no-backup] [--dry-run]"
[ $# -ge 1 ] || die "Usage: deploy-to <user@host> [--scripts-only] [--include-ssh] [--no-backup] [--run-setup] [--profile work|personal] [--dry-run]"
local target="$1"; shift
local scripts_only=false
local skip_ssh=true # default: skip .ssh/ — avoid pushing keys/config to servers
local no_backup=false
local run_setup=false
local setup_profile="work" # default profile for servers
local dry_run=false
while [[ $# -gt 0 ]]; do
case "$1" in
--scripts-only) scripts_only=true; shift ;;
--include-ssh) skip_ssh=false; shift ;;
--no-backup) no_backup=true; shift ;;
--dry-run) dry_run=true; shift ;;
--scripts-only) scripts_only=true; shift ;;
--include-ssh) skip_ssh=false; shift ;;
--no-backup) no_backup=true; shift ;;
--run-setup) run_setup=true; shift ;;
--profile) setup_profile="${2:-work}"; shift 2 ;;
--dry-run) dry_run=true; shift ;;
*) die "Unknown option: $1" ;;
esac
done
@@ -944,11 +948,17 @@ cmd_deploy_to() {
local backed_up=0
for rel in "${remote_paths[@]}"; do
# Check if the file actually exists on the remote before fetching
if ssh "$target" "[ -f ~/$rel ]" 2>/dev/null; then
# Check if the file/dir actually exists on the remote before fetching
if ssh "$target" "[ -e ~/$rel ]" 2>/dev/null; then
local local_dest="$backup_base/$rel"
mkdir -p "$(dirname "$local_dest")"
if scp -q "$target:~/$rel" "$local_dest" 2>/dev/null; then
# Use -r for directories, plain scp for files
if ssh "$target" "[ -d ~/$rel ]" 2>/dev/null; then
mkdir -p "$local_dest"
if scp -rq "$target:~/$rel/." "$local_dest/" 2>/dev/null; then
(( backed_up++ )) || true
fi
elif scp -q "$target:~/$rel" "$local_dest" 2>/dev/null; then
(( backed_up++ )) || true
fi
fi
@@ -1018,17 +1028,107 @@ cmd_deploy_to() {
fi
if $dry_run; then
echo " [dry-run] ~/$rel"
echo " [dry-run] ~/$rel$([ -d "$src" ] && echo '/')"
else
# Ensure parent directory exists on remote
local parent; parent="$(dirname "$rel")"
[[ "$parent" != "." ]] && ssh "$target" "mkdir -p ~/$parent"
scp -q "$src" "$target:~/$rel"
if [ -d "$src" ]; then
# For directories: remove stale dest first (avoids double-nesting on re-run)
# then scp -r into the parent so the dir name is preserved correctly.
ssh "$target" "rm -rf ~/$rel"
if [[ "$parent" == "." ]]; then
scp -rq "$src" "$target:~/"
else
ssh "$target" "mkdir -p ~/$parent"
scp -rq "$src" "$target:~/$parent/"
fi
else
[[ "$parent" != "." ]] && ssh "$target" "mkdir -p ~/$parent"
scp -q "$src" "$target:~/$rel"
fi
success "Deployed: ~/$rel"
(( deployed++ )) || true
fi
done < "$MANIFEST"
# ---- 5. Deploy hosts/<hostname>.bashrc.local → ~/.bashrc.local ----
# Strip user@ prefix, then strip domain suffix to get short hostname
local remote_short; remote_short="${target##*@}"
remote_short="${remote_short%%.*}"
local host_local="$DOTFILES_DIR/hosts/${remote_short}.bashrc.local"
if [ -f "$host_local" ]; then
echo
info "Found host-specific config: hosts/${remote_short}.bashrc.local"
if $dry_run; then
echo " [dry-run] hosts/${remote_short}.bashrc.local → ~/.bashrc.local"
else
# Back up existing remote .bashrc.local if not already captured above
if $no_backup; then
: # skip
elif ssh "$target" '[ -L ~/.bashrc.local ]' 2>/dev/null; then
# It's a symlink (NFS setup) — back up the target file
local real_path
real_path=$(ssh "$target" 'readlink -f ~/.bashrc.local' 2>/dev/null || true)
if [[ -n "$real_path" ]]; then
local bl_backup="$HOME/.dotfiles_backup/remote-${remote_short}-$(date +%Y%m%d_%H%M%S)"
mkdir -p "$bl_backup"
scp -q "$target:$real_path" "$bl_backup/.bashrc.local" 2>/dev/null || true
info "Backed up remote $real_path$bl_backup/.bashrc.local"
fi
elif ssh "$target" '[ -f ~/.bashrc.local ]' 2>/dev/null; then
local bl_backup="$HOME/.dotfiles_backup/remote-${remote_short}-$(date +%Y%m%d_%H%M%S)"
mkdir -p "$bl_backup"
scp -q "$target:~/.bashrc.local" "$bl_backup/.bashrc.local" 2>/dev/null || true
info "Backed up remote ~/.bashrc.local → $bl_backup/.bashrc.local"
fi
# Detect NFS home on the remote and deploy to /opt/kenjim/ if needed
local _remote_nfs=false
if ssh "$target" 'df -P "$HOME" 2>/dev/null | tail -1 | grep -qE ":|nfs"' 2>/dev/null; then
_remote_nfs=true
fi
if $_remote_nfs; then
info "NFS home detected on $target — deploying to /opt/kenjim/.bashrc.local"
# Ensure /opt/kenjim exists — skip sudo if it already does
if ! ssh "$target" '[ -d /opt/kenjim ]' 2>/dev/null; then
info "Creating /opt/kenjim on $target (requires sudo)..."
ssh -t "$target" 'sudo mkdir -p /opt/kenjim && sudo chown $(id -u):$(id -g) /opt/kenjim && chmod 700 /opt/kenjim'
fi
scp -q "$host_local" "$target:/opt/kenjim/.bashrc.local"
ssh "$target" 'chmod 600 /opt/kenjim/.bashrc.local && ln -sfn /opt/kenjim/.bashrc.local ~/.bashrc.local'
success "Deployed: hosts/${remote_short}.bashrc.local → /opt/kenjim/.bashrc.local (symlinked from ~)"
else
scp -q "$host_local" "$target:~/.bashrc.local"
success "Deployed: hosts/${remote_short}.bashrc.local → ~/.bashrc.local"
fi
(( deployed++ )) || true
fi
else
info "No host-specific config found at hosts/${remote_short}.bashrc.local — skipping."
info "Create one to manage ~/.bashrc.local centrally: dotfiles/hosts/${remote_short}.bashrc.local"
fi
# ---- 6. Optionally run setup on the remote ----
if ! $dry_run; then
local do_setup=$run_setup
if ! $run_setup; then
echo
read -r -p "Run setup_enterprise_ai_bash.sh on $target now? Creates dirs, writes shell config. (y/n): " _ans
[[ "$_ans" == [yY] ]] && do_setup=true
fi
if $do_setup; then
echo
info "Running setup on $target (profile=$setup_profile)..."
info "This will create the directory structure and write shell config."
echo
ssh -t "$target" \
"MACHINE_PROFILE=${setup_profile} DOTFILES_REMOTE=${DOTFILES_REMOTE} bash ~/scripts/setup_enterprise_ai_bash.sh"
success "Setup complete on $target."
fi
fi
echo
if $dry_run; then
info "Dry run complete. Re-run without --dry-run to transfer files."
@@ -1036,6 +1136,7 @@ cmd_deploy_to() {
bold "Deploy complete: $deployed file(s) deployed, $skipped skipped."
info "Files were copied directly (no symlinks). Re-run deploy-to to push updates."
$skip_ssh && info "~/.ssh/ was skipped. Use --include-ssh to also deploy ~/.ssh/config."
! $run_setup && info "Tip: add --run-setup to also create directories and shell config on the remote."
fi
}
@@ -1067,14 +1168,17 @@ ${BOLD}COMMANDS — SSH & Keys${RESET}
${BOLD}COMMANDS — Multi-machine${RESET}
remote-bootstrap <user@host> [--profile work|personal]
Upload scripts and run full setup on a remote machine
deploy-to <user@host> [--scripts-only] [--include-ssh] [--no-backup] [--dry-run]
deploy-to <user@host> [--scripts-only] [--include-ssh] [--no-backup] [--run-setup] [--profile work|personal] [--dry-run]
SCP tracked dotfiles + scripts directly to a server.
Use when the server can't reach the Gitea repo.
Backs up existing remote files locally before overwriting.
--scripts-only Only push ~/scripts/, skip dotfiles
--include-ssh Also deploy ~/.ssh/config (skipped by default)
--no-backup Skip the pre-deploy remote backup
--dry-run Preview what would be transferred
--scripts-only Only push ~/scripts/, skip dotfiles
--include-ssh Also deploy ~/.ssh/config (skipped by default)
--no-backup Skip the pre-deploy remote backup
--run-setup Run setup_enterprise_ai_bash.sh on the remote
after deploy (creates dirs, shell config)
--profile work|personal Profile to pass to setup (default: work)
--dry-run Preview what would be transferred
${BOLD}QUICK START — this machine (work)${RESET}
./dotfiles_manager.sh init

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
set -euo pipefail
echo "🔍 Detecting Ollama model directories and linking into OLLAMA_MODELS"
# Load env if available
if [ -f "$HOME/.bashrc" ]; then
set +u
# shellcheck disable=SC1091
source "$HOME/.bashrc" || true
set -u
fi
OLLAMA_MODELS="${OLLAMA_MODELS:-$HOME/models/ollama}"
mkdir -p "$OLLAMA_MODELS"
candidates=(
"$HOME/.ollama/models"
"$HOME/.local/share/ollama/models"
"/var/lib/ollama/models"
"/usr/local/var/ollama/models"
"$HOME/.ollama"
)
linked=0
for cand in "${candidates[@]}"; do
if [ -d "$cand" ]; then
# skip empty directories
if [ -z "$(ls -A "$cand" 2>/dev/null)" ]; then
echo " Found $cand but it's empty — skipping"
continue
fi
name=$(basename "$cand")
dest="$OLLAMA_MODELS/$name"
if [ -e "$dest" ]; then
echo " Destination exists: $dest — skipping"
continue
fi
ln -sfn "$cand" "$dest"
echo "✅ Linked $cand$dest"
linked=$((linked+1))
fi
done
if [ $linked -eq 0 ]; then
echo "⚠️ No existing Ollama model directories detected in common locations."
echo "You can place models in: $OLLAMA_MODELS or run: pull_ollama_model <model-ref> (see scripts/ollama_tmux.sh)"
else
echo "🎉 Completed linking ($linked). Verify with: ls -la $OLLAMA_MODELS"
fi
echo "Done."

144
scripts/ollama_tmux.sh Executable file
View File

@@ -0,0 +1,144 @@
#!/usr/bin/env bash
set -euo pipefail
# Ollama tmux helper and model utilities
# Source this file or call functions directly: source scripts/ollama_tmux.sh
# Ensure environment variables exist
if [ -f "$HOME/.bashrc" ]; then
set +u
# shellcheck disable=SC1091
source "$HOME/.bashrc" || true
set -u
fi
: "${OLLAMA_MODELS:=$HOME/models/ollama}"
start_ollama_tmux() {
session="ollama"
# Use provided command or sensible default. Ollama uses env vars (OLLAMA_HOST)
# Example: OLLAMA_HOST=0.0.0.0:11434 ollama serve
default_cmd="${OLLAMA_CMD:-ollama serve}"
cmd="${1:-$default_cmd}"
echo "Using command: $cmd"
if [ -n "${OLLAMA_HOST:-}" ]; then
echo "OLLAMA_HOST is set to: $OLLAMA_HOST"
fi
if ! command -v tmux >/dev/null 2>&1; then
echo "⚠️ tmux not installed. Install tmux and re-run."
return 2
fi
# Create models dir if needed
mkdir -p "$OLLAMA_MODELS"
if tmux has-session -t "$session" 2>/dev/null; then
echo " tmux session '$session' already running. Attach with: tmux attach -t $session"
return 0
fi
echo "🔁 Starting ollama in tmux session '$session' with command: $cmd"
tmux new-session -d -s "$session" "$cmd"
sleep 0.5
if tmux has-session -t "$session" 2>/dev/null; then
echo "✅ Started. Attach: tmux attach -t $session"
else
echo "❌ Failed to start tmux session. Check logs or run the command directly: $cmd"
return 1
fi
}
pull_ollama_model() {
if [ "$#" -lt 1 ]; then
echo "Usage: pull_ollama_model <model-ref>"
return 2
fi
if ! command -v ollama >/dev/null 2>&1; then
echo "⚠️ ollama CLI not found. Install first."
return 3
fi
model="$1"
echo "⬇️ Pulling model: $model"
ollama pull "$model"
}
import_local_model() {
if [ "$#" -lt 1 ]; then
echo "Usage: import_local_model <path-to-model-dir-or-file>"
return 2
fi
src="$1"
if [ ! -e "$src" ]; then
echo "⚠️ Source not found: $src"
return 3
fi
mkdir -p "$OLLAMA_MODELS"
dest="$OLLAMA_MODELS/$(basename "$src")"
ln -sfn "$src" "$dest"
echo "🔗 Linked $src$dest"
echo "Note: depending on your ollama installation you may need to reindex or use the ollama CLI to register the model."
}
stop_ollama_tmux() {
session="ollama"
if tmux has-session -t "$session" 2>/dev/null; then
tmux kill-session -t "$session"
echo "🛑 Stopped tmux session '$session'"
else
echo " No tmux session named '$session' running"
fi
}
print_usage() {
cat <<EOF
Usage: $(basename "$0") <command> [args]
Commands:
start [<cmd>] Start ollama in tmux (optional command overrides default)
stop Stop the tmux session named 'ollama'
pull <model-ref> Pull a model using the ollama CLI
import <path> Import/link a local model directory/file into OLLAMA_MODELS
help Show this help
If you want to use these as shell functions, source this file instead:
source scripts/ollama_tmux.sh
EOF
}
if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
# Script executed directly; provide a simple CLI wrapper
cmd="${1:-}"
case "$cmd" in
start)
# shift and pass remaining args as the command
shift || true
start_ollama_tmux "$@"
exit $?
;;
stop)
stop_ollama_tmux
exit $?
;;
pull)
shift || true
pull_ollama_model "$@"
exit $?
;;
import)
shift || true
import_local_model "$@"
exit $?
;;
help|--help|-h|"")
print_usage
exit 0
;;
*)
echo "Unknown command: $cmd"
print_usage
exit 2
;;
esac
else
echo "Loaded ollama tmux helper. Functions: start_ollama_tmux, stop_ollama_tmux, pull_ollama_model, import_local_model"
fi

View File

@@ -186,6 +186,69 @@ fi
echo "✅ .bashrc.local written for profile: $MACHINE_PROFILE"
# ---- NFS-aware placement for work servers ----
# Work servers with NFS-mounted home dirs share ~/.bashrc.local across hosts.
# To keep per-machine overrides, store the real file in /opt/kenjim/ and symlink.
if [[ "$MACHINE_PROFILE" == "work" ]]; then
_is_nfs_home=false
case "$(hostname -s)" in
etqc-*|etbg-*|engtech-dev-*|qnc-kenjim-toby-shell*|qtaas*|bng-kenjim-toby-shell*|btaas*|kenjim-taas*)
if df -P "$HOME" 2>/dev/null | tail -1 | grep -qE ':|nfs'; then
_is_nfs_home=true
elif mount | grep -q "on ${HOME%%/} .*type nfs"; then
_is_nfs_home=true
fi
;;
esac
if $_is_nfs_home; then
OPT_DIR="/opt/kenjim"
OPT_LOCAL="$OPT_DIR/.bashrc.local"
echo "🔗 NFS home detected — relocating .bashrc.local to $OPT_LOCAL"
if [ ! -d "$OPT_DIR" ]; then
echo " Creating $OPT_DIR ..."
sudo mkdir -p "$OPT_DIR"
sudo chown "$(id -u):$(id -g)" "$OPT_DIR"
chmod 700 "$OPT_DIR"
fi
# If ~/.bashrc.local is already a symlink (previous run), the cat above
# wrote through it into the target. Remove the symlink first so mv
# doesn't see source and destination as the same file.
if [ -L "$BASHRC_LOCAL" ]; then
rm -f "$BASHRC_LOCAL"
# Content already landed at the symlink target; just ensure perms
chmod 600 "$OPT_LOCAL"
else
mv "$BASHRC_LOCAL" "$OPT_LOCAL"
chmod 600 "$OPT_LOCAL"
fi
ln -sfn "$OPT_LOCAL" "$BASHRC_LOCAL"
echo " Linked: ~/.bashrc.local → $OPT_LOCAL"
# VS Code Remote stores large caches in ~/.vscode-server and
# ~/.vscode-remote-containers — keep them on local disk, not NFS.
for _vsdir in .vscode-server .vscode-remote-containers; do
_opt_target="$OPT_DIR/$_vsdir"
_home_link="$HOME_DIR/$_vsdir"
mkdir -p "$_opt_target"
if [ -d "$_home_link" ] && [ ! -L "$_home_link" ]; then
# Existing real directory — move contents then replace with symlink
echo " Moving ~/$_vsdir$OPT_DIR/$_vsdir ..."
rsync -a "$_home_link/" "$_opt_target/" 2>/dev/null || \
cp -a "$_home_link/." "$_opt_target/" 2>/dev/null || true
rm -rf "$_home_link"
fi
ln -sfn "$_opt_target" "$_home_link"
echo " Linked: ~/$_vsdir$_opt_target"
done
echo "✅ Per-machine .bashrc.local and VS Code dirs stored outside NFS at $OPT_DIR"
fi
fi
# ------------------------------------------------------
# 4⃣ INITIALIZE DOTFILES REPO (with Gitea remote)
# ------------------------------------------------------