Skip to content

Commit 13ade99

Browse files
SashaMITcursoragent
andcommitted
docs(infrastructure): reconcile acme.sh deploy paths + GoDaddy DNS backlog
Refreshes SSL_CERTIFICATES.md with the current post-2026-05-15 state of the wildcard cert stack on InterServer: - acme.sh now deploys directly to /etc/letsencrypt/live/ela.city/, the same path nginx reads from. Renewals reach nginx with no manual step. - Wildcard cert refreshed via forced renewal on 2026-05-15 21:09 UTC. Validity extended to 2026-08-13 (was 2026-07-27). - Two zombie certbot renewal configs (cloud.ela.city, demo.ela.city) for unused single-domain certs were moved aside earlier the same evening; no longer generating daily cron-failure noise. Snapshot directories and revert scripts saved on InterServer for both operations. Adds a new consolidated task at .cursor/tasks/GODADDY-DNS-BACKLOG-2026-05/ that groups the items still blocked on Sasha being back from travel with access to the Thailand SIM for GoDaddy SMS 2FA: 1. DNS: elastossmartchain.ela.city -> 38.242.211.112 (unblocks SEC-2026-04-22-WAVE6 A8 TLS pinning across 5 call sites) 2. DNS: rpc.ela.city -> 38.242.211.112 (unblocks SUPERNODE-RPC-PROXY for v1.2.8 default-RPC switch) 3. (optional) GoDaddy API credential rotation Includes verification commands and acceptance criteria. The cert deploy-path reconciliation (originally Item 3 of this backlog) is already complete and noted in the Completed Items section. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 01a55c4 commit 13ade99

2 files changed

Lines changed: 174 additions & 15 deletions

