
Quando un servizio va giù, la prima domanda che si pone chiunque lo utilizzi è sempre la stessa: “è un problema mio o il server è down?”.
Una status page pubblica risolve elegantemente questo problema, dando visibilità trasparente sullo stato dei propri servizi senza dover rispondere a decine di messaggi durante un disservizio.
Kener è una soluzione open source per status page e uptime monitoring costruita su SvelteKit e pensata per essere leggera da self-hostare pur offrendo funzionalità che normalmente si trovano solo in prodotti SaaS a pagamento: gestione incidenti, finestre di manutenzione programmate, notifiche multi-canale, badge di stato incorporabili e supporto multilingua.
Il tutto distribuito con licenza MIT e un’immagine Docker pronta all’uso.
In questo articolo vedremo come installare Kener su una macchina Ubuntu Server 26.04 LTS tramite Docker Compose affiancandolo a Redis (dipendenza obbligatoria per cache e scheduler) e a un volume persistente per il database SQLite.
Copriremo anche alcuni accorgimenti pratici emersi direttamente durante l’installazione come la corretta gestione dei permessi sul volume dati e la scelta tra deployment in root o in subpath utili per evitare gli errori più comuni che si incontrano al primo avvio.
PREREQUISITI
- Ubuntu Server 26.04 aggiornato
- Docker Engine + Docker Compose plugin installati
- Una porta libera sull’host (default 3000)
INSTALLAZIONE DI DOCKER
Se Docker non è ancora installato eseguire i comandi:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin |
CREAZIONE STRUTTURA DELLE CARTELLE
|
0 1 2 |
mkdir -p /opt/kener/database cd /opt/kener |
CONFIGURAZIONE FILE DOCKER COMPOSE
Creare il file di configurazione con il comando:
|
0 |
nano /opt/kener/docker-compose.yml |
Quindi incollare il segente contenuto:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
services: kener-redis: image: redis:7-alpine container_name: kener-redis restart: unless-stopped kener: image: docker.io/rajnandan1/kener:latest-status container_name: kener-status restart: unless-stopped depends_on: - kener-redis ports: - "3000:3000" volumes: - ./database:/app/database environment: - KENER_SECRET_KEY=CAMBIA_QUESTA_STRINGA_CASUALE - ORIGIN=http://IP_O_DOMINIO:3000 - REDIS_URL=redis://kener-redis:6379 - TZ=Europe/Rome |
Salvare e chiudere il file di configurazione
Generare una secret key sicura con il comando:
|
0 |
openssl rand -hex 32 |
Sostituire il valore generato al posto di CAMBIA_QUESTA_STRINGA_CASUALE, e impostare ORIGIN con l’IP o il dominio reale che userai per accedere.
CONFIGURAZIONE DEI PERMESSI
Eseguire i comandi in sequenza:
|
0 1 2 |
docker compose down sudo chown -R 1000:1000 /opt/kener/database docker compose up -d |
AVVIO DELLO STACK
Avviare lo stack con i seguenti comandi:
|
0 1 2 |
cd /opt/kener docker compose up -d |
Dovremmo visualizzare il seguente output:
|
0 1 2 3 4 5 |
[+] up 35/35 ✔ Image docker.io/rajnandan1/kener:latest-status Pulled 11.2s ✔ Image redis:7-alpine Pulled 4.2s ✔ Network kener_default Created 0.0s ✔ Container kener-redis Started 5.1s ✔ Container kener-status Started |
Verificare lo stato di docker con i seguenti comandi:
|
0 |
docker compose ps |
Dovremmo vedere un output simile al seguente:
|
0 1 2 |
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS kener-redis redis:7-alpine "docker-entrypoint.s…" kener-redis About a minute ago Up About a minute 6379/tcp kener-status docker.io/rajnandan1/kener:latest-status "./docker-entrypoint…" kener About a minute ago Up About a minute (healthy) 0.0.0.0:3000->3000/tcp, [::]:3000->3000/tcp |
Eseguire quindi il comando:
|
0 |
docker compose logs -f kener |
Se è tutto OK dovremmo visualizzare il seguente output:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
kener-status | [dotenv@17.2.4] injecting env (0) from .env -- tip: ⚙️ enable debug logging with { debug: true } kener-status | [dotenv@17.2.4] injecting env (0) from .env -- tip: ⚙️ load multiple .env files with { path: ['.env.local', '.env'] } kener-status | Configuring database with type sqlite kener-status | [dotenv@17.2.4] injecting env (0) from .env -- tip: 🔑 add access controls to secrets: https://dotenvx.com/ops kener-status | [dotenv@17.2.4] injecting env (0) from .env -- tip: 🔑 add access controls to secrets: https://dotenvx.com/ops kener-status | [dotenv@17.2.4] injecting env (0) from .env -- tip: 🔐 encrypt with Dotenvx: https://dotenvx.com kener-status | [dotenv@17.2.4] injecting env (0) from .env -- tip: 🔐 prevent committing .env to code: https://dotenvx.com/precommit kener-status | Configuring database with type sqlite kener-status | [dotenv@17.2.4] injecting env (0) from .env -- tip: 🔐 prevent committing .env to code: https://dotenvx.com/precommit kener-status | [dotenv@17.2.4] injecting env (0) from .env -- tip: ✅ audit secrets and track compliance: https://dotenvx.com/ops kener-status | Error running migrations: SqliteError: unable to open database file kener-status | at new Database (/app/node_modules/better-sqlite3/lib/database.js:69:26) kener-status | at Client_BetterSQLite3.acquireRawConnection (/app/node_modules/knex/lib/dialects/better-sqlite3/index.js:14:12) kener-status | at create (/app/node_modules/knex/lib/client.js:262:39) kener-status | at process.processTicksAndRejections (node:internal/process/task_queues:104:5) { kener-status | code: 'SQLITE_CANTOPEN' kener-status | } kener-status | Running seed... kener-status | Error running seed: Error: Error while executing "/app/seeds/generate_template.ts" seed: unable to open database file kener-status | at Seeder._waterfallBatch (/app/node_modules/knex/lib/migrations/seed/Seeder.js:118:23) kener-status | SqliteError: unable to open database file kener-status | at new Database (/app/node_modules/better-sqlite3/lib/database.js:69:26) kener-status | at Client_BetterSQLite3.acquireRawConnection (/app/node_modules/knex/lib/dialects/better-sqlite3/index.js:14:12) kener-status | at create (/app/node_modules/knex/lib/client.js:262:39) { kener-status | original: SqliteError: unable to open database file kener-status | at new Database (/app/node_modules/better-sqlite3/lib/database.js:69:26) kener-status | at Client_BetterSQLite3.acquireRawConnection (/app/node_modules/knex/lib/dialects/better-sqlite3/index.js:14:12) kener-status | at create (/app/node_modules/knex/lib/client.js:262:39) { kener-status | code: 'SQLITE_CANTOPEN' kener-status | } kener-status | } kener-status | Kener is running on port 3000! kener-status | Using option immediately with every does not affect the job's schedule. Job will run immediately anyway. kener-status | Maintenance event scheduler started (runs every hour) kener-status | Daily cleanup scheduler started (runs at 00:00 UTC) kener-status | Running maintenance event scheduler... kener-status | Error processing maintenances for event generation: SqliteError: unable to open database file kener-status | at new Database (/app/node_modules/better-sqlite3/lib/database.js:69:26) kener-status | at Client_BetterSQLite3.acquireRawConnection (/app/node_modules/knex/lib/dialects/better-sqlite3/index.js:14:12) kener-status | at create (/app/node_modules/knex/lib/client.js:262:39) kener-status | at process.processTicksAndRejections (node:internal/process/task_queues:104:5) { kener-status | code: 'SQLITE_CANTOPEN' kener-status | } kener-status | Maintenance scheduler completed. Processed 0 maintenances, created 0 events. kener-status | _ __ _ _ _ _ kener-status | | |/ /___ _ __ ___ _ __ __ _| || | / | / | kener-status | | ' // _ \ '_ \ / _ \ '__| \ \ / / || |_ | | | | kener-status | | . \ __/ | | | __/ | \ V /|__ _|| |_| | kener-status | |_|\_\___|_| |_|\___|_| \_/ |_|(_)_(_)_| kener-status | kener-status | Kener version 4.1.1 is running! |
PRIMO ACCESSO DA WEBGUI
Aprire il browser e richiamare il link:
http://IP_DEL_SERVER:3000/status/account/signin
Al primo avvio partirà il wizard di setup per creare l’account amministratore.
Inserire il nome dell’utente, la mail e password quindi cliccare Create Account
Se è andato tutto a buon fine dovremmo visualizzare la Dashboard di Kener
CARATTERISTICHE DI KENER
Ecco l’elenco dettagliato delle caratteristiche di Kener organizzato per area funzionale:
Monitoraggio dei servizi
- 11 tipi di monitor supportati: HTTP/API, TCP, Ping, DNS, SSL, SQL e altri protocolli comuni
- Scheduling basato su cron, con intervallo minimo di 1 minuto per check
- Configurazione flessibile via YAML: puoi definire tu stesso la logica che determina se un servizio è UP, DOWN o DEGRADED, non solo un semplice check binario
- Stato di default configurabile per un monitor (es. defaultStatus=DOWN se non viene ricevuto un aggiornamento entro l’intervallo previsto)
- Data Explorer: sezione per ispezionare lo storico dei check, analizzare i fallimenti e i trend di uptime nel tempo
Gestione incidenti
- Creazione incidenti tramite GitHub Issues con rich text, oppure via API REST dedicate
- Sistema di trigger: condizioni intelligenti per instradare automaticamente notifiche e automazioni operative in base agli eventi
- Template di messaggistica: modelli riutilizzabili per standardizzare le comunicazioni di incidenti e notifiche
Manutenzioni programmate
- Pianificazione di maintenance window con scheduler dedicato (nei log lo hai visto girare ogni ora)
- Generazione automatica degli eventi di manutenzione associati ai monitor
Notifiche
- Supporto nativo per Slack, Discord, webhook generici
- Sistema di notifica per i subscriber della status page (utenti finali che vogliono essere avvisati sui disservizi)
Interfaccia e personalizzazione
- Tema chiaro/scuro
- Costruito su SvelteKit + shadcn-svelte, interfaccia moderna e reattiva
- Responsive design per dispositivi mobili
- 100% accessibility score dichiarato
- Supporto multilingua: 21 lingue disponibili
- Badge generator per stato e uptime dei singoli monitor, embeddabili altrove
- Widget/iframe embed per integrare un monitor in altre pagine/dashboard
- Dominio personalizzato supportato
- SEO e social media ready (meta tag automatici)
Sicurezza e gestione accessi
- Vault/secret management: storage sicuro per chiavi e credenziali usate nelle integrazioni
- API Key management: emissione e revoca di chiavi per automazioni e integrazioni di terze parti
- KENER_SECRET_KEY dedicata per la sicurezza delle sessioni
Analytics
- Integrazione con provider esterni: Google Analytics, Plausible, Mixpanel, Umami, Microsoft Clarity e altri
Deployment e infrastruttura
- Immagine Docker ufficiale pronta all’uso, deploy dichiarato “in meno di 2 minuti” con Docker Compose
- Redis obbligatorio come dipendenza per cache, sessioni e coda dei job di scheduling
- Storage SQLite locale, senza necessità di un database esterno separato
- Supporto base path per hosting sotto Kubernetes/subpath
- Licenza MIT, quasi 5.000 star su GitHub
- Nessun supporto commerciale/SLA ufficiale — progetto community-driven, quindi da valutare in ottica di rischio se lo porti in produzione critica

0 Commenti