documentazione di pingtxt
Tutto, tranne due variabili d'ambiente, si configura dall'interfaccia web e viene salvato nel database. Il README su GitHub ha lo stesso contenuto, in inglese.
──avviare l'hub
docker run -d --name pingtxt --restart unless-stopped \-p 8090:8090 -v ./data:/data \ghcr.io/federico-it/pingtxt:latest
Oppure docker compose up -d con il docker-compose.yml del repository. Apri http://localhost:8090, crea l'account admin, aggiungi i monitor. I binari per Linux e macOS sono nella pagina delle release.
Le immagini girano con l'utente senza privilegi pingtxt (uid 10001). All'avvio l'entrypoint assegna /data a quell'utente (i volumi delle versioni precedenti erano scritti da root), gli permette di usare un socket Docker montato e tiene solo CAP_NET_RAW per il ping. Esegui i comandi della CLI con docker exec -u pingtxt pingtxt pingtxt ...; per saltare il passaggio come root, imposta user: "10001:10001" e chown -R 10001:10001 ./data.
URL pubblico, località integrata, conservazione dei dati, valori predefiniti dei nuovi monitor, utenti e accesso stanno in impostazioni. All'avvio vengono lette solo queste:
| env | predefinito | |
|---|---|---|
PINGTXT_ADDR | :8090 | indirizzo di ascolto |
PINGTXT_DATA | /data | cartella del database SQLite |
PINGTXT_DB_URL | PostgreSQL o MariaDB/MySQL al posto di SQLite |
──postgresql o mariadb
SQLite è il predefinito e non richiede altro. Per tenere i dati in PostgreSQL (13+) o MariaDB (10.6+) / MySQL (8.0.13+), avvia l'hub con PINGTXT_DB_URL. Le tabelle vengono create e migrate all'avvio. I file compose qui sotto avviano hub e database con un solo comando; imposta le password in .env prima del primo avvio.
curl -O https://raw.githubusercontent.com/federico-it/pingtxt/main/docker-compose.postgres.ymlecho "DB_PASSWORD=$(openssl rand -hex 16)" > .envdocker compose -f docker-compose.postgres.yml up -d
curl -O https://raw.githubusercontent.com/federico-it/pingtxt/main/docker-compose.mariadb.ymlprintf "DB_PASSWORD=%s\nDB_ROOT_PASSWORD=%s\n" $(openssl rand -hex 16) $(openssl rand -hex 16) > .envdocker compose -f docker-compose.mariadb.yml up -d
Con un tuo server di database, crea un database vuoto e un utente, poi:
PINGTXT_DB_URL=postgres://pingtxt:secret@db.example.com:5432/pingtxt?sslmode=requirePINGTXT_DB_URL=mariadb://pingtxt:secret@db.example.com:3306/pingtxt # va bene anche mysql://
I caratteri speciali nella password vanno codificati per URL. Aggregazione dello storico, metriche Prometheus ed export della configurazione funzionano allo stesso modo con ogni database. I backup integrati nelle impostazioni sono file SQLite: con PostgreSQL o MariaDB fai il backup del server con i suoi strumenti.
docker exec pingtxt-postgres pg_dump -U pingtxt -Fc pingtxt > pingtxt.dumpdocker stop pingtxtdocker exec -i pingtxt-postgres pg_restore -U pingtxt -d pingtxt --clean --if-exists < pingtxt.dumpdocker start pingtxt
docker exec pingtxt-mariadb sh -c 'mariadb-dump -u pingtxt -p"$MARIADB_PASSWORD" --single-transaction pingtxt' > pingtxt.sqldocker stop pingtxtdocker exec -i pingtxt-mariadb sh -c 'mariadb -u pingtxt -p"$MARIADB_PASSWORD" pingtxt' < pingtxt.sqldocker start pingtxt
Per spostare un hub SQLite esistente, esporta la configurazione con i segreti (impostazioni → export della configurazione) e importala nel nuovo hub. Lo storico non viene spostato.
──reverse proxy
Metti l'hub dietro un reverse proxy con TLS (Caddy, Traefik, nginx) e imposta l'url pubblico nelle impostazioni, così lo usano i callback di accesso e i comandi degli agent. L'upgrade WebSocket deve essere permesso su /api/agent/ws.
status.example.com {reverse_proxy 127.0.0.1:8090}
──aggiungere una località (agent)
Nell'interfaccia vai in agent → aggiungi agent: ricevi un token e i comandi pronti da incollare.
# Dockerdocker run -d --name pingtxt-agent --restart unless-stopped --cap-add NET_RAW \-e PINGTXT_HUB=https://status.example.com -e PINGTXT_TOKEN=pt_xxx \-v pingtxt-agent:/data ghcr.io/federico-it/pingtxt-agent:latest# Linux + systemd (binario scaricato dal tuo hub)curl -fsSL https://status.example.com/install-agent.sh | sudo sh -s -- --hub https://status.example.com --token pt_xxx# disinstallazionecurl -fsSL https://status.example.com/install-agent.sh | sudo sh -s -- --uninstall
Poi spunta la nuova località nei monitor che vuoi. L'hub pianifica ogni controllo e lo manda agli agent; gli agent non hanno stato, non aprono porte e si ricollegano con backoff.
Con più località il monitor è down quando ne fallisce più della metà, e degradato oltre la soglia impostata nelle impostazioni. L'uptime segue questo stato, non i singoli controlli: una sola località che fallisce tra tante non lo abbassa.
──aggiornamento degli agent
L'hub include i binari degli agent compilati con la sua stessa versione. Gli agent (installati con lo script o in Docker) si aggiornano da soli quando si ricollegano dopo un aggiornamento dell'hub: scaricano il binario dall'hub, ne verificano SHA-256 e versione, lo sostituiscono e si riavviano. Se l'aggiornamento fallisce, resta in funzione il binario precedente.
- agent → aggiorna gli agent automaticamente lo attiva o disattiva; gli agent non aggiornati hanno anche un pulsante per aggiornarli.
- Per tenere un agent alla sua versione usa
-no-auto-update(oppurePINGTXT_NO_AUTO_UPDATE=1in/etc/pingtxt-agent.env). - Gli agent si aggiornano da soli solo da un hub in https (o in http semplice su un indirizzo IP di loopback o privato). Per permetterlo comunque in http semplice, usa
-insecure-update(PINGTXT_INSECURE_UPDATE=1). - Gli agent confrontano anche il checksum dell'hub con il file
SHA256SUMSdella release GitHub di quella versione, così un hub manomesso non può distribuire un suo binario.-verify-update(PINGTXT_VERIFY_UPDATE) èautoper impostazione predefinita (saltato con un avviso se GitHub non è raggiungibile),strictper installare solo release pubblicate che corrispondono, oppureoffper fork e build private. - Gli agent in Docker tengono il nuovo binario nel volume
/datae lo eseguono da lì dopo un riavvio, senza socket Docker. Monta un volume con nome (-v pingtxt-agent:/data) per non perdere gli aggiornamenti quando il container viene ricreato. Scaricando una nuova immagine riparte il suo binario e il volume viene svuotato. - Se invece vuoi container immutabili, imposta
PINGTXT_NO_AUTO_UPDATE=1e lascia che un aggiornatore di immagini scarichi:latest(What's Up Docker o il fork mantenuto di Watchtower). Serve il socket Docker, e l'agent segue così l'ultima release invece della versione dell'hub. - Tag Docker:
:latestè la release più recente,:1.2.3una release precisa,:mainl'ultima build del branch main.
──tipi di controllo
| tipo | destinazione | cosa viene controllato |
|---|---|---|
| http(s) | https://example.com | codici di stato, header, body, regole JSON, scadenza TLS |
| parola chiave | url + testo | il body della risposta contiene (o non contiene) una parola chiave |
| porta tcp | host:port | la connessione si apre (IPv6: [2001:db8::1]:443) |
| ping | host o IP | echo ICMP o ICMPv6 (gli agent richiedono NET_RAW) |
| dns | nome + tipo di record | si risolve, valore atteso facoltativo |
| postgresql | postgres://user:pass@host:5432/db | connessione + query (predefinita SELECT 1), valore atteso facoltativo |
| mysql / mariadb | mysql://user:pass@host:3306/db | come postgresql |
| redis | redis://:pass@host:6379/0 | AUTH + PING, rediss:// per TLS |
| mongodb | mongodb://user:pass@host:27017/ | hello, auth, ping; mostra primary/secondary |
| container docker | nome o id | down se non è in esecuzione, si sta riavviando, è in pausa o unhealthy |
| grpc health | grpc://host:port[/service] | grpc.health.v1 Check risponde SERVING |
| smtp | smtp://host:587 | saluto, EHLO, STARTTLS quando disponibile |
| server mcp | https://host/mcp | handshake initialize, controlli facoltativi su tools/list |
| heartbeat | URL di push | il tuo job chiama l'URL; down quando smette |
Le password negli URL di connessione sono nascoste nell'elenco e nelle notifiche; usa un utente in sola lettura. I controlli Docker richiedono /var/run/docker.sock sull'hub o sull'agent che li esegue (aggiungi -v /var/run/docker.sock:/var/run/docker.sock:ro).
──tempo di risposta per fase
I controlli HTTP e con parola chiave misurano dove va il tempo: risoluzione DNS, connessione, handshake TLS, attesa del primo byte (TTFB, il server al lavoro) e trasferimento del body. Nella pagina del monitor passa il grafico dei tempi di risposta a per fase, per località o tutte insieme; passa sopra una latenza nel log per vedere il dettaglio di quel controllo. Con i redirect le fasi di ogni passaggio vengono sommate. Gli agent misurano le fasi da questa versione in poi: aggiorna quelli più vecchi per vederne i dati.
──ipv6
Ogni tipo di controllo funziona su IPv6. Gli host con soli record AAAA funzionano senza fare nulla; scrivi gli indirizzi IPv6 tra parentesi quadre quando segue una porta ([2001:db8::1]:443, https://[2001:db8::1]/, redis://[2001:db8::1]:6379). Ping e dns vogliono l'indirizzo senza parentesi.
versione ip su un host dual-stack: IPv4 o IPv6 apre una connessione con la famiglia che risponde per prima, quindi un IPv6 rotto passa inosservato; solo IPv4 o solo IPv6 usano una sola famiglia; IPv4 e IPv6 le controlla entrambe e fallisce se una delle due fallisce. Il valore predefinito si imposta nelle impostazioni e ogni monitor può cambiarlo (API ip_family: 0 predefinito, 1, 4, 6, 46). Gli agent più vecchi di questa versione non lo supportano e segnalano il controllo come fallito: aggiornali.
Hub e agent verificano se raggiungono IPv6 all'avvio e ogni 10 minuti (lo mostrano la pagina degli agent e il modulo del monitor). Una località senza IPv6 non si può scegliere per solo IPv6 o IPv4 e IPv6; lì IPv4 o IPv6 e il predefinito dell'istanza controllano su IPv4. PINGTXT_IPV6=on o off salta la verifica.
L'hub ascolta su IPv4 e IPv6 (:8090). I container Docker non hanno IPv6 per impostazione predefinita, quindi i controlli verso destinazioni IPv6 falliscono da un container finché IPv6 non viene attivato sulla sua rete (Docker 27 o successivo, e IPv6 sul server):
networks:default:enable_ipv6: true
Con docker run: docker network create --ipv6 pingtxt e --network pingtxt, oppure --network host.
──controlli sulla risposta (JSON)
I monitor HTTP e con parola chiave possono controllare il body JSON della risposta, per esempio un endpoint di health che restituisce {"status": "ready", "checks": {"redis": {"status": "ok", "latencyMs": 3}}}. Aggiungi le regole in controlli sulla risposta nel modulo del monitor: devono passare tutte, altrimenti il controllo fallisce e il risultato, l'incidente e la notifica dicono quale regola non è rispettata, per esempio checks.redis.status: expected "ok", got "error".
| percorso | operatore | valore |
|---|---|---|
status | equals | ready |
checks.redis.status | equals | ok |
checks.worker.ageMs | < | 60000 |
items[0].id | exists |
- I percorsi usano punti e parentesi quadre:
a.b,items[0](oitems.0,items[-1]per l'ultimo),["key.with.dots"]. È ammesso un$.iniziale. - Operatori: uguale, diverso, contiene (sottostringa, elemento di un array o chiave di un oggetto), non contiene, esiste, non esiste, >, >=, <, <= (numeri) e corrisponde (espressione regolare).
- I valori si confrontano per tipo: i numeri come numeri (
3è uguale a3.0),true/false/nullper nome, oggetti e array come JSON. - Le regole funzionano anche sugli agent. Gli agent più vecchi di questa funzione segnalano il controllo come fallito chiedendo di aggiornarli, invece di farlo passare senza verificarlo.
──server mcp
Un monitor server mcp controlla un server Model Context Protocol remoto: esegue l'handshake initialize e, se il server ha dei tool, li elenca con tools/list. Il risultato mostra nome e versione del server, la versione del protocollo negoziata, il trasporto e il numero di tool.
- destinazione: l'URL dell'endpoint, per esempio
https://mcp.example.com/mcp. - trasporto:
autoprova lo streamable HTTP e ripiega sul vecchio trasporto HTTP+SSE (2024-11-05) quando la POST viene rifiutata; sceglistreamableosseper forzarne uno. - header: inviati con ogni richiesta, per esempio
Authorization: Bearer <token>. Un 401 o un 403 manda il monitor down. Gli utenti in sola lettura non vedono i valori. - tool richiesti (separati da virgola) e tool minimi: il monitor va down quando un tool sparisce o il server ne elenca meno.
I tool non vengono mai chiamati. Gli endpoint https ricevono gli avvisi di scadenza del certificato TLS come i monitor http. Gli agent più vecchi di questa versione segnalano unknown monitor type: mcp: aggiornali.
──monitor heartbeat (cron job)
Un monitor heartbeat (push) riceve un URL segreto. Chiamalo alla fine di ogni esecuzione, con qualsiasi metodo HTTP:
0 3 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 3 https://status.example.com/api/push/<token> >/dev/null
Va down quando non arriva nessuna chiamata entro il periodo atteso più la tolleranza. Parametri facoltativi nella query: status=down, msg=, ping= (durata dell'esecuzione in ms).
──status page
Si creano in status: scegli monitor o interi gruppi, il loro ordine e se mostrare gli incidenti passati. Una pagina è pubblica su https://<hub>/status/<slug>/. I visitatori vedono nomi, stato, uptime e orari degli incidenti, mai destinazioni, località o messaggi di errore.
Per un dominio personalizzato (per esempio status.example.com), impostalo sulla pagina, punta il suo DNS all'hub e instrada l'host verso pingtxt nel reverse proxy. Su quell'host viene servita solo la status page.
Per tenere privata una pagina, attiva proteggi con una password. I visitatori vedono allora un modulo per la password; quella giusta apre la pagina per 30 giorni in quel browser, insieme ai suoi badge e al modulo di iscrizione. La password è salvata come hash, i tentativi sbagliati sono limitati e cambiarla disconnette tutti i visitatori. Agli utenti con accesso non serve mai.
Pubblica incidenti su una pagina con una cronologia di aggiornamenti scritti (stiamo indagando, causa individuata, sotto osservazione, risolto). Scegliendo un canale email in iscrizioni via email, i visitatori possono iscriversi: confermano con un link, poi ricevono ogni aggiornamento via email, ognuno con un link per disiscriversi.
Badge per il README: ogni pagina pubblicata ha badge SVG per il suo stato generale e per ogni monitor che mostra (stato, uptime, tempo di risposta). Copiali dalla pagina del monitor o dall'editor della status page:
[](https://status.example.com/status/acme/)
Tipi: status, uptime, response; period= 24h, 7d, 30d o 90d; facoltativi label= e style=flat-square. Le bozze e i monitor che non sono nella pagina non hanno badge.
──finestre di manutenzione
Singole o ricorrenti (ogni giorno, settimana o mese, in qualsiasi fuso orario), per alcuni o tutti i monitor, gruppi o tag. I controlli continuano, ma non si aprono incidenti né partono avvisi, e quei controlli non contano per l'uptime.
──avvisi di scadenza
Certificati TLS dei monitor https e registrazioni dei domini (RDAP, con WHOIS come riserva per registri come il .it). Le soglie in giorni si impostano nelle impostazioni (predefinite 14/7/3/1 per i certificati, 30/14/7/1 per i domini): un avviso per ogni soglia superata, uno alla scadenza, uno al rinnovo.
──notifiche
Webhook (JSON), Discord, Slack, Telegram, ntfy ed email (SMTP con STARTTLS/TLS, oppure l'API di Resend con una API key di un dominio verificato). Aggiungili in notifiche, provali prima di salvare e collegali ai monitor.
I report periodici, nella stessa pagina, mandano via email uptime, incidenti e tempi di inattività dell'ultima settimana (ogni lunedì) o dell'ultimo mese (il giorno 1) per gruppo di monitor, a confronto con il periodo precedente. Scegli i canali email, eventualmente alcuni gruppi, l'ora e il fuso orario; guarda l'anteprima di un report o invialo subito prima di attivarlo.
Ogni canale ha un ambito: tutti i monitor (anche quelli futuri), i monitor di alcuni gruppi e tag, oppure solo i monitor collegati uno per uno; e gli eventi che riceve: down, up, degradato (spento di default), scadenza del certificato e del dominio. Collega un monitor uno per uno, dal canale o dal form del monitor, per aggiungerlo, cambiarne gli eventi o escluderlo da un canale su tutti i monitor. I canali già esistenti continuano a ricevere tutto quello che ricevevano prima.
Escalation e promemoria si impostano per canale. invia dopo N minuti avvisa il canale solo se a quel punto il monitor è ancora down (un telefono di reperibilità, un responsabile), così i disservizi brevi non lo raggiungono mai. ripeti ogni N minuti manda un promemoria STILL DOWN finché il monitor resta down (almeno 5). I webhook includono reminder e down_since. Durante le finestre di manutenzione non viene inviato nulla; gli avvisi in sospeso partono quando la finestra finisce.
──single sign-on
In impostazioni → autenticazione attiva GitHub, Google o un OpenID Connect generico (Authentik, Keycloak, Authelia, Pocket ID, Zitadel, Okta, Entra ID...), incolla client id e secret e registra l'URL di callback mostrato lì.
- Gli accessi vengono associati agli utenti esistenti tramite l'email verificata. Si possono consentire nuovi account, anche solo per alcuni domini email.
- Rimasto fuori dopo aver disattivato l'accesso con password? Esegui
docker exec -u pingtxt pingtxt pingtxt -enable-password-logine riavvia.
──autenticazione a due fattori
In impostazioni → autenticazione a due fattori inquadra il codice QR con una qualsiasi app di autenticazione. Ricevi 10 codici di recupero monouso. Per azzerarla a un utente: impostazioni → utenti → azzera 2fa, oppure docker exec -u pingtxt pingtxt pingtxt -reset-2fa you@example.com.
──token api
Crea token personali in impostazioni → token api, in sola lettura o lettura + scrittura, con una scadenza facoltativa. Vengono mostrati una sola volta e salvati come hash.
curl -H "Authorization: Bearer ptk_..." https://status.example.com/api/monitors
GET /api/monitors accetta ?group=<id> e ?tag=<id>. I token non arrivano mai agli endpoint dell'account (password, 2FA, token, utenti, impostazioni dell'istanza).
Tutti gli endpoint, con parametri ed esempi, sono nel riferimento API. Ogni hub serve anche il documento OpenAPI 3.1 su /api/openapi.json e una Swagger UI interattiva su /api/docs (con un link da impostazioni → token api).
──server mcp dell'hub
L'hub è un server MCP su /mcp (Streamable HTTP): Claude e altri assistenti AI possono dirti cosa è down, leggere incidenti e tempi di risposta, e creare monitor o finestre di manutenzione. Ruoli e segreti nascosti sono gli stessi dell'API.
OAuth 2.1, niente da copiare: aggiungi https://status.example.com/mcp come connettore personalizzato in claude.ai o Claude Desktop (oppure claude mcp add --transport http pingtxt https://status.example.com/mcp e poi /mcp in Claude Code). Accedi a pingtxt nel browser e scegli sola lettura o lettura + scrittura (solo admin). Sono supportati discovery, registrazione dinamica dei client, PKCE e refresh token a rotazione; gli access token durano un'ora e valgono su /mcp e sull'API. Le app collegate si possono scollegare in impostazioni → token api. Dietro un proxy, imposta l'URL pubblico nelle impostazioni.
Token API, per i client senza OAuth: i token di lettura hanno i tool di lettura, un token lettura + scrittura di un admin ha anche i tool che modificano i dati.
claude mcp add --transport http pingtxt https://status.example.com/mcp \--header "Authorization: Bearer ptk_..."
{"mcpServers": {"pingtxt": {"command": "npx","args": ["-y", "mcp-remote", "https://status.example.com/mcp","--header", "Authorization:${PINGTXT_AUTH}"],"env": { "PINGTXT_AUTH": "Bearer ptk_..." }}}}
{"mcpServers": {"pingtxt": {"url": "https://status.example.com/mcp","headers": { "Authorization": "Bearer ptk_..." }}}}
| tool | cosa fa |
|---|---|
get_overview | monitor per stato, agent online, incidenti aperti |
list_monitors | stato, uptime, tempo di risposta; filtri per stato, gruppo, tag, nome |
get_monitor | impostazioni, uptime 24h/7g/30g, stato per località, scadenze |
get_monitor_results | ultimi risultati dei controlli |
list_incidents | incidenti, solo aperti o per monitor |
list_maintenances | finestre di manutenzione e prossima occorrenza |
list_groups · list_tags · list_agents · list_status_pages | gli id per tutto il resto |
create / update / pause / delete_monitor | token di scrittura di un admin |
create / delete_maintenance | token di scrittura di un admin, orari ISO 8601 |
──app native
L'app iOS accede con OAuth 2.1 (authorization code + PKCE) sulla pagina di accesso dell'hub, quindi funzionano password, 2FA, GitHub, Google e OpenID Connect. È il client pubblico integrato pingtxt-ios con redirect URI pingtxt://oauth: nessun secret e nessuna registrazione. Gli admin scelgono sola lettura o lettura + scrittura nella pagina di consenso, gli utenti in sola lettura ricevono sempre la sola lettura.
| passo | richiesta |
|---|---|
| accesso | GET /oauth/authorize?response_type=code&client_id=pingtxt-ios&redirect_uri=pingtxt://oauth&scope=read%20write&state=…&code_challenge=…&code_challenge_method=S256 |
| ottenere i token | POST /oauth/token grant_type=authorization_code&code=…&client_id=pingtxt-ios&redirect_uri=pingtxt://oauth&code_verifier=… |
| chiamare l'api | Authorization: Bearer pma_… |
| rinnovo | POST /oauth/token grant_type=refresh_token&refresh_token=pmr_…&client_id=pingtxt-ios |
| uscita | POST /oauth/revoke token=pmr_…&client_id=pingtxt-ios |
Gli access token durano un'ora e valgono su tutta l'API come un token API con lo stesso scope (mai sugli endpoint dell'account). I refresh token durano 30 giorni dall'ultimo uso e ruotano: ogni rinnovo ne restituisce uno nuovo, e riusarne uno vecchio chiude l'accesso. Ogni accesso è elencato in impostazioni → token api → app collegate, da dove si può scollegare.
──prometheus
GET /metrics richiede un token di lettura, a meno che non sia attivo impostazioni → metriche prometheus → pubblico. L'output resta in cache per 10 secondi.
scrape_configs:- job_name: pingtxtscheme: httpsauthorization:credentials: ptk_...static_configs:- targets: ["status.example.com"]
| metrica | significato |
|---|---|
pingtxt_monitor_up | 1 up o degradato, 0 down |
pingtxt_monitor_uptime_ratio | uptime per intervallo (24h, 7d, 30d) |
pingtxt_check_latency_seconds | ultimo controllo per località |
pingtxt_check_phase_seconds | DNS, connessione, TLS e primo byte dell'ultimo controllo HTTP |
pingtxt_cert_expiry_days | giorni alla scadenza del certificato |
pingtxt_domain_expiry_days | giorni alla scadenza del dominio |
pingtxt_agent_connected | connessione degli agent |
──aggiornamento + backup
docker compose pull && docker compose up -d
Le migrazioni del database partono all'avvio. Con SQLite tutto lo stato è un solo file, /data/pingtxt.db: impostazioni → backup del database ne fa copie mentre l'hub è in funzione, su richiesta o a orari pianificati, e le ripristina. Con PostgreSQL o MariaDB usa pg_dump o mariadb-dump. Gli agent installati con lo script seguono da soli la versione dell'hub.
Mentre l'hub si riavvia o si aggiorna, i browser mostrano una pagina pingtxt si sta aggiornando che segue le migrazioni e si ricarica da sola quando l'hub è pronto, e /api/health risponde 503. Le schede aperte aspettano sulla stessa schermata invece di dare errore. Quando il container è del tutto fermo (mentre scarica la nuova immagine), i browser che avevano già aperto pingtxt in https la mostrano dalla cache; la primissima visita riceve l'errore del reverse proxy finché l'hub non torna in ascolto.
Le build di release chiedono a GitHub l'ultima release ogni 12 ore e mostrano un avviso agli admin quando ne esce una più recente. Disattivalo in impostazioni → aggiornamenti, oppure avvia l'hub con PINGTXT_DISABLE_UPDATE_CHECK=true perché non contatti mai GitHub.
──statistiche d'uso
Dopo l'installazione, agli admin viene chiesto una volta se l'hub può inviare statistiche d'uso anonime. Non viene inviato nulla finché qualcuno non dice sì, e la risposta si può cambiare in qualsiasi momento in impostazioni → statistiche d'uso, che mostra anche il prossimo report esatto.
Una volta all'ora l'hub invia a telemetry.pingtxt.com solo questo:
id: un id casuale creato la prima volta che si attivano le statistiche. Non cambia mai e non dice nulla dell'hub.version: la versione di pingtxt.monitors: quanti monitor non sono in pausa.agents: quanti agent sono collegati.
Nessun nome, destinazione, indirizzo, risultato o email, e il servizio non salva indirizzi IP. Avvia l'hub con PINGTXT_DISABLE_TELEMETRY=true per disattivare le statistiche per sempre e nascondere la domanda. Le build di sviluppo non inviano mai nulla.
I totali sono pubblici su telemetry.pingtxt.com (JSON su /v1/stats): hub, monitor e agent attivi, versioni in uso e 90 giorni di storico. Mai il report di un singolo hub.
──verificare una release
Le release successive alla v0.1.0 sono firmate con cosign in modalità keyless, legate al workflow GitHub che le ha compilate. Ogni release include SHA256SUMS e la sua firma SHA256SUMS.sigstore.json; le immagini su ghcr.io sono firmate per digest.
V=v0.2.0base=https://github.com/federico-it/pingtxt/releases/download/$Vcurl -fsSLO $base/SHA256SUMS -O $base/SHA256SUMS.sigstore.json -O $base/pingtxt-agent-linux-amd64cosign verify-blob SHA256SUMS --bundle SHA256SUMS.sigstore.json \--certificate-identity "https://github.com/federico-it/pingtxt/.github/workflows/release.yml@refs/tags/$V" \--certificate-oidc-issuer https://token.actions.githubusercontent.comsha256sum --ignore-missing -c SHA256SUMS
cosign verify ghcr.io/federico-it/pingtxt:${V#v} \--certificate-identity "https://github.com/federico-it/pingtxt/.github/workflows/docker.yml@refs/tags/$V" \--certificate-oidc-issuer https://token.actions.githubusercontent.com
──compilare dai sorgenti
Servono Go 1.26+, Node.js 22+ con npm, make e git. Nessun compilatore C (tutto si compila con CGO_ENABLED=0).
git clone https://github.com/federico-it/pingtxt.git && cd pingtxtgit checkout v1.2.3 # facoltativo: il tag di una releasemake web hub agent agents
| target | output | |
|---|---|---|
make web | internal/ui/dist | l'interfaccia web, inclusa nell'hub: eseguilo prima di make hub |
make hub | dist/pingtxt | l'hub per questa macchina, interfaccia inclusa |
make agent | dist/pingtxt-agent | l'agent per questa macchina |
make agents | dist/agents/ | agent per linux amd64/arm64/arm e darwin, serviti dall'hub allo script di installazione e per gli aggiornamenti |
La versione viene da git describe (si cambia con VERSION=v1.2.3). Compila hub e agent dallo stesso checkout: gli agent si aggiornano alla versione dell'hub.
./dist/pingtxt # dati in ./data, agent da ./dist/agents, :8090PINGTXT_DATA=/var/lib/pingtxt PINGTXT_AGENT_DIR=/usr/local/share/pingtxt/agents /usr/local/bin/pingtxt
I controlli ping usano un raw socket con CAP_NET_RAW, altrimenti un socket ICMP senza privilegi (permesso da net.ipv4.ping_group_range). Fuori da Docker: sudo setcap cap_net_raw+ep /usr/local/bin/pingtxt (e per l'agent); PINGTXT_UNPRIVILEGED_PING=1 o 0 forza uno dei due. Un esempio di unit systemd è nel README.
V=$(git describe --tags --always)CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags "-s -w -X main.version=$V" -o dist/pingtxt-linux-arm64 ./cmd/pingtxtCGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -trimpath -ldflags "-s -w -X main.version=$V" -o dist/pingtxt-agent-linux-armv7 ./cmd/pingtxt-agent
make docker # pingtxt:dev e pingtxt-agent:devdocker build --build-arg VERSION=$(git describe --tags --always) -t pingtxt:dev .docker build --build-arg VERSION=$(git describe --tags --always) -f Dockerfile.agent -t pingtxt-agent:dev .docker buildx build --platform linux/amd64,linux/arm64 -t registry.example.com/pingtxt:dev --push .
Per avviare un file compose con la tua build, aggiungi docker-compose.build.yml dopo di esso. Vale per SQLite, PostgreSQL e MariaDB (prima crea il .env con le password):
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --builddocker compose -f docker-compose.postgres.yml -f docker-compose.build.yml up -d --builddocker compose -f docker-compose.mariadb.yml -f docker-compose.build.yml up -d --build
──contribuire
pingtxt è software libero con licenza AGPL-3.0: usalo, ospitalo sui tuoi server e modificalo liberamente; se distribuisci una versione modificata o la offri come servizio ad altri, pubblicane i sorgenti con la stessa licenza. Segnalazioni di bug, correzioni e nuovi tipi di controllo o di notifica sono benvenuti.
- bug: cerca prima tra le issue, poi apri un bug report con la versione (la trovi nelle impostazioni), come lo esegui, i passi per riprodurlo e i log.
- idee: apri una feature request. Per le modifiche più grandi, concorda l'approccio in una issue prima di scrivere codice.
- sicurezza: mai in una issue pubblica. Segnalalo in privato, vedi SECURITY.md.
- pull request: fai un fork, crea un branch da
main, eseguimake test lint, apri la PR versomain. La unisce un maintainer quando i controlligoewebpassano e la review è approvata.
git clone https://github.com/<you>/pingtxt.git && cd pingtxt(cd web && npm ci)make dev-hub # hub su :8090make dev-web # interfaccia su :3000, inoltra /api
Tutto il resto, stile dei commit e del codice compreso, è in CONTRIBUTING.md (in inglese). Chi partecipa segue il codice di condotta.