sops-nix 비밀을 NixOS와 home-manager로, git-safe 방식으로

발행: (2026년 2월 17일 오후 05:57 GMT+9)
13 분 소요
원문: Dev.to

Source: Dev.to

NixOS 설정(또는 모든 dotfiles)을 버전 관리하면 전체 시스템이 재현 가능해집니다.
하지만 그 파일들에 포함된 API 키나 비밀번호는 평문으로 저장소에 보관됩니다.

  • 단순히 .gitignore 로 무시할 수 없습니다 – NixOS는 빌드/활성화 시점에 값이 필요합니다.
  • 환경 변수로 노출하고 싶지도 않습니다.

해결책:sops‑nix 를 사용하세요 – SOPS 로 비밀을 암호화하고 암호화된 파일을 커밋합니다.
활성화 시 sops‑nix 가 해당 파일을 복호화하는데, 복호화 키는 오직 여러분의 머신에만 존재하고(저장소에는 절대 없음)
dotfiles는 완전히 재현 가능하고, 푸시할 수 있으며, 유출 위험이 없습니다.

개요

  • 관리해야 할 첫 번째 비밀: EXA_API_KEY (Exa.ai용).
  • 이 가이드는 SSH 키에서 파생된 age 키를 사용한 단일 머신 설정을 보여줍니다 (Michael Stapelberg의 접근 방식을 기반으로 수정함).
  • 선택 사항: 빌드 경고를 없애기 위해 자신을 신뢰된 사용자로 추가합니다.
# configuration.nix
nix.settings.trusted-users = [ "@wheel" "noor" ];

한 번 재빌드:

sudo nixos-rebuild switch

Source:

1️⃣ Age 키 스토어 준비하기

# sops가 age 키를 찾을 디렉터리를 생성합니다
mkdir -p ~/.config/sops/age/

필요한 도구가 포함된 임시 Nix 쉘에 들어갑니다:

nix shell nixpkgs#ssh-to-age nixpkgs#age

1.1 SSH 개인 키로 age 신원 만들기

# SSH 키에 암호가 설정돼 있다면, 입력하라는 프롬프트가 표시됩니다.
ssh-to-age -private-key -i ~/.ssh/id_ed25519 -o ~/.config/sops/age/keys.txt

권한을 잠그세요 (강력히 권장):

chmod 600 ~/.config/sops/age/keys.txt

1.2 개인용 age 수신자 얻기

age-keygen -y ~/.config/sops/age/keys.txt
# → 예시와 같은 값이 출력됩니다: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxx

출력된 값을 복사해 두세요 – 나중에 필요합니다.

1.3 시스템 SSH 호스트 키가 존재하는지 확인하기

ls /etc/ssh/ssh_host_ed25519_key   # 존재해야 합니다

존재하지 않는 경우, 모든 호스트 키를 생성합니다:

sudo ssh-keygen -A

1.4 시스템 age 수신자 얻기 (호스트 키에서 파생)

cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
# → 예시와 같은 값이 출력됩니다: age1yyyyyyyyyyyyyyyyyyyyyyyyyyyy

이 값도 복사해 두세요.

임시 쉘을 종료합니다:

exit

이제 두 개의 수신자가 준비되었습니다:

수신자값 (예시)
admin (개인)age1xxxxx…
system (호스트)age1yyyyy…

2️⃣ .sops.yaml 설정 만들기

dotfiles 저장소 루트에 파일을 생성합니다 (예: ~/nixos-dotfiles/.sops.yaml):

# .sops.yaml
keys:
  - &admin age1xxxxx...   # Your personal age recipient
  - &system age1yyyyy...  # Your system's SSH host key

creation_rules:
  - path_regex: secrets/[^/]+\.yaml$
    key_groups:
      - age:
          - *admin
          - *system

이 설정이 하는 일

  • 개인 키 (&admin) – 일반 사용자로서 비밀을 복호화/편집할 수 있게 해줍니다 (sudo 없이, SSH 암호를 반복 입력할 필요 없음).
  • 시스템 키 (&system) – 부팅 시 시스템이 자동으로 비밀을 복호화하고 /run/secrets/ 아래에 노출합니다.

