GitリポジトリにAPIキーやデータベースのパスワードをうっかりコミットしてしまった——そんなヒヤッとした経験はないでしょうか。SOPSは、シークレットを暗号化したままGitに含められるツールです。暗号化キーを持つ人だけが元の値を取り出せるので、GitHubに公開してもキーが漏れない限り中身は守られます。
本記事では Ubuntu 24.04 LTS(Docker公式イメージ ubuntu:24.04)に SOPS v3.13.1 をインストールし、AGE(推奨)と GPG の2方式で実際にシークレットを暗号化・復号して検証しました。コマンドの出力・暗号化前後のファイルサイズはすべて実際のコンテナで取得した実測値です。結論から言うと、新規プロジェクトでは AGE 一択で、GPG は暗号化後のファイルが AGE の倍近く膨らむという意外な結果も出ました。
この記事のポイント
- SOPS は
aptでは提供されておらず、GitHub Releases からバイナリを取得してインストールする(Ubuntu 22.04 / 24.04 共通) - AGE 方式が推奨:
apt install age(24.04 で v1.1.1)で入り、age1...形式の公開鍵1本で完結する - SOPS は「値だけ」を暗号化し、YAML/ENV のキー名は平文のまま残る。
git diffで変更箇所の構造が見える - 暗号化後のサイズは実測で AGE が約13.7倍、GPG が約25.0倍。GPG は PGPメッセージ本体を埋め込むぶん重い
.sops.yamlにルールを書けば--ageフラグなしで鍵を自動選択できる
目次
- SOPSとは:なぜシークレットをGitに含められるのか
- 前提環境
- SOPS のインストール(GitHub バイナリ)
- AGE を使った暗号化・復号(推奨)
- GPG を使った暗号化・復号(レガシー対応)
- AGE vs GPG 比較:暗号化後サイズの差が大きい
- Ubuntu 22.04 と 24.04 のパッケージ差
- .sops.yaml で暗号化ルールを自動化する
- Gitへの安全なコミット手順
- GitHub Actions での復号(CI/CD連携)
- よくあるエラーと解決策
- まとめ
SOPSとは:なぜシークレットをGitに含められるのか
SOPS(Secrets OPerationS)は、もともと Mozilla が開発したシークレット管理ツールです。.yaml / .env / .json ファイルの「値の部分だけ」を暗号化し、キー名(構造)は平文のまま保持します。キー名が見えるので、git diff でどのシークレットが変更されたかを構造的に把握できるのが大きな特徴です。
たとえば次のような db.yaml を AGE で暗号化すると、値だけが ENC[AES256_GCM,...] 形式に置き換わります。以下は実際に ubuntu:24.04 コンテナで実行した出力です。
database:
host: db.example.com
password: SUPER_SECRET_DB_PASS ← 平文・Gitに含めてはいけない
api_key: sk_live_abcdef0123456789 ← 平文・Gitに含めてはいけない
# 暗号化後(secrets/db.enc.yaml)← Gitに安全にコミット可
database:
host: ENC[AES256_GCM,data:iHfJvh6mBDqcADiT5UE=,iv:kfkZGU4c…,type:str]
password: ENC[AES256_GCM,data:NPhGJ1V5+IBQTZCNhf2qqrLmtTc=,iv:Tuyjn…,type:str]
api_key: ENC[AES256_GCM,data:ssf3XBnt4NEGrqtXqpryCG55yFR/Bgyc,iv:NniTs…,type:str]
sops:
version: 3.13.1
キー名(database / host / password / api_key)は平文のまま、値だけが暗号化されているのが分かります。秘密鍵を持つ人だけがこれを元に戻せます。
注意
本記事のコマンドは Ubuntu 24.04 LTS(Docker公式イメージ ubuntu:24.04、実測では 24.04.4)で検証しています。SOPS v3.13.1、age v1.1.1、gnupg v2.4.4 を使用。Ubuntu 22.04 でも同じ手順で動作しますが、後述の通りパッケージのバージョンが異なります。
前提環境
- OS: Ubuntu 24.04.4 LTS(
ubuntu:24.04Docker イメージ、arm64、2026-06-15 実測) - SOPS: v3.13.1(GitHub Releases バイナリ)
- AGE: v1.1.1(
apt install ageで取得) - GPG: GnuPG v2.4.4(
apt install gnupgで取得) - Git: v2.43.0、OpenSSL: 3.0.13(いずれも 24.04 標準)
SOPS のインストール(GitHub バイナリ)
正直、これが最初の詰まりポイントです。SOPS は Ubuntu の公式 apt リポジトリに登録されていません。apt install sops としても「パッケージが見つかりません」と言われます。GitHub Releases からバイナリを直接ダウンロードする必要があります。
手順1:依存パッケージをインストールする
# curl / wget / ca-certificates(HTTPS通信用)と、後で使う age / gnupg / git をまとめて入れる
手順2:SOPS の最新バージョンを取得してインストールする
以下は実際に ubuntu:24.04 コンテナ(arm64)で実行したログです。uname -m から CPU アーキテクチャを自動判別しているので、x86_64(一般的なVPS)でも arm64(Apple Siliconなど)でも同じコマンドが通ります。
arm64
$ SOPS_VER=$(curl -s https://api.github.com/repos/getsops/sops/releases/latest \
| grep ‘”tag_name”‘ | sed ‘s/.*”v\([^”]*\)”.*/\1/’)
$ echo “Latest SOPS version: v${SOPS_VER}”
Latest SOPS version: v3.13.1
$ sudo wget -q \
“https://github.com/getsops/sops/releases/download/v${SOPS_VER}/sops-v${SOPS_VER}.linux.${ARCH}” \
-O /usr/local/bin/sops
$ sudo chmod +x /usr/local/bin/sops
$ sops –version
sops 3.13.1 (latest)

