收紧 Go Agent 安装入口配置

This commit is contained in:
WuYongJie 2026-06-01 10:21:13 +08:00
parent 70a2a20006
commit 2e35feb1d8
6 changed files with 343 additions and 54 deletions

View File

@ -2,12 +2,14 @@
`flnxi-agent-go` 是面向私有化部署场景的 Go 版安装与运维 Agent。
当前定位:Go 版 Agent 更适合作为后续私有化交付的轻量入口;但当前默认安装脚本还没把认证变量和完整版本链路全部接好,不能直接当成“已经可正式交付”的成品。若现场仍使用 Node 版 Agent,先确认既有安装链路和端口占用,再决定是否切换。
当前定位:Go 版 Agent 更适合作为后续私有化交付的轻量入口;它已经收紧了 Agent 自身认证、主应用固定版本镜像和许可证运行参数,但管理界面、安装向导、异常恢复和客户现场验收流程仍未完全闭环,不能直接当成“已经可正式交付”的成品。若现场仍使用 Node 版 Agent,先确认既有安装链路和端口占用,再决定是否切换。
重要现状:
- `install.sh` 已不再默认拉取旧 Harbor `latest` 镜像,必须通过 `AGENT_IMAGE` 或 `--image` 显式传入完整 Agent 版本镜像。
- Go 版 Agent 内部安装和更新素材系统已改为读取完整版本镜像,不再默认拉取旧 Harbor / `latest`。
- 安装素材系统时必须提供完整主应用版本镜像,不能使用无版本 tag 或 `latest`。
- 安装素材系统时必须提供许可证服务参数;缺少关键参数时会在拉镜像前失败,避免客户装出一个启动不了的半成品。
- 版本列表需要通过 `FLNXI_VERSION_LIST_URL` 显式配置来源;未配置时不会伪造 `latest` 或默认版本。
- 当前仍建议先作为内部验证入口,等管理界面和客户安装流程联调完成后,再提升为客户正式安装主入口。
@ -61,17 +63,26 @@ docker run -d \
| `FLNXI_POSTGRES_IMAGE` | 安装时使用的 PostgreSQL 镜像;也兼容读取 `POSTGRES_IMAGE` | `postgres:15-alpine` |
| `FLNXI_MINIO_IMAGE` | 安装时使用的 MinIO 镜像;也兼容读取 `MINIO_IMAGE` | `minio/minio:RELEASE.2025-04-22T22-12-26Z` |
| `FLNXI_VERSION_LIST_URL` | Agent 管理界面可选版本列表来源,返回 Registry tags 结构 | 未设置 |
| `LICENSE_SERVER_URL` | 主应用许可证服务地址,安装素材系统时会写入主应用容器 | 未设置 |
| `LICENSE_PROJECT_CODE` | 主应用许可证项目编码,安装素材系统时会写入主应用容器 | 未设置 |
| `LICENSE_REQUEST_SIGNING_SECRET` | 主应用请求许可证服务的签名密钥,至少 32 字符 | 未设置 |
| `LICENSE_PUBLIC_KEY` | 主应用验签用许可证公钥 | 未设置 |
| `LOCAL_ENCRYPTION_KEY` | 主应用本地许可证缓存加密密钥,至少 32 字符;未传入时 Agent 会为本次安装生成 | 自动生成 |
版本说明:
- 当前 Go 版 Agent 的版本列表不再写死 Harbor;后续正式交付前,需要决定版本列表来自 Registry tags、许可证服务,还是发布管理接口。
- 它还没有像 Node 版 Agent 那样完整接入 `LICENSE_SERVER_URL` / `LICENSE_PROJECT_CODE` 的远端版本检查链路。
- Go 版 Agent 目前会把主应用启动必需的许可证配置写入容器,但还没有把“许可证服务可安装版本、灰度版本、客户授权版本范围”做成最终客户安装向导。
安装素材系统前,至少要给 Agent 容器配置:
```bash
-e FLNXI_MATERIAL_IMAGE=registry.example.com/flnxi/material/flnxi-material:1.0.1
-e FLNXI_MATERIAL_IMAGE_REPOSITORY=registry.example.com/flnxi/material/flnxi-material
-e LICENSE_SERVER_URL=https://license.example.com
-e LICENSE_PROJECT_CODE=flnxi-sucai
-e LICENSE_REQUEST_SIGNING_SECRET='<at-least-32-characters>'
-e LICENSE_PUBLIC_KEY='<license-public-key>'
```
## 安全建议

