Skip to content

Commit 8fb7e91

Browse files
aster-voidclaude
andcommitted
meta: add sops for secrets management
- secrets.dev.yaml / secrets.prod.yaml (encrypted) - .sops-age-key.txt (git-ignored, team-shared) - sops exec-env for automatic decryption 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 93ae8c3 commit 8fb7e91

File tree

7 files changed

+94
-4
lines changed

7 files changed

+94
-4
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ vite.config.ts.timestamp-*
1515
.env.*
1616
!.env.sample
1717
!.env.test
18+
.sops-age-key.txt
1819
.DS_Store
1920
Thumbs.db
2021
*.db

.sops.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
keys:
2+
- &project age1gsn5pg5pkk89zsukc94gqwlu7zyrep0prm7pwc787tcegapgmvgqzeq64c
3+
4+
creation_rules:
5+
- path_regex: secrets\.(dev|prod)\.yaml$
6+
key_groups:
7+
- age:
8+
- *project

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ utcode.net の CMS 駆動版フォーク (フォークではない) です。そ
77
環境構築
88

99
- [devenv](https://devenv.sh/) パッケージをインストールします
10+
- `.sops-age-key.txt` を配置します(チームメンバーから取得)
1011

1112
```sh
1213
direnv allow
@@ -42,6 +43,33 @@ process compose に接続 (F10 + enter で退出)
4243
bun attach
4344
```
4445

46+
## Secrets
47+
48+
シークレットは sops で暗号化されています。
49+
50+
```sh
51+
# 編集
52+
sops secrets.dev.yaml
53+
sops secrets.prod.yaml
54+
```
55+
56+
### 鍵のローテーション
57+
58+
```sh
59+
# 1. 新しい鍵を生成
60+
age-keygen
61+
62+
# 2. .sops.yaml に新しい公開鍵を追加(古い鍵も残す)
63+
64+
# 3. .sops-age-key.txt に新しい秘密鍵を追加(古い鍵も残す)
65+
66+
# 4. 再暗号化(古い鍵で復号→新しい鍵で暗号化)
67+
sops updatekeys -y secrets.dev.yaml
68+
sops updatekeys -y secrets.prod.yaml
69+
70+
# 5. 古い鍵を .sops.yaml と .sops-age-key.txt から削除
71+
```
72+
4573
## Data Access Layer
4674

4775
データ操作は DAL `$lib/server/data/*` から import します。直接 db を触りません。

devenv.nix

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{pkgs, ...}: {
2-
packages = [pkgs.postgresql];
2+
packages = [pkgs.postgresql pkgs.sops pkgs.age];
3+
4+
env.SOPS_AGE_KEY_FILE = ".sops-age-key.txt";
35

46
languages.javascript = {
57
enable = true;
@@ -12,7 +14,7 @@
1214

1315
dotenv.disableHint = true;
1416
processes.dev = {
15-
exec = "bun dev";
17+
exec = "sops exec-env secrets.dev.yaml 'vite dev'";
1618
process-compose.availability = {
1719
restart = "on_failure";
1820
backoff_seconds = 10;

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"version": "0.0.1",
55
"type": "module",
66
"scripts": {
7-
"dev": "bun --env-file=.env vite dev",
8-
"build": "bun --env-file=.env vite build",
7+
"dev": "sops exec-env secrets.dev.yaml 'vite dev'",
8+
"build": "sops exec-env secrets.prod.yaml 'vite build'",
99
"preview": "vite preview",
1010
"prepare": "svelte-kit sync",
1111
"test-check": "bun test",

secrets.dev.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
DATABASE_URL: ENC[AES256_GCM,data:DT1kdctK4pK5GF/Ysn3ULxVOK3Vu+7cb7sA=,iv:rqxTwZ31IwSJ4IcrKxdiTQLP7KNAmkf8NBTU5sOZpA0=,tag:KqrGB6S1dgKniSbA+z5pmA==,type:str]
2+
BETTER_AUTH_URL: ENC[AES256_GCM,data:HTm98h7WLoXX92kkFAB3SF8DQE3s,iv:/yFx+YaJHkGi5+mMIDc2dW7bWXEPrLfl4udJAbfx75c=,tag:GxJutrvSDayFdIam7DBWsA==,type:str]
3+
BETTER_AUTH_SECRET: ENC[AES256_GCM,data:iWFfgHGgQhqxHQPS0MrhOQuCaHFi5Y474Ret+WMkjoeVjo5wGQzGmQaaRcE=,iv:CWOE30RroxpvX9Mm9D/1M9jFhEaILwAqAVxcNhpxGKc=,tag:UXWoHgK39mrc+x9LMSCYiA==,type:str]
4+
GITHUB_CLIENT_ID: ""
5+
GITHUB_CLIENT_SECRET: ""
6+
S3_ENDPOINT: ENC[AES256_GCM,data:8DKqTQi0rLcxlbtQZOYaQOtstRlv,iv:ipAyykxrhdicmfT3l1oI4MSjIN6lVs5EiPVKrke8cJQ=,tag:SCRhvHIkQKJdz0UzhJ6rjQ==,type:str]
7+
S3_ACCESS_KEY: ENC[AES256_GCM,data:iZkREoP5BhiHvw==,iv:Urs+Ux5JDVsfJleuFAKrFxHF9Xg3/m7uEph0kln5Hv0=,tag:l5tXx04AVGfdAiRJJHb3nw==,type:str]
8+
S3_SECRET_KEY: ENC[AES256_GCM,data:53MOStu3RyL3CA==,iv:5nzXZ3BV5gYgTj0Kt4YJEDhidLXRqQiq4YyCe4fiXCo=,tag:RkJ+WKqylheG5azXkhRlnw==,type:str]
9+
S3_BUCKET: ENC[AES256_GCM,data:NOun,iv:UhkU0jiq8pee9jboSLDZT3XK+fG9NrLozhWaEAKxqRM=,tag:omC3c8OYgS2KbbpwIwMWvA==,type:str]
10+
S3_PUBLIC_URL: ENC[AES256_GCM,data:o/JRmwxFNqjrMHZJ/eoynCIMcjNIC7G3nw==,iv:8Ut2k/uuhobj7i37J3P3Vb/AUhFLofSoWB6X+Y3g39o=,tag:j1XOf1meTwI0ZoqoYeEvjg==,type:str]
11+
UNSAFE_DISABLE_AUTH: ENC[AES256_GCM,data:qQfxNQ==,iv:j250CMhk9ZPKEXrVjh+Ls99gEpqhAzQSdCtBhbyDRkA=,tag:9R7/YtAI+VgJUKAPcTHpQg==,type:str]
12+
sops:
13+
age:
14+
- recipient: age1gsn5pg5pkk89zsukc94gqwlu7zyrep0prm7pwc787tcegapgmvgqzeq64c
15+
enc: |
16+
-----BEGIN AGE ENCRYPTED FILE-----
17+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaZ0NjbVpFbVJ5TS8xSlNW
18+
a0hmOXRrQ2xpYkVJWHhVRm9lODRTUldxeTE0CnRGemp4dEZKV29JbjhPL2RVa3lG
19+
WGNTdE9RYmZ0L1BQRjQyQ1dwU0x3dlkKLS0tIFc4NXE4ZFRhYmFtWlR2M3lpWVV1
20+
Y2M0Q3NYeFBVTjZKOFNIS0x6dnRPUEEKCt8q9U5HaLS0Mm2JNmODlECAYjN8nn+1
21+
zlbwhcAUqbhFd8HteSbp8jTgp14PUuig/c2c3JDOmgQfiITZaxLayQ==
22+
-----END AGE ENCRYPTED FILE-----
23+
lastmodified: "2025-12-23T06:23:33Z"
24+
mac: ENC[AES256_GCM,data:lyuVzf2Zm8UTIMQNFCeg1BIKR9pfHOorS08alTMKJRHwdqKsziDu9lm86/6iOmUFpyasoG1J2sZN95ltq0IPOooV9sm28QvlNon8HBaNGkgvVRfCeU9vuKQrcp7OOSGI2Vqe38ZIveyBbhTPtqjoLuJfnXkoFiV2s1kPgySxFLM=,iv:OsDm31BPcCveHRqPpn8IpO3GvwKJ/DfCx/eYbWHGceY=,tag:xvVJ2K6xE12HykR8CIpcGA==,type:str]
25+
unencrypted_suffix: _unencrypted
26+
version: 3.11.0

secrets.prod.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
DATABASE_URL: ENC[AES256_GCM,data:yeNu+S3M0VnuH7hvK3kGRF2go8EbS2MotGCw+6Jlc3y+nyS8GOP+RzhCy7NnXZ+5zN+CBN4fKrg1qpTOenINluWhwD5AQbjYaCgtm+oIdL7Cg+raoEwNhRsbd1t1xe+svybfnhzgOzsyOyif3NlF9+vL4NLgb8qDT8AB,iv:x+YcNSMnPlPqr2e2gTh7NBq70A+YDKZyy3VvvKvyRjY=,tag:3CD7DaCUiAzVRrsKiO4qcg==,type:str]
2+
BETTER_AUTH_URL: ENC[AES256_GCM,data:mMEpPLOUsbmHwyUvdJwv4/jflivYHg==,iv:nGCNOmoWa30ysfcnWY3gubhFgPxx3RopmM/tIjr+EMA=,tag:977UziyM+GqVX7SK3Cs+3g==,type:str]
3+
BETTER_AUTH_SECRET: ENC[AES256_GCM,data:Rgh5ya4IBiS+ZKQk+8lpLxVjzXV6sDK7U6TGrHHi3V/uuMg55HDjbkmLwONbm7PuQOqTpV+3pISlG/dRInlh/wmJcl2Mr3nGcqTEFaA2rRmxdIVJfNqidxNC7KoBdSFcO2NY8ZCpICrjrxl9494wXEXXCHYQscltopfNQAFGlvI=,iv:l69cgwj8+uTj0xw+L9F+UDLXCg0wYs7gwb8SXQKW858=,tag:zQwqgfBMFrGUWJs47ISfBA==,type:str]
4+
GITHUB_CLIENT_ID: ENC[AES256_GCM,data:SKLeGCEiy8BP3UmtebbiZICqw+k=,iv:n50b+6abyQBFNkOSBKuPBcMqlLUOR39wlktL4nJGaRw=,tag:vDZv+aOeNcpXQ+A4SJ0ciw==,type:str]
5+
GITHUB_CLIENT_SECRET: ENC[AES256_GCM,data:18cBqoMAL7IiR4dl3n1GhvOmmFyZhVe8hqR+qY8fXrK+qdegdKWqng==,iv:3l45zSgfHFhCnVpZ2R7n5CQg4tgxKuhlZfRN08dqU8M=,tag:QB328THI7oAi0yq+0Ek6Cg==,type:str]
6+
S3_ENDPOINT: ENC[AES256_GCM,data:rVTUiIUOPfTeDsi/3RzIa3LhkqwYstDV8vUv3506+kLPL8DICEct0csfsHSaBa6fgQ87e8go0m3IF7+50YpGSn8=,iv:m1btfdrLSQTrtuBjBMRmextX0RCZgsLsCkI2J1knr04=,tag:Xxbx2qTqAefATucxBD7SOQ==,type:str]
7+
S3_ACCESS_KEY: ENC[AES256_GCM,data:JH70m0+9+KlfjXlDzVqJGYLFy8xRN3fxIV0YwmB9aRE=,iv:dOeu3KHCRrUIUiraFgMf2/tXlTxZioh1+aR5wqshP94=,tag:hTdWpkb8Im3ypxZ1Ijsf+Q==,type:str]
8+
S3_SECRET_KEY: ENC[AES256_GCM,data:QEc9T5yC+iZoV403CqqBTJCsDCdzH2FV0vQoRlEU6vM0oK5PrHiTOXUwe4WMSFCiz3ioBvgQOKHoan963U0gZA==,iv:0qZE002nF25N91pvITA65qBSyi2mDzRXNP/2pcBnI0o=,tag:gFQU5CJDr0FDWiWcFl05Ng==,type:str]
9+
S3_BUCKET: ENC[AES256_GCM,data:kKVmATCe2JYggI5bXjch9kiCbqVb,iv:WBVmx8TWKbJ3xWHiGy3/Os4xlPfcuDMz3xoWnzsTato=,tag:BqnD6HXBC4A9qqeREcB6Sw==,type:str]
10+
S3_PUBLIC_URL: ENC[AES256_GCM,data:yF9V11xmPsO9fAyozCVUWwC+z16+guLMNA==,iv:n8mEi0E8bvxK68hHZ6yd8dBlfi10sETNNXQBMt1ygrw=,tag:7ZK8/MM2xVTi8N65q0+v5g==,type:str]
11+
sops:
12+
age:
13+
- recipient: age1gsn5pg5pkk89zsukc94gqwlu7zyrep0prm7pwc787tcegapgmvgqzeq64c
14+
enc: |
15+
-----BEGIN AGE ENCRYPTED FILE-----
16+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwRWovR2lYZjk5UzQ0Y2Ri
17+
QXAxam5LaEY2S3hFREVEUHJzdDNQbCs2T3hnCkprMDNlamZPQmhvTXh1SUdOUHNX
18+
OEhTYWlLMVdsaVRuUDdPRVZvRmc3VkEKLS0tIGlOK1JScmJtQVJPWXErZkc2VVNR
19+
NHZSdEp1WGc4S2ppK1ZKcDZnU0JRQmMKJj4n6DBAozt2DTlYFIhd1jWWLGMYalAM
20+
+Txthl+D2hQNSITfK7jzVXIhk4z3g2ahNXscRmgrU9u4V0Jj6Gzz/g==
21+
-----END AGE ENCRYPTED FILE-----
22+
lastmodified: "2025-12-23T06:48:31Z"
23+
mac: ENC[AES256_GCM,data:51C/AiU7T7aqHxqvhl/+sc82nigPHlKzLDXqXDyfR5PGfNKsnP7/u/X3xsp6VhNv+itnRCp/29rG3qjKnbjm04uS28bIRmSzaUrDK6/b3ASnJIexhsuAeZFsjqPaJ0IpECdrmn7D2ZXrJQw7qx1LpKlFsHBK8awlE1JDcmdAFXY=,iv:hF63GDjwaKZ5t+/oN5heoFSLHuIJ9tgvqyHNoaDxmjA=,tag:L9gvHacn2UAi693OkVydGA==,type:str]
24+
unencrypted_suffix: _unencrypted
25+
version: 3.11.0

0 commit comments

Comments
 (0)