OpenClaw에서 안전하게 Secret 관리하기
설정 파일에 API 키를 평문으로 적어두는 건 항상 불안한 일이에요. 실수로 코드를 푸시했다가 보안 사고가 터질까 봐 걱정해 본 적 다들 있으시죠? 그렇다고 관리를 너무 복잡하게 하면 애플리케이션 실행 자체가 꼬이기도 하고요.
OpenClaw는 이런 고민을 해결하기 위해 SecretRef 기능을 제공해요. 설정 파일에 직접 비밀번호를 적지 않아도 되니 훨씬 안전하고 깔끔하게 관리할 수 있답니다.
필요한 것
섹션 제목: “필요한 것”- OpenClaw 설치 환경
- 사용할 API 키 또는 인증 자격 증명
빠른 시작
섹션 제목: “빠른 시작”OpenClaw에서 Secret을 사용하는 가장 빠른 방법은 SecretRef 객체를 사용하는 거예요. 5분 안에 설정을 마칠 수 있어요.
- 객체 형식 맞추기: 평문 대신 아래와 같은 표준 객체 형식을 사용하세요.
{ source: "env", provider: "default", id: "OPENAI_API_KEY" }
- Onboarding 활용: 대화형 모드로 onboarding을 실행하고 SecretRef 저장 방식을 선택하세요. 저장하기 전에 미리 유효성을 검사(Preflight)해 주므로 실수를 방지할 수 있어요.
OpenClaw는 실행 시점에 모든 Secret을 메모리 스냅샷으로 불러와요. 덕분에 요청이 처리되는 중에 외부 Secret Provider에 장애가 생겨도 서비스에는 영향이 없어요.
SecretRef 사용 규칙
섹션 제목: “SecretRef 사용 규칙”모든 곳에서 동일한 객체 구조를 사용해야 해요:
{ source: "env" | "file" | "exec", provider: "default", id: "..." }
1. source: “env”
섹션 제목: “1. source: “env””환경 변수에서 값을 가져오는 방식이에요.
{ source: "env", provider: "default", id: "OPENAI_API_KEY" }- Validation:
provider는 소문자, 숫자, 하이픈, 언더바만 가능해요.id는 대문자, 숫자, 언더바 조합이어야 해요.
2. source: “file”
섹션 제목: “2. source: “file””파일 내의 특정 값을 JSON pointer로 지칭해요.
{ source: "file", provider: "filemain", id: "/providers/openai/apiKey" }- Validation:
id는 반드시/로 시작하는 절대 경로 형태여야 해요. RFC6901 이스케이핑 규칙을 따라야 합니다.
3. source: “exec”
섹션 제목: “3. source: “exec””외부 명령어를 실행해 값을 가져와요.
{ source: "exec", provider: "vault", id: "providers/openai/apiKey" }- Validation:
id는 알파벳이나 숫자로 시작해야 하며, 특수문자(._:/-)를 포함할 수 있어요.
문제 해결
섹션 제목: “문제 해결”문제가 생겼을 때 당황하지 마세요. OpenClaw는 로그를 통해 명확한 이유를 알려줘요.
- Startup 실패: 활성화된 설정(Active surface)에서 SecretRef를 해결할 수 없으면 안전을 위해 즉시 실행을 중단해요.
- SECRETS_REF_IGNORED_INACTIVE_SURFACE: 설정은 되어 있지만 현재 사용하지 않는 기능(비활성 채널 등)에서 발생한 문제는 이 진단 코드와 함께 무시되니 안심하세요.
- Gateway 로그 확인:
gateway.auth관련 SecretRef를 설정했다면 로그에서active혹은inactive상태를 확인하세요. 다른 인증 방식(예: 환경 변수)이 우선순위를 가져가서inactive가 된 것인지 바로 알 수 있어요. - Onboarding 실패: Preflight 단계에서 에러가 나면 화면에 표시된 내용을 확인하고 다시 시도하세요.
다음 단계
섹션 제목: “다음 단계”프로젝트를 진행하다 보면 API 키나 데이터베이스 비밀번호 같은 민감한 정보를 어디에 보관할지 항상 고민하게 되죠. 어떤 환경에서는 환경 변수를 쓰고, 어떤 곳에서는 별도의 파일을 사용하다 보니 관리 포인트가 늘어나서 번거로울 때가 많아요.
다양한 소스에서 Secret을 가져오는 과정을 하나로 통합하고 싶다면, OpenClaw의 Provider 설정을 활용해 보세요.
필요한 것
섹션 제목: “필요한 것”- OpenClaw 설정 파일
secrets.providers구성 정의- (선택 사항) Secret이 저장된 JSON 파일 또는 외부 Vault 실행 파일
빠른 시작
섹션 제목: “빠른 시작”secrets.providers 아래에 사용할 Provider를 정의하는 것으로 시작할 수 있어요. 아래 예시 코드는 환경 변수, 로컬 파일, 그리고 외부 실행 파일을 모두 사용하는 구성을 보여줍니다.
{ secrets: { providers: { default: { source: "env" }, filemain: { source: "file", path: "~/.openclaw/secrets.json", mode: "json", // 또는 "singleValue" }, vault: { source: "exec", command: "/usr/local/bin/openclaw-vault-resolver", args: ["--profile", "prod"], passEnv: ["PATH", "VAULT_ADDR"], jsonOnly: true, }, }, defaults: { env: "default", file: "filemain", exec: "vault", }, resolution: { maxProviderConcurrency: 4, maxRefsPerProvider: 512, maxBatchBytes: 262144, }, },}Env provider
섹션 제목: “Env provider”allowlist를 통해 허용 목록을 선택적으로 설정할 수 있어요.- 환경 변수 값이 누락되었거나 비어 있으면 resolution에 실패하게 됩니다.
File provider
섹션 제목: “File provider”- 지정된
path에서 로컬 파일을 읽어와요. mode: "json"은 JSON 객체 페이로드를 예상하며id를 포인터로 해석합니다.mode: "singleValue"는 ref id를"value"로 예상하고 파일 내용 전체를 반환해요.- 경로는 반드시 소유권 및 권한 체크를 통과해야 합니다.
- Windows 보안 주의사항: 경로에 대한 ACL 확인을 사용할 수 없는 경우 resolution이 실패합니다. 신뢰할 수 있는 경로에 한해서만
allowInsecurePath: true를 설정해 보안 체크를 우회할 수 있어요.
Exec provider
섹션 제목: “Exec provider”- 쉘(shell) 없이 설정된 절대 경로의 바이너리를 직접 실행합니다.
- 기본적으로
command는 심볼릭 링크가 아닌 일반 파일을 가리켜야 해요. - Homebrew shim과 같은 심볼릭 링크 경로를 허용하려면
allowSymlinkCommand: true를 설정하세요. OpenClaw가 확인된 대상 경로를 검증합니다. - 패키지 매니저 경로(예:
/opt/homebrew)를 위해allowSymlinkCommand와trustedDirs를 함께 사용하는 것이 좋습니다. - timeout, no-output timeout, 출력 바이트 제한, env allowlist, trusted dirs 설정을 지원해요.
- Windows 보안 주의사항: 커맨드 경로에 대한 ACL 확인이 불가능하면 실패합니다. 신뢰할 수 있는 경로라면
allowInsecurePath: true를 사용하세요.
Request 페이로드 (stdin):
{ "protocolVersion": 1, "provider": "vault", "ids": ["providers/openai/apiKey"] }Response 페이로드 (stdout):
{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "<openai-api-key>" } } // pragma: allowlist secretID별 선택적 에러 응답:
{ "protocolVersion": 1, "values": {}, "errors": { "providers/openai/apiKey": { "message": "not found" } }}문제 해결
섹션 제목: “문제 해결”-
환경 변수 값을 찾을 수 없나요? 환경 변수가 실제로 설정되어 있는지, 혹은
allowlist에서 누락되지 않았는지 확인해 보세요. 값이 비어 있으면 resolution이 중단됩니다. -
Windows에서 경로 보안 에러가 발생하나요? ACL 확인이 불가능한 환경이라면 resolution이 실패할 수 있어요. 해당 경로가 안전하다면
allowInsecurePath: true옵션을 추가해 보세요. -
심볼릭 링크 명령어가 실행되지 않나요? 보안을 위해 기본적으로 심볼릭 링크는 차단됩니다.
allowSymlinkCommand: true를 설정하고, 해당 경로를trustedDirs에 추가했는지 확인해 보세요.
궁금한 점이 더 있다면 AI Setup Assistant에게 물어보세요!
다음 단계
섹션 제목: “다음 단계”API 키를 설정 파일에 텍스트 그대로 적어두는 건 보안상 위험할 수 있어요. 매번 환경 변수를 수동으로 설정하는 것도 꽤 번거로운 일이죠. 이럴 때 외부 CLI 도구를 활용해 비밀값을 실시간으로 가져오면 훨씬 안전하고 편합니다.
보안 도구에서 직접 값을 읽어오기 때문에 키 노출 위험을 줄일 수 있고, 팀원들과 보안 설정을 공유하기도 좋습니다. 대표적인 도구들을 어떻게 연동하는지 바로 확인해볼게요.
필요한 것
섹션 제목: “필요한 것”- 연동하려는 외부 CLI 도구 (1Password CLI, HashiCorp Vault CLI, 또는
sops) - 해당 도구의 실행 파일 경로 및 접근 권한
빠른 시작
섹션 제목: “빠른 시작”외부 CLI를 통해 비밀값을 가져오는 세 가지 예시예요. secrets 설정에서 exec 소스를 정의하고, models 설정의 apiKey에서 해당 프로바이더를 참조하면 됩니다.
1Password CLI
섹션 제목: “1Password CLI”1Password CLI(op)를 사용해 비밀번호를 읽어오는 방법이에요.
{ secrets: { providers: { onepassword_openai: { source: "exec", command: "/opt/homebrew/bin/op", allowSymlinkCommand: true, // required for Homebrew symlinked binaries trustedDirs: ["/opt/homebrew"], args: ["read", "op://Personal/OpenClaw QA API Key/password"], passEnv: ["HOME"], jsonOnly: false, }, }, }, models: { providers: { openai: { baseUrl: "https://api.openai.com/v1", models: [{ id: "gpt-5", name: "gpt-5" }], apiKey: { source: "exec", provider: "onepassword_openai", id: "value" }, }, }, },}HashiCorp Vault CLI
섹션 제목: “HashiCorp Vault CLI”HashiCorp Vault CLI를 사용하여 KV(Key-Value) 저장소에서 API 키를 가져오는 설정이에요.
{ secrets: { providers: { vault_openai: { source: "exec", command: "/opt/homebrew/bin/vault", allowSymlinkCommand: true, // required for Homebrew symlinked binaries trustedDirs: ["/opt/homebrew"], args: ["kv", "get", "-field=OPENAI_API_KEY", "secret/openclaw"], passEnv: ["VAULT_ADDR", "VAULT_TOKEN"], jsonOnly: false, }, }, }, models: { providers: { openai: { baseUrl: "https://api.openai.com/v1", models: [{ id: "gpt-5", name: "gpt-5" }], apiKey: { source: "exec", provider: "vault_openai", id: "value" }, }, }, },}sops
섹션 제목: “sops”암호화된 JSON 파일에서 sops를 통해 특정 키를 추출하는 방식이에요.
{ secrets: { providers: { sops_openai: { source: "exec", command: "/opt/homebrew/bin/sops", allowSymlinkCommand: true, // required for Homebrew symlinked binaries trustedDirs: ["/opt/homebrew"], args: ["-d", "--extract", '["providers"]["openai"]["apiKey"]', "/path/to/secrets.enc.json"], passEnv: ["SOPS_AGE_KEY_FILE"], jsonOnly: false, }, }, }, models: { providers: { openai: { baseUrl: "https://api.openai.com/v1", models: [{ id: "gpt-5", name: "gpt-5" }], apiKey: { source: "exec", provider: "sops_openai", id: "value" }, }, }, },}문제 해결
섹션 제목: “문제 해결”Homebrew로 설치한 바이너리를 실행할 때 오류가 발생하나요?
Homebrew를 통해 설치된 바이너리는 심볼릭 링크로 연결된 경우가 많아요. 이럴 때는 반드시 allowSymlinkCommand: true 옵션을 설정해야 합니다. 또한 trustedDirs에 /opt/homebrew와 같은 경로를 추가하여 해당 디렉토리의 실행 파일을 신뢰하도록 설정해주세요.
다음 단계
섹션 제목: “다음 단계”코드에 비밀번호나 API 키를 직접 적어두었다가 가슴 철렁했던 적 있으시죠? 환경 변수로 관리해도 보안 요구사항이 까다로워지면 관리가 정말 힘들어집니다. 특히 인증 정보가 만료되거나 교체될 때마다 서비스를 재시작해야 한다면 운영 난이도는 급격히 올라가고 실수가 발생하기 마련이에요.
OpenClaw는 이런 문제를 해결하기 위해 SecretRef라는 구조를 사용합니다. 인증 정보를 안전하게 참조하고, 서비스 중단 없이 갱신할 수 있는 방법을 정리해 드릴게요.
필요한 것
섹션 제목: “필요한 것”- SecretRef Credential Surface에서 지원하는 Credential 목록 확인
- OpenClaw Gateway 실행 환경
빠른 시작
섹션 제목: “빠른 시작”5분 안에 SecretRef를 적용하고 활성화하는 방법입니다.
- Ref 필드 사용: 설정 파일에서 plaintext 필드 대신
Ref로 끝나는 필드를 사용하세요. 예를 들어 Google Chat 설정 시serviceAccount대신serviceAccountRef를 사용하면 됩니다. - 우선순위 확인: 만약 plaintext와 Ref가 모두 있다면, 지원되는 경로에서는 Ref가 우선권을 가집니다.
- 설정 적용: Gateway를 시작하거나, 실행 중이라면
secrets.reload명령어로 설정을 다시 불러오세요. - 상태 확인: 활성화에 성공하면 snapshot이 원자적으로(atomically) 교체되어 즉시 적용됩니다.
주요 동작 및 우선순위
섹션 제목: “주요 동작 및 우선순위”OpenClaw는 인증 정보를 처리할 때 명확한 우선순위를 따릅니다.
- Ref가 없는 필드: 기존 방식 그대로 유지됩니다.
- Ref가 있는 필드: 활성화 단계에서 해당 surface에 필수로 요구됩니다.
- Google Chat 호환성:
serviceAccountRef가 plaintext인serviceAccount보다 우선합니다. Ref가 설정되면 같은 레벨의 plaintext 값은 무시됩니다.
동작 중에 다음과 같은 경고나 감사 신호를 볼 수 있습니다.
SECRETS_REF_OVERRIDES_PLAINTEXT: 런타임 경고로, plaintext 대신 Ref가 사용되고 있음을 알려줍니다.REF_SHADOWED:auth-profiles.json의 인증 정보가openclaw.json의 Ref보다 우선할 때 발생하는 감사 결과입니다.
참고로, 런타임에서 생성되거나 순환되는 인증 정보, OAuth refresh 관련 자료는 읽기 전용인 SecretRef 해석에서 제외됩니다.
활성화 트리거 (Activation Triggers)
섹션 제목: “활성화 트리거 (Activation Triggers)”Secret 활성화는 다음 상황에서 실행됩니다.
- Startup: 프리플라이트 체크와 최종 활성화가 진행됩니다. 이때 실패하면 Gateway 시작 자체가 중단됩니다.
- Config reload:
hot-apply경로 또는restart-check경로를 통해 실행됩니다. - 수동 리로드:
secrets.reload명령어를 통해 직접 실행할 수 있습니다.
런타임에 리로드가 실패하더라도 걱정하지 마세요. 마지막으로 성공했던(last-known-good) snapshot을 그대로 유지하여 서비스가 중단되지 않도록 보호합니다.
상태 신호 및 복구
섹션 제목: “상태 신호 및 복구”리로드가 실패하여 정상 상태를 벗어나면 OpenClaw는 ‘degraded’ 상태가 됩니다. 이때 다음과 같은 시스템 이벤트와 로그 코드가 발생합니다.
SECRETS_RELOADER_DEGRADED: 상태가 나빠졌을 때 한 번 발생합니다. 런타임은 마지막 정상 snapshot을 유지합니다.SECRETS_RELOADER_RECOVERED: 다음 활성화에 성공하면 한 번 발생합니다.
이미 degraded 상태인 상황에서 계속 실패한다면 로그에 경고는 남지만, 이벤트가 중복해서 대량으로 발생하지는 않습니다.
명령어 경로에서의 해석
섹션 제목: “명령어 경로에서의 해석”CLI 명령어들도 Gateway snapshot RPC를 통해 SecretRef를 해석할 수 있습니다. 크게 두 가지 동작으로 나뉩니다.
Strict 명령어 경로
openclaw memory (원격 메모리 경로)나 openclaw qr --remote 같은 명령어들이 해당됩니다. 활성 snapshot에서 값을 읽으며, 필요한 SecretRef를 사용할 수 없으면 즉시 실패합니다.
Read-only 명령어 경로
openclaw status, openclaw status --all, openclaw channels status, openclaw channels resolve, 그리고 읽기 전용 doctor/config repair 흐름이 해당됩니다.
- Gateway가 실행 중이면 활성 snapshot을 먼저 읽습니다.
- Gateway를 사용할 수 없거나 해석이 불완전하면 로컬 fallback을 시도합니다.
- 그래도 SecretRef를 찾을 수 없다면 “configured but unavailable in this command path” 같은 진단 메시지와 함께 제한된 결과만 보여줍니다.
이러한 degraded 동작은 해당 명령어 안에서만 국한되며, 실제 런타임의 시작이나 인증 경로에는 영향을 주지 않습니다.
문제 해결
섹션 제목: “문제 해결”- 백엔드에서 Secret을 교체했는데 반영이 안 돼요: 백엔드에서 Secret이 순환(rotation)된 후에는
openclaw secrets reload를 실행하여 snapshot을 갱신해야 합니다. - 명령어 실행 시 “unavailable in this command path”가 떠요: 해당 명령어가 SecretRef에 접근할 수 없는 환경이거나 Gateway RPC(
secrets.resolve) 연결에 문제가 있는지 확인해 보세요. - Gateway가 시작되지 않고 종료돼요: Startup 단계에서 SecretRef 활성화에 실패하면 안전을 위해 시작을 중단합니다. 설정 파일의 Ref 경로가 올바른지 확인하세요.
도움이 필요하신가요? AI Setup Assistant에게 질문해 보세요.
다음 단계
섹션 제목: “다음 단계”개발을 하다 보면 나도 모르게 설정 파일이나 .env 파일에 API 키를 Plaintext로 남겨두는 실수를 하곤 해요. 어디에 어떤 민감한 정보가 노출되어 있는지 일일이 찾아내는 일은 정말 번거롭고 실수하기 쉽죠. 이제 OpenClaw의 시크릿 워크플로우를 사용해 이 과정을 자동화하고 보안을 강화해 보세요.
What You’ll Need
섹션 제목: “What You’ll Need”시작하기 전에 다음 파일들이 준비되어 있는지 확인해 주세요.
openclaw.jsonauth-profiles.json.envagents/*/agent/models.json(생성된 경우)auth.json(Legacy 버전 사용 시)
Quick Start
섹션 제목: “Quick Start”가장 빠르게 시크릿을 정리하는 5분 완성 경로예요. 다음 명령어를 순서대로 실행하면 됩니다.
# 1. 현재 노출된 시크릿이 있는지 확인합니다.openclaw secrets audit --check
# 2. 대화형 헬퍼를 통해 시크릿을 안전하게 설정합니다.openclaw secrets configure
# 3. 설정이 잘 적용되었는지 다시 확인합니다.openclaw secrets audit --checkSecrets Audit 상세 분석
섹션 제목: “Secrets Audit 상세 분석”secrets audit 명령어를 실행하면 시스템이 다음 항목들을 꼼꼼하게 찾아내요.
- Plaintext 노출:
openclaw.json,auth-profiles.json,.env, 그리고 생성된models.json내에 그대로 노출된 값들을 찾아요. - Header 잔여물:
models.json내에 남아있는 민감한 Header 정보를 감지해요. 이름 기반의 Heuristic 방식(예:authorization,x-api-key,token,secret,password,credential)을 사용합니다. - 참조 및 우선순위: 해결되지 않은 Reference(
unresolved refs)나auth-profiles.json이openclaw.json보다 우선시되어 발생하는 우선순위 간섭(precedence shadowing)을 찾아냅니다. - Legacy 데이터: 구버전의
auth.json이나 OAuth 관련 잔여 데이터를 식별해요.
Secrets Configure 활용하기
섹션 제목: “Secrets Configure 활용하기”secrets configure는 대화형 헬퍼예요. 다음과 같은 작업을 순차적으로 도와줍니다.
- Provider 설정:
env,file,exec중 원하는secrets.providers를 먼저 구성해요. - 필드 선택:
openclaw.json과auth-profiles.json내에서 시크릿이 포함된 필드를 선택할 수 있어요. - SecretRef 캡처:
source,provider,id와 같은 상세 정보를SecretRef형식으로 저장합니다. - 즉시 적용: Preflight 확인을 거쳐 변경 사항을 바로 반영할 수 있어요.
상황에 따라 특정 모드만 실행할 수도 있습니다.
openclaw secrets configure --providers-onlyopenclaw secrets configure --skip-provider-setupopenclaw secrets configure --agent <id>
저장된 플랜 적용하기 (Secrets Apply)
섹션 제목: “저장된 플랜 적용하기 (Secrets Apply)”설정 플랜을 파일로 저장했다면, apply 명령어로 한 번에 적용하세요.
# 플랜 적용하기openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
# 실제 적용 전에 미리 시뮬레이션하기openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run정확한 타겟 경로 규약이나 거부 규칙이 궁금하다면 Secrets Apply Plan Contract 문서를 참고해 보세요.
꼭 알아두어야 할 안전 정책
섹션 제목: “꼭 알아두어야 할 안전 정책”OpenClaw는 보안을 위해 의도적으로 과거의 Plaintext 시크릿 값을 포함하는 롤백 백업을 생성하지 않아요.
- 모든 쓰기 작업 전에는 Preflight 단계가 성공해야 합니다.
- 파일 업데이트는 원자적 파일 교체(Atomic file replacement) 방식을 사용해요.
- 실패 시에는 최선을 다해(Best-effort) 복구를 시도하지만, Plaintext 값 자체를 보관하지는 않는다는 점을 기억해 주세요.
Troubleshooting
섹션 제목: “Troubleshooting”- Legacy 데이터 문제: OpenClaw는 실행 시 더 이상 Plaintext로 저장된 Legacy 인증 정보에 의존하지 않아요.
api_key같은 Legacy 항목이 발견되면 자동으로 제거(Scrub)합니다. - Web UI 설정: 복잡한
SecretInput조합을 설정할 때는 Web UI의 폼 모드보다 Raw 에디터 모드를 사용하는 것이 훨씬 편할 수 있어요.
궁금한 점이 더 있다면 AI Setup Assistant에게 물어보세요!
What’s Next
섹션 제목: “What’s Next”- CLI 명령어 상세: secrets
- 플랜 상세 규약: Secrets Apply Plan Contract
- 인증 설정 가이드: Authentication
- 보안 포스처 확인: Security
- 환경 변수 우선순위: Environment Variables
OpenClaw Expert
아직 막혀 있나요?
이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.