main
md 228 lines 7.42 KB
Rendered Raw
1 ---
2 title: Wallet and ENS
3 description: How Portal uses local identities, admin tokens, SIWE, and ENS gasless DNS import.
4 ---
5
6 # Wallet and ENS
7
8 Portal uses Ethereum-style signatures in several different places. They are
9 related, but they do not all mean "connect a browser wallet".
10
11 ## Identity Surfaces
12
13 | Surface | Key material | Purpose |
14 |---------|--------------|---------|
15 | Tunnel identity | Local `identity.json` secp256k1 private key, or BIP-39 mnemonic plus derivation path | Signs SIWE lease registration challenges |
16 | Relay identity | Relay `IDENTITY_PATH/identity.json` secp256k1 private key, or BIP-39 mnemonic plus derivation path | Signs relay descriptors, lease access tokens, and ENS base-domain address |
17 | Relay admin token | `ADMIN_TOKEN` | Signs in to `/admin` and authorizes relay policy changes |
18 | Agent wallet | Optional browser wallet allowlist | Reads loopback agent status through `/agent/status` |
19 | ENS gasless DNS | DNSSEC plus `ENS1 ...` TXT records | Lets ENS-aware clients resolve the relay domain and lease hostnames to Portal identities |
20
21 ## Tunnel SIWE Registration
22
23 Tunnel registration always uses a SIWE challenge internally:
24
25 1. The tunnel creates or loads a local identity from `identity.json`.
26 2. The tunnel asks the relay for `/sdk/register/challenge`.
27 3. The relay returns a SIWE message with statement `Register a portal lease`.
28 4. The tunnel signs that message with the local identity private key using
29 Ethereum `personal_sign` semantics.
30 5. The relay verifies the signature and returns a lease-scoped access token.
31 6. The access token is used for renew, unregister, reverse connect, keyless
32 signing access, and UDP backhaul authentication.
33
34 This does not require MetaMask or a user wallet. It is accountless identity
35 proof based on the local tunnel key. `identity.json` may store a raw
36 `private_key`, or a BIP-39 `mnemonic` with `derivation_path` such as
37 `m/44'/60'/0'/0/0`.
38
39 There is no `--auth siwe` flag. The current CLI command is:
40
41 ```bash
42 portal expose 3000 --name myapp
43 ```
44
45 Use a stable identity path when the lease identity must survive working
46 directory changes:
47
48 ```bash
49 portal expose 3000 \
50 --name myapp \
51 --identity-path ~/.config/portal/myapp.identity.json
52 ```
53
54 The public lease name is a single DNS label such as `myapp`. It is not an ENS
55 name such as `alice.eth`.
56
57 ## Relay Admin Token Login
58
59 The relay admin API uses a configured token. Set `ADMIN_TOKEN` to a long random
60 value before exposing the admin UI or policy API.
61
62 Example:
63
64 ```bash
65 ADMIN_TOKEN=$(openssl rand -hex 32)
66 ```
67
68 Admin token flow:
69
70 1. `POST /api/admin/auth/login` with `{ "token": "<admin-token>" }`.
71 2. The relay returns an `access_token`.
72 3. Admin endpoints require `Authorization: Bearer <access_token>`.
73
74 The token returned by login is the configured admin token; browser logout clears
75 the local stored token.
76
77 ## Agent Wallet Login
78
79 The local agent also exposes SIWE wallet auth endpoints:
80
81 ```text
82 /agent/auth/challenge
83 /agent/auth/login
84 /agent/auth/logout
85 /agent/auth/status
86 ```
87
88 Agent wallet access is intentionally narrow:
89
90 - `agent.allowed_wallets` restricts which wallet addresses can sign in.
91 - when `allowed_wallets` is empty, any wallet can sign in to the loopback auth
92 endpoint.
93 - wallet-authenticated requests can read `/agent/status`.
94 - config mutation, tunnel changes, relay changes, shutdown, and multi-hop edits
95 still require the bearer token in `<state_dir>/agent-endpoint.json`.
96
97 Example:
98
99 ```toml
100 [agent]
101 allowed_wallets = ["0x1234567890abcdef1234567890abcdef12345678"]
102 ```
103
104 See [Portal Agent](/portal-agent) for the control API details.
105
106 ## ENS Gasless DNS Import
107
108 ENS gasless DNS import is optional relay-side DNS automation. It is separate
109 from tunnel registration and admin token login.
110
111 When enabled, Portal uses the configured DNS provider to:
112
113 - enable or inspect DNSSEC for the relay base domain
114 - publish `ENS1 ...` TXT records for the base domain
115 - publish `ENS1 ...` TXT records for lease hostnames
116 - keep A records for lease hostnames in sync with the relay public IPv4
117 - remove lease hostname records when leases unregister or expire
118
119 Portal writes TXT values in this shape:
120
121 ```text
122 ENS1 0x238A8F792dFA6033814B18618aD4100654aeef01 <address>
123 ```
124
125 The base-domain address is the relay identity address. Lease hostname addresses
126 come from the tunnel identity that registered each lease.
127
128 ENS gasless automation does not perform an onchain ENS claim transaction. It
129 only prepares DNSSEC-backed DNS records for ENS-aware clients.
130
131 ## Enable ENS Gasless
132
133 Requirements:
134
135 - public relay domain, not `localhost`
136 - `ACME_DNS_PROVIDER=cloudflare`, `gcloud`, `route53`, or `vultr`
137 - provider credentials with DNS write access
138 - `ENS_GASLESS_ENABLED=true`
139 - DNSSEC active at the parent zone
140
141 Hetzner and Njalla are supported for managed ACME DNS automation, but not for ENS gasless automation because Portal does not automate DNSSEC signing for those providers.
142
143 Example:
144
145 ```bash
146 PORTAL_URL=https://portal.example.com
147 IDENTITY_PATH=/portal-certs
148 ACME_DNS_PROVIDER=cloudflare
149 CLOUDFLARE_TOKEN=cf_xxxxxxxxxxxxxxxxx
150 ENS_GASLESS_ENABLED=true
151 ```
152
153 The same provider is used for ACME DNS-01, managed A records, ECH HTTPS records,
154 DNSSEC, and ENS TXT records. If manual `fullchain.pem` and `privatekey.pem`
155 already exist under `IDENTITY_PATH`, Portal keeps using those certificate files
156 and still uses the provider for ENS/DNS automation.
157
158 ## DNSSEC And Registrar State
159
160 DNSSEC has two sides:
161
162 - the DNS provider signs the hosted zone
163 - the registrar publishes the DS record at the parent zone
164
165 Portal can automate provider-side setup for supported providers. It cannot
166 always publish the registrar-side DS record. If `/sdk/domain` reports a pending
167 DNSSEC state and a `ds_record`, copy that DS record into the registrar's DNSSEC
168 settings and wait for propagation.
169
170 ## Check ENS Status
171
172 The relay exposes ENS status through `/sdk/domain`:
173
174 ```bash
175 curl https://portal.example.com/sdk/domain
176 ```
177
178 Relevant response fields:
179
180 | Field | Meaning |
181 |-------|---------|
182 | `ens.enabled` | ENS gasless automation is enabled for a non-local relay domain |
183 | `ens.verified` | Portal considers DNSSEC active and the last sync successful |
184 | `ens.provider` | DNS provider used for automation |
185 | `ens.address` | Base-domain ENS address, usually the relay identity address |
186 | `ens.dnssec_state` | Provider DNSSEC state |
187 | `ens.ds_record` | DS record that may need registrar publication |
188 | `ens.message` | Provider-specific DNSSEC guidance |
189 | `ens.last_error` | Last ENS/DNS sync error |
190
191 The relay frontend shows an `ENS verified` badge when `ens.verified` is true.
192
193 DNS checks:
194
195 ```bash
196 dig +short DS portal.example.com
197 dig +short TXT portal.example.com
198 dig +short TXT myapp.portal.example.com
199 ```
200
201 Expected TXT records start with `ENS1`.
202
203 ## Troubleshooting
204
205 `ENS_GASLESS_ENABLED=true` fails at startup:
206
207 - set `ACME_DNS_PROVIDER`
208 - provide the provider credentials
209 - use a public `PORTAL_URL`, not localhost
210
211 `ens.verified` stays false:
212
213 - publish the DS record at the registrar
214 - wait for DNSSEC propagation
215 - check `ens.last_error` from `/sdk/domain`
216 - confirm the provider token can edit DNS records
217
218 A lease hostname has no ENS TXT record:
219
220 - confirm the tunnel is registered and not expired
221 - confirm the hostname is under the relay base domain
222 - check relay logs for `ensure ens gasless txt` or provider errors
223
224 ## Next Steps
225
226 - [Deployment](/deployment#ens-gasless-automation): production setup
227 - [Security Model](/security-model): identity and TLS trust boundaries
228 - [Portal Agent](/portal-agent): local durable tunnel management