⚠️ 주의: SSH 호스트 키 (/etc/ssh/ssh_host_ed25519_key)를 회전/재생성하면 새로운 호스트 수신자를 사용해 모든 비밀을 다시 암호화해야 합니다. 그렇지 않으면 부팅 시 복호화에 실패합니다.

3️⃣ 첫 번째 비밀을 만들고 암호화하기

cd ~/nixos-dotfiles
mkdir -p secrets

SOPS로 파일을 엽니다 (nix run 래퍼가 올바른 버전을 가져옵니다):

nix run nixpkgs#sops -- secrets/secrets.yaml

편집기가 열리면 비밀을 추가합니다:

EXA_API_KEY: "your_actual_api_key_here"

저장하고 종료합니다. 이제 파일이 암호화되었습니다.

암호화를 확인합니다:

cat secrets/secrets.yaml
# → ENC[AES256_GCM,...] 로 시작하는 값을 볼 수 있습니다

오직 당신만(~/.config/sops/age/keys.txt 파일을 사용) 이 파일을 복호화할 수 있습니다.

나중에 편집/보기 위해서는:

nix run nixpkgs#sops -- secrets/secrets.yaml

4️⃣ sops‑nix를 NixOS 설정에 연결하기

4.1 sops‑nix를 Flake 입력으로 추가하기

