@caelo-cms/provisioning 0.10.35 → 0.10.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter.d.ts +7 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/cli.js +81 -12
- package/dist/cli.js.map +1 -1
- package/dist/compose.d.ts +12 -0
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +12 -4
- package/dist/compose.js.map +1 -1
- package/dist/default-firewall.d.ts +45 -0
- package/dist/default-firewall.d.ts.map +1 -0
- package/dist/default-firewall.js +171 -0
- package/dist/default-firewall.js.map +1 -0
- package/dist/deployed-release.d.ts +5 -3
- package/dist/deployed-release.d.ts.map +1 -1
- package/dist/deployed-release.js +6 -4
- package/dist/deployed-release.js.map +1 -1
- package/dist/gateway-credentials.d.ts +42 -0
- package/dist/gateway-credentials.d.ts.map +1 -0
- package/dist/gateway-credentials.js +95 -0
- package/dist/gateway-credentials.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/install-state.d.ts +27 -0
- package/dist/install-state.d.ts.map +1 -1
- package/dist/install-state.js +67 -0
- package/dist/install-state.js.map +1 -1
- package/dist/lifecycle.d.ts +6 -0
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +225 -56
- package/dist/lifecycle.js.map +1 -1
- package/dist/runtime-secrets.d.ts +39 -2
- package/dist/runtime-secrets.d.ts.map +1 -1
- package/dist/runtime-secrets.js +77 -8
- package/dist/runtime-secrets.js.map +1 -1
- package/dist/self-hosted-roles.d.ts +64 -0
- package/dist/self-hosted-roles.d.ts.map +1 -0
- package/dist/self-hosted-roles.js +77 -0
- package/dist/self-hosted-roles.js.map +1 -0
- package/dist/stack-contract.d.ts +68 -3
- package/dist/stack-contract.d.ts.map +1 -1
- package/dist/stack-contract.js +69 -12
- package/dist/stack-contract.js.map +1 -1
- package/dist/stack-converge.d.ts +24 -18
- package/dist/stack-converge.d.ts.map +1 -1
- package/dist/stack-converge.js +47 -2
- package/dist/stack-converge.js.map +1 -1
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +4 -2
- package/dist/wizard.js.map +1 -1
- package/dist/wizards/gcp.d.ts.map +1 -1
- package/dist/wizards/gcp.js +64 -2
- package/dist/wizards/gcp.js.map +1 -1
- package/package.json +3 -3
- package/stacks/aws/README.md +1 -1
- package/stacks/aws/index.ts +20 -2
- package/stacks/azure/README.md +1 -1
- package/stacks/azure/index.ts +46 -7
- package/stacks/gcp/README.md +1 -1
- package/stacks/gcp/index.ts +25 -5
- package/stacks/gcp-firebase/index.ts +23 -2
- package/stacks/self-hosted/index.ts +26 -12
package/stacks/azure/index.ts
CHANGED
|
@@ -82,6 +82,11 @@ function randomHex(bytes: number): string {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
const postgresPassword = pulumi.secret(randomHex(32));
|
|
85
|
+
// #613 — one password per database role, so the gateway (public_role +
|
|
86
|
+
// gateway_role) never holds admin_role's. bootstrap.sh creates the roles
|
|
87
|
+
// with these (PUBLIC_ROLE_PASSWORD / GATEWAY_ROLE_PASSWORD).
|
|
88
|
+
const publicRolePassword = pulumi.secret(randomHex(32));
|
|
89
|
+
const gatewayRolePassword = pulumi.secret(randomHex(32));
|
|
85
90
|
const csrfSecret = pulumi.secret(randomHex(32));
|
|
86
91
|
const cookieSecret = pulumi.secret(randomHex(32));
|
|
87
92
|
const anthropicApiKey = pulumi.secret(process.env.ANTHROPIC_API_KEY ?? "");
|
|
@@ -110,6 +115,8 @@ function keyVaultSecret(shortName: string, value: pulumi.Output<string>): azure.
|
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
const _pgSecret = keyVaultSecret("pg-password", postgresPassword);
|
|
118
|
+
keyVaultSecret("public-role-password", publicRolePassword);
|
|
119
|
+
keyVaultSecret("gateway-role-password", gatewayRolePassword);
|
|
113
120
|
keyVaultSecret("csrf-secret", csrfSecret);
|
|
114
121
|
keyVaultSecret("cookie-secret", cookieSecret);
|
|
115
122
|
keyVaultSecret("anthropic-api-key", anthropicApiKey);
|
|
@@ -152,9 +159,18 @@ const _pgPublic = new azure.dbforpostgresql.Database(`${namePrefix}-cms-public-d
|
|
|
152
159
|
const adminDatabaseUrl = pulumi
|
|
153
160
|
.all([pgServer.fullyQualifiedDomainName, postgresPassword])
|
|
154
161
|
.apply(([host, pw]) => `postgresql://caelo_admin:${pw}@${host}:5432/cms_admin?sslmode=require`);
|
|
155
|
-
|
|
162
|
+
// What the admin connects to cms_public with (DDL, migrations, moderation).
|
|
163
|
+
const publicAdminDatabaseUrl = pulumi
|
|
156
164
|
.all([pgServer.fullyQualifiedDomainName, postgresPassword])
|
|
157
|
-
.apply(([host, pw]) => `postgresql://
|
|
165
|
+
.apply(([host, pw]) => `postgresql://caelo_admin:${pw}@${host}:5432/cms_public?sslmode=require`);
|
|
166
|
+
// The gateway's two logins (#613): public_role on cms_public and
|
|
167
|
+
// gateway_role on cms_admin, each with its own password.
|
|
168
|
+
const publicDatabaseUrl = pulumi
|
|
169
|
+
.all([pgServer.fullyQualifiedDomainName, publicRolePassword])
|
|
170
|
+
.apply(([host, pw]) => `postgresql://public_role:${pw}@${host}:5432/cms_public?sslmode=require`);
|
|
171
|
+
const gatewayDatabaseUrl = pulumi
|
|
172
|
+
.all([pgServer.fullyQualifiedDomainName, gatewayRolePassword])
|
|
173
|
+
.apply(([host, pw]) => `postgresql://gateway_role:${pw}@${host}:5432/cms_admin?sslmode=require`);
|
|
158
174
|
|
|
159
175
|
// === 4. Storage account + containers ===
|
|
160
176
|
const storage = new azure.storage.StorageAccount(`${namePrefix}-st`, {
|
|
@@ -215,6 +231,12 @@ const cappEnv = new azure.app.ManagedEnvironment(`${namePrefix}-capp-env`, {
|
|
|
215
231
|
|
|
216
232
|
interface ContainerAppArgs {
|
|
217
233
|
readonly serviceName: string;
|
|
234
|
+
/**
|
|
235
|
+
* The service's database connection env. The admin-side services get
|
|
236
|
+
* admin_role's URLs; the gateway gets only its own two logins (#613,
|
|
237
|
+
* CLAUDE.md §2 — never an admin_role credential).
|
|
238
|
+
*/
|
|
239
|
+
readonly databaseEnv: ReadonlyArray<{ name: string; value: pulumi.Input<string> }>;
|
|
218
240
|
readonly extraEnv?: ReadonlyArray<{ name: string; value: pulumi.Input<string> }>;
|
|
219
241
|
/** Defaults to 0.5 vCPU / 1 GiB. */
|
|
220
242
|
readonly resources?: { readonly cpu: number; readonly memory: string };
|
|
@@ -246,8 +268,7 @@ function containerApp(args: ContainerAppArgs): azure.app.ContainerApp {
|
|
|
246
268
|
env: [
|
|
247
269
|
{ name: "CAELO_PROVIDER", value: "azure" },
|
|
248
270
|
{ name: "CAELO_ENV", value: env },
|
|
249
|
-
|
|
250
|
-
{ name: "PUBLIC_ADMIN_DATABASE_URL", value: publicDatabaseUrl },
|
|
271
|
+
...args.databaseEnv,
|
|
251
272
|
{
|
|
252
273
|
name: "MEDIA_STORAGE_URL",
|
|
253
274
|
value: pulumi.interpolate`https://${storage.name}.blob.core.windows.net/media`,
|
|
@@ -261,18 +282,34 @@ function containerApp(args: ContainerAppArgs): azure.app.ContainerApp {
|
|
|
261
282
|
});
|
|
262
283
|
}
|
|
263
284
|
|
|
285
|
+
const adminDatabaseEnv = [
|
|
286
|
+
{ name: "ADMIN_DATABASE_URL", value: adminDatabaseUrl },
|
|
287
|
+
{ name: "PUBLIC_ADMIN_DATABASE_URL", value: publicAdminDatabaseUrl },
|
|
288
|
+
];
|
|
264
289
|
const adminApp = containerApp({
|
|
265
290
|
serviceName: "admin",
|
|
291
|
+
databaseEnv: adminDatabaseEnv,
|
|
266
292
|
resources: adminResources,
|
|
267
293
|
// #551 — the public site URL; the admin seeds site_defaults.site_base_url
|
|
268
294
|
// from it (canonical, og:url, sitemap) when it is not configured yet.
|
|
269
295
|
extraEnv: [{ name: "CAELO_SITE_URL", value: `https://${domain}` }],
|
|
270
296
|
});
|
|
271
|
-
const _gatewayApp = containerApp({
|
|
272
|
-
|
|
273
|
-
|
|
297
|
+
const _gatewayApp = containerApp({
|
|
298
|
+
serviceName: "gateway",
|
|
299
|
+
databaseEnv: [
|
|
300
|
+
{ name: "GATEWAY_DATABASE_URL", value: gatewayDatabaseUrl },
|
|
301
|
+
{ name: "PUBLIC_DATABASE_URL", value: publicDatabaseUrl },
|
|
302
|
+
],
|
|
303
|
+
});
|
|
304
|
+
const _orchestratorApp = containerApp({
|
|
305
|
+
serviceName: "orchestrator",
|
|
306
|
+
databaseEnv: adminDatabaseEnv,
|
|
307
|
+
});
|
|
308
|
+
const _runnerApp = containerApp({ serviceName: "runner", databaseEnv: adminDatabaseEnv });
|
|
274
309
|
const edgeRouterApp = containerApp({
|
|
275
310
|
serviceName: "edge-router",
|
|
311
|
+
// Serves the static site and the A/B routing manifest; no database.
|
|
312
|
+
databaseEnv: [],
|
|
276
313
|
extraEnv: [
|
|
277
314
|
{
|
|
278
315
|
name: "STATIC_BUCKET_URL",
|
|
@@ -304,6 +341,7 @@ const dnsRecordsRequired: DnsRecord[] = [
|
|
|
304
341
|
const out: CloudAdapterOutputs = {
|
|
305
342
|
adminDatabaseUrl: adminDatabaseUrl as unknown as string,
|
|
306
343
|
publicDatabaseUrl: publicDatabaseUrl as unknown as string,
|
|
344
|
+
gatewayDatabaseUrl: gatewayDatabaseUrl as unknown as string,
|
|
307
345
|
mediaStorageUrl:
|
|
308
346
|
pulumi.interpolate`https://${storage.name}.blob.core.windows.net/media` as unknown as string,
|
|
309
347
|
mediaCdnBaseUrl: pulumi.interpolate`https://${domain}/media` as unknown as string,
|
|
@@ -317,6 +355,7 @@ const out: CloudAdapterOutputs = {
|
|
|
317
355
|
|
|
318
356
|
export const adminDatabaseUrlOut = out.adminDatabaseUrl;
|
|
319
357
|
export const publicDatabaseUrlOut = out.publicDatabaseUrl;
|
|
358
|
+
export const gatewayDatabaseUrlOut = out.gatewayDatabaseUrl;
|
|
320
359
|
export const mediaStorageUrlOut = out.mediaStorageUrl;
|
|
321
360
|
export const mediaCdnBaseUrlOut = out.mediaCdnBaseUrl;
|
|
322
361
|
export const bootstrapUrlOut = out.bootstrapUrl;
|
package/stacks/gcp/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Pulumi stack provisioning Caelo on GCP managed services. Implements the shared `
|
|
|
11
11
|
| CDN | Cloud CDN backend bucket (operator wires the URL map + load balancer for v1; full LB in P15 review-pass) |
|
|
12
12
|
| Edge compute (A/B + redirects) | Cloud Run service `<env>-edge-router` running `edge-handler.ts` with `@caelo-cms/edge-router` |
|
|
13
13
|
| Container runtime | Four Cloud Run services (admin / gateway / orchestrator / runner) |
|
|
14
|
-
| Secret store | Secret Manager: postgres-password + secret-kek (Pulumi)
|
|
14
|
+
| Secret store | Secret Manager: postgres-password (admin_role) + secret-kek (Pulumi); internal-secret, tool-approval-secret, public-role-password and gateway-role-password (created by the CLI before `pulumi up`, see `src/runtime-secrets.ts`). Cloud Run reads each as a `secretKeyRef`; database URLs carry no password. The gateway's service account reads only the two gateway role passwords (#613); `gateway_role` itself is created by migration 0248 and gets its password from the CLI after migrations. |
|
|
15
15
|
| Edge-log sink | Cloud Logging project sink → BigQuery dataset `<env>_edge_logs` (queryable by P12A analytics plugin) |
|
|
16
16
|
|
|
17
17
|
The Caelo runtime never knows it's on GCP — every Cloud Run service consumes plain `DATABASE_URL` / `MEDIA_STORAGE_URL` / `SECRETS_PROVIDER` env vars.
|
package/stacks/gcp/index.ts
CHANGED
|
@@ -245,8 +245,22 @@ const runtimeSecretIds: Record<RuntimeSecret, pulumi.Input<string>> = {
|
|
|
245
245
|
"secret-kek": kekSecret.resource.secretId,
|
|
246
246
|
"internal-secret": gcpSecretId(env, "internal-secret"),
|
|
247
247
|
"tool-approval-secret": gcpSecretId(env, "tool-approval-secret"),
|
|
248
|
+
"public-role-password": gcpSecretId(env, "public-role-password"),
|
|
249
|
+
"gateway-role-password": gcpSecretId(env, "gateway-role-password"),
|
|
248
250
|
};
|
|
249
251
|
|
|
252
|
+
// #613 — public_role's own password (CLI-generated, stack-contract.ts
|
|
253
|
+
// DATABASE_ROLE_SECRET), so the gateway, which reads it, never holds
|
|
254
|
+
// admin_role's. gateway_role is not declared here: migration 0248 creates
|
|
255
|
+
// it in SQL (an API-created user would join cloudsqlsuperuser) and the CLI
|
|
256
|
+
// sets its password after migrations.
|
|
257
|
+
const publicRolePassword = pulumi.secret(
|
|
258
|
+
gcp.secretmanager.getSecretVersionOutput(
|
|
259
|
+
{ project, secret: gcpSecretId(env, "public-role-password") },
|
|
260
|
+
{ provider: gcpProvider },
|
|
261
|
+
).secretData,
|
|
262
|
+
);
|
|
263
|
+
|
|
250
264
|
// =========================================================================
|
|
251
265
|
// Tier 4 — Cloud SQL Postgres (private IP only; HA + retention configurable)
|
|
252
266
|
// =========================================================================
|
|
@@ -307,7 +321,7 @@ const pgAdminUser = new gcp.sql.User(
|
|
|
307
321
|
|
|
308
322
|
const pgPublicUser = new gcp.sql.User(
|
|
309
323
|
`${namePrefix}-pg-public`,
|
|
310
|
-
{ instance: sqlInstance.name, name: "public_role", password:
|
|
324
|
+
{ instance: sqlInstance.name, name: "public_role", password: publicRolePassword },
|
|
311
325
|
opts,
|
|
312
326
|
);
|
|
313
327
|
|
|
@@ -631,7 +645,12 @@ const envContractInputs = {
|
|
|
631
645
|
env,
|
|
632
646
|
domain,
|
|
633
647
|
region,
|
|
634
|
-
databaseUrls: {
|
|
648
|
+
databaseUrls: {
|
|
649
|
+
admin: dbUrls.admin,
|
|
650
|
+
publicAdmin: dbUrls.publicAdmin,
|
|
651
|
+
public: dbUrls.public,
|
|
652
|
+
gateway: dbUrls.gateway,
|
|
653
|
+
},
|
|
635
654
|
} as const;
|
|
636
655
|
|
|
637
656
|
function cloudRunService(args: CloudRunArgs): gcp.cloudrunv2.Service {
|
|
@@ -721,9 +740,8 @@ const gatewaySvc = cloudRunService({
|
|
|
721
740
|
minInstances: gatewayMinInstances,
|
|
722
741
|
maxInstances: 100,
|
|
723
742
|
memory: "512Mi",
|
|
724
|
-
// public_role on cms_public
|
|
725
|
-
//
|
|
726
|
-
// SERVICE_SECRET_ENV.gateway).
|
|
743
|
+
// public_role on cms_public + gateway_role on cms_admin, each with its
|
|
744
|
+
// own password; never admin_role (#613, CLAUDE.md §2).
|
|
727
745
|
contractEnv: gatewayEnvContract(envContractInputs),
|
|
728
746
|
});
|
|
729
747
|
|
|
@@ -1116,6 +1134,7 @@ const out: CloudAdapterOutputs = {
|
|
|
1116
1134
|
// Password-less — the password lives only in Secret Manager.
|
|
1117
1135
|
adminDatabaseUrl: dbUrls.admin as unknown as string,
|
|
1118
1136
|
publicDatabaseUrl: dbUrls.public as unknown as string,
|
|
1137
|
+
gatewayDatabaseUrl: dbUrls.gateway as unknown as string,
|
|
1119
1138
|
mediaStorageUrl: pulumi.interpolate`gs://${mediaBucket.name}` as unknown as string,
|
|
1120
1139
|
mediaCdnBaseUrl: pulumi.interpolate`https://${domain}/media` as unknown as string,
|
|
1121
1140
|
bootstrapUrl:
|
|
@@ -1129,6 +1148,7 @@ const out: CloudAdapterOutputs = {
|
|
|
1129
1148
|
|
|
1130
1149
|
export const adminDatabaseUrlOut = out.adminDatabaseUrl;
|
|
1131
1150
|
export const publicDatabaseUrlOut = out.publicDatabaseUrl;
|
|
1151
|
+
export const gatewayDatabaseUrlOut = out.gatewayDatabaseUrl;
|
|
1132
1152
|
export const mediaStorageUrlOut = out.mediaStorageUrl;
|
|
1133
1153
|
export const mediaCdnBaseUrlOut = out.mediaCdnBaseUrl;
|
|
1134
1154
|
export const bootstrapUrlOut = out.bootstrapUrl;
|
|
@@ -219,8 +219,22 @@ const runtimeSecretIds: Record<RuntimeSecret, pulumi.Input<string>> = {
|
|
|
219
219
|
"secret-kek": kekSecret.resource.secretId,
|
|
220
220
|
"internal-secret": gcpSecretId(env, "internal-secret"),
|
|
221
221
|
"tool-approval-secret": gcpSecretId(env, "tool-approval-secret"),
|
|
222
|
+
"public-role-password": gcpSecretId(env, "public-role-password"),
|
|
223
|
+
"gateway-role-password": gcpSecretId(env, "gateway-role-password"),
|
|
222
224
|
};
|
|
223
225
|
|
|
226
|
+
// #613 — public_role's own password (CLI-generated, stack-contract.ts
|
|
227
|
+
// DATABASE_ROLE_SECRET), so the gateway, which reads it, never holds
|
|
228
|
+
// admin_role's. gateway_role is not declared here: migration 0248 creates
|
|
229
|
+
// it in SQL (an API-created user would join cloudsqlsuperuser) and the CLI
|
|
230
|
+
// sets its password after migrations.
|
|
231
|
+
const publicRolePassword = pulumi.secret(
|
|
232
|
+
gcp.secretmanager.getSecretVersionOutput(
|
|
233
|
+
{ project, secret: gcpSecretId(env, "public-role-password") },
|
|
234
|
+
{ provider: gcpProvider },
|
|
235
|
+
).secretData,
|
|
236
|
+
);
|
|
237
|
+
|
|
224
238
|
// =========================================================================
|
|
225
239
|
// Tier 4 — Cloud SQL Postgres (private IP only; HA configurable)
|
|
226
240
|
// =========================================================================
|
|
@@ -279,7 +293,7 @@ const pgAdminUser = new gcp.sql.User(
|
|
|
279
293
|
);
|
|
280
294
|
new gcp.sql.User(
|
|
281
295
|
`${namePrefix}-public-user`,
|
|
282
|
-
{ instance: sqlInstance.name, name: "public_role", password:
|
|
296
|
+
{ instance: sqlInstance.name, name: "public_role", password: publicRolePassword },
|
|
283
297
|
opts,
|
|
284
298
|
);
|
|
285
299
|
|
|
@@ -576,7 +590,12 @@ const envContractInputs = {
|
|
|
576
590
|
env,
|
|
577
591
|
domain,
|
|
578
592
|
region,
|
|
579
|
-
databaseUrls: {
|
|
593
|
+
databaseUrls: {
|
|
594
|
+
admin: dbUrls.admin,
|
|
595
|
+
publicAdmin: dbUrls.publicAdmin,
|
|
596
|
+
public: dbUrls.public,
|
|
597
|
+
gateway: dbUrls.gateway,
|
|
598
|
+
},
|
|
580
599
|
} as const;
|
|
581
600
|
|
|
582
601
|
// Gateway provisioned first so we can pass its name/region into the
|
|
@@ -947,6 +966,7 @@ const out: CloudAdapterOutputs = {
|
|
|
947
966
|
// Password-less — the password lives only in Secret Manager.
|
|
948
967
|
adminDatabaseUrl: dbUrls.admin as unknown as string,
|
|
949
968
|
publicDatabaseUrl: dbUrls.public as unknown as string,
|
|
969
|
+
gatewayDatabaseUrl: dbUrls.gateway as unknown as string,
|
|
950
970
|
mediaStorageUrl: pulumi.interpolate`gs://${mediaBucket.name}` as unknown as string,
|
|
951
971
|
// Firebase Hosting serves media via its own CDN; we proxy through
|
|
952
972
|
// the Firebase site's apex domain for canonical URLs.
|
|
@@ -963,6 +983,7 @@ const out: CloudAdapterOutputs = {
|
|
|
963
983
|
|
|
964
984
|
export const adminDatabaseUrlOut = out.adminDatabaseUrl;
|
|
965
985
|
export const publicDatabaseUrlOut = out.publicDatabaseUrl;
|
|
986
|
+
export const gatewayDatabaseUrlOut = out.gatewayDatabaseUrl;
|
|
966
987
|
export const mediaStorageUrlOut = out.mediaStorageUrl;
|
|
967
988
|
export const mediaCdnBaseUrlOut = out.mediaCdnBaseUrl;
|
|
968
989
|
export const bootstrapUrlOut = out.bootstrapUrl;
|
|
@@ -42,21 +42,35 @@ const tokenPath = resolve(caeloDir, "pending-token.json");
|
|
|
42
42
|
// in the state file; `pulumi stack output --show-secrets postgresPassword`
|
|
43
43
|
// is the operator's recovery path.
|
|
44
44
|
const postgresPassword = pulumi.secret(randomHex(32));
|
|
45
|
+
// #613 — one password per application role; the gateway gets only the
|
|
46
|
+
// public_role and gateway_role ones.
|
|
47
|
+
const adminRolePassword = pulumi.secret(randomHex(32));
|
|
48
|
+
const publicRolePassword = pulumi.secret(randomHex(32));
|
|
49
|
+
const gatewayRolePassword = pulumi.secret(randomHex(32));
|
|
45
50
|
const minioRootUser = "caelo";
|
|
46
51
|
const minioRootPassword = pulumi.secret(randomHex(32));
|
|
47
52
|
|
|
48
|
-
const composeYaml = pulumi
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
const composeYaml = pulumi
|
|
54
|
+
.all([
|
|
55
|
+
postgresPassword,
|
|
56
|
+
minioRootPassword,
|
|
57
|
+
adminRolePassword,
|
|
58
|
+
publicRolePassword,
|
|
59
|
+
gatewayRolePassword,
|
|
60
|
+
])
|
|
61
|
+
.apply(([pgPw, minioPw, adminPw, publicPw, gatewayPw]) =>
|
|
62
|
+
generateDockerCompose({
|
|
63
|
+
domain,
|
|
64
|
+
postgresPassword: pgPw,
|
|
65
|
+
rolePasswords: { admin: adminPw, public: publicPw, gateway: gatewayPw },
|
|
66
|
+
minioRootUser,
|
|
67
|
+
minioRootPassword: minioPw,
|
|
68
|
+
anthropicApiKey: process.env.ANTHROPIC_API_KEY,
|
|
69
|
+
resendApiKey: process.env.RESEND_API_KEY,
|
|
70
|
+
diskSize: "20Gi",
|
|
71
|
+
...(adminMemory ? { adminMemory } : {}),
|
|
72
|
+
}),
|
|
73
|
+
);
|
|
60
74
|
|
|
61
75
|
const caddyConf = generateCaddyfile({
|
|
62
76
|
ownerEmail,
|