View File

@ -0,0 +1,23 @@
import fs from 'fs'
import path from 'path'
describe('flnxi-agent-go/install.sh', () => {
const script = fs.readFileSync(
path.join(process.cwd(), 'flnxi-agent-go', 'install.sh'),
'utf8'
)
it('不会把 Agent 镜像当作素材系统镜像兜底', () => {
expect(script).toContain('FLNXI_MATERIAL_IMAGE=${FLNXI_MATERIAL_IMAGE:-}')
expect(script).not.toContain('FLNXI_MATERIAL_IMAGE=${FLNXI_MATERIAL_IMAGE:-$AGENT_IMAGE}')
})
it('会把素材系统安装必需的许可证配置透传给 Agent 容器', () => {
expect(script).toContain('LICENSE_SERVER_URL=${LICENSE_SERVER_URL:-}')
expect(script).toContain('LICENSE_PROJECT_CODE=${LICENSE_PROJECT_CODE:-}')
expect(script).toContain('LICENSE_REQUEST_SIGNING_SECRET=${LICENSE_REQUEST_SIGNING_SECRET:-}')
expect(script).toContain('LICENSE_PUBLIC_KEY=${LICENSE_PUBLIC_KEY:-}')
expect(script).toContain('LOCAL_ENCRYPTION_KEY=${LOCAL_ENCRYPTION_KEY:-}')
expect(script).toContain('未完整配置许可证服务参数')
})
})

View File

