Skip to content

Commit a682da4

Browse files
committed
docs: add issue specification for #413
1 parent b219a24 commit a682da4

1 file changed

Lines changed: 164 additions & 0 deletions

File tree

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Feature: Floating IP Support
2+
3+
**Issue**: #413
4+
**Parent Epic**: None
5+
**Related**: #405 - Deploy Hetzner Demo Tracker and Document the Process
6+
7+
## Overview
8+
9+
The deployer is not aware of **floating IPs** (also called static IPs, reserved IPs,
10+
or elastic IPs depending on the provider). A floating IP is an IP address owned
11+
independently of any specific server and can be reassigned between servers without
12+
changing DNS.
13+
14+
During the Hetzner Demo deployment (#405) floating IPs were used deliberately to allow
15+
zero-downtime failover and maintenance:
16+
17+
- **Instance IP**: `46.225.234.201` — the bare VM's IP, stored in the deployer's
18+
internal environment state after provisioning
19+
- **Floating IP**: `116.202.176.169` — the IP published in all DNS A records
20+
21+
The deployer has no concept of floating IPs. It records the instance IP during
22+
`provision` and uses that IP as the expected DNS target in the `test` command's
23+
DNS checks. Because DNS points to the floating IP, every domain in the environment
24+
triggers a false-positive warning during `test`:
25+
26+
```text
27+
⚠️ DNS check: api.torrust-tracker-demo.com resolves to [116.202.176.169]
28+
but expected 46.225.234.201
29+
```
30+
31+
This is not an error. The deployment works correctly — traffic reaches the server
32+
through the floating IP. The deployer simply lacks the notion of a separate "public"
33+
IP that differs from the provisioned instance IP.
34+
35+
The DNS setup for this deployment (floating IP assignment, VM network configuration,
36+
and DNS record creation) is documented in
37+
[docs/deployments/hetzner-demo-tracker/post-provision/dns-setup.md](../deployments/hetzner-demo-tracker/post-provision/dns-setup.md).
38+
39+
## Goals
40+
41+
- [ ] Allow users to specify a floating IP (or more generally, a public IP) that is
42+
separate from the instance IP in the environment configuration
43+
- [ ] Use the floating IP as the expected DNS target in `test` DNS checks when it
44+
is configured, eliminating false-positive warnings
45+
- [ ] Consider using the floating IP during provisioning to automatically assign it to
46+
the newly created instance (provider-dependent)
47+
- [ ] Expose the floating IP in `provision` and `Running` state output so operators
48+
can confirm which IP is serving traffic
49+
50+
## Specifications
51+
52+
### Motivation: Why Floating IPs?
53+
54+
Floating IPs decouple the publicly announced address from the physical server, providing:
55+
56+
1. **Zero-downtime failover**: If the primary server fails, the floating IP can be
57+
reassigned to a standby server in seconds. DNS TTLs are not a concern because the
58+
IP itself does not change.
59+
2. **Maintenance without downtime**: A new server can be fully provisioned and
60+
configured before traffic is cut over by reassigning the floating IP.
61+
62+
Other providers use different terminology for the same concept:
63+
64+
| Provider | Term |
65+
| ------------ | ---------------- |
66+
| Hetzner | Floating IP |
67+
| AWS | Elastic IP |
68+
| GCP | Reserved IP |
69+
| DigitalOcean | Reserved IP |
70+
| Azure | Static Public IP |
71+
72+
### Current Behavior (Limitation)
73+
74+
1. `provision` stores the instance IP in the environment state.
75+
2. `configure`, `release`, and `run` use the instance IP — no issue here since
76+
these commands operate on the instance directly.
77+
3. `test` resolves each domain via DNS and compares the result against the instance IP.
78+
When DNS points to a floating IP instead, the comparison fails and the deployer
79+
emits a warning for every domain.
80+
4. The deployer works correctly despite the warnings; the false positives are noise.
81+
82+
### Proposed Configuration Change
83+
84+
The environment config (or a provider-specific section) should accept an optional
85+
`public_ip` (or `floating_ip`) field:
86+
87+
```json
88+
"provider": {
89+
"name": "hetzner",
90+
"instance_ip": "46.225.234.201",
91+
"public_ip": "116.202.176.169"
92+
}
93+
```
94+
95+
When `public_ip` is present:
96+
97+
- The `test` command DNS checks compare resolved IPs against `public_ip`, not
98+
`instance_ip`.
99+
- The `provision` output includes `public_ip` alongside `instance_ip`.
100+
- Future: `provision` could automatically assign the floating IP to the instance
101+
via provider APIs.
102+
103+
### Current Workaround
104+
105+
Until this feature is implemented, `test` command DNS warnings can be safely ignored
106+
when floating IPs are in use. Verify manually that:
107+
108+
1. Each domain resolves to the expected floating IP.
109+
2. Services are reachable through those domains.
110+
111+
See [docs/deployments/hetzner-demo-tracker/commands/improvements.md](../deployments/hetzner-demo-tracker/commands/improvements.md)
112+
and [docs/deployments/hetzner-demo-tracker/post-provision/dns-setup.md](../deployments/hetzner-demo-tracker/post-provision/dns-setup.md)
113+
for the specific setup used in the Hetzner demo deployment.
114+
115+
## Implementation Plan
116+
117+
### Phase 1: Environment Config Schema
118+
119+
- [ ] Add optional `public_ip` field to the environment config schema
120+
(`schemas/environment-config.json`)
121+
- [ ] Parse and store `public_ip` in the environment domain types
122+
- [ ] Validate: if `public_ip` is present it must be a valid IPv4/IPv6 address
123+
124+
### Phase 2: `test` Command DNS Checks
125+
126+
- [ ] When `public_ip` is configured, use it as the expected target in DNS checks
127+
instead of the instance IP
128+
- [ ] Update warning/success messages to indicate which IP was expected and which
129+
IP was found
130+
- [ ] Add unit tests for the DNS check logic covering the floating-IP case
131+
132+
### Phase 3: `provision` Output
133+
134+
- [ ] Include `public_ip` in the `provision` command output when configured
135+
- [ ] Include `public_ip` in the `Running` state output
136+
137+
### Phase 4: Documentation
138+
139+
- [ ] Update the environment config user guide to document the `public_ip` field
140+
- [ ] Add a note in the provider guide explaining floating IP support
141+
142+
## Acceptance Criteria
143+
144+
> **Note for Contributors**: These criteria define what the PR reviewer will check.
145+
> Use this as your pre-review checklist before submitting the PR to minimize
146+
> back-and-forth iterations.
147+
148+
**Quality Checks**:
149+
150+
- [ ] Pre-commit checks pass: `./scripts/pre-commit.sh`
151+
152+
**Task-Specific Criteria**:
153+
154+
- [ ] `test` command emits no DNS warnings when `public_ip` is configured and DNS
155+
resolves to that IP
156+
- [ ] `provision` output includes `public_ip` when configured
157+
- [ ] Environment config schema validates `public_ip` as a valid IP address
158+
- [ ] Unit tests cover DNS check with and without `public_ip`
159+
- [ ] Documentation updated
160+
161+
## Related Documentation
162+
163+
- [docs/deployments/hetzner-demo-tracker/post-provision/dns-setup.md](../deployments/hetzner-demo-tracker/post-provision/dns-setup.md) — actual DNS setup using floating IPs
164+
- [docs/deployments/hetzner-demo-tracker/commands/improvements.md](../deployments/hetzner-demo-tracker/commands/improvements.md) — original field observation

0 commit comments

Comments
 (0)