Porturi și preview-uri
Ajungi la un server de dezvoltare din mediu printr-un URL de preview sau o redirecționare locală de port și decizi cine îl poate deschide.
Orice port care ascultă în mediu este raportat de daemon la fiecare 15 secunde. Nimic nu e accesibil din exterior până nu îl publici cu o vizibilitate; abia atunci primește un URL de preview pe preview.codai.ro și poate fi redirecționat pe mașina ta. Tot traficul circulă prin WebSocket-ul de ieșire al daemonului — mediul nu deschide niciodată un port de intrare.
URL-uri de preview
https://{port}-{slug}.preview.codai.ro/
3000-brivio-k3xq.preview.codai.roslug este slug-ul mediului, unic la nivel global (3–40 de litere mici, cifre sau cratime). Relay-ul face proxy HTTP/1.1 către 127.0.0.1:{port} din mașină, păstrează Host, adaugă X-Forwarded-For/Proto/Host și transmite răspunsul nemodificat (cookie-uri, CSP, cache), plus un header X-Codai-Environment.
WebSocket-urile funcționează, deci și hot reload-ul: Vite are nevoie de server.allowedHosts: ['.preview.codai.ro']; Next.js acceptă host-ul redirecționat așa cum este. Un upstream care vorbește el însuși HTTPS ({port}s-{slug}) nu este încă suportat și răspunde 501 https_upstream_not_supported.
Vizibilitate
| Vizibilitate | Cine poate deschide portul |
|---|---|
owner | Doar proprietarul mediului. Aceasta este valoarea implicită pentru orice port pe care nu l-ai publicat. |
org | Proprietarul și membrii organizației mediului. |
authenticated | Proprietarul și fiecare membru al acestui mediu (orice rol) — nu orice utilizator codai. |
public | Oricine, fără autentificare. |
Dezvoltatorii pot publica până la authenticated; public cere maintainer sau mai mult. Fiecare schimbare se înregistrează ca eveniment port_visibility_changed.
Vizualizarea Medii → meniul ⋯ al mediului → Porturi. Fiecare port care ascultă își afișează procesul și un selector de vizibilitate (Doar eu, Organizație, Utilizatori autentificați, Public), plus Copiază URL-ul de previzualizare și Deschide previzualizarea.
Hub-ul nu are încă un panou de porturi; folosește desktop-ul, CLI-ul sau API-ul.
Deschiderea unui preview care nu e public
Un browser care vizitează un preview nepublic trebuie să dovedească cine este. Relay-ul acceptă, în ordine:
- Un token de preview în
?token=sau în header-ulX-Preview-Token— legat de un singur mediu și un singur port, valabil implicit 60 s (până la 24 h). Acordă ce putea vedea persoana care l-a generat. - Cookie-ul
codai_previewpe.preview.codai.ro(12 h) — conține doar identitatea ta; vizibilitatea se verifică din nou la fiecare cerere. Authorization: Bearer codai_…— pentru scripturi și clienți nativi.
Cea mai simplă cale este un link cu token:
codaid env preview brivio-k3xq 3000 --ttl 600
# https://3000-brivio-k3xq.preview.codai.ro/?token=codai_pv1.…sau direct la relay:
curl -X POST https://relay.codai.ro/v1/environments/$ENV_ID/preview-token \
-H "Authorization: Bearer $CODAI_API_KEY" -H "Content-Type: application/json" \
-d '{ "port": 3000, "ttl_s": 600 }'{ "token": "codai_pv1.…", "expires_at": "2026-09-25T10:10:00.000Z", "ttl_s": 600, "port": 3000,
"host": "3000-brivio-k3xq.preview.codai.ro", "url": "https://3000-brivio-k3xq.preview.codai.ro/?token=codai_pv1.…" }Pentru a seta cookie-ul, un client apelează GET https://preview.codai.ro/v1/environments/{id}/preview-cookie cu o cheie bearer (opțional cu ?redirect= către un URL de preview din același domeniu, pentru un 302). Doar proprietarul și membrii pot genera cookie-uri sau tokenuri; ceilalți primesc 404.
Un vizitator fără credențiale primește JSON, nu o redirecționare la login:
| Status | code | Semnificație |
|---|---|---|
401 | preview_auth_required | Port nepublic și niciun token, cookie sau cheie valide. |
403 | preview_forbidden | Ești autentificat, dar vizibilitatea te exclude. |
404 | environment_not_found | Niciun mediu cu acel slug (un slug nou poate avea nevoie de până la 30 s ca să fie recunoscut). |
404 | bad_preview_host | Hostname-ul nu se potrivește cu {port}-{slug}.preview.codai.ro. |
503 | environment_offline | Daemonul nu e conectat (Retry-After: 5). |
503 | env_on_other_instance | Daemonul e pe altă instanță de relay (Retry-After: 2); reîncearcă. |
429 | max_streams | Peste 256 de fluxuri deschise pe acest mediu. |
502 | upstream_error | Nimic nu a răspuns pe port — de obicei serverul încă nu ascultă. |
Redirecționează un port pe mașina ta
codaid env forward brivio-k3xq 5432 --local 15432
# 127.0.0.1:15432 → 5432 în mediu
psql "postgres://[email protected]:15432/app"Fiecare conexiune TCP locală devine un flux prin relay, supus aceleiași verificări de vizibilitate (un port refuzat se închide cu port_forbidden). Merge orice TCP simplu — baze de date, Redis, orice. Aplicația desktop nu are încă o interfață de redirecționare.
Limite
| Limită | Valoare |
|---|---|
| Fluxuri deschise per mediu | 256 |
| Date netrimise per flux | 256 KB, apoi fluxul se închide cu backpressure |
| Flux TCP/HTTP inactiv | 10 min (terminalele nu expiră niciodată) |
| Cea mai lungă conexiune | 1 oră — timeout-ul de cerere al relay-ului; clienții se reconectează |
| Căderea daemonului | fluxurile deschise se închid la 30 s după deconectarea daemonului; nu sunt reluate |
Tailscale ca rută directă opțională este planificat; azi tot traficul trece prin relay.
Medii administrate
VM-uri pe care codai le provizionează pentru tine pe OpenStack sau Hetzner — dimensiuni, regiuni, pornire și oprire, oprire automată și snapshot-uri.
Medii de echipă
Împarte un mediu cu echipa — roluri, cont Linux și interval de porturi per membru, repository partajat, lock de build și moduri de izolare.