Add secrets skeleton and Homebrew lock snapshot

This commit is contained in:
2026-03-08 17:31:52 +08:00
parent d317204745
commit 3483e0a826
12 changed files with 2272 additions and 2 deletions
+6 -2
View File
@@ -6,8 +6,12 @@
# Machine-local shell state
zsh/90-machine.local.zsh
# Secrets should stay outside git
config/secrets/
# Tracked secret scaffolding, but never commit live secret material here
config/secrets/*
!config/secrets/README.md
!config/secrets/examples/
config/secrets/examples/*
!config/secrets/examples/*.example.zsh
# Optional sanitized backups
config/clash/*.bak
+9
View File
@@ -39,15 +39,24 @@ Do not commit secrets here.
- Keep API tokens in `~/.config/secrets/` or the macOS Keychain.
- Treat live Clash provider files as untracked machine state unless sanitized.
Initialize the local secrets skeleton with:
```bash
./scripts/secrets/bootstrap.sh
```
## Tracked Recovery Assets
- `Brewfile` rebuilds the Homebrew toolchain baseline.
- `config/homebrew/Brewfile.lock.json` captures installed package versions as a
lock-style recovery snapshot.
- `config/clash/config.public.yaml` preserves the ClashX base port/controller
settings that make the local mixed proxy port stay on `7890`.
- `config/clash/clashx.public.yaml` is a sanitized export of the live Clash
config with hostnames and passwords replaced by placeholders.
- `scripts/brew/export-brewfile.sh` refreshes `Brewfile` from the current
machine state.
- `scripts/brew/export-lockfile.rb` refreshes the Homebrew version snapshot.
- `scripts/clash/export-public-config.rb` refreshes the sanitized Clash template
from the live local config.
+13
View File
@@ -74,6 +74,13 @@ xcode-select --install
brew bundle --file ~/work/codes/tools/macos/dotfiles/Brewfile
```
仓库还提供一个锁定式版本快照:
- `config/homebrew/Brewfile.lock.json`
用途是帮助你确认“当前机器当时装的是哪些版本”,但它不是 Homebrew 的
原生严格锁文件。
### 2. 拉取 dotfiles
```bash
@@ -136,6 +143,12 @@ cp zsh/90-machine.local.example.zsh zsh/90-machine.local.zsh
- `ANTHROPIC_AUTH_TOKEN`
- 其他不应该进入 git 的 token 和内网地址
如果只是新机器初始化,先创建 secrets 骨架:
```bash
./scripts/secrets/bootstrap.sh
```
### 5. 恢复语言与开发运行时
这台机器当前依赖的运行时包括:
File diff suppressed because it is too large Load Diff
+37
View File
@@ -0,0 +1,37 @@
# Homebrew Recovery Notes
This directory keeps two different recovery artifacts:
- `../../Brewfile`: desired package set
- `Brewfile.lock.json`: installed version snapshot from a real machine
## What each file means
`Brewfile`
- Good for rebuilding the package set on a new machine
- Stable and easy to review
- Does not guarantee exact versions
`Brewfile.lock.json`
- Snapshot of installed taps, formulae, casks, and version strings
- Useful for audit, drift checks, and approximate rebuilds
- Not a true package manager lockfile in the npm / Cargo sense
Homebrew is rolling. Exact reinstall of every historical version is not always
possible without extra work such as `brew extract`, custom taps, or archived
bottles.
## Recommended restore flow
1. Run `brew bundle --file Brewfile`
2. Compare the result with `Brewfile.lock.json`
3. Only pin or backfill exact versions when they matter
## Refresh commands
```bash
./scripts/brew/export-brewfile.sh
./scripts/brew/export-lockfile.rb
```
+38
View File
@@ -0,0 +1,38 @@
# Secrets Layout
This repository tracks the structure of the secrets directory, not the secret
values themselves.
## Live location
Actual machine-local files live in:
```text
~/.config/secrets/
```
Those files are loaded by `zsh/80-local-loader.zsh`.
## Recommended live files
- `~/.config/secrets/agent-env.zsh`
- `~/.config/secrets/tooling-env.zsh`
Create or refresh the skeleton with:
```bash
./scripts/secrets/bootstrap.sh
```
## Rules
- Do not commit real secrets into this repository.
- Keep real secret files mode `600`.
- Store only comments or placeholders in the tracked example files.
## Typical contents
- API tokens
- private base URLs
- local override endpoints
- credentials that must not be stored in `~/.zshrc`
@@ -0,0 +1,6 @@
# Copy or bootstrap this into ~/.config/secrets/agent-env.zsh
# and keep the real file out of git.
#
# export ANTHROPIC_BASE_URL="https://example.internal/api"
# export ANTHROPIC_AUTH_TOKEN="replace-me"
# export GITHUB_PERSONAL_ACCESS_TOKEN="replace-me"
@@ -0,0 +1,6 @@
# Copy or bootstrap this into ~/.config/secrets/tooling-env.zsh
# and keep the real file out of git.
#
# export DOCKER_HOST="unix://${HOME}/.orbstack/run/docker.sock"
# export OPENAI_BASE_URL="https://example.internal/v1"
# export INTERNAL_PROXY_URL="http://127.0.0.1:7890"
+7
View File
@@ -21,6 +21,7 @@ check_path "${repo_root}/scripts"
check_path "${HOME}/.zshrc"
check_path "${HOME}/.zshrc.d"
check_path "${HOME}/bin"
check_path "${HOME}/.config/secrets"
if grep -Fq "# dotfiles bootstrap start" "${HOME}/.zshrc" 2>/dev/null; then
echo "[ok] ~/.zshrc contains managed bootstrap block"
@@ -34,4 +35,10 @@ else
echo "[warn] codex not found on PATH"
fi
if [[ -f "${HOME}/.config/secrets/agent-env.zsh" ]]; then
echo "[ok] ~/.config/secrets/agent-env.zsh exists"
else
echo "[warn] ~/.config/secrets/agent-env.zsh is missing"
fi
exit "${status}"
+1
View File
@@ -7,6 +7,7 @@ bootstrap_end="# dotfiles bootstrap end"
zshrc="${HOME}/.zshrc"
"${repo_root}/scripts/shell/sync-zsh-links.sh"
"${repo_root}/scripts/secrets/bootstrap.sh"
if [[ ! -f "${zshrc}" ]]; then
touch "${zshrc}"
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env ruby
require "json"
require "open3"
require "time"
def capture(*cmd)
stdout, stderr, status = Open3.capture3(*cmd)
abort(stderr.empty? ? "command failed: #{cmd.join(' ')}" : stderr) unless status.success?
stdout.lines.map(&:strip).reject(&:empty?)
end
repo_root = File.expand_path("../..", __dir__)
output = ARGV[0] || File.join(repo_root, "config/homebrew/Brewfile.lock.json")
data = {
"generated_at" => Time.now.utc.iso8601,
"taps" => capture("brew", "tap").sort,
"formulae" => capture("brew", "list", "--formula", "--versions").sort.map do |line|
name, *versions = line.split(/\s+/)
{ "name" => name, "versions" => versions }
end,
"casks" => capture("brew", "list", "--cask", "--versions").sort.map do |line|
name, *versions = line.split(/\s+/)
{ "name" => name, "versions" => versions }
end
}
File.write(output, JSON.pretty_generate(data) + "\n")
puts "Wrote #{output}"
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
live_dir="${HOME}/.config/secrets"
examples_dir="${repo_root}/config/secrets/examples"
mkdir -p "${live_dir}"
if [[ ! -f "${live_dir}/README.md" ]]; then
cp "${repo_root}/config/secrets/README.md" "${live_dir}/README.md"
fi
for example in "${examples_dir}"/*.example.zsh; do
base_name="$(basename "${example}" .example.zsh).zsh"
target="${live_dir}/${base_name}"
if [[ ! -f "${target}" ]]; then
cp "${example}" "${target}"
chmod 600 "${target}"
echo "Created ${target}"
fi
done
echo "Secrets skeleton is ready in ${live_dir}"