Environment Configuration Reference (AWS)
AWS deployment environments (dev / prd, etc.) are defined in
infra/config/environments.ts (copied from environments.example.ts; forks
commit it). Settings resolve in this order: CLI -c flags > env entry > scale
defaults > built-in defaults. Note that -c only applies to environment
entry fields (scale / dbEngine / enableOpenSearch, etc.) — for
site-scoped fields (domainName / allowedIpRanges / basicAuth, etc.) the
-c channel is ignored in multi-site environments (preventing one -c
from stamping every site at once).
The top level of the file exports the CodeConnections connection ARN (shared by all envs) and, optionally, the account the pipelines are expected to be built in:
export const connectionArn = 'arn:aws:codeconnections:...:connection/...'export const pipelineAccount = '000000000000' // optional; validated against the active credentialsThe multi-site shape (declaring sites) is the standard way to create an
environment. Fields split into “environment entry” fields (shared resources +
CI/CD) and “site entry” fields (site-specific settings).
Account strategy (dev / prd)
Section titled “Account strategy (dev / prd)”Separate AWS accounts are recommended for prd vs dev (isolation of failures,
permissions, and billing; a contained blast radius). Setting a distinct account
per environment separates them at the account boundary.
Running multiple environments in one account is also supported (for evaluation /
small / cost-conscious setups), with one caveat: deploying the same commit to
dev and prd near-simultaneously can race on pushing the same tag to the CDK
bootstrap image ECR repository the two environments share (image tags are a hash
of the build content, so the same commit yields the same tag). The conflict is
transient and self-healing — re-running the failed deploy resolves it (the
already-pushed image is skipped). To avoid it for good, make that ECR
repository’s tags MUTABLE, or stagger the dev and prd deploys. See
docs/specs/en/phase4-deploy.md in the repository for the procedure.
Holding the pipeline in its own account
Section titled “Holding the pipeline in its own account”The account running CI/CD (CodePipeline) is chosen independently of the target
accounts. The pipeline deploys by assuming the bootstrap roles of the target
account, so keeping only the pipelines in a dedicated CI/CD account and dealing
dev / prd out to separate accounts is supported. For the setup this needs —
bootstrapping the target accounts, where the connection lives — see
docs/specs/en/phase4-deploy.md in the repository.
The top-level pipelineAccount is optional, but recommended once the accounts are
separated. Left unset, the pipeline is created in whichever account the credentials
running cdk deploy KukanPipeline belong to — run it from a prd session and a second
pipeline grows in prd. Set, synth stops when the credentials are for another account.
Note that with separate accounts the pipeline’s artifact bucket is encrypted with a KMS customer-managed key (decided automatically), adding roughly $1 per month per key.
Environment entry fields
Section titled “Environment entry fields”Settings for the shared resources (database, OpenSearch, VPC, ECS cluster) and CI/CD.
| Field | Type | Default | Description |
|---|---|---|---|
account |
string | required | Target AWS account ID. Misdeployment guard (CDK refuses to deploy with mismatched credentials) |
region |
string | ap-northeast-1 |
Target region |
scale |
small | medium | large |
small |
Deployment size (controls resource sizing as one knob) |
dbEngine |
rds | aurora |
scale-dependent (small=rds, medium/large=aurora) | Database engine |
enableOpenSearch |
boolean | true |
false → PostgreSQL full-text search fallback |
cpuArchitecture |
arm64 | x86_64 |
arm64 |
CPU of the web and worker tasks (Graviton by default). The images are built for it (see “CPU architecture” below) |
rdsCaCertificate |
rds-ca-rsa2048-g1 | rds-ca-rsa4096-g1 | rds-ca-ecc384-g1 |
rds-ca-rsa2048-g1 |
CA that issues the database’s server certificate, which the web and worker verify when they connect (see “Database certificate” below) |
bedrock |
object | false |
enabled (Titan v2) | Semantic search, AI metadata suggestions, and AI-written descriptions. false disables (AI_TYPE=none). Fields under “bedrock fields” below |
githubRepo |
string | none | CodeConnections source repository (owner/repo). Envs without it get no pipeline |
deployBranch |
string | main |
Branch that deploys this env in pipeline mode |
deployNotification |
boolean | none | Post deploy outcomes to Slack (pipeline mode only). The webhook URL goes into a secret the stack creates |
overrides |
deep-partial | none | Fine-grained overrides of the scale preset (see “overrides” below) |
sites |
SiteConfig[] | none (the legacy single-site shape) | The sites this environment hosts. Always declare it for new deployments (one entry is fine) |
deployConcurrency |
number | 2 |
Sites deployed at once after the canary. Their simultaneous rolling updates count against the database connection budget; synth fails when it does not fit |
ecrImageRetention |
number | 100 |
Images kept (newest first) in the CDK bootstrap ECR repository. Environments in one account share the repository, so give them the same value (synth fails otherwise) |
cdnLogRetentionDays |
number | 90 |
Days CloudFront access logs are kept (applies to every site in the environment) |
enableExecuteCommand |
boolean | false |
Every site’s default for ECS Exec; a site’s enableExecuteCommand wins (see “ECS Exec” below) |
bedrock fields
Section titled “bedrock fields”| Field | Type | Default | Description |
|---|---|---|---|
region |
string | the deployment region | Bedrock API region |
embeddingModel |
string | amazon.titan-embed-text-v2:0 |
Embedding model ID. Changing it needs a redeploy and regenerated embeddings |
embeddingDimensions |
number | adapter default (1024) | Embedding dimensions |
vectorMinSimilarity |
number | the model’s measured recommendation | Override of the similarity floor for semantic search |
completionModels |
string[] | ['jp.anthropic.claude-haiku-5-5'] |
Generation models the task role may InvokeModel. Also the dashboard’s model options; the first is the default for AI metadata suggestions. Needs a redeploy |
summaryModel |
string | none (no AI-written descriptions) | Model that writes AI descriptions (abstracts). Synth fails unless it is in completionModels |
CPU architecture
Section titled “CPU architecture”The web and worker tasks run on arm64 (Graviton) by default, which costs about 20% less on
Fargate than x86_64. Set cpuArchitecture: 'x86_64' for an environment that should run on
x86_64. It is an environment-level setting; it cannot differ per site, and -c cannot
override it.
- The pipeline builds the images on a CodeBuild of the tasks’ architecture (Tokyo and Osaka
have ARM). Set
x86_64for a pipeline in a Region without ARM CodeBuild (ARM_CONTAINER) - A standalone deploy can build images for an architecture other than the local machine’s.
Docker Desktop (Windows / Mac) needs nothing more. On Linux with Docker Engine alone, run
docker run --privileged --rm tonistiigi/binfmt --install arm64once - An existing environment switches over in an ordinary deploy (the tasks are replaced)
Database certificate
Section titled “Database certificate”The web and worker verify the server certificate on their TLS connections to RDS / Aurora
(POSTGRES_SSLMODE=verify-full). The CA bundle they check it against is in the images.
In a multi-site deployment, the Lambda that creates each site’s database verifies the certificate
too (against the CAs bundled with the Lambda runtime).
rdsCaCertificatepins the CA that issues the server certificate. Left out, the account’s default would apply, andmodify-certificatescan change that. The defaultrds-ca-rsa2048-g1is offered in every Region; the other two are not offered in some, such as Mumbai and Zurich- The bundle in the images covers every Region of the commercial partition. GovCloud and China Regions publish their own bundles, which it cannot verify (unsupported)
- On an existing environment whose instances use a CA other than
rdsCaCertificate, the deploy switches the CA and the database restarts - It is an environment-level setting (the database is shared by the environment’s sites);
-ccannot override it
Site entry fields (sites[])
Section titled “Site entry fields (sites[])”Site-specific settings. They cannot appear on the environment entry (synth
fails), except bedrock / overrides / enableExecuteCommand: there the environment value
is every site’s default, and the site’s value goes on top of it.
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | required | Site key (^[a-z][a-z0-9]{1,15}$), used in resource names kukan-<env>-<site>-* and database kukan_<site> |
brand |
string | default (the brand brands/default) |
Web image brand (KUKAN_BRAND). Defaults to default; omitting it and brand: 'default' are equivalent (the brands/default brand). Any other value requires a matching apps/web/brands/<brand>/ (an unknown brand fails the image build) |
albPriority |
number | derived from the site name | Listener rule priority on the shared ALB (ADR-049). Omit → a stable hash of the site name (1000–49999); set 1–999 explicitly on the site being added only when synth reports a collision |
domainName |
string | none | Custom domain (defaults to the CloudFront domain) |
hostedZoneId |
string | none | Route53 hosted zone ID (needed with domainName) |
hostedZoneName |
string | none | Route53 hosted zone name (same) |
certificateArn |
string | auto-created in standalone mode | us-east-1 ACM certificate ARN. Required in pipeline mode when domainName is set |
webAclArn |
string | auto-created in standalone mode | us-east-1 WAF WebACL ARN (sharable across sites). Required in pipeline mode when WAF is on |
enableWaf |
boolean | ON (OFF when allowedIpRanges / basicAuth set) |
WAF managed rules on CloudFront (~$9/month) |
allowedIpRanges |
string[] | none | IP restriction (CloudFront Function, IPv4 CIDR + IPv6) |
basicAuth |
{ username, password } |
none | Basic auth gate, OR-combined with allowedIpRanges (light gate only) |
enableIpv6Dns |
boolean | ON (OFF when allowedIpRanges set) |
An AAAA alias for the domain, so it is reached over IPv6 too. Behind allowedIpRanges, turn it on only once the list holds the IPv6 prefixes of every place it admits (a device admitted by IPv4 would come over IPv6 and get a 403) |
bucketName |
string | auto-named | S3 bucket name (globally unique auto-naming when omitted) |
enableGa4DataApi |
boolean | false |
GA4 access analytics dashboard |
nameSiteInUserAgent |
boolean | false |
Name the site’s URL in the worker’s User-Agent (USER_AGENT_URL), so operators of the servers it fetches from can reach you. Set true only on a site anyone may visit and search engines may index; synth rejects it alongside allowedIpRanges / basicAuth |
enableExecuteCommand |
boolean | the environment’s (else false) |
Allow ECS Exec into this site’s web and worker tasks. It may also be written on the environment entry, where it becomes every site’s default (see “ECS Exec” below) |
timeZone |
string | Asia/Tokyo |
IANA zone times are prerendered in; the browser then shows the viewer’s |
bedrock |
object | false |
the environment’s | Override of the environment’s bedrock (deep-merged; arrays replace). false turns AI off for this site alone. Synth fails when the environment has bedrock: false |
overrides |
partial | none | Site-owned sections only (see “overrides” below) |
If you later switch certificateArn / webAclArn to external ARNs, the
previously auto-created certificate / WebACL is not deleted (RemovalPolicy.RETAIN,
so deleting a resource CloudFront still references cannot fail the deploy). How
you clean up afterward depends on whether any managed resource remains:
- Only one of the certificate / WAF switched to an external ARN (the other stays auto-created): the GlobalStack remains, and only the switched resource leaves the template and is detached by RETAIN. Delete it manually if unneeded
- Both switched (i.e. the last managed resource):
needsGlobalStack=false, so the whole GlobalStack drops out of the assembly — no “remove the resource” update is ever sent, and the physical GlobalStack lingers still managing the resources. Deleting the certificate / WebACL directly here would drift the stack. Instead, after confirming RETAIN is persisted withget-template, delete the GlobalStack by physical stack name (RETAIN keeps the resources alive through the stack deletion), then delete the certificate / WebACL manually if they are genuinely unused (a WebACL keeps billing while it exists)
That retain policy is only persisted to CloudFormation by a deploy where the resource is still present in the template. So upgrading from an older version that predates this behavior and switching the ARN in the same deploy would remove the resource under its old (delete) policy and fail the deploy while CloudFront still references it. On existing environments, do it in two steps (environments created fresh on a version with this behavior carry RETAIN from the first deploy, so they can switch in one):
- Deploy the latest version first to persist RETAIN on the GlobalStack, then
confirm it landed with
aws cloudformation get-template(us-east-1) — the certificate / WebACL should showDeletionPolicy: Retain - Switch the ARN in a separate later deploy
ECS Exec
Section titled “ECS Exec”Opening a shell in the web and worker containers with aws ecs execute-command is off by
default. Set enableExecuteCommand: true on the entry of the site you investigate, and deploy.
- It is a site-level setting and applies to both the web and worker of that site. Only that site’s task roles get the ECS Exec permissions
- Written on the environment entry, it becomes every site’s default; a value on a site entry
wins. In the single-site shape (no
sites), write it on the environment entry -ccannot override it (the pipeline never sees-c, so a site that has it on says so in the config file)- A deploy changes only the service setting and the task role’s permissions, not the task
definition, so it does not replace the tasks. Whether ECS Exec works is decided when a task
starts
- Turned on: tasks started after the deploy accept sessions. To use it right away, replace
the tasks with
aws ecs update-service --cluster <cluster> --service <service> --force-new-deployment(or wait for the next image deploy) - Turned off: the task role loses the ECS Exec permissions, so new sessions cannot open
- Turned on: tasks started after the deploy accept sessions. To use it right away, replace
the tasks with
- A shell in a container can read the secret values injected as environment variables
- Who opened a session, when, and into which task is in the CloudTrail event history (the
ExecuteCommandmanagement event, 90 days). What is typed and shown inside the session is not recorded
overrides
Section titled “overrides”Fine-grained overrides of the scale preset. They apply as a deep merge — scale
defaults ← env overrides ← site overrides — and the allowed range differs
per level:
- Environment entry: every section (
web/worker/db/opensearch/dbPool/backup). Shared-resource sizing, DB retention, and the AWS Backup schedule are environment-level only - Site entry: site-owned sections only (
web/worker(excepthealthPort) /dbPool, plus the S3 versioning settings ofbackup). Overridingdb/opensearch/backup.awsBackup/backup.dbBackupRetentionDaysis rejected at synth
For the per-scale default values, see “Scale defaults” in
docs/specs/en/phase4-deploy.md in the repository.
Backward compatibility: the single-site shape
Section titled “Backward compatibility: the single-site shape”Every site entry field except name / brand / albPriority may also be written directly on
the environment entry — but only in an environment that does not declare
sites. This is backward compatibility with the earlier single-site
shape (the all-in-one stack) and exists for already-deployed environments.
- Do not use this shape for new deployments — declare
siteseven for a single site - Mixing the shapes (
sitesplus env-level site fields) is rejected at synth (exceptbedrock/overrides/enableExecuteCommand, the exceptions above) sitescannot be added to an already-deployed single-site-shape environment (that would replace resources; see the blue/green procedure in Multi-Site Operation)