File tree

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Task: GoDaddy DNS Backlog — When Back From Travel
2+
3+
**Task ID**: GODADDY-DNS-BACKLOG-2026-05
4+
**Created**: 2026-05-15
5+
**Status**: Agreed (blocked on travel return)
6+
**Priority**: **HIGH** — items here are unblocking multiple downstream work streams
7+
**Owner**: Sasha (DNS access portion) + Agent (server-side portion)
8+
**Trigger to start**: Sasha back from current travel cycle with access to Thailand SIM for GoDaddy SMS 2FA
9+
10+
## Description
11+
12+
This task consolidates **all DNS-related work currently blocked** on GoDaddy access. GoDaddy is the DNS provider for `ela.city`, and SMS 2FA is tied to a Thailand-only phone number that's unreachable while Sasha is travelling internationally. Multiple in-flight workstreams are paused waiting on a single short DNS-management session.
13+
14+
This document is **the consolidated execution checklist** for when Sasha is back. Linked tasks remain authoritative for the deeper context of each item; this doc gives one place to look at the queue.
15+
16+
## Background
17+
18+
During the supernode RCE remediation (2026-05-15) and related infrastructure audit, two independent items were identified that share the same blocker — they need DNS changes at GoDaddy:
19+
20+
1. **TLS pinning fix** (security gap, SEC-2026-04-22-WAVE6 item A8) — switch 5 `rejectUnauthorized: false` call sites to proper TLS verification by introducing a named hostname instead of a raw IP.
21+
2. **Supernode RPC proxy** (decentralisation milestone, SUPERNODE-RPC-PROXY) — ship a hostname-fronted RPC endpoint so v1.2.8 PC2 nodes can stop depending on public Alchemy/Infura RPC.
22+
23+
A third item — reconciliation of acme.sh's deploy path with nginx's read path — was originally listed here but was **completed server-side on 2026-05-15** (no GoDaddy access was needed for it). See [§ Completed Items](#completed-items) below.
24+
25+
## Items In This Backlog
26+
27+
### 1. DNS: `elastossmartchain.ela.city``38.242.211.112`
28+
29+
| Field | Value |
30+
|---|---|
31+
| **Action** | Add A record at GoDaddy: `elastossmartchain.ela.city``38.242.211.112` (TTL 30 min) |
32+
| **Why** | Contabo serves a valid `*.ela.city` wildcard cert from this IP, but PC2 code currently connects by raw IP and therefore can't do TLS hostname verification. Adding any `*.ela.city` A record pointing at the IP enables hostname-based TLS. |
33+
| **Unblocks** | [SEC-2026-04-22-WAVE6-HARDENING](../SEC-2026-04-22-WAVE6-HARDENING/SEC-2026-04-22-WAVE6-HARDENING.md) Item A8 — switch 5 `rejectUnauthorized: false` call sites to verified TLS |
34+
| **Verify** | `dig +short elastossmartchain.ela.city` returns `38.242.211.112` after ~5 min |
35+
| **Post-action** | Agent runs the A8 code change: switches `hostname: '38.242.211.112'``hostname: 'elastossmartchain.ela.city'` in 5 places, removes 5 `rejectUnauthorized: false` flags, atomic commit, deploy via `scripts/deploy-supernode.sh` |
36+
37+
### 2. DNS: `rpc.ela.city``38.242.211.112`
38+
39+
| Field | Value |
40+
|---|---|
41+
| **Action** | Add A record at GoDaddy: `rpc.ela.city``38.242.211.112` (TTL 30 min) |
42+
| **Why** | Need a stable, branded hostname for the supernode-fronted Alchemy/Infura proxy so PC2 nodes can default to it rather than public RPC providers. |
43+
| **Unblocks** | [SUPERNODE-RPC-PROXY](../SUPERNODE-RPC-PROXY/SUPERNODE-RPC-PROXY.md) — deploy nginx → Alchemy/Infura proxy on Contabo, with cert via certbot DNS-01 |
44+
| **Verify** | `dig +short rpc.ela.city` returns `38.242.211.112` after ~5 min |
45+
| **Post-action** | Agent deploys `pc2-rpc-base.service` on Contabo, issues cert via certbot DNS-01 or extends wildcard coverage, updates `pc2-node/src/static.ts` to bake `https://rpc.ela.city/base` into default `BASE_RPC_URLS`. Ships in v1.2.8. |
46+
47+
### 3. (Optional) Verify / rotate GoDaddy API credentials
48+
49+
| Field | Value |
50+
|---|---|
51+
| **Action** | While in the GoDaddy dashboard already: review the Production API key. Confirm last-used date is recent (matching acme.sh renewals). Optionally rotate (issue new key, update `~/.acme.sh/account.conf`, revoke old). |
52+
| **Why** | Credential hygiene. API keys silent-fail on use don't always alert; periodic rotation reduces blast radius if leaked. |
53+
| **Verify** | After rotation: `/root/.acme.sh/acme.sh --renew -d '*.ela.city' --force` succeeds end-to-end (uses one of the 5/week Let's Encrypt rate-limit slots). |
54+
| **Optional** | This is "nice to have" not blocking. Skip if short on time during the visit. |
55+
56+
## Completed Items
57+
58+
### ✅ Cert deploy-path reconciliation (completed 2026-05-15)
59+
60+
Originally listed as Item 3 in this backlog. Did not require GoDaddy access. Completed server-side on 2026-05-15 21:09 UTC.
61+
62+
| Field | Value |
63+
|---|---|
64+
| **Action taken** | On InterServer: ran `acme.sh --install-cert -d '*.ela.city' --ecc --key-file /etc/letsencrypt/live/ela.city/privkey.pem --fullchain-file /etc/letsencrypt/live/ela.city/fullchain.pem --reloadcmd "systemctl reload nginx"` to update install paths. Then ran `acme.sh --renew -d '*.ela.city' -d 'ela.city' --force --ecc` to validate the end-to-end pipeline. |
65+
| **Outcome** | acme.sh now deploys to `/etc/letsencrypt/live/ela.city/` (same path nginx reads from). Forced renewal succeeded: fresh cert issued (serial `05EB0E...`), installed at the new path, nginx reloaded, external probe confirmed the new cert is served. Cert validity extended to **2026-08-13** (was 2026-07-27 before). |
66+
| **Snapshot** | `/root/acme-path-reconcile-20260515T210925Z/` on InterServer |
67+
| **Revert** | `/root/revert-acme-paths-20260515T210925Z.sh` (one-shot rollback if ever needed) |
68+
| **Verified** | Live HTTPS probes on `demo.ela.city`, `map.ela.city`, `sash.ela.city` all healthy post-change. All 4 critical services (pc2-gateway, pc2-cluster, pc2-network-map, nginx) active. |
69+
70+
## Suggested execution order when back
71+
72+
1. **Item 1** — add A record `elastossmartchain.ela.city`. Agent waits for propagation, then ships the A8 code change. ~15 min including code change + deploy.
73+
2. **Item 2** — add A record `rpc.ela.city`. Agent deploys `pc2-rpc-base.service`. ~30 min including config + cert + smoke.
74+
3. (Optional) **Item 3** — credential rotation. ~5 min.
75+
76+
**Total**: ~45–50 min including buffer for DNS propagation between items.
77+
78+
## Acceptance Criteria
79+
80+
- [ ] `dig +short elastossmartchain.ela.city` resolves to `38.242.211.112`
81+
- [ ] `dig +short rpc.ela.city` resolves to `38.242.211.112`
82+
- [ ] 5 `rejectUnauthorized: false` flags removed from PC2 codebase
83+
- [ ] `https://rpc.ela.city/base` serves valid JSON-RPC and is the default `BASE_RPC_URLS[0]` in `pc2-node/src/static.ts`
84+
- [x] **Forced acme.sh renewal lands in `/etc/letsencrypt/live/ela.city/` and nginx serves the new cert serial** _(done 2026-05-15)_
85+
- [ ] All affected services smoke-tested: `pc2-gateway`, `pc2-cluster`, `pc2-network-map`, `pc2-rpc-base` (Contabo), plus external HTTPS probes for `demo.ela.city`, `map.ela.city`, `elastossmartchain.ela.city`, `rpc.ela.city`
86+
87+
## Files Affected (anticipated)
88+
89+
- DNS records at GoDaddy (no repo file)
90+
- `pc2-node/src/static.ts` (Item 1, Item 2)
91+
- 4 additional call sites identified in SEC-2026-04-22-WAVE6 A8 (Item 1)
92+
- `pc2-node/src/index.ts` if RPC proxy default routing changes (Item 2)
93+
- `/etc/nginx/sites-available/pc2-rpc-base` on Contabo (Item 2) — server-side only
94+
- `/etc/systemd/system/pc2-rpc-base.service` on Contabo (Item 2) — server-side only
95+
- `/root/.acme.sh/*.ela.city_ecc/*.ela.city.conf` on InterServer (Item 3) — server-side only
96+
97+
## Testing Strategy
98+
99+
Each item has its own smoke tests; the consolidated suite for "all items complete" is:
100+
101+
```bash
102+
# Item 1 verification
103+
dig +short elastossmartchain.ela.city # → 38.242.211.112
104+
curl -fsS https://elastossmartchain.ela.city/rpc/esc -X POST \
105+
-H 'Content-Type: application/json' \
106+
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","id":1}' | head
107+
108+
# Item 2 verification
109+
dig +short rpc.ela.city # → 38.242.211.112
110+
curl -fsS https://rpc.ela.city/base -X POST \
111+
-H 'Content-Type: application/json' \
112+
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","id":1}' | head
113+
114+
# Item 3 verification
115+
echo | openssl s_client -servername demo.ela.city -connect demo.ela.city:443 2>/dev/null \
116+
| openssl x509 -noout -serial -dates # Fresh serial + new notBefore date
117+
```
118+
119+
## Linked Tasks
120+
121+
- [`SEC-2026-04-22-WAVE6-HARDENING`](../SEC-2026-04-22-WAVE6-HARDENING/SEC-2026-04-22-WAVE6-HARDENING.md) — A8 TLS pinning (Item 1 unblocks this)
122+
- [`SUPERNODE-RPC-PROXY`](../SUPERNODE-RPC-PROXY/SUPERNODE-RPC-PROXY.md) — Alchemy/Infura proxy (Item 2 unblocks this)
123+
- [`docs/pc2-infrastructure/SSL_CERTIFICATES.md`](../../../docs/pc2-infrastructure/SSL_CERTIFICATES.md) — current state of cert stack (Item 3 fixes the deploy-path mismatch flagged in §"Known Issues")
124+
125+
## Notes
126+
127+
- The acme.sh wildcard auto-renewal pipeline **is functioning** day-to-day (last successful renewal 2026-04-28); the deploy-path mismatch is a latent issue, not an active failure.
128+
- Two zombie certbot renewal configs (`cloud.ela.city`, `demo.ela.city`) were cleaned up on 2026-05-15. Revert script on InterServer at `/root/revert-cert-zombies-20260515T203915Z.sh` if ever needed.
129+
- GoDaddy API access is currently working (acme.sh credentials in `~/.acme.sh/account.conf`). No need to fetch new credentials unless rotating per Item 4.
130+
- Items 1 and 2 are independent — either order works. Item 3 has no DNS dependency and can be done first or in parallel.

docs/pc2-infrastructure/SSL_CERTIFICATES.md

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,32 @@
55
## Current Setup (Wildcard Certificate) ✅
66

77
### Certificate Details
8-
- **Provider**: Let's Encrypt
8+
- **Provider**: Let's Encrypt (ECDSA P-256)
99
- **Challenge**: DNS-01 (via GoDaddy API)
10-
- **Tool**: acme.sh
10+
- **Tool**: acme.sh (cron-scheduled, daily at 23:40 UTC)
1111
- **Scope**: `*.ela.city` + `ela.city` (wildcard)
12-
- **Location**: `/etc/nginx/ssl/wildcard/`
12+
- **Current cert**: issued **2026-05-15**, expires **2026-08-13** (90-day Let's Encrypt cycle, acme.sh auto-renews ~60 days in)
13+
- **Next renewal cycle**: tracked by acme.sh at `/root/.acme.sh/*.ela.city_ecc/*.ela.city.conf` (`Le_NextRenewTimeStr`)
14+
15+
### Certificate Files (post-acme.sh path reconciliation, 2026-05-15)
16+
17+
After the deploy-path reconciliation on 2026-05-15 ([§ Operational History](#operational-history-2026-05-15)), acme.sh deploys directly to the path nginx reads from. **No more cabinet mismatch.**
1318

14-
### Certificate Files
1519
```
16-
/etc/nginx/ssl/wildcard/
17-
├── ela.city.crt # Full chain certificate
18-
└── ela.city.key # Private key
20+
/etc/letsencrypt/live/ela.city/ ← acme.sh installs here ← nginx reads from here
21+
├── cert.pem # End-entity certificate
22+
├── fullchain.pem # End-entity + intermediate(s)
23+
└── privkey.pem # Private key (mode 0600)
24+
25+
/root/.acme.sh/*.ela.city_ecc/ ← acme.sh's internal source of truth (cert generation)
26+
├── *.ela.city.cer
27+
├── *.ela.city.key
28+
├── fullchain.cer
29+
└── *.ela.city.conf # has Le_RealKeyPath + Le_RealFullChainPath pointing at /etc/letsencrypt/live/ela.city/
1930
```
2031

32+
The pipeline is now fully autonomous: acme.sh's daily cron checks if renewal is due → if yes, issues a fresh cert from Let's Encrypt via the GoDaddy DNS-01 challenge → installs the new cert directly at `/etc/letsencrypt/live/ela.city/` → runs `systemctl reload nginx` to make it live. **No human in the loop.**
33+
2134
### Coverage
2235
**ALL** `*.ela.city` subdomains are automatically covered:
2336
- ✅ demo.ela.city
@@ -196,17 +209,33 @@ export GD_Secret='<secret>'
196209
197210
---
198211
199-
## Current Status
212+
## Current Status (2026-05-15)
200213
201214
| Item | Status |
202215
|------|--------|
203-
| Wildcard Certificate | ✅ Active (`*.ela.city`) |
204-
| Issuer | Let's Encrypt E7 |
205-
| Valid From | Jan 22, 2026 |
206-
| Valid Until | Apr 22, 2026 |
207-
| Auto-Renewal | ✅ Configured (acme.sh cron) |
208-
| HTTP→HTTPS Redirect | ✅ Enabled |
216+
| Wildcard Certificate (`*.ela.city`) | ✅ Active and served by nginx |
217+
| Issuer | Let's Encrypt E8 (ECDSA) |
218+
| Valid From | 2026-05-15 |
219+
| Valid Until | 2026-08-13 (90-day cycle) |
220+
| Auto-Renewal Tool | ✅ acme.sh cron (`40 23 * * *`) |
221+
| Renewal Method | DNS-01 via GoDaddy API (creds in `acme.sh` config) |
222+
| Front-end | nginx (since C-1, 2026-05-15) |
223+
| Read path | `/etc/letsencrypt/live/ela.city/fullchain.pem` |
224+
| Deploy path (acme.sh) | `/etc/letsencrypt/live/ela.city/` ✅ matches read path |
225+
| HTTP→HTTPS Redirect | ✅ nginx-managed (301 from `:80`) |
226+
| ACME challenge location block | ✅ `/.well-known/acme-challenge/` → `/var/www/html` (in `pc2-gateway` site) |
227+
| End-to-end renewal verified | ✅ Forced renewal 2026-05-15 succeeded; nginx serves the fresh cert serial |
228+
229+
## Operational History (2026-05-15)
230+
231+
The cert stack went through three coordinated changes on 2026-05-15, all reversible with on-server scripts:
232+
233+
1. **C-1 nginx fronting** (14:54–14:57 UTC) — InterServer's gateway migrated to live behind nginx. Brought TLS termination under nginx so the cert path could be standardised.
234+
2. **Zombie cleanup** (20:39 UTC) — Two pre-existing certbot renewal configs for unused single-domain certs (`cloud.ela.city`, `demo.ela.city`) were moved aside with `.disabled-<timestamp>` suffix. Both had been failing daily for weeks (port 80 collision); neither cert was actually used. Revert: `/root/revert-cert-zombies-20260515T203915Z.sh`. Snapshot: `/root/cert-zombies-cleanup-20260515T203915Z/`.
235+
3. **acme.sh deploy-path reconciliation** (21:09 UTC) — acme.sh's `Le_RealFullChainPath` and `Le_RealKeyPath` updated to point at `/etc/letsencrypt/live/ela.city/` instead of `/etc/nginx/ssl/wildcard/`. Followed by a forced renewal to validate end-to-end: a fresh cert was issued by Let's Encrypt, installed at the new path, and nginx auto-reloaded to serve it. The serial currently visible on the wire (`05EB0E...`, valid May 15 → Aug 13) confirms the pipeline works. Revert: `/root/revert-acme-paths-20260515T210925Z.sh`. Snapshot: `/root/acme-path-reconcile-20260515T210925Z/`.
236+
237+
Going forward, the wildcard cert auto-renews itself with no human in the loop. Expected cadence: acme.sh checks every day at 23:40 UTC, renews when the cert is ≤30 days from expiry (roughly day 60 of 90), deploys directly to nginx's read path, and reloads nginx — all autonomously.
209238
210239
---
211240
212-
*Last Updated: January 22, 2026*
241+
*Last Updated: 2026-05-15 21:15 UTC (post-reconciliation, end-to-end verified)*

0 commit comments

Comments
 (0)