GitHub の Releases ページにも、まさにこの手順(バイナリをダウンロードして /usr/local/bin/sops に置き、実行権限を付ける)が公式の案内として書かれています。バージョンが v3.13.1 であることもページ上部の「Latest」バッジで確認できます。

AGE を使った暗号化・復号(推奨)
AGE(エイジ)は Filippo Valsorda が設計した現代的な暗号化ツールです。GPG に比べてコマンドが圧倒的にシンプルで、Ubuntu 24.04 では apt install age で v1.1.1 が入ります。チームで使う場合も age1... という公開鍵のテキストを共有するだけです。
手順1:AGE キーペアを生成する
Public key: age1f0k5drkkjj37p2c3eup0kuwsylpeqlvdmfs0kww2xnqvdkuxsg0s9aa8z0
$ cat ~/.config/sops/age/keys.txt
# created: 2026-06-14T16:18:11+00:00
# public key: age1f0k5drkkjj37p2c3eup0kuwsylpeqlvdmfs0kww2xnqvdkuxsg0s9aa8z0
AGE-SECRET-KEY-1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
↑ 秘密鍵。絶対に公開・Gitに含めないこと(本記事ではマスク表示)
注意:秘密鍵は絶対に公開しない
AGE-SECRET-KEY-1... から始まる行が秘密鍵です。この値が漏れると暗号化したシークレットがすべて復号されてしまいます。パスワードマネージャーなど安全な場所にバックアップを取り、Gitには絶対に追加しないでください。
手順2:シークレットファイルを暗号化・復号する
暗号化は sops --encrypt --age <公開鍵> ファイル名、復号は sops --decrypt です。SOPS_AGE_KEY_FILE 環境変数に秘密鍵ファイルのパスを設定しておけば、復号時に --age を付けなくても自動で正しい鍵が使われます。以下はすべて実測の出力です。
$ AGE_PUB=$(grep ‘public key:’ $SOPS_AGE_KEY_FILE | sed ‘s/.*public key: //’)
$ sops –encrypt –age “$AGE_PUB” secrets/db.yaml > secrets/db.enc.yaml
$ cat secrets/db.enc.yaml
database:
host: ENC[AES256_GCM,data:iHfJvh6mBDqcADiT5UE=,iv:kfkZGU4c…,type:str]
password: ENC[AES256_GCM,data:NPhGJ1V5+IBQTZCNhf2qqrLmtTc=,iv:Tuyjn…,type:str]
api_key: ENC[AES256_GCM,data:ssf3XBnt4NEGrqtXqpryCG55yFR/Bgyc,iv:NniTs…,type:str]
sops:
age:
– recipient: age1f0k5drkkjj37p2c3eup0kuwsylpeqlvdmfs0kww2xnqvdkuxsg0s9aa8z0
version: 3.13.1
$ sops –decrypt secrets/db.enc.yaml | head -2
database:
host: db.example.com ← 復号成功

recipient 行に暗号化に使った公開鍵が記録されます。Ubuntu 24.04 で実際に動かした結果、暗号化前113バイトのファイルが暗号化後1,545バイト(約13.7倍)になりました。AGE は X25519 鍵で AES256-GCM の鍵をラップする方式で、メタデータも YAML の sops: セクションにすっきりまとまります。
AGE 本体のソースや使い方は GitHub(FiloSottile/age)で確認できます。SOPS とは独立したツールですが、SOPS のバックエンドとして広く使われています。

GPG を使った暗号化・復号(レガシー対応)
既存のチームで GPG 鍵を使っている、あるいは GPG の鍵管理インフラが整っている場合は GPG 方式も使えます。AGE より設定が複雑ですが、エンタープライズ環境では GPG のほうが歓迎されることもあります。
手順1:gnupg をインストールして鍵を生成する
CI/CD で使う想定で、パスフレーズなし(%no-protection)の鍵をバッチモードで生成しました。実測では RSA 3072 ビットの鍵が作られています。
$ gpg –list-keys
pub rsa3072 2026-06-14 [SCEAR]
6BC1F9EF7F4DA4AC6961D911143A2C24BD7B3180
uid [ultimate] LinuxLab Demo <demo@linuxlab.jp>
sub rsa3072 2026-06-14 [SEA]
$ FPR=$(gpg –list-keys –with-colons | awk -F: ‘/^fpr/{print $10; exit}’)
$ echo “$FPR”
6BC1F9EF7F4DA4AC6961D911143A2C24BD7B3180
注意:鍵長を上げたい場合
バッチファイルの Key-Length を 4096 にすれば RSA 4096 ビットの鍵を作れます。本番運用ではパスフレーズを設定し(%no-protection を外す)、CI 用には別途パスフレーズなしのサブ鍵を切るのが安全です。
手順2:GPG でシークレットを暗号化・復号する
$ head -3 secrets/db.enc.env
DB_HOST=ENC[AES256_GCM,data:L4Wuy7+S4N5LmztqaZlraHU=,iv:XzGad…,type:str]
DB_PORT=ENC[AES256_GCM,data:5lL4hg==,iv:1GFaR…,type:str]
DB_PASS=ENC[AES256_GCM,data:hRBWaGKjAKC7sK6myY0y1x6ZTfc=,iv:WLJYZ…,type:str]
$ grep ‘^sops_pgp.*map_fp’ secrets/db.enc.env
sops_pgp__list_0__map_fp=6BC1F9EF7F4DA4AC6961D911143A2C24BD7B3180
$ sops –decrypt secrets/db.enc.env
DB_HOST=postgres.internal ← 復号成功
DB_PASS=SUPER_SECRET_DB_PASS ← 復号成功

GPG の場合、.env ファイルの末尾に sops_lastmodified / sops_mac / sops_pgp__list_0__map_fp といったメタデータが平文キー名で追加されます。さらに sops_pgp__list_0__map_enc として PGPメッセージ本体(-----BEGIN PGP MESSAGE-----)まで丸ごと埋め込まれるため、ファイルがかなり大きくなります。実測では 68バイトのファイルが暗号化後1,701バイト(約25.0倍)になりました。
AGE vs GPG 比較:暗号化後サイズの差が大きい

両方を同じ条件で動かして驚いたのは、暗号化後のファイルサイズが GPG(約25.0倍)と AGE(約13.7倍)でほぼ倍違う点です。元ファイルのサイズが違うので単純比較はできませんが、GPG は鍵を包む PGPメッセージ本体をファイルに埋め込むため、どうしてもオーバーヘッドが大きくなります。AGE は X25519 ベースでメタデータがコンパクトです。
学習コスト・鍵管理・CI/CD との親和性まで含めて総合すると、新規プロジェクトでは AGE を選ぶのがほぼ一択です。コマンドがシンプルで、後述の GitHub Actions 連携も環境変数1本で済みます。GPG は既存の鍵インフラとの互換性が必要な場面でのみ検討すれば十分でしょう。
Ubuntu 22.04 と 24.04 のパッケージ差
「22.04 のサーバーでも同じ手順で動くの?」という疑問に答えるため、ubuntu:22.04 と ubuntu:24.04 の両方で apt install age gnupg を実行し、入るバージョンを比較しました。

結論として、SOPS 本体はどちらの Ubuntu でも apt に無く、GitHub から取得する点は共通です。違うのは apt で入る age / gnupg のバージョンで、age は 22.04 の 1.0.0 から 24.04 で 1.1.1 に、gnupg は 2.2.27 から 2.4.4 に上がっています。手順そのものは両バージョンで変わりません。22.04 でも本記事のコマンドはそのまま使えます。
.sops.yaml で暗号化ルールを自動化する
毎回 --age <公開鍵> を指定するのは面倒です。プロジェクトルートに .sops.yaml を置くと、ファイルパスのパターンに応じて鍵が自動選択されます。実測で --age なしの sops --encrypt が exit_code=0 で成功し、enc ファイルの recipient が指定鍵と一致することを確認しました。
creation_rules:
– path_regex: secrets/.*\.yaml$
age: age1f0k5drkkjj37p2c3eup0kuwsylpeqlvdmfs0kww2xnqvdkuxsg0s9aa8z0
– path_regex: secrets/.*\.env$
age: age1f0k5drkkjj37p2c3eup0kuwsylpeqlvdmfs0kww2xnqvdkuxsg0s9aa8z0
$ sops –encrypt secrets/app.yaml > secrets/app.enc.yaml; echo exit_code=$?
exit_code=0
# –age フラグなし → path_regex が secrets/*.yaml にマッチして鍵を自動選択
$ grep -m1 recipient secrets/app.enc.yaml
– recipient: age1f0k5drkkjj37p2c3eup0kuwsylpeqlvdmfs0kww2xnqvdkuxsg0s9aa8z0

チームメンバーが複数いる場合は、公開鍵をカンマ区切りで並べます。全員の公開鍵で暗号化されるので、チームの誰でも自分の秘密鍵で復号できます。
creation_rules:
– path_regex: secrets/.*\.yaml$
age: >-
age1alice…(Aliceの公開鍵),
age1bob…(Bobの公開鍵),
age1carol…(Carolの公開鍵)
Gitへの安全なコミット手順
ここが本記事の核心です。暗号化済みファイルを Git に追加し、平文と秘密鍵は .gitignore で除外するのが正しい手順です。
secrets/*.yaml # 平文シークレットは Git に含めない
!secrets/*.enc.yaml # ただし暗号化済みは例外的に含める
keys.txt # AGE 秘密鍵も絶対に含めない
$ git add .sops.yaml secrets/app.enc.yaml
$ git status
Changes to be committed:
new file: .sops.yaml
new file: secrets/app.enc.yaml ← 暗号化済み(安全)
Untracked files:
secrets/app.yaml ← 平文(.gitignore で除外済み)
$ git commit -m ‘feat: add encrypted secrets for production’
[main 3f7a1b2] feat: add encrypted secrets for production
注意:コミット前に pre-commit フックで二重チェックを
うっかり平文や秘密鍵をコミットしないよう、git-secrets や pre-commit フックで「AGE-SECRET-KEY-」や生の password: パターンを検出するルールを追加しておくと安心です。.gitignore だけに頼らない多層防御が有効です。
GitHub Actions での復号(CI/CD連携)
CI/CD パイプラインで暗号化シークレットを使う場合、AGE の秘密鍵を GitHub の Secrets に登録し、SOPS_AGE_KEY 環境変数として渡します。SOPS はこの変数が設定されていれば、ファイルパスではなく直接その鍵で復号します。
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
# SOPS インストール(apt に無いので GitHub から取得)
– name: Install SOPS
run: |
SOPS_VER=$(curl -s https://api.github.com/repos/getsops/sops/releases/latest \
| grep tag_name | sed ‘s/.*”v\([^”]*\)”.*/\1/’)
sudo wget -q “https://github.com/getsops/sops/releases/download/v${SOPS_VER}/sops-v${SOPS_VER}.linux.amd64” \
-O /usr/local/bin/sops && sudo chmod +x /usr/local/bin/sops
# GitHub Secrets から AGE 秘密鍵を注入して復号
– name: Decrypt secrets
env:
SOPS_AGE_KEY: ${{ secrets.AGE_SECRET_KEY }}
run: |
sops –decrypt secrets/app.enc.yaml > secrets/app.yaml
GitHub の Repository Settings → Secrets and variables → Actions に AGE_SECRET_KEY として秘密鍵の中身(AGE-SECRET-KEY-1...)を登録しておけば、上記のワークフローがビルド時に復号してくれます。SOPS や AGE の最新情報は公式サイト(getsops.io)も参考になります。

