
팀을 위한 현대적인 git 기반 age 암호화 비밀 관리자입니다.
cottage는 팀이 git 저장소에서 age-encrypted 비밀을 관리하기 위한 GitOps 도구입니다.
비밀을 암호화/복호화하고, 수신자(recipients)를 관리하며, 비밀을 저장소 밖으로 유지하면서도 VCS를 통한 쉬운 공유를 가능하게 하는 간단한 워크플로우를 제공합니다. cottage는 또한 암호화된 비밀의 편집된(redacted) 미리보기를 생성하여 가시성을 높이고, 영구 및 임시 복호화 워크플로우를 모두 지원하며, 비밀이 평문으로 커밋되지 않도록 보장합니다.

.gitignore를 자동으로 업데이트합니다.ctg diff는 로컬에서 수정된 비밀과 추적된 암호화 대응 파일 간의 diff를 보여줍니다.ctg decrypt/sync는 복호화된 비밀을 디스크에 유지합니다.ctg run(단축어 ctgx) 및 ctg edit는 작업 전에 비밀을 복호화하며, 이전에 디스크에 이미 존재했다면 유지하고, 그렇지 않았다면 작업 후 자동으로 정리합니다.ctg encrypt --clean, ctg run --clean, ctg edit --clean은 이전에 존재했더라도 복호화된 파일이 디스크에서 정리되도록 보장합니다.ctg env는 복호화된 비밀을 디스크에 전혀 쓰지 않고 환경 변수로 주입하여 명령을 실행합니다.# rust: cargo-binstall/cargo
cargo binstall --locked cottage
cargo install --locked cottage
# python: pip/uv/uvx
pip install cottage
uv pip install cottage
uvx --from cottage ctg --version
# node: yarn/pnpm/npx
yarn global add @sayanarijit/cottage
pnpm add -g @sayanarijit/cottage
npx -p @sayanarijit/cottage ctg --version
Docker 이미지로도 사용할 수 있습니다:
# Docker
docker run --rm -v $PWD:/app sayanarijit/cottage --version
# Podman
podman run --rm -v $PWD:/app quay.io/sayanarijit/cottage --version
또는 GitHub에서 최신 릴리스를 다운로드하세요.
Cottage VS Code 확장을 사용하여 ctg를 설치하고, Copilot 안전 훅을 추가하고, 탐색기에서 파일을 암호화하고, 에디터 워크플로우를 통해 .cott.age 파일을 열 수 있습니다.
Visual Studio Marketplace에서 설치하거나, vscode-plugin-cottage에서 로컬로 빌드하여 설치하세요.
VSX 파일을 다운로드하여 Cursor 또는 Eclipse IDE에 설치하세요. VS Code 확장과 유사하게 작동합니다.
cottage.vim 플러그인을 사용하여 Vim 또는 Neovim에서 비밀을 암호화/복호화하세요.
아래의 모든 통합은 AI 에이전트가 ctg/ctgx를 직접 실행하거나 비밀 파일을 보거나 편집하는 것을 방지합니다: .cottage/ 내부의 모든 것, 모든 *.cott.* 파일(암호화된 *.cott.age 블롭 및 편집된 *.cott.toml 미리보기), 그리고 디스크에 여전히 *.cott.age 대응 파일이 있는 모든 복호화된 파일.
Claude Code를 사용하는 경우, 비밀이 있는 저장소에 .claude/settings.json 및 .claude/hooks/deny-secrets.py를 추가하여 Claude Code 세션이 비밀을 안전하게 처리하도록 하거나, claude-plugin-cottage 플러그인을 설치하세요.
VS Code에서 GitHub Copilot을 사용하는 경우, 비밀이 있는 저장소에 .github/hooks/ctg-policy.json 및 .github/hooks/scripts/deny_ctg_command.py를 추가하여 Copilot 세션이 복호화된 파일을 정리하고, 직접적인 ctg 셸 명령을 차단하고, 비밀 파일에 대한 접근을 차단하도록 하거나, VS Code에서 이를 설정하려면 vscode-plugin-cottage 확장을 설치하세요.
VS Code는 .claude/settings.json 훅 정의도 로드합니다. 동일한 저장소에 Claude와 Copilot 훅 파일을 모두 유지하는 경우, 동일한 정리 훅을 실수로 두 번 실행하지 않도록 주의하세요.
Codex를 사용하는 경우, 비밀이 있는 저장소에 .codex/hooks.json 및 .codex/hooks/deny-ctg.py를 추가하여 Codex 세션이 비밀을 안전하게 처리하도록 하거나, codex-plugin-cottage 플러그인을 설치하세요.
Codex는 로컬 훅이 실행되기 전에 검토되어야 합니다. 파일을 추가한 후 저장소에서 Codex를 시작하고 /hooks를 사용하여 프로젝트 훅을 검토하고 신뢰하세요.
Antigravity(agy)를 사용하는 경우, 비밀이 있는 저장소에 .agents/hooks.json 및 .agents/scripts/deny-ctg.py를 추가하여 Antigravity 세션이 비밀을 안전하게 처리하도록 하거나, agy-plugin-cottage 플러그인을 설치하세요.
Cursor를 사용하는 경우, 비밀이 있는 저장소에 .cursor/hooks.json, .cursor/hooks/deny-ctg.py, .cursor/hooks/deny-read-secrets.py, .cursor/rules/deny-ctg.mdc 및 .cursorignore를 추가하여 Cursor 세션이 비밀을 안전하게 처리하도록 하세요.
Cursor는 먼저 훅을 활성화해야 합니다. Cursor 설정 > 훅을 열고 훅을 활성화한 다음 에이전트 세션을 다시 시작하여 프로젝트 훅이 적용되도록 하세요. .cursorignore는 추가로 비밀 파일이 Cursor의 인덱싱과 에이전트의 컨텍스트에 포함되지 않도록 합니다.
프로젝트 초기화:
mkdir project && cd project
git init # 선택 사항, cottage는 git과 함께 사용할 때 더 잘 작동하지만 필수는 아닙니다
ctg init # .cottage 디렉터리와 필요한 파일을 설정합니다
tree -a
# .
# ├ .cottage/ <- `ctg init`에 의해 자동 생성됨
# │ ├ identity <- 개인 키, 안전하게 보관하세요. 전역으로 사용하려면 `~/.config/cottage/identity`로 이동하거나 기존 개인 키 중 하나에 대한 소프트 링크로 교체하세요.
# │ └ recipients/ <- 팀이 모든 수신자의 공개 키를 보관하는 곳입니다.
# │ └ sayanarijit <- 공개 키. 커밋하세요. 기존 공개 키를 사용하려면 해당 키를 여기에 복사(소프트링크 아님)하세요.
# ├ .git/...
# ├ .gitattributes <- git diff 오염을 방지하기 위해 `*.cott.age binary linguist-generated filter=cottage-encrypted -diff` 추가됨
# └ .gitignore <- 명백한 이유로 `/.cottage/identity` 추가됨
# cottage가 수행한 모든 것을 정리하려면 언제든지 `ctg clean --all`을 실행할 수 있습니다.
비밀 생성 또는 편집:
# `ctg edit`는 $EDITOR에서 열기 전에 파일을 복호화하고 저장 시 다시 암호화합니다.
# 복호화된 파일이 `ctg edit` 실행 전에 디스크에 없었다면 이후 정리됩니다.
# 이미 존재했다면 디스크에 유지됩니다.
ctg edit secret.yml
# `ctg edit` 또는 `ctg encrypt`와 함께 `--clean`을 사용하여 이전에 존재했더라도 복호화된 파일이 삭제되도록 보장합니다
ctg edit secret.yml --clean # $EDITOR에서 열고, 저장 시 암호화하고, 정리합니다
ctg encrypt secret.yml --clean # secret.yml을 암호화하고 정리합니다
# secret.yml 암호화
# secret.yml.cott.age로
# secret.yml.cott.toml 편집
# .gitignore 편집
# secret.yml 삭제
복호화된 비밀로 명령 실행:
cat secret.yml
# cat: secret.yml: No such file or directory
# `ctg run`(또는 단축어 `ctgx`)은 명령 실행 전에 비밀을 복호화합니다.
# 복호화된 파일이 사전에 디스크에 없었다면 명령 완료 후 자동으로 정리됩니다.
# 사전에 이미 존재했다면 디스크에 유지됩니다.
ctg run -- kubectl apply -f secret.yml # secret.yml.cott.age를 secret.yml로 복호화하고 명령을 실행합니다
ctg run -- kubectl apply -f secret.yml.cott.age # 경로 인수를 복호화된 파일 경로로도 대체합니다
ctg run -- kubectl apply -f . # .의 모든 .cott.age 파일을 복호화하고 명령을 실행합니다
ctg run -- ./deploy.sh # 저장소의 모든 .cott.age 파일을 복호화하고 명령을 실행합니다
cat secret.yml
# cat: secret.yml: No such file or directory
# 이전에 존재했더라도 복호화된 파일이 정리되도록 `--clean`을 사용하세요
ctg run --clean ./deploy.sh
또는 단축어를 사용하세요:
ctgx -- ./deploy.sh
ctgx --clean -- ./deploy.sh
비밀을 디스크에 전혀 쓰지 않고 환경 변수로 주입하여 명령 실행:
ctg env -- ./deploy.sh # .env.cott.age(기본값)의 비밀을 디스크에 쓰지 않고 내보낸 다음 deploy.sh를 실행합니다
ctg env -F .env.prod.cott.age -- ./deploy.sh # .env.cott.age 대신 .env.prod.cott.age에서 내보냅니다
ctg env -F secrets.json.cott.age -- printenv COTTAGE_SECRET # dotenv 파일이 아닌 파일도 지원합니다.
비밀을 팀원과 공유하려면 git 저장소에 푸시하기만 하면 됩니다.
git add .
git commit -m "Add secret.yml"
git push origin main
팀원에게 .cottage/recipients에 공개 키를 추가하고 변경 사항을 푸시하도록 요청하세요. 그런 다음 풀하고 그들을 위해 비밀을 다시 암호화할 수 있습니다.
git pull origin main
ctg decrypt --skip-verify-recipients # 재암호화를 위해 누락된 비밀을 복호화합니다
ctg encrypt # 모든 비밀을 다시 암호화합니다
# secret.yml 암호화
# secret.yml.cott.age로
# secret.yml.cott.toml 편집
ctg clean # 선택 사항
# secret.yml 삭제
# 변경 사항 검토, 커밋 및 푸시
git add .
git commit -m "Add new recipient to secrets"
git push origin main
이제 팀원은 최신 변경 사항을 풀고 스스로 비밀을 복호화할 수 있습니다.
prek 또는 pre-commit을 사용하여 커밋 전에 비밀을 자동으로 확인/암호화하고 체크아웃 후 복호화하는 git 훅을 설정할 수 있습니다.
prek.toml 파일을 추가한 후 다음을 실행하세요:
prek install
prek install --hook-type post-checkout
prek install --hook-type post-merge
prek install --hook-type post-rewrite
메타데이터 파일에서 비밀이 암호화되어야 하는 수신자를 주석으로 지정할 수 있습니다. 이를 통해 환경(예: 스테이징 vs 프로덕션)에 따라 다른 비밀을 갖고 관련 수신자에게만 암호화할 수 있습니다.
# secret.yml.cott.toml
[secret]
allow = ["sayanarijit"] # sayanarijit에 대해서만 암호화
# secret.yml.cott.toml
[secret]
deny = ["sayanarijit"] # sayanarijit을 제외한 모든 사람에게 암호화
# secret.yml.cott.toml
[secret]
allow = ["env/staging/*"] # 글로브 패턴 지원, env/staging의 수신자에게만 암호화
deny = ["env/staging/badservice"] # badservice를 제외한 env/staging의 모든 사람에게 암호화
거부 규칙은 허용 규칙보다 우선합니다.
자세한 내용은 메타데이터 사양을 참조하세요.
CI에서 ctg verify를 실행하여 암호화된 비밀과 수신자 목록이 메타데이터 규칙과 일치하는지 확인하여 변조를 방지할 수 있습니다.
# .github/workflows/cottage-verify.yml
name: Cottage Verify
on: [push, pull_request]
permissions:
contents: read
jobs:
verify-secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Verify secrets
run: docker run --rm -v "${{ github.workspace }}:/app" ghcr.io/sayanarijit/cottage verify
cottage를 사용하면 git뿐만 아니라 API가 있는 모든 제공자와 비밀을 동기화할 수 있습니다.
이를 위해 프로젝트 루트에 cottage.toml이라는 파일을 만들고 업스트림 설정을 구성하세요.
여기에서 예제 cottage.toml 및 여기에서 비밀별 업스트림 구성을 참조하세요.
여기에서 예제 플러그인 구현을 참조하세요.
워크플로우는 git과 유사하지만, git pull 및 git push 대신 ctg pull 및 ctg push를 실행하여 구성된 업스트림과 비밀을 동기화합니다.
예제:
# 최신 변경 사항을 로컬 암호화 비밀로 풀
# `git pull origin`과 유사
ctg pull myvault
# 로컬 복호화 비밀과 diff 비교
ctg diff
# 로컬 복호화 비밀을 로컬 암호화 비밀과 동기화
ctg sync
# 로컬 암호화 비밀의 변경 사항을 업스트림으로 푸시
# `git push origin main`과 유사
ctg push myvault
자세한 내용은 업스트림 구성 사양을 참조하세요.
Cottage는 비밀을 동기화하기 위한 다양한 플러그인 제공자를 지원합니다. 바로 사용할 수 있는 플러그인 스크립트는 examples/plugins 디렉터리에서 확인할 수 있습니다:
Cottage Sync를 사용하여 여러 기기에서 비밀을 동기화하고 CLI 없이 탐색하세요.
더 많은 사용 예제는 examples 디렉터리를 참조하세요.
# -v, -vv 또는 -vvv로 디버그 로그 확인
ctg run -vvv -- ./deploy.sh
age는 사용성과 최소 공격 표면에 중점을 둔 안전한 파일 암호화를 위해 최적화된 현대적이고 간단한 알고리즘을 사용합니다. 또한 SSH RSA 및 Ed25519 키를 지원하지만, 별도의 목적과 범위에 대해 다른 키를 사용하는 것이 권장됩니다.
SOPS와 cottage는 많은 중복 기능이 있지만, cottage는 다음과 같은 장점이 있습니다:
cottage는 dotenvx에서 ctg env API를 차용했습니다.
ctg clean은 로컬 저장소에서 모든 복호화된 비밀을 삭제하여 AI 에이전트를 조금 더 안심하고 실행할 수 있게 합니다.ctg init은 모든 디렉터리를 비밀 저장소로 전환합니다.git pull/diff/push처럼 ctg pull/diff/push를 사용할 수 있습니다.