Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ No modules.
| [cloudflare_dns_record.xnoto_dev_root](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/dns_record) | resource |
| [cloudflare_dns_record.xnoto_dev_www](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/dns_record) | resource |
| [cloudflare_ruleset.cache_rules](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/ruleset) | resource |
| [cloudflare_ruleset.response_headers](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/ruleset) | resource |
| [cloudflare_zero_trust_access_application.alertmanager](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/zero_trust_access_application) | resource |
| [cloudflare_zero_trust_access_application.grafana_alerts](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/zero_trust_access_application) | resource |
| [cloudflare_zero_trust_access_application.k3s](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/zero_trust_access_application) | resource |
Expand Down Expand Up @@ -101,3 +102,27 @@ This root owns only the bootstrap tunnel DNS required to reach the Kubernetes
API before cluster workloads are available. `TunnelBinding` owns workload
tunnel DNS, including the MCP gateway endpoints. Do not add a workload hostname
to this OpenTofu root.

## OpenCode HSTS

`cf-opencode-hsts.tf` configures the zone response-header ruleset with a rule
matching only HTTPS requests to `opencode.makeitwork.cloud`. It sets
`Strict-Transport-Security: max-age=86400` (one day), without
`includeSubDomains` or `preload`. Native OpenCode authentication and existing
HTTPS redirection are unchanged. No Cloudflare Access, workload DNS/tunnel,
or AWX cleanup is included.

This root owns the response-header entrypoint. Review and preserve its full
rule list before adding other header rules; do not create a competing
entrypoint or adopt an existing one without reviewing its rules. PR CI plans
validate the proposed changes; `main` runs a fresh environment-associated
apply, not the saved PR plan. Merge and apply authorization are separate.

After approved apply, verify the HTTPS UI and unauthenticated API responses
carry the header, native phone login and session continuity still work, and
sibling hostnames are unaffected. A successful plan is not live verification.

For rollback, first serve `max-age=0` over HTTPS through this rule, then remove
it after the rollback has been reviewed and applied. Simply removing the
header does not clear browser policies; they otherwise expire up to one day
after their last receipt. Preserve HTTPS throughout.
25 changes: 25 additions & 0 deletions cf-opencode-hsts.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
resource "cloudflare_ruleset" "response_headers" {
zone_id = local.zone_id
name = "Response header transforms"
description = "Hostname-scoped response security headers"
kind = "zone"
phase = "http_response_headers_transform"

rules = [
{
ref = "opencode_hsts"
action = "rewrite"
action_parameters = {
headers = {
"strict-transport-security" = {
operation = "set"
value = "max-age=86400"
}
}
}
expression = "(http.host eq \"opencode.makeitwork.cloud\" and http.request.scheme eq \"https\")"
description = "One-day HSTS for the OpenCode HTTPS hostname only"
enabled = true
}
]
}
Loading