fix(sub2api): update to 0.1.150 safely (#4690)

This commit is contained in:
okxlin
2026-07-10 20:09:40 +08:00
committed by GitHub
parent 97fad7f9fb
commit cd35d6530b
13 changed files with 290 additions and 143 deletions
-6
View File
@@ -1,6 +0,0 @@
#!/bin/bash
set -euo pipefail
# 当前适配使用 1Panel 数据库 / Redis 依赖注入。
# 这里只初始化应用自身的数据目录。
mkdir -p "${APP_DATA_DIR_1:-./data}"
-6
View File
@@ -1,6 +0,0 @@
#!/bin/bash
set -euo pipefail
# 升级时确保应用自身的数据目录存在。
# 数据库与 Redis 数据由 1Panel 依赖应用管理。
mkdir -p "${APP_DATA_DIR_1:-./data}"
@@ -8,7 +8,7 @@ additionalProperties:
label:
en: Database Service
zh: 数据库服务
zh-hant: 資料庫服務
zh-Hant: 資料庫服務
ja: データベースサービス
ko: 데이터베이스 서비스
ru: Служба базы данных
@@ -23,7 +23,7 @@ additionalProperties:
label:
en: Database
zh: 数据库服务
zh-hant: 資料庫服務
zh-Hant: 資料庫服務
ja: データベース
ko: 데이터베이스
ru: База данных
@@ -42,7 +42,7 @@ additionalProperties:
label:
en: Database Name
zh: 数据库名
zh-hant: 資料庫名稱
zh-Hant: 資料庫名稱
ja: データベース名
ko: 데이터베이스 이름
ru: Имя базы данных
@@ -60,7 +60,7 @@ additionalProperties:
label:
en: Database User
zh: 数据库用户
zh-hant: 資料庫使用者
zh-Hant: 資料庫使用者
ja: データベースユーザー
ko: 데이터베이스 사용자
ru: Пользователь базы данных
@@ -78,7 +78,7 @@ additionalProperties:
label:
en: Database Port
zh: 数据库端口
zh-hant: 資料庫連接埠
zh-Hant: 資料庫連接埠
ja: データベースポート
ko: 데이터베이스 포트
ru: Порт базы данных
@@ -95,7 +95,7 @@ additionalProperties:
label:
en: Database Password
zh: 数据库用户密码
zh-hant: 資料庫使用者密碼
zh-Hant: 資料庫使用者密碼
ja: データベースパスワード
ko: 데이터베이스 비밀번호
ru: Пароль базы данных
@@ -114,7 +114,7 @@ additionalProperties:
label:
en: Redis Service
zh: Redis服务
zh-hant: Redis 服務
zh-Hant: Redis 服務
ja: Redis サービス
ko: Redis 서비스
ru: Служба Redis
@@ -130,7 +130,7 @@ additionalProperties:
label:
en: Redis Service Port
zh: Redis服务端口
zh-hant: Redis 服務連接埠
zh-Hant: Redis 服務連接埠
ja: Redis サービスポート
ko: Redis 서비스 포트
ru: Порт службы Redis
@@ -147,7 +147,7 @@ additionalProperties:
label:
en: Redis Password
zh: Redis 密码
zh-hant: Redis 密碼
zh-Hant: Redis 密碼
ja: Redis パスワード
ko: Redis 비밀번호
ru: Пароль Redis
@@ -164,7 +164,7 @@ additionalProperties:
label:
en: Redis Database
zh: Redis 数据库
zh-hant: Redis 資料庫
zh-Hant: Redis 資料庫
ja: Redis データベース
ko: Redis 데이터베이스
ru: База данных Redis
@@ -180,7 +180,7 @@ additionalProperties:
label:
en: Web Port
zh: Web 访问端口
zh-hant: Web 訪問埠
zh-Hant: Web 訪問埠
ja: Webポート
ko: 웹 포트
ru: Веб-порт
@@ -197,7 +197,7 @@ additionalProperties:
label:
en: Timezone
zh: 时区
zh-hant: 時區
zh-Hant: 時區
ja: タイムゾーン
ko: 시간대
ru: Часовой пояс
@@ -213,7 +213,7 @@ additionalProperties:
label:
en: Server Mode
zh: 服务模式
zh-hant: 服務模式
zh-Hant: 服務模式
ja: サーバーモード
ko: 서버 모드
ru: Режим сервера
@@ -234,7 +234,7 @@ additionalProperties:
label:
en: Run Mode
zh: 运行模式
zh-hant: 運行模式
zh-Hant: 運行模式
ja: 実行モード
ko: 실행 모드
ru: Режим работы
@@ -255,7 +255,7 @@ additionalProperties:
label:
en: Admin Email
zh: 管理员邮箱
zh-hant: 管理員郵箱
zh-Hant: 管理員郵箱
ja: 管理者メール
ko: 관리자 이메일
ru: Email администратора
@@ -271,7 +271,7 @@ additionalProperties:
label:
en: Admin Password
zh: 管理员密码
zh-hant: 管理員密碼
zh-Hant: 管理員密碼
ja: 管理者パスワード
ko: 관리자 비밀번호
ru: Пароль администратора
@@ -284,36 +284,34 @@ additionalProperties:
- default: ""
edit: true
envKey: JWT_SECRET
labelEn: JWT Secret
labelZh: JWT 密钥
labelEn: JWT Secret (blank to auto-generate)
labelZh: JWT 密钥(留空自动生成)
label:
en: JWT Secret
zh: JWT 密钥
zh-hant: JWT 金鑰
ja: JWT シークレット
ko: JWT 시크릿
ru: JWT-секрет
ms: Rahsia JWT
pt-br: Segredo JWT
random: true
required: true
en: JWT Secret (blank to auto-generate)
zh: JWT 密钥(留空自动生成)
zh-Hant: JWT 金鑰(留空自動產生)
ja: JWT シークレット(空欄で自動生成)
ko: JWT 시크릿(비워 두면 자동 생성)
ru: JWT-секрет (пусто = создать автоматически)
ms: Rahsia JWT (kosong untuk jana automatik)
pt-br: Segredo JWT (vazio para gerar automaticamente)
required: false
type: password
- default: ""
edit: true
envKey: TOTP_ENCRYPTION_KEY
labelEn: TOTP Encryption Key
labelZh: TOTP 加密密钥
labelEn: TOTP Encryption Key (blank to auto-generate)
labelZh: TOTP 加密密钥(留空自动生成)
label:
en: TOTP Encryption Key
zh: TOTP 加密密钥
zh-hant: TOTP 加密金鑰
ja: TOTP 暗号化キー
ko: TOTP 암호화 키
ru: Ключ шифрования TOTP
ms: Kunci penyulitan TOTP
pt-br: Chave de criptografia TOTP
random: true
required: true
en: TOTP Encryption Key (blank to auto-generate)
zh: TOTP 加密密钥(留空自动生成)
zh-Hant: TOTP 加密金鑰(留空自動產生)
ja: TOTP 暗号化キー(空欄で自動生成)
ko: TOTP 암호화 키(비워 두면 자동 생성)
ru: Ключ TOTP (пусто = создать автоматически)
ms: Kunci TOTP (kosong untuk jana automatik)
pt-br: Chave TOTP (vazia para gerar automaticamente)
required: false
type: password
- default: ""
edit: true
@@ -323,7 +321,7 @@ additionalProperties:
label:
en: Update Proxy URL
zh: 更新代理地址
zh-hant: 更新代理地址
zh-Hant: 更新代理地址
ja: 更新プロキシ URL
ko: 업데이트 프록시 URL
ru: URL прокси для обновлений
@@ -340,7 +338,7 @@ additionalProperties:
label:
en: App Data Directory
zh: 应用数据目录
zh-hant: 應用資料目錄
zh-Hant: 應用資料目錄
ja: アプリデータディレクトリ
ko: 앱 데이터 디렉터리
ru: Каталог данных приложения
@@ -1,6 +1,6 @@
services:
sub2api:
image: "ghcr.io/wei-shaw/sub2api:0.1.147"
image: "ghcr.io/wei-shaw/sub2api:0.1.150"
container_name: ${CONTAINER_NAME}
restart: always
networks:
+45
View File
@@ -0,0 +1,45 @@
#!/bin/bash
set -euo pipefail
mkdir -p "${APP_DATA_DIR_1:-./data}"
touch .env
chmod 600 .env
generate_secret() {
if command -v openssl >/dev/null 2>&1; then
openssl rand -hex 32
else
od -An -N32 -tx1 /dev/urandom | tr -d ' \n'
fi
}
read_env_value() {
key="$1"
[ -f .env ] || return 0
sed -n "s/^${key}=//p" .env | tail -n 1 | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//"
}
write_env_value() {
key="$1"
value="$2"
touch .env
tmp_file="$(mktemp .env.XXXXXX)"
awk -v key="$key" -v value="$value" '
BEGIN { updated = 0 }
$0 ~ "^" key "=" { print key "=" value; updated = 1; next }
{ print }
END { if (!updated) print key "=" value }
' .env >"$tmp_file"
chmod 600 "$tmp_file"
mv "$tmp_file" .env
}
jwt_secret="${JWT_SECRET:-$(read_env_value JWT_SECRET)}"
if [ "${#jwt_secret}" -lt 32 ]; then
write_env_value JWT_SECRET "$(generate_secret)"
fi
totp_key="${TOTP_ENCRYPTION_KEY:-$(read_env_value TOTP_ENCRYPTION_KEY)}"
if [ -z "$totp_key" ]; then
write_env_value TOTP_ENCRYPTION_KEY "$(generate_secret)"
fi
+45
View File
@@ -0,0 +1,45 @@
#!/bin/bash
set -euo pipefail
mkdir -p "${APP_DATA_DIR_1:-./data}"
touch .env
chmod 600 .env
generate_secret() {
if command -v openssl >/dev/null 2>&1; then
openssl rand -hex 32
else
od -An -N32 -tx1 /dev/urandom | tr -d ' \n'
fi
}
read_env_value() {
key="$1"
[ -f .env ] || return 0
sed -n "s/^${key}=//p" .env | tail -n 1 | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//"
}
write_env_value() {
key="$1"
value="$2"
touch .env
tmp_file="$(mktemp .env.XXXXXX)"
awk -v key="$key" -v value="$value" '
BEGIN { updated = 0 }
$0 ~ "^" key "=" { print key "=" value; updated = 1; next }
{ print }
END { if (!updated) print key "=" value }
' .env >"$tmp_file"
chmod 600 "$tmp_file"
mv "$tmp_file" .env
}
jwt_secret="${JWT_SECRET:-$(read_env_value JWT_SECRET)}"
if [ "${#jwt_secret}" -lt 32 ]; then
write_env_value JWT_SECRET "$(generate_secret)"
fi
totp_key="${TOTP_ENCRYPTION_KEY:-$(read_env_value TOTP_ENCRYPTION_KEY)}"
if [ -z "$totp_key" ]; then
write_env_value TOTP_ENCRYPTION_KEY "$(generate_secret)"
fi
+37 -42
View File
@@ -1,55 +1,50 @@
# Sub2API
## 应用简介
提供 OpenAI 兼容接口的 AI 网关服务。
## 产品介绍
Sub2API 是一个提供 OpenAI 兼容接口的 AI 网关服务,可集中管理上游账号、订阅配额、访问令牌和用量统计
英文说明:AI gateway service with OpenAI-compatible APIs.
## 主要功能
- 提供 OpenAI 兼容 API 和统一管理界面
- 管理账号、用户、令牌、配额与用量统计
- 支持 PostgreSQL 持久化和 Redis 缓存
- 支持多种 AI 服务的转发与兼容处理
## 访问说明
安装完成后,通过 1Panel 显示的 Web 端口访问管理界面。首次安装会根据表单参数初始化管理员账号、数据库和 Redis 连接。
## Introduction
Sub2API is an AI gateway with OpenAI-compatible APIs for managing upstream accounts, subscriptions, access tokens, quotas, and usage.
## Features
- OpenAI-compatible APIs and a centralized administration interface
- Account, user, token, quota, and usage management
- PostgreSQL persistence and Redis caching
- Forwarding and compatibility support for multiple AI providers
## 部署说明
- 本应用使用 Docker Compose 在 1Panel 中部署
- 应用分类:AI
- 支持架构:amd64
- 可选版本:`latest``0.1.138`
- 安装后按应用表单中的端口访问 Web UI、SSH 或对应服务。
- 安装前需要在 1Panel 中准备 PostgreSQL 和 Redis 服务
- `JWT_SECRET``TOTP_ENCRYPTION_KEY` 留空时,生命周期脚本会生成 64 位十六进制密钥并写入 `.env`
- 升级时会保留长度不少于 32 字节的自定义 `JWT_SECRET`;旧版生成的过短值会被替换,因此现有登录会话可能需要重新登录
- 已配置的 TOTP 加密密钥不会在升级时覆盖,避免破坏现有双因素认证
## 端口
| 变量 | 说明 | 默认值 | 必填 |
| --- | --- | --- | --- |
| PANEL_DB_PORT | 数据库端口 | 5432 | 是 |
| REDIS_PORT | Redis服务端口 | 6379 | 是 |
| PANEL_APP_PORT_HTTP | Web 访问端口 | 8080 | 是 |
## 数据持久化
| 变量 | 说明 | 默认值 | 必填 |
| --- | --- | --- | --- |
| APP_DATA_DIR_1 | 应用数据目录 | ./data | 是 |
升级或迁移前,请在 1Panel 中备份上述数据目录。
## 配置项
| 变量 | 说明 | 默认值 | 必填 |
| --- | --- | --- | --- |
| PANEL_DB_TYPE | 数据库服务 | postgresql | 是 |
| PANEL_DB_NAME | 数据库名 | sub2api | 是 |
| PANEL_DB_USER | 数据库用户 | sub2api | 是 |
| PANEL_DB_USER_PASSWORD | 数据库用户密码 | - | 是 |
| REDIS_HOST | Redis服务 | - | 是 |
| PANEL_REDIS_ROOT_PASSWORD | Redis 密码 | - | 是 |
| REDIS_DB | Redis 数据库 | 0 | 是 |
| SERVER_MODE | 服务模式 | release | 是 |
| RUN_MODE | 运行模式 | standard | 是 |
| ADMIN_EMAIL | 管理员邮箱 | admin@sub2api.local | 是 |
## 使用说明
### 反向代理说明
如果你在 Nginx 后面反代 Sub2API,并且需要兼容 Codex CLI 等依赖下划线请求头的客户端,请在 Nginx 的 `http` 块中开启:
## 反向代理说明
如果在 Nginx 后面反代 Sub2API,并需要兼容 Codex CLI 等依赖下划线请求头的客户端,请在 Nginx 的 `http` 块中开启:
```nginx
underscores_in_headers on;
```
这是上游 README 明确提到的要求,否则某些带下划线的头可能被 Nginx 丢弃,影响会话粘性部分 CLI 场景。
否则部分带下划线的请求头可能被 Nginx 丢弃,影响会话粘性部分 CLI 场景。
## 数据持久化
| 路径 | 说明 |
| --- | --- |
| `${APP_DATA_DIR_1}` | Sub2API 应用数据目录 |
| PostgreSQL 服务 | 业务数据和配置 |
| Redis 服务 | 缓存和运行状态 |
升级或迁移前,请备份应用数据目录和 PostgreSQL 数据库。
## 参考资料
- 官网: <https://github.com/Wei-Shaw/sub2api>
- 项目仓库: <https://github.com/Wei-Shaw/sub2api>
- 部署文档: <https://github.com/Wei-Shaw/sub2api/blob/main/deploy/README.md>
+40 -42
View File
@@ -8,7 +8,7 @@ additionalProperties:
label:
en: Database Service
zh: 数据库服务
zh-hant: 資料庫服務
zh-Hant: 資料庫服務
ja: データベースサービス
ko: 데이터베이스 서비스
ru: Служба базы данных
@@ -23,7 +23,7 @@ additionalProperties:
label:
en: Database
zh: 数据库服务
zh-hant: 資料庫服務
zh-Hant: 資料庫服務
ja: データベース
ko: 데이터베이스
ru: База данных
@@ -42,7 +42,7 @@ additionalProperties:
label:
en: Database Name
zh: 数据库名
zh-hant: 資料庫名稱
zh-Hant: 資料庫名稱
ja: データベース名
ko: 데이터베이스 이름
ru: Имя базы данных
@@ -60,7 +60,7 @@ additionalProperties:
label:
en: Database User
zh: 数据库用户
zh-hant: 資料庫使用者
zh-Hant: 資料庫使用者
ja: データベースユーザー
ko: 데이터베이스 사용자
ru: Пользователь базы данных
@@ -78,7 +78,7 @@ additionalProperties:
label:
en: Database Port
zh: 数据库端口
zh-hant: 資料庫連接埠
zh-Hant: 資料庫連接埠
ja: データベースポート
ko: 데이터베이스 포트
ru: Порт базы данных
@@ -95,7 +95,7 @@ additionalProperties:
label:
en: Database Password
zh: 数据库用户密码
zh-hant: 資料庫使用者密碼
zh-Hant: 資料庫使用者密碼
ja: データベースパスワード
ko: 데이터베이스 비밀번호
ru: Пароль базы данных
@@ -114,7 +114,7 @@ additionalProperties:
label:
en: Redis Service
zh: Redis服务
zh-hant: Redis 服務
zh-Hant: Redis 服務
ja: Redis サービス
ko: Redis 서비스
ru: Служба Redis
@@ -130,7 +130,7 @@ additionalProperties:
label:
en: Redis Service Port
zh: Redis服务端口
zh-hant: Redis 服務連接埠
zh-Hant: Redis 服務連接埠
ja: Redis サービスポート
ko: Redis 서비스 포트
ru: Порт службы Redis
@@ -147,7 +147,7 @@ additionalProperties:
label:
en: Redis Password
zh: Redis 密码
zh-hant: Redis 密碼
zh-Hant: Redis 密碼
ja: Redis パスワード
ko: Redis 비밀번호
ru: Пароль Redis
@@ -164,7 +164,7 @@ additionalProperties:
label:
en: Redis Database
zh: Redis 数据库
zh-hant: Redis 資料庫
zh-Hant: Redis 資料庫
ja: Redis データベース
ko: Redis 데이터베이스
ru: База данных Redis
@@ -180,7 +180,7 @@ additionalProperties:
label:
en: Web Port
zh: Web 访问端口
zh-hant: Web 訪問埠
zh-Hant: Web 訪問埠
ja: Webポート
ko: 웹 포트
ru: Веб-порт
@@ -197,7 +197,7 @@ additionalProperties:
label:
en: Timezone
zh: 时区
zh-hant: 時區
zh-Hant: 時區
ja: タイムゾーン
ko: 시간대
ru: Часовой пояс
@@ -213,7 +213,7 @@ additionalProperties:
label:
en: Server Mode
zh: 服务模式
zh-hant: 服務模式
zh-Hant: 服務模式
ja: サーバーモード
ko: 서버 모드
ru: Режим сервера
@@ -234,7 +234,7 @@ additionalProperties:
label:
en: Run Mode
zh: 运行模式
zh-hant: 運行模式
zh-Hant: 運行模式
ja: 実行モード
ko: 실행 모드
ru: Режим работы
@@ -255,7 +255,7 @@ additionalProperties:
label:
en: Admin Email
zh: 管理员邮箱
zh-hant: 管理員郵箱
zh-Hant: 管理員郵箱
ja: 管理者メール
ko: 관리자 이메일
ru: Email администратора
@@ -271,7 +271,7 @@ additionalProperties:
label:
en: Admin Password
zh: 管理员密码
zh-hant: 管理員密碼
zh-Hant: 管理員密碼
ja: 管理者パスワード
ko: 관리자 비밀번호
ru: Пароль администратора
@@ -284,36 +284,34 @@ additionalProperties:
- default: ""
edit: true
envKey: JWT_SECRET
labelEn: JWT Secret
labelZh: JWT 密钥
labelEn: JWT Secret (blank to auto-generate)
labelZh: JWT 密钥(留空自动生成)
label:
en: JWT Secret
zh: JWT 密钥
zh-hant: JWT 金鑰
ja: JWT シークレット
ko: JWT 시크릿
ru: JWT-секрет
ms: Rahsia JWT
pt-br: Segredo JWT
random: true
required: true
en: JWT Secret (blank to auto-generate)
zh: JWT 密钥(留空自动生成)
zh-Hant: JWT 金鑰(留空自動產生)
ja: JWT シークレット(空欄で自動生成)
ko: JWT 시크릿(비워 두면 자동 생성)
ru: JWT-секрет (пусто = создать автоматически)
ms: Rahsia JWT (kosong untuk jana automatik)
pt-br: Segredo JWT (vazio para gerar automaticamente)
required: false
type: password
- default: ""
edit: true
envKey: TOTP_ENCRYPTION_KEY
labelEn: TOTP Encryption Key
labelZh: TOTP 加密密钥
labelEn: TOTP Encryption Key (blank to auto-generate)
labelZh: TOTP 加密密钥(留空自动生成)
label:
en: TOTP Encryption Key
zh: TOTP 加密密钥
zh-hant: TOTP 加密金鑰
ja: TOTP 暗号化キー
ko: TOTP 암호화 키
ru: Ключ шифрования TOTP
ms: Kunci penyulitan TOTP
pt-br: Chave de criptografia TOTP
random: true
required: true
en: TOTP Encryption Key (blank to auto-generate)
zh: TOTP 加密密钥(留空自动生成)
zh-Hant: TOTP 加密金鑰(留空自動產生)
ja: TOTP 暗号化キー(空欄で自動生成)
ko: TOTP 암호화 키(비워 두면 자동 생성)
ru: Ключ TOTP (пусто = создать автоматически)
ms: Kunci TOTP (kosong untuk jana automatik)
pt-br: Chave TOTP (vazia para gerar automaticamente)
required: false
type: password
- default: ""
edit: true
@@ -323,7 +321,7 @@ additionalProperties:
label:
en: Update Proxy URL
zh: 更新代理地址
zh-hant: 更新代理地址
zh-Hant: 更新代理地址
ja: 更新プロキシ URL
ko: 업데이트 프록시 URL
ru: URL прокси для обновлений
@@ -340,7 +338,7 @@ additionalProperties:
label:
en: App Data Directory
zh: 应用数据目录
zh-hant: 應用資料目錄
zh-Hant: 應用資料目錄
ja: アプリデータディレクトリ
ko: 앱 데이터 디렉터리
ru: Каталог данных приложения
+41 -2
View File
@@ -1,6 +1,45 @@
#!/bin/bash
set -euo pipefail
# 当前适配使用 1Panel 数据库 / Redis 依赖注入。
# 这里只初始化应用自身的数据目录。
mkdir -p "${APP_DATA_DIR_1:-./data}"
touch .env
chmod 600 .env
generate_secret() {
if command -v openssl >/dev/null 2>&1; then
openssl rand -hex 32
else
od -An -N32 -tx1 /dev/urandom | tr -d ' \n'
fi
}
read_env_value() {
key="$1"
[ -f .env ] || return 0
sed -n "s/^${key}=//p" .env | tail -n 1 | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//"
}
write_env_value() {
key="$1"
value="$2"
touch .env
tmp_file="$(mktemp .env.XXXXXX)"
awk -v key="$key" -v value="$value" '
BEGIN { updated = 0 }
$0 ~ "^" key "=" { print key "=" value; updated = 1; next }
{ print }
END { if (!updated) print key "=" value }
' .env >"$tmp_file"
chmod 600 "$tmp_file"
mv "$tmp_file" .env
}
jwt_secret="${JWT_SECRET:-$(read_env_value JWT_SECRET)}"
if [ "${#jwt_secret}" -lt 32 ]; then
write_env_value JWT_SECRET "$(generate_secret)"
fi
totp_key="${TOTP_ENCRYPTION_KEY:-$(read_env_value TOTP_ENCRYPTION_KEY)}"
if [ -z "$totp_key" ]; then
write_env_value TOTP_ENCRYPTION_KEY "$(generate_secret)"
fi
+41 -2
View File
@@ -1,6 +1,45 @@
#!/bin/bash
set -euo pipefail
# 升级时确保应用自身的数据目录存在。
# 数据库与 Redis 数据由 1Panel 依赖应用管理。
mkdir -p "${APP_DATA_DIR_1:-./data}"
touch .env
chmod 600 .env
generate_secret() {
if command -v openssl >/dev/null 2>&1; then
openssl rand -hex 32
else
od -An -N32 -tx1 /dev/urandom | tr -d ' \n'
fi
}
read_env_value() {
key="$1"
[ -f .env ] || return 0
sed -n "s/^${key}=//p" .env | tail -n 1 | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//"
}
write_env_value() {
key="$1"
value="$2"
touch .env
tmp_file="$(mktemp .env.XXXXXX)"
awk -v key="$key" -v value="$value" '
BEGIN { updated = 0 }
$0 ~ "^" key "=" { print key "=" value; updated = 1; next }
{ print }
END { if (!updated) print key "=" value }
' .env >"$tmp_file"
chmod 600 "$tmp_file"
mv "$tmp_file" .env
}
jwt_secret="${JWT_SECRET:-$(read_env_value JWT_SECRET)}"
if [ "${#jwt_secret}" -lt 32 ]; then
write_env_value JWT_SECRET "$(generate_secret)"
fi
totp_key="${TOTP_ENCRYPTION_KEY:-$(read_env_value TOTP_ENCRYPTION_KEY)}"
if [ -z "$totp_key" ]; then
write_env_value TOTP_ENCRYPTION_KEY "$(generate_secret)"
fi