Skip to content

Commit 0f81708

Browse files
committed
feat(documentation): add note for OPNsense firewall configuration and clarify deployment steps
1 parent a7039d7 commit 0f81708

1 file changed

Lines changed: 17 additions & 23 deletions

File tree

docs/getting-started.md

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ If you enabled the `connectivity.vpn` block, export the pre-shared keys as an en
134134
export TF_VAR_vpn_pre_shared_keys='{"onprem"={"tunnel1"="<20+ chars>","tunnel2"="<20+ chars>"}}'
135135
```
136136

137+
> [!NOTE]
138+
> If you deploy the provided OPNsense firewall make sure to follow [Configure OPNsense firewall](#configure-opnsense-firewall) afterwards. Until then the appliance filters nothing and its web GUI answers on the public IP.
139+
137140
In any case run opentofu to deploy the infrastructure:
138141

139142
```bash
@@ -242,33 +245,22 @@ What the policy does, and which traffic directions it can actually see, is in [W
242245
> [!NOTE]
243246
> The policy is pushed with the [`browningluke/opnsense`](https://registry.terraform.io/providers/browningluke/opnsense/latest/docs) provider. It maps OPNsense's expanded read format back to what was written, so in-place updates and drift detection work — the generic `Mastercard/restapi` provider cannot do this and makes objects effectively write-once. It is community maintained and its author advises against production use, so weigh that before relying on it.
244247
245-
**1. Decide which firewall interface OpenTofu should talk to**
246-
247-
*Public: OpenTofu runs outside the Network Area* — a workstation, or a CI runner on the public internet. This is the normal case for a first deployment, because nothing is inside the area yet. Traffic goes over the appliance's public address:
248-
249-
```bash
250-
tofu output connectivity_firewall_public_ip # the endpoint
251-
curl -s https://ifconfig.me # your own public address
252-
```
253-
254-
*Private: OpenTofu runs inside the Network Area* — a CI runner in a landing zone, a jumphost, or an established site-to-site VPN. Nothing to look up: the LAN address is the default, and your source address is already covered by `10.0.0.0/16`.
255-
256-
**2. Enable the policy**
248+
**1. Enable the policy**
257249

258250
Uncomment the `firewall_config` block in `config/hub-and-spoke-firewall.tfvars`. It comes with default rules: internet egress with NAT, spoke-to-spoke limited to HTTPS and ICMP, and the two floating rules that take the web GUI off the internet.
259251

260-
Two entries need your values, and what you put there follows from step 1:
252+
Two entries need your values:
261253

262254
```hcl
263-
# Example for public
255+
# Public: OpenTofu runs outside the Network Area* — a workstation, or a CI runner on the public internet. This is the normal case for a first deployment, because nothing is inside the area yet. Traffic goes over the appliance's public address:
264256
265-
endpoint = "https://<connectivity_firewall_public_ip>"
257+
endpoint = "https://<connectivity_firewall_public_ip>" # get it from running "tofu output connectivity_firewall_public_ip"
266258
fw_management = {
267-
content = ["10.0.0.0/16", "<your public address>/32"]
259+
content = ["10.0.0.0/16", "<your public address>/32"] # get it eg by running "curl -s https://ifconfig.me" or better use a fixed ip range
268260
}
269261
270262
271-
# Example for private
263+
# Private: OpenTofu runs inside the Network Area* — a CI runner in a landing zone, a jumphost, or an established site-to-site VPN. Nothing to look up: the LAN address is the default, and your source address is already covered by `10.0.0.0/16`:
272264
273265
# omit endpoint
274266
fw_management = {
@@ -281,20 +273,22 @@ fw_management = {
281273
>
282274
> A dynamic home or office address will eventually change and lock out a later run.
283275
284-
**3. Bootstrap the API key, then push the policy**
276+
**2. Bootstrap the API key, then push the policy**
285277

286278
```bash
287279
tofu apply -var firewall_bootstrap=true && tofu apply -var firewall_bootstrap=true
288280
```
289281

290-
The first pass derives the API key (waiting for the appliance to finish booting, which takes a few minutes) and caches it in `src/.firewall-api-credentials.json`, gitignored. The second stores it in the management Secrets Manager and pushes aliases, static routes, rules and NAT. Two passes are unavoidable: the provider needs the key at plan time, and a value created during an apply cannot configure a provider in that same run, which is why they chain safely as one command.
282+
The first `tofu apply` derives the API key (waiting for the appliance to finish booting, which takes a few minutes) and caches it in `src/.firewall-api-credentials.json`, gitignored. The second `tofu apply` stores it in the management Secrets Manager and pushes aliases, static routes, rules and NAT.
283+
284+
Two runs are unavoidable: the provider needs the key at plan time, and a value created during an apply cannot configure a provider in that same run.
291285

292286
The appliance login it uses comes from `firewall_admin_password`, which defaults to the `root` password baked into the STACKIT OPNsense image, so nothing has to be exported for a fresh deployment.
293287

294288
> [!IMPORTANT]
295-
> That default is baked into the image, and between the two applies the web GUI is reachable from the internet. Change the password on the appliance (**System → Access → Users**). The password is only used to derive the API key. Once the key exists, it is no longer read at all.
289+
> Change the password on the appliance (**System → Access → Users**). The password is only used to derive the API key. Once the key exists, it is no longer read at all.
296290
297-
**4. Drop the bootstrap variable and delete the cache file**
291+
**3. Drop the bootstrap variable and delete the cache file**
298292

299293
From here on every apply is a plain `tofu apply` with no variables:
300294

@@ -305,7 +299,7 @@ tofu apply
305299

306300
**Rotating the key**
307301

308-
Re-running the bootstrap revokes every existing API key on the appliance and mints a fresh one, which immediately invalidates the copy in the Secrets Manager. The follow-up is therefore not optional: bump `firewall_api_secret_version` by one, so the new key is written through. Forgetting the bump fails loudly with a 401 instead of silently keeping a dead key.
302+
Re-running the bootstrap revokes every existing API key on the appliance and mints a fresh one, which immediately invalidates the copy in the Secrets Manager. The follow-up is therefore not optional: bump `firewall_api_secret_version` by one, so the new key is written through. Forgetting the bump fails with a 401 instead of silently keeping a dead key.
309303

310304
```bash
311305
rm -f src/.firewall-api-credentials.json
@@ -315,7 +309,7 @@ tofu apply -var firewall_bootstrap=true # writes it to the Secrets Manager
315309
rm src/.firewall-api-credentials.json
316310
```
317311

318-
### DNS automation for Gateway API resources
312+
### Kubernetes: DNS automation for Gateway API resources
319313

320314
For Gateway API resources (for example Envoy Gateway with `Gateway` + `HTTPRoute`), use DNS records directly via `stackit_dns_record_set` until native provider support for `extensions.dns.gatewayApi` is available.
321315

0 commit comments

Comments
 (0)