よくあるエラーと解決策
① sops: command not found
エラー
bash: sops: command not found
または apt-get install sops で「パッケージが見つかりません」と言われる
原因:SOPS は Ubuntu の公式 apt リポジトリにありません。GitHub Releases からバイナリをダウンロードする必要があります。上記の「SOPS のインストール」手順を参照してください。22.04 でも 24.04 でも同じです。
② Failed to get the data key required to decrypt the SOPS file
エラー
Failed to get the data key required to decrypt the SOPS file.
原因:秘密鍵が見つかりません。以下の3点を確認してください。
$ echo $SOPS_AGE_KEY_FILE
# 何も表示されない場合は設定が必要
$ export SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt
# 確認2: キーファイルが存在するか
$ ls -la ~/.config/sops/age/keys.txt
# 確認3: 暗号化時と同じ公開鍵か(enc.yaml の recipient と keys.txt を照合)
$ grep recipient secrets/app.enc.yaml
– recipient: age1f0k5drkkjj37p2c3eup0kuwsylpeqlvdmfs0kww2xnqvdkuxsg0s9aa8z0
$ grep ‘public key’ ~/.config/sops/age/keys.txt
# public key: age1f0k5drkkjj37p2c3eup0kuwsylpeqlvdmfs0kww2xnqvdkuxsg0s9aa8z0
# 上の2行が一致していれば正しい秘密鍵
③ exec: “gpg”: executable file not found
GPG 方式を使おうとして gnupg が入っていない場合のエラーです。sudo apt-get install -y gnupg でインストールしてください。
④ sops –encrypt 後にファイルサイズが激増した
これは正常な動作です。実測では AGE で約13.7倍(113B→1,545B)、GPG で約25.0倍(68B→1,701B)になりました。暗号化キーのラップ処理とメタデータが含まれるため、元ファイルが小さいほど相対的なサイズ増加が大きくなります。実運用上の問題になることはまずありません。
まとめ
Ubuntu 24.04 LTS(ubuntu:24.04 Docker公式イメージ)で SOPS v3.13.1 を使い、シークレットを AGE / GPG で暗号化する手順を実際に動かして確認しました。
- SOPS は apt では提供されていないので、GitHub Releases からバイナリを取得する(22.04 / 24.04 共通)
- AGE は
apt install age(24.04 で v1.1.1)で入り、設定がシンプル。新規プロジェクトでは AGE が推奨 - SOPS は値のみを暗号化し、YAML/ENV のキー名は平文のまま残る。
git diffが読みやすい - 暗号化後のサイズは実測で AGE が約13.7倍、GPG が約25.0倍。GPG は PGPメッセージを埋め込むぶん重い
.sops.yamlのpath_regexで鍵を自動選択でき、GitHub Actions ではSOPS_AGE_KEYで CI/CD 連携できる
VPS を借りて本番環境を運用するなら、データベースのパスワードや API キーをどう安全に管理するかは避けて通れない問題です。SOPS を使えば、シークレットを Git で管理しながらもセキュリティを保てます。
VPS の選び方や Ubuntu サーバーの初期設定については、以下も参考にしてください。



コメント