# flake.nix
{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    sops-nix = {
      url = "github:Mic92/sops-nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, home-manager, sops-nix }:
    let
      system = "x86_64-linux";
    in {
      nixosConfigurations.nixos = nixpkgs.lib.nixosSystem {
        inherit system;
        modules = [
          sops-nix.nixosModules.sops          # **Important:** `sops-nix.homeManagerModules.sops` must be imported so the `sops` options are visible inside `home.nix`.
        ];
      };
    };
}

4.2 home.nix에서 비밀 설정하기

# home.nix
{ config, ... }:

{
  # Tell sops‑nix where your age private key lives
  sops.age.keyFile = "${config.home.homeDirectory}/.config/sops/age/keys.txt";

  # Default SOPS file for this user
  sops.defaultSopsFile = ./secrets/secrets.yaml;

  # Declare the secret we want to expose
  sops.secrets.EXA_API_KEY = { };

  # Export a session variable that points to the decrypted file
  home.sessionVariables = {
    EXA_API_KEY = "${config.sops.secrets.EXA_API_KEY.path}";
  };
}

얻을 수 있는 것

  • 로그인 시 EXA_API_KEY/run/user/<uid>/secrets/EXA_API_KEY 아래의 임시 파일을 가리킵니다.
  • 해당 파일에는 원시 키 값이 들어 있습니다.
  • 쉘에서 읽으려면: cat "$EXA_API_KEY".

Note: sops‑nix는 비밀을 파일로 저장하고, 원시 환경 변수로 저장하지 않습니다. 파일 경로에서 비밀을 읽을 수 있는 프로그램은 바로 사용할 수 있습니다.

5️⃣ 비밀 사용하기

# 셸에서
echo "My key is: $(cat "$EXA_API_KEY")"

프로그램이 원시 값을 환경 변수에 직접 넣어야 할 경우, 다음과 같이 래핑할 수 있습니다:

export EXA_API_KEY=$(cat "$EXA_API_KEY")
my-program --api-key "$EXA_API_KEY"

요약

단계수행한 작업
1️⃣SSH 키에서 age 신원을 생성하고 개인 및 시스템 수신자를 모두 수집했습니다.
2️⃣.sops.yaml 파일을 생성하여 SOPS에 secrets/ 아래 파일을 암호화/복호화할 수 있는 수신자를 지정했습니다.
3️⃣EXA_API_KEYsecrets/secrets.yaml에 추가하고 SOPS로 암호화했습니다.
4️⃣sops‑nix를 플레이크에 추가하고, NixOS와 Home Manager 모두에 모듈을 활성화했으며, 키 파일과 비밀 파일을 지정했습니다.
5️⃣복호화된 비밀 파일을 가리키는 세션 변수를 내보내어 사용 준비를 마쳤습니다.

이제 NixOS 설정(또는 모든 dotfiles 저장소)을 공개 또는 공유 Git 원격에 안전하게 푸시할 수 있으며 비밀이 절대 유출되지 않습니다. 🎉

Source:

sops‑nix 로 API 키 추가하기

1. 왜 추가 단계가 필요할까?

API_KEY파일 경로가 아닙니다. 파일을 기대하는 프로그램을 동작시키려면 두 가지 방법이 있습니다:

  1. 프로그램을 파일을 읽도록 설정합니다 (*_FILE 환경 변수를 지원하는 프로그램이 많습니다).
  2. 프로그램을 래핑/실행해서 파일 내용을 환경 변수에 넣어줍니다.

재빌드 후에는 기존 터미널 창을 모두 닫으세요 – 열려 있는 쉘은 새로운 변수들을 인식하지 못합니다. 새 터미널을 열어 업데이트된 환경을 확인합니다.

2. 시스템‑레벨 sops 설정

~/nixos-dotfiles/configuration.nix에 다음을 추가합니다 (NixOS 모듈에 필요한 외부 { … }: 래퍼에 주의).

{ ... }:

{
  sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
}

무엇을 하는가

  • NixOS sops 모듈이 복호화에 사용할 시스템‑레벨 SSH 호스트 키를 선언합니다.
  • configuration.nix (NixOS 레벨)에 있어야 하며, home.nix 에서는 안 됩니다.
  • Home‑Manager sops 모듈은 자체 sops.age.keyFile(Step 4에서 설정)을 사용합니다.
  • 부팅 시 사용자 개입 없이 복호화를 가능하게 하고, 향후 시스템‑레벨 비밀을 사용할 수 있게 합니다.

3. 재빌드 및 적용

sudo nixos-rebuild switch --flake ~/nixos-dotfiles#nixos

재빌드 후 선택 사항

옵션명령비고
A – 재부팅 (가장 간단)sudo reboot모든 서비스가 새로운 env‑var를 인식하도록 보장합니다.
B – 서비스 재시작bash\nsystemctl --user daemon-reload\nsystemctl --user restart sops-nix.service\n이전에 서비스가 활성화되지 않았다면 동작하지 않을 수 있습니다 (home‑manager 이슈).

4. 비밀 확인

터미널을 열고 실행합니다:

echo $EXA_API_KEY
# → /run/user/1000/secrets/EXA_API_KEY 와 같은 경로가 출력돼야 합니다

cat $EXA_API_KEY
# → 실제 API‑key 값이 출력됩니다

5. 암호화된 비밀 파일 편집

cd ~/nixos-dotfiles
nix run nixpkgs#sops -- secrets/secrets.yaml

수정 후 저장, 커밋, 재빌드합니다.

git add flake.nix configuration.nix home.nix .sops.yaml secrets/secrets.yaml
git commit -m "Add EXA_API_KEY secret with sops-nix"
git push

중요:

  • 개인 age 비밀키(~/.config/sops/age/keys.txt)는 절대 커밋되지 않으며, 레포 외부에 보관됩니다.
  • 암호화된 파일(secrets/secrets.yaml)은 비밀키 없이는 사용할 수 없으므로 안전하게 커밋할 수 있습니다.

6. 우리가 한 일 (요약)

  • 기존 SSH 호스트 키(ssh-to-age)를 이용해 age 키를 생성하고 ~/.config/sops/age/keys.txt에 저장(추적되지 않음).
  • 두 수신자를 지정한 .sops.yaml을 설정: 편집용 개인 age 키와 부팅 시 복호화를 위한 시스템 SSH 호스트 키.
  • sops를 사용해 암호화된 비밀 파일(secrets/secrets.yaml)을 생성.
  • 플레이크에 sops‑nix를 연결: configuration.nix의 NixOS 모듈과 home.nix의 Home‑Manager 모듈.
  • 비밀을 환경 변수 $EXA_API_KEY 로 노출했으며, 이는 /run/user/1000/secrets/EXA_API_KEY 에 복호화된 파일을 가리킵니다.

암호화된 파일은 안전하게 푸시할 수 있으며, 비밀키는 절대로 머신을 떠나지 않습니다. (다음 글에서는 YAML 파일을 이용해 Kubernetes 클러스터에서 sops를 활용하는 방법을 다룰 예정입니다.)

0 조회
Back to Blog

관련 글

더 보기 »

채용 중인 기업 — 2026년 2월

Dev‑First 기업의 오픈 포지션: Product engineers, Developer advocates, 혹은 Community builders? 새해를 맞아 dev tools 분야에서 새로운 기회를 시작하세요.