Scelta architetturale
Su Debian 12 la strada più pulita per Ansible Semaphore è usare il binario ufficiale, un database PostgreSQL locale e un reverse proxy Nginx davanti all’interfaccia web. È la combinazione più semplice da mantenere, con meno dipendenze rispetto a un deployment containerizzato e con una gestione chiara dei permessi. In produzione assumo sempre che l’interfaccia web sia esposta solo tramite HTTPS e che il servizio applicativo resti in ascolto su localhost.
Obiettivo: installazione ripetibile, avvio automatico con systemd, configurazione persistente in file separati e verifica finale con login nella UI.
Prerequisiti su Debian 12
Serve un host Debian 12 aggiornato, accesso root o sudo, un nome DNS già puntato verso la macchina e almeno PostgreSQL 15 disponibile localmente. Se il server è dietro firewall o security group, apri solo le porte necessarie: 22 per SSH, 80 e 443 per Nginx. La porta interna di Semaphore non va esposta all’esterno.
Verifica base del sistema:
sudo apt update
sudo apt -y full-upgrade
sudo rebootDopo il riavvio controlla che il sistema sia allineato:
cat /etc/debian_version
uname -rSe usi un hostname dedicato, imposta il FQDN prima di procedere. Non è obbligatorio, ma evita confusione nei certificati e nei log.
Installazione dei pacchetti base
Installa PostgreSQL, Nginx e gli strumenti utili. In questa fase non tocchiamo ancora Semaphore.
sudo apt update
sudo apt -y install postgresql nginx curl ca-certificates gnupgControlla che i servizi siano attivi:
systemctl status postgresql --no-pager
systemctl status nginx --no-pagerSe uno dei due non parte, fermati qui e guarda i log con:
journalctl -u postgresql -n 50 --no-pager
journalctl -u nginx -n 50 --no-pagerSu un host pulito Debian 12 PostgreSQL dovrebbe essere già in ascolto su socket locale e Nginx dovrebbe rispondere sulla porta 80 con la pagina di default.
Creazione del database PostgreSQL
Semaphore usa un database relazionale per utenti, playbook, template e job history. PostgreSQL è la scelta più solida. Creo un database dedicato e un utente dedicato, senza riutilizzare account di sistema.
sudo -u postgres psqlDentro la console SQL:
CREATE USER semaphore WITH PASSWORD 'SOSTITUISCI_CON_PASSWORD_FORTE';
CREATE DATABASE semaphore OWNER semaphore;
\qNon lasciare password in chiaro nei comandi se puoi evitarlo. Meglio usare una variabile temporanea o un prompt interattivo. Se devi automatizzare, proteggi il file di configurazione con permessi stretti.
Verifica l’accesso:
psql -h 127.0.0.1 -U semaphore -d semaphore -c 'SELECT version();'Se fallisce, controlla `pg_hba.conf`, il metodo di autenticazione e la password del ruolo. Su Debian il file tipico è in `/etc/postgresql/15/main/pg_hba.conf`.
Installazione di Ansible Semaphore
Per Debian 12 conviene scaricare il binario ufficiale dalla release del progetto oppure usare il pacchetto disponibile se presente nel tuo repository interno. La logica non cambia: il servizio deve girare come utente non privilegiato e avere configurazione persistente su disco.
Creo utente e directory dedicate:
sudo useradd --system --home /var/lib/semaphore --shell /usr/sbin/nologin semaphore
sudo mkdir -p /etc/semaphore /var/lib/semaphore
sudo chown -R semaphore:semaphore /var/lib/semaphoreScarica il binario dalla release ufficiale corrispondente alla tua architettura. Esempio generico:
cd /tmp
curl -LO https://github.com/ansible-semaphore/semaphore/releases/download/vX.Y.Z/semaphore_amd64.deb
sudo apt -y install ./semaphore_amd64.debSe usi un archivio tar.gz invece del pacchetto, estrai il binario in un path standard come `/usr/local/bin/semaphore` e verifica i permessi:
which semaphore
semaphore versionSe il comando non esiste, il problema è banale: path errato o installazione incompleta. Prima di andare avanti, risolvi quello.
Configurazione iniziale di Semaphore
Semaphore può essere inizializzato con un file di configurazione e con una procedura guidata. Per una macchina server, preferisco un file controllabile e un database PostgreSQL già pronto.
Crea un file di configurazione dedicato, ad esempio `/etc/semaphore/config.json`, con permessi stretti. Il formato preciso può variare leggermente in base alla versione, quindi verifica sempre con la documentazione della release installata. Il punto importante è tenere separati database, porta di ascolto, directory dati e chiavi sensibili.
Esempio concettuale dei parametri da definire:
- porta locale di ascolto, ad esempio 3000
- indirizzo bind su `127.0.0.1`
- backend PostgreSQL con host, database, utente e password
- directory dati sotto `/var/lib/semaphore`
- secret key applicativa generata casualmente
Genera una chiave sicura per l’applicazione:
openssl rand -hex 32Salvala nel file di configurazione o nel meccanismo previsto dalla tua versione, con permessi leggibili solo dal servizio. Verifica i permessi del file:
sudo chown root:semaphore /etc/semaphore/config.json
sudo chmod 640 /etc/semaphore/config.jsonSe la tua versione usa un file YAML o variabili d’ambiente, il principio resta identico: niente segreti in chiaro in shell history, niente permessi world-readable.
Unità systemd
Il passo che evita problemi operativi è l’unità systemd dedicata. In questo modo Semaphore parte al boot, si riavvia in caso di crash e mantiene log coerenti nel journal.
Crea `/etc/systemd/system/semaphore.service` con un approccio minimale:
[Unit]
Description=Ansible Semaphore
After=network.target postgresql.service
Wants=postgresql.service
[Service]
User=semaphore
Group=semaphore
WorkingDirectory=/var/lib/semaphore
ExecStart=/usr/bin/semaphore server --config /etc/semaphore/config.json
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
[Install]
WantedBy=multi-user.targetSe il path del binario è diverso, correggi `ExecStart`. Prima di abilitare il servizio, ricarica systemd e verifica la sintassi:
sudo systemctl daemon-reload
sudo systemd-analyze verify /etc/systemd/system/semaphore.serviceAttiva e avvia:
sudo systemctl enable --now semaphoreControlla lo stato:
systemctl status semaphore --no-pager
journalctl -u semaphore -n 100 --no-pagerSe il servizio non sale, le cause tipiche sono tre: config errata, permessi sui file, porta già occupata. In meno di cinque minuti falsifichi tutto con i log del journal e con il controllo della porta in ascolto.
Reverse proxy Nginx
Esporre direttamente Semaphore su Internet non è una buona idea. Nginx davanti gestisce TLS, header corretti e, se serve, rate limit e redirect. La web app resta in locale.
Creo un virtual host dedicato, ad esempio `/etc/nginx/sites-available/semaphore`:
server {
listen 80;
server_name semaphore.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}Abilita il sito e verifica la configurazione:
sudo ln -s /etc/nginx/sites-available/semaphore /etc/nginx/sites-enabled/semaphore
sudo nginx -t
sudo systemctl reload nginxA questo punto prova dal server:
curl -I http://127.0.0.1
curl -I http://semaphore.example.comSe il sito risponde in locale ma non via nome DNS, il problema è a monte: DNS, firewall o vhost sbagliato. Se Nginx restituisce 502, Semaphore non è in ascolto o ascolta su porta diversa.
TLS con Let’s Encrypt
Per produzione, HTTPS è obbligatorio. Su Debian 12 la via più semplice è Certbot con plugin Nginx.
sudo apt -y install certbot python3-certbot-nginx
sudo certbot --nginx -d semaphore.example.comVerifica il rinnovo automatico:
systemctl status certbot.timer --no-pager
certbot renew --dry-runDopo l’emissione del certificato, controlla che il sito risponda su 443 e che il redirect da HTTP a HTTPS funzioni. Se hai un CDN o un proxy esterno, verifica che non stia terminando lui il TLS con un certificato scaduto.
Accesso iniziale e hardening minimo
Apri il browser su `https://semaphore.example.com` e completa il primo login amministrativo. Subito dopo crea utenti nominali, gruppi e chiavi SSH separate per ambiente. Non usare una sola chiave condivisa per tutto.
Hardening minimo da applicare:
- porta applicativa bindata solo su `127.0.0.1`
- utente di servizio senza shell e senza home interattiva
- file di configurazione con permessi 640 o più restrittivi
- backup del database PostgreSQL prima di ogni upgrade
- accesso web solo via HTTPS
Se il server è esposto su Internet, aggiungi un controllo di accesso ulteriore, ad esempio allowlist IP o autenticazione a monte, se il tuo scenario lo richiede.
Backup e ripristino
La parte che salva davvero è il backup del database. Senza database, Semaphore perde inventario, job history e configurazione applicativa. Salva anche la directory dati se la tua configurazione la usa per contenuti persistenti.
Esempio di dump PostgreSQL:
pg_dump -h 127.0.0.1 -U semaphore -d semaphore | gzip > /root/backup-semaphore.sql.gzTest di ripristino in ambiente di staging o su database vuoto:
gunzip -c /root/backup-semaphore.sql.gz | psql -h 127.0.0.1 -U semaphore -d semaphoreSe il restore fallisce, non partire dal servizio web: risolvi prima il database. È il punto di verità dell’applicazione.
Verifica finale operativa
La checklist minima è questa:
- `systemctl status semaphore` mostra `active (running)`
- `curl -I http://127.0.0.1:3000` restituisce un codice 200 o un redirect atteso
- `curl -I https://semaphore.example.com` risponde con certificato valido e senza errori TLS
- il login UI funziona e salva una modifica persistente
- `journalctl -u semaphore -n 50` non mostra stack trace o errori di connessione al DB
Se uno di questi punti fallisce, il layer da controllare è già indicato: servizio, proxy, certificato o database. Non fare tuning prima di avere la catena base funzionante.
Upgrade controllato
Gli upgrade vanno trattati come change controllato. Prima leggi le note di release, poi fai backup del database e solo dopo sostituisci il binario o aggiorni il pacchetto. Se usi systemd, mantieni pronta la possibilità di rollback al binario precedente e al dump del database precedente.
Sequenza prudente:
- backup del database
- backup del file di configurazione
- stop del servizio
- aggiornamento binario o pacchetto
- start del servizio
- verifica login e job esistenti
Se qualcosa non torna, rollback immediato: ripristina il binario precedente, ricarica l’unità e, se necessario, riporta il database al dump precedente. Non mischiare dati nuovi con binari vecchi senza un motivo preciso.
Assunzione operativa: Debian 12 con PostgreSQL locale, Nginx come reverse proxy e Semaphore esposto solo via HTTPS.
Note pratiche di troubleshooting
I problemi più comuni sono quasi sempre questi: porta occupata, config non valida, password DB errata, permessi sbagliati sulla directory dati, DNS non allineato al virtual host. La falsificazione rapida si fa sempre nello stesso ordine: log del servizio, stato della porta, risposta HTTP locale, risposta HTTPS pubblica.
ss -ltnp | grep 3000
journalctl -u semaphore -n 50 --no-pager
nginx -t
curl -I http://127.0.0.1:3000Se vuoi un’installazione davvero pulita, conserva in un repository privato il file systemd, il file Nginx e la configurazione applicativa senza segreti. I segreti vanno gestiti con permessi stretti o con un vault dedicato, non in documentazione operativa.
Con questa struttura hai un’installazione solida, ripetibile e facile da amministrare su Debian 12, senza dipendere da passaggi fragili o da configurazioni implicite.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.