@ -219,7 +219,7 @@ run_agent() {
)
run_args+=(
-e "FLNXI_MATERIAL_IMAGE=${FLNXI_MATERIAL_IMAGE:-$AGENT_IMAGE}"
-e "FLNXI_MATERIAL_IMAGE=${FLNXI_MATERIAL_IMAGE:-}"
-e "APP_IMAGE=${APP_IMAGE:-}"
-e "FLNXI_MATERIAL_IMAGE_REPOSITORY=${FLNXI_MATERIAL_IMAGE_REPOSITORY:-}"
-e "FLNXI_POSTGRES_IMAGE=${FLNXI_POSTGRES_IMAGE:-}"
@ -227,8 +227,21 @@ run_agent() {
-e "FLNXI_MINIO_IMAGE=${FLNXI_MINIO_IMAGE:-}"
-e "MINIO_IMAGE=${MINIO_IMAGE:-}"
-e "FLNXI_VERSION_LIST_URL=${FLNXI_VERSION_LIST_URL:-}"
-e "LICENSE_SERVER_URL=${LICENSE_SERVER_URL:-}"
-e "LICENSE_PROJECT_CODE=${LICENSE_PROJECT_CODE:-}"
-e "LICENSE_REQUEST_SIGNING_SECRET=${LICENSE_REQUEST_SIGNING_SECRET:-}"
-e "LICENSE_PUBLIC_KEY=${LICENSE_PUBLIC_KEY:-}"
-e "LOCAL_ENCRYPTION_KEY=${LOCAL_ENCRYPTION_KEY:-}"
)
if [ -z "${FLNXI_MATERIAL_IMAGE:-${APP_IMAGE:-}}" ]; then
print_warning "未配置 FLNXI_MATERIAL_IMAGE / APP_IMAGE,Agent 可启动,但安装素材系统前必须补充完整主应用版本镜像"
fi
if [ -z "${LICENSE_SERVER_URL:-}" ] || [ -z "${LICENSE_PROJECT_CODE:-}" ] || [ -z "${LICENSE_REQUEST_SIGNING_SECRET:-}" ] || [ -z "${LICENSE_PUBLIC_KEY:-}" ]; then
print_warning "未完整配置许可证服务参数,Agent 安装素材系统时会先拦截并提示补齐"
fi
if [ -n "$AGENT_AUTH_USERNAME" ] && [ -n "$AGENT_AUTH_PASSWORD" ]; then
run_args+=(
-e "AGENT_AUTH_USERNAME=$AGENT_AUTH_USERNAME"

View File

@ -112,12 +112,82 @@ func resolveInstallImages(req InstallRequest) (string, string, string, error) {
if materialImage == "" {
return "", "", "", fmt.Errorf("%s or %s is required", envMaterialImage, envMaterialImageCompat)
}
if err := validateFixedImageTag(materialImage); err != nil {
return "", "", "", fmt.Errorf("material image: %w", err)
}
postgresImage := firstNonEmpty(req.PostgresImage, os.Getenv(envPostgresImage), os.Getenv(envPostgresImageCompat), "postgres:15-alpine")
minioImage := firstNonEmpty(req.MinioImage, os.Getenv(envMinioImage), os.Getenv(envMinioImageCompat), "minio/minio:RELEASE.2025-04-22T22-12-26Z")
return materialImage, postgresImage, minioImage, nil
}
type InstallLicenseConfig struct {
ServerURL string
ProjectCode string
RequestSigningSecret string
PublicKey string
LocalEncryptionKey string
}
func resolveInstallLicenseConfig(req InstallRequest, secrets InstallSecrets) (InstallLicenseConfig, error) {
config := InstallLicenseConfig{
ServerURL: firstNonEmpty(req.LicenseServerURL, os.Getenv(envLicenseServerURL)),
ProjectCode: firstNonEmpty(req.LicenseProjectCode, os.Getenv(envLicenseProjectCode)),
RequestSigningSecret: firstNonEmpty(req.LicenseRequestSigningSecret, os.Getenv(envLicenseRequestSigningSecret)),
PublicKey: firstNonEmpty(req.LicensePublicKey, os.Getenv(envLicensePublicKey)),
LocalEncryptionKey: firstNonEmpty(req.LocalEncryptionKey, os.Getenv(envLocalEncryptionKey), secrets.LocalEncryptionKey),
}
missing := make([]string, 0)
if config.ServerURL == "" {
missing = append(missing, envLicenseServerURL)
}
if config.ProjectCode == "" {
missing = append(missing, envLicenseProjectCode)
}
if len(config.RequestSigningSecret) < 32 {
missing = append(missing, envLicenseRequestSigningSecret+"(至少32字符)")
}
if config.PublicKey == "" {
missing = append(missing, envLicensePublicKey)
}
if len(config.LocalEncryptionKey) < 32 {
missing = append(missing, envLocalEncryptionKey+"(至少32字符)")
}
if len(missing) > 0 {
return InstallLicenseConfig{}, fmt.Errorf("missing material license config: %s", strings.Join(missing, ", "))
}
return config, nil
}
func materialAppEnv(req InstallRequest, secrets InstallSecrets, licenseConfig InstallLicenseConfig, localIP string, webPort int) []string {
return []string{
"LICENSE_KEY=" + req.LicenseKey,
"LICENSE_SERVER_URL=" + licenseConfig.ServerURL,
"LICENSE_PROJECT_CODE=" + licenseConfig.ProjectCode,
"LICENSE_REQUEST_SIGNING_SECRET=" + licenseConfig.RequestSigningSecret,
"LICENSE_PUBLIC_KEY=" + licenseConfig.PublicKey,
"LOCAL_ENCRYPTION_KEY=" + licenseConfig.LocalEncryptionKey,
"DATABASE_URL=postgresql://" + secrets.DbUser + ":" + secrets.DbPassword + "@flnxi-db:5432/" + secrets.DbName,
// S3/MinIO 配置(内部访问使用 Docker 网络)
"S3_ENDPOINT=http://flnxi-minio:9000",
"S3_ACCESS_KEY_ID=" + secrets.MinioRootUser,
"S3_SECRET_ACCESS_KEY=" + secrets.MinioRootPassword,
"S3_BUCKET=" + secrets.S3Bucket,
"S3_REGION=us-east-1",
"S3_ENABLE_PATH_STYLE=1",
// S3 公开访问配置(浏览器访问使用宿主机 IP)
"S3_PUBLIC_DOMAIN=http://" + localIP + ":9000/" + secrets.S3Bucket,
"SERVER_IP=" + localIP,
"MINIO_API_PORT=9000",
// NextAuth 配置
"NEXTAUTH_SECRET=" + secrets.NextAuthSecret,
"NEXTAUTH_URL=http://" + localIP + ":" + fmt.Sprintf("%d", webPort),
"APP_PUBLIC_URL=http://" + localIP + ":" + fmt.Sprintf("%d", webPort),
}
}
func resolveUpdateImage(req UpdateRequest) (string, error) {
if image := firstNonEmpty(req.Image); image != "" {
if err := validateFixedImageTag(image); err != nil {
@ -173,14 +243,19 @@ func validateFixedImageTag(image string) error {
}
const (
envMaterialImage = "FLNXI_MATERIAL_IMAGE"
envMaterialImageCompat = "APP_IMAGE"
envMaterialImageRepository = "FLNXI_MATERIAL_IMAGE_REPOSITORY"
envPostgresImage = "FLNXI_POSTGRES_IMAGE"
envPostgresImageCompat = "POSTGRES_IMAGE"
envMinioImage = "FLNXI_MINIO_IMAGE"
envMinioImageCompat = "MINIO_IMAGE"
envVersionListURL = "FLNXI_VERSION_LIST_URL"
envMaterialImage = "FLNXI_MATERIAL_IMAGE"
envMaterialImageCompat = "APP_IMAGE"
envMaterialImageRepository = "FLNXI_MATERIAL_IMAGE_REPOSITORY"
envPostgresImage = "FLNXI_POSTGRES_IMAGE"
envPostgresImageCompat = "POSTGRES_IMAGE"
envMinioImage = "FLNXI_MINIO_IMAGE"
envMinioImageCompat = "MINIO_IMAGE"
envVersionListURL = "FLNXI_VERSION_LIST_URL"
envLicenseServerURL = "LICENSE_SERVER_URL"
envLicenseProjectCode = "LICENSE_PROJECT_CODE"
envLicenseRequestSigningSecret = "LICENSE_REQUEST_SIGNING_SECRET"
envLicensePublicKey = "LICENSE_PUBLIC_KEY"
envLocalEncryptionKey = "LOCAL_ENCRYPTION_KEY"
)
var (
@ -206,13 +281,18 @@ type UpdateStatus struct {
}
type InstallRequest struct {
LicenseKey string `json:"licenseKey"`
DataPath string `json:"dataPath"`
WebPort int `json:"webPort"`
AuthToken string `json:"authToken,omitempty"`
MaterialImage string `json:"materialImage,omitempty"`
PostgresImage string `json:"postgresImage,omitempty"`
MinioImage string `json:"minioImage,omitempty"`
LicenseKey string `json:"licenseKey"`
DataPath string `json:"dataPath"`
WebPort int `json:"webPort"`
AuthToken string `json:"authToken,omitempty"`
MaterialImage string `json:"materialImage,omitempty"`
PostgresImage string `json:"postgresImage,omitempty"`
MinioImage string `json:"minioImage,omitempty"`
LicenseServerURL string `json:"licenseServerUrl,omitempty"`
LicenseProjectCode string `json:"licenseProjectCode,omitempty"`
LicenseRequestSigningSecret string `json:"licenseRequestSigningSecret,omitempty"`
LicensePublicKey string `json:"licensePublicKey,omitempty"`
LocalEncryptionKey string `json:"localEncryptionKey,omitempty"`
}
type UpdateRequest struct {
@ -272,7 +352,14 @@ func GetInstallStatus(dc *docker.Client) gin.HandlerFunc {
}
}
func runInstall(dc *docker.Client, req InstallRequest) {
type installDockerClient interface {
PullImageWithProgress(ctx context.Context, image string, authStr string, onProgress func(current, total int64, status string)) error
ExecOnHost(ctx context.Context, cmd string) error
CreateNetworkIfNotExists(ctx context.Context, name string) error
CreateAndStartContainer(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, name string) (string, error)
}
func runInstall(dc installDockerClient, req InstallRequest) {
ctx := context.Background()
setStep := func(step string, progress int, msg string) {
statusMutex.Lock()
@ -302,6 +389,12 @@ func runInstall(dc *docker.Client, req InstallRequest) {
return
}
licenseConfig, err := resolveInstallLicenseConfig(req, secrets)
if err != nil {
setErr("许可证配置缺失: " + err.Error())
return
}
// 拉取素材系统镜像 (0-30%)
setStep("拉取镜像", 1, "正在拉取素材系统镜像...")
err = dc.PullImageWithProgress(ctx, materialImage, authStr, func(current, total int64, status string) {
@ -421,27 +514,9 @@ func runInstall(dc *docker.Client, req InstallRequest) {
// 启动素材系统
setStep("启动服务", 90, "启动素材系统...")
cfg := &container.Config{
Image: materialImage,
User: "0", // 以 root 用户运行,确保有权限写入挂载目录
Env: []string{
"LICENSE_KEY=" + req.LicenseKey,
"DATABASE_URL=postgresql://" + secrets.DbUser + ":" + secrets.DbPassword + "@flnxi-db:5432/" + secrets.DbName,
// S3/MinIO 配置(内部访问使用 Docker 网络)
"S3_ENDPOINT=http://flnxi-minio:9000",
"S3_ACCESS_KEY_ID=" + secrets.MinioRootUser,
"S3_SECRET_ACCESS_KEY=" + secrets.MinioRootPassword,
"S3_BUCKET=" + secrets.S3Bucket,
"S3_REGION=us-east-1",
"S3_ENABLE_PATH_STYLE=1",
// S3 公开访问配置(浏览器访问使用宿主机 IP)
"S3_PUBLIC_DOMAIN=http://" + localIP + ":9000/" + secrets.S3Bucket,
"SERVER_IP=" + localIP,
"MINIO_API_PORT=9000",
// NextAuth 配置
"NEXTAUTH_SECRET=" + secrets.NextAuthSecret,
"NEXTAUTH_URL=http://" + localIP + ":" + fmt.Sprintf("%d", webPort),
"APP_PUBLIC_URL=http://" + localIP + ":" + fmt.Sprintf("%d", webPort),
},
Image: materialImage,
User: "0", // 以 root 用户运行,确保有权限写入挂载目录
Env: materialAppEnv(req, secrets, licenseConfig, localIP, webPort),
ExposedPorts: nat.PortSet{"3000/tcp": struct{}{}},
}
hcfg := &container.HostConfig{

View File

@ -54,6 +54,121 @@ func TestResolveUpdateImageRejectsLatestVersion(t *testing.T) {
}
}
func TestResolveInstallImagesRequiresFixedMaterialTag(t *testing.T) {
tests := []struct {
name string
image string
wantErr string
}{
{name: "missing", image: "", wantErr: envMaterialImage},
{name: "no tag", image: "registry.local:5000/material/flnxi-material", wantErr: "fixed version tag"},
{name: "latest", image: "registry.local:5000/material/flnxi-material:latest", wantErr: "latest is not allowed"},
{name: "fixed tag", image: "registry.local:5000/material/flnxi-material:1.0.1"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, _, _, err := resolveInstallImages(InstallRequest{MaterialImage: tt.image})
if tt.wantErr != "" {
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
t.Fatalf("resolveInstallImages() error = %v, want contains %q", err, tt.wantErr)
}
return
}
if err != nil {
t.Fatalf("resolveInstallImages() unexpected error: %v", err)
}
if got != tt.image {
t.Fatalf("resolveInstallImages() material = %q, want %q", got, tt.image)
}
})
}
}
func TestResolveInstallLicenseConfigRequiresMaterialRuntimeSecrets(t *testing.T) {
secrets := InstallSecrets{LocalEncryptionKey: strings.Repeat("b", 32)}
_, err := resolveInstallLicenseConfig(InstallRequest{}, secrets)
if err == nil {
t.Fatal("resolveInstallLicenseConfig() expected error")
}
for _, want := range []string{
envLicenseServerURL,
envLicenseProjectCode,
envLicenseRequestSigningSecret,
envLicensePublicKey,
} {
if !strings.Contains(err.Error(), want) {
t.Fatalf("resolveInstallLicenseConfig() error = %q, want %q", err.Error(), want)
}
}
}
func TestMaterialAppEnvIncludesLicenseRuntimeConfig(t *testing.T) {
req := InstallRequest{LicenseKey: "FLNXI-TEST"}
secrets := InstallSecrets{
DbUser: "flnxi",
DbPassword: "db-pass",
DbName: "flnxi",
MinioRootUser: "minio",
MinioRootPassword: "minio-pass",
S3Bucket: "materials",
NextAuthSecret: "next-secret",
LocalEncryptionKey: strings.Repeat("b", 32),
}
licenseConfig := InstallLicenseConfig{
ServerURL: "https://license.example.test",
ProjectCode: "flnxi-sucai",
RequestSigningSecret: strings.Repeat("a", 32),
PublicKey: "-----BEGIN PUBLIC KEY-----\\nabc\\n-----END PUBLIC KEY-----",
LocalEncryptionKey: secrets.LocalEncryptionKey,
}
env := envSliceToMap(materialAppEnv(req, secrets, licenseConfig, "192.168.1.20", 4320))
for _, want := range []string{
envLicenseServerURL,
envLicenseProjectCode,
envLicenseRequestSigningSecret,
envLicensePublicKey,
envLocalEncryptionKey,
"DATABASE_URL",
"S3_PUBLIC_DOMAIN",
"NEXTAUTH_URL",
"APP_PUBLIC_URL",
} {
if env[want] == "" {
t.Fatalf("materialAppEnv() missing %s in %v", want, env)
}
}
if env["APP_PUBLIC_URL"] != "http://192.168.1.20:4320" {
t.Fatalf("APP_PUBLIC_URL = %q, want host URL", env["APP_PUBLIC_URL"])
}
}
func TestRunInstallStopsBeforePullWhenLicenseConfigMissing(t *testing.T) {
resetInstallStatusForTest()
fake := &fakeInstallDocker{}
runInstall(fake, InstallRequest{MaterialImage: "registry.local:5000/material/flnxi-material:1.0.1"})
statusMutex.RLock()
status := *installStatus
statusMutex.RUnlock()
if status.Status != "failed" {
t.Fatalf("install status = %q, want failed", status.Status)
}
if !strings.Contains(status.Error, "许可证配置缺失") {
t.Fatalf("install error = %q, want license config error", status.Error)
}
if len(fake.pulledImages) != 0 {
t.Fatalf("pulled images = %v, want none before license config is valid", fake.pulledImages)
}
if len(fake.createdContainers) != 0 {
t.Fatalf("created containers = %v, want none before license config is valid", fake.createdContainers)
}
}
func TestRunUpdateRestoresOldContainerAfterHealthCheckFailure(t *testing.T) {
resetUpdateStatusForTest()
@ -116,6 +231,50 @@ func resetUpdateStatusForTest() {
statusMutex.Unlock()
}
func resetInstallStatusForTest() {
statusMutex.Lock()
installStatus = &InstallStatus{Status: "running", Step: "初始化", Progress: 0}
statusMutex.Unlock()
}
func envSliceToMap(values []string) map[string]string {
result := make(map[string]string, len(values))
for _, value := range values {
parts := strings.SplitN(value, "=", 2)
if len(parts) != 2 {
continue
}
result[parts[0]] = parts[1]
}
return result
}
type fakeInstallDocker struct {
pulledImages []string
createdContainers []string
}
func (f *fakeInstallDocker) PullImageWithProgress(ctx context.Context, image string, authStr string, onProgress func(current, total int64, status string)) error {
f.pulledImages = append(f.pulledImages, image)
if onProgress != nil {
onProgress(1, 1, "done")
}
return nil
}
func (f *fakeInstallDocker) ExecOnHost(ctx context.Context, cmd string) error {
return nil
}
func (f *fakeInstallDocker) CreateNetworkIfNotExists(ctx context.Context, name string) error {
return nil
}
func (f *fakeInstallDocker) CreateAndStartContainer(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, name string) (string, error) {
f.createdContainers = append(f.createdContainers, name)
return name + "-id", nil
}
type fakeUpdateDocker struct {
container *docker.ContainerInfo
healthErr error
@ -197,3 +356,4 @@ func contains(values []string, want string) bool {
}
var _ updateDockerClient = (*fakeUpdateDocker)(nil)
var _ installDockerClient = (*fakeInstallDocker)(nil)

View File

@ -7,13 +7,14 @@ import (
)
type InstallSecrets struct {
DbUser string
DbPassword string
DbName string
MinioRootUser string
MinioRootPassword string
S3Bucket string
NextAuthSecret string
DbUser string
DbPassword string
DbName string
MinioRootUser string
MinioRootPassword string
S3Bucket string
NextAuthSecret string
LocalEncryptionKey string
}
func generateInstallSecrets() (InstallSecrets, error) {
@ -32,14 +33,20 @@ func generateInstallSecrets() (InstallSecrets, error) {
return InstallSecrets{}, err
}
localEncryptionKey, err := randomHex(32)
if err != nil {
return InstallSecrets{}, err
}
return InstallSecrets{
DbUser: "flnxi",
DbPassword: dbPassword,
DbName: "flnxi",
MinioRootUser: "flnxi",
MinioRootPassword: minioPassword,
S3Bucket: "flnxi",
NextAuthSecret: nextAuthSecret,
DbUser: "flnxi",
DbPassword: dbPassword,
DbName: "flnxi",
MinioRootUser: "flnxi",
MinioRootPassword: minioPassword,
S3Bucket: "flnxi",
NextAuthSecret: nextAuthSecret,
LocalEncryptionKey: localEncryptionKey,
}, nil
}