Treu els secrets del .zshrc amb 1Password CLI
Guardo la meva configuració de la shell en un repo de dotfiles per poder fer
track dels canvis a git. Però algunes claus API havien d'estar disponibles a
l'inici de la shell, i fer hardcoding al .zshrc no era una opció. Així que les
carregava des d'un fitxer .env separat — un que es quedava fora del repo.
Els secrets encara estaven en text pla, simplement en un fitxer diferent. Un
git add incorrecte i estarien a l'historial. Llavors vaig pensar: 1Password
podria gestionar això.
Vaig moure les claus allà i ara les carrego a l'inici de la shell amb
op inject — una crida, desbloqueig biomètric, sense fitxers en text pla
enlloc.
El problema amb els secrets al .env i .zshrc
La majoria de desenvolupadors guarden secrets d'una de dues maneres: un fitxer
.env o sentències export escampades per les configs de la shell. De
qualsevol manera, els valors són text pla i acaben a còpies de seguretat, repos
de dotfiles o historial de la shell.
Vaig escriure sobre emmagatzematge segur de credencials per a Node.js amb cross-keychain. Les variables d'entorn de la Shell són un problema diferent — carreguen abans que qualsevol aplicació s'executi, i cada procés al teu terminal necessita accés a elles.
1Password CLI (op) soluciona això a nivell de shell.
Crea un vault i habilita el desbloqueig biomètric
Instal·la la 1Password CLI primer, després configura dues coses abans de tocar la teva config de la shell.
Un vault per als secrets. Vaig crear un vault anomenat development amb
múltiples entrades per a cada servei. Cada secret és el camp de credencials per
a aquest servei. Això et dona URIs netes tipus
op://development/<SERVICE_NAME>/credentials. Pots organitzar-ho com vulguis,
però recomano una estructura consistent per a una fàcil referència.
Desbloqueig biomètric. Sense això, op et demana la teva contrasenya mestra
cada cop que obres un terminal. Habilita-ho a l'aplicació d'escriptori de
1Password a Settings → Developer → "Integrate with 1Password CLI". Després
d'això, op s'autentica via Touch ID o el keychain del teu sistema.
Divideix la teva shell en dos fitxers
Amb el vault a lloc, substitueix el teu fitxer .env amb dos fitxers de shell.
Un per a configuració no secreta que zsh fa source automàticament. Un per a
secrets que op inject processa abans de carregar.
.zshenv — configuració plana, sense secrets
export EDITOR="nvim"export LANG="en_US.UTF-8"export PATH="$HOME/.local/bin:$PATH"export NODE_ENV="development"
Zsh fa source d'aquest fitxer automàticament a cada invocació de la shell — interactiva, no interactiva, scripts, comandes SSH. Cap secret aquí, mai.
.zshsecrets — referències a secrets, no valors
export GITHUB_TOKEN="{{ op://development/github/credentials }}"export ANTHROPIC_API_KEY="{{ op://development/anthropic/credentials }}"export NPM_TOKEN="{{ op://development/npm/credentials }}"
És segur fer commit al teu repo de dotfiles. Qualsevol que ho llegeixi veu URIs
op://, no credencials.
.zshrc — connecta-ho tot
if command -v op &>/dev/null; theneval "$(op inject -i ~/.zshsecrets 2>/dev/null)" || echo "⚠ op: secrets not loaded"fi
op inject llegeix la plantilla, resol cada referència {{ op://... }} contra
el teu vault de 1Password, i treu el resultat amb valors reals. eval executa
els exports. Si op no està autenticat o no està disponible, la shell encara
s'inicia — simplement no tindràs els secrets carregats fins que executis
op signin i tornis a fer source.
Per què op inject en lloc de op read
Dues maneres d'extreure secrets d'op. Lectures per variable:
export GITHUB_TOKEN="$(op read 'op://development/github/credentials' 2>/dev/null)"
O injecció de plantilla, que és el que utilitzo jo. La diferència és el
rendiment. Cada op read genera un subprocés i fa una crida a l'API. Amb més de
5 secrets, l'inici de la shell creix 1–2 segons. op inject resol tot en una
sola crida — al voltant de 200–400ms amb desbloqueig biomètric habilitat.
La neteja que no et pots saltar
Després de migrar, vaig fer tres coses:
Eliminar cada secret hardcoded dels meus fitxers de shell. Un grep ràpid troba els que s'han quedat enrere:
grep -rn 'export.*KEY\|export.*TOKEN\|export.*SECRET' ~/.zsh*
Netejar el meu historial de git dels dotfiles. Si mai has fet commit de secrets — encara que els esborressis més tard — encara són a l'historial. git filter-repo o BFG Repo-Cleaner poden purgar-los.
Rotar cada token que hagi estat en text pla. Encara que els teus secrets mai toquessin un repo de git, podrien haver viscut en còpies de seguretat de Time Machine o historial de la shell. Si no estàs segur de la teva exposició completa, rota. No és opcional.
Compromisos
Latència d'inici. La crida op inject afegeix 200–400ms a l'inici de la
shell. Sense desbloqueig biomètric, op demana la teva contrasenya mestra —
dolorós si obres terminals freqüentment. Fins i tot amb ell habilitat, el prompt
de Touch ID interromp el flux quan obres terminals en successió ràpida.
Buits d'autenticació. Si op no està autenticat, els teus secrets no
carregaran. Ho notaràs quan una comanda falli, llavors executa op signin i
source ~/.zshrc. És una fricció menor i un intercanvi raonable per no tenir
secrets en text pla.
Sense suport remot. Les sessions SSH a màquines remotes no tindran op. Si
necessites secrets allà, necessitaràs un mecanisme diferent — comptes de servei
d'op, o fer forwarding de variables específiques a través de la config SSH.
Un repo de dotfiles que pots fer públic
El meu repo de dotfiles és ara segur per al públic. Cada secret viu a 1Password,
un fitxer de plantilla amb URIs op:// els carrega a l'inici, i Touch ID
gestiona la resta.
Si necessites secrets en màquines remotes, la documentació de la CLI de 1Password cobreix comptes de servei i SSH agent forwarding.