Installazione su macOS (nativa)
XIQUIL su macOS si installa come LaunchDaemon di sistema, senza Docker. Lo script bash install.sh rileva il PostgreSQL già presente (Homebrew, Postgres.app o EDB) o lo installa via Homebrew, configura l’utente di servizio _xiquil, il certificato TLS, CLI wrapper xiquil, icona nella menubar (con start/stop/riavvio del servizio) e launcher /Applications/XIQUIL.app.
Funziona su Apple Silicon (M1/M2/M3/M4 — arm64) e Intel (x86_64). La distribuzione è un tarball .tar.gz senza code signing né notarization Apple: l’app bundle viene creato localmente dall’installer, quindi Gatekeeper non lo blocca anche senza firma.
Questa guida copre la versione 0.21.0-beta.1-nativetest.12+. Versioni precedenti non hanno il pacchetto macOS.
Requisiti
Sezione intitolata “Requisiti”- macOS 13 (Ventura) o superiore — verifica con
sw_vers -productVersion - Apple Silicon (arm64) o Intel (x86_64) — verifica con
uname -m - Python 3.11+ (
python3 --version). Se assente, lo script suggeriscebrew install [email protected] - Xcode Command Line Tools (
xcode-select --install). Lo script offre l’installazione se mancanti - PostgreSQL 18 — uno fra:
- Homebrew
postgresql@18(raccomandato — l’installer può installarlo automaticamente) - Postgres.app (drag-and-drop GUI, popolare tra dev)
- EDB installer
.pkg - Server PostgreSQL remoto (LAN o cloud)
- Homebrew
- 2 GB RAM minimo (4 GB raccomandati)
- 800 MB di spazio disco
- Privilegi admin (l’installer richiede
sudo)
Download
Sezione intitolata “Download”Vai su Releases di GitHub e scarica il tarball corretto per la tua architettura:
# Sostituisci X.Y.Z con la versione desiderataVERSION=X.Y.Z
# Apple Silicon (M1/M2/M3/M4)curl -L -O "https://github.com/JustVitLab/xiquil/releases/download/v${VERSION}/xiquil-${VERSION}-macos-arm64.tar.gz"tar xzf "xiquil-${VERSION}-macos-arm64.tar.gz"
# Intel (Mac pre-2020)curl -L -O "https://github.com/JustVitLab/xiquil/releases/download/v${VERSION}/xiquil-${VERSION}-macos-x64.tar.gz"tar xzf "xiquil-${VERSION}-macos-x64.tar.gz"
cd "xiquil-${VERSION}"Installazione (fresh)
Sezione intitolata “Installazione (fresh)”Avvia lo script come root:
sudo bash desktop/macos/install.shWizard interattivo
Sezione intitolata “Wizard interattivo”Il wizard chiede i parametri in sequenza. Tutti hanno default sensati (basta premere Invio).
1. Pre-flight check
Verifica in ordine:
- macOS rilevato (
uname→Darwin) - Xcode Command Line Tools (
xcode-select -p) — se mancanti, offrexcode-select --install - Python ≥ 3.11 (cerca in
/opt/homebrew/bin/,/usr/local/bin/,/usr/bin/) - Installazione esistente (
launchctl print system/com.xiquil.server) → modalità upgrade
2. PostgreSQL
Lo script rileva automaticamente le installazioni note, in ordine di precedenza:
| # | Sorgente | Path tipico | Marker |
|---|---|---|---|
| 1 | Homebrew postgresql@18 | /opt/homebrew/opt/postgresql@18/bin/ (Apple Silicon) o /usr/local/opt/postgresql@18/bin/ (Intel) | homebrew |
| 2 | Postgres.app | /Applications/Postgres.app/Contents/Versions/<ver>/bin/ | postgres_app |
| 3 | EDB installer | /Library/PostgreSQL/<ver>/bin/ | edb |
| 4 | Server remoto | inserito nei prompt successivi | remote |
Se nessuna sorgente è presente, lo script propone l’installazione automatica via Homebrew (brew install postgresql@18 + brew services start postgresql@18). Prima di procedere sonda la porta 5432 con lsof. Se occupata (Docker container, pgBouncer, ecc.), aborta con messaggio chiaro.
Il marker POSTGRES_INSTALLATION viene scritto in xiquil.env e usato dall’uninstaller per decidere quali opzioni di rimozione mostrare. PostgreSQL non viene mai rimosso automaticamente dall’uninstaller — solo il database/ruolo XIQUIL è opzionalmente droppabile.
3. Database
| Campo | Default | Note |
|---|---|---|
| Host | localhost | Cambia per DB remoto. Marker → remote se non locale |
| Porta | 5432 | |
| Nome database | xiquil | |
| Utente proprietario | xiquil_admin | |
| Password applicativo | autogenerata | 24 caratteri base64. Scritta in xiquil.env |
Se il DB è locale, lo script:
- Crea il role con
CREATE ROLE xiquil_admin WITH LOGIN PASSWORD '...'(idempotente: usaALTER ROLEse esiste) - Crea il database con
createdb -O xiquil_admin --locale-provider=icu --icu-locale=en-US xiquil - Testa la connessione con
psql -c "SELECT 1"— se fallisce, aborta prima di andare avanti
Su Homebrew/Postgres.app il superuser è l’utente che ha installato PostgreSQL (di solito ${SUDO_USER}); su EDB è il classico ruolo postgres. L’installer si adatta automaticamente.
4. Rete
| Campo | Default | Note |
|---|---|---|
| Indirizzo di ascolto | 127.0.0.1 | 0.0.0.0 per LAN. Cambia anche ALLOWED_HOSTS |
| Porta HTTPS | 8443 | Su macOS evitiamo 443 (collide con AirPlay Receiver e richiede root) |
| Hostname consentiti | localhost,$(hostname) | Aggiungi IP LAN se accedi da altri PC |
| Fuso orario | Europe/Rome | Formato IANA |
5. Account amministratore (solo prima installazione)
| Campo | Note |
|---|---|
| Email del primo admin | |
| Password | Min 8 caratteri, confermata |
Cosa fa lo script
Sezione intitolata “Cosa fa lo script”In ordine, durante “Installazione in corso”:
- Verifica root, macOS, Xcode CLT, Python ≥ 3.11
- Se upgrade:
launchctl bootout system/com.xiquil.server+ polling 30s +pkill -9 -f /usr/local/opt/xiquil.*native_startupinsurance - Rileva PostgreSQL (Homebrew/Postgres.app/EDB) o offre install via Homebrew (con sonda porta 5432)
- Crea utente di sistema
_xiquilviadscl(UID assegnato nel range 250–299, gruppo dedicato_xiquil, shell/usr/bin/false, hidden) - Crea directory:
/usr/local/opt/xiquil/(applicazione)/Library/Application Support/XIQUIL/data/{uploads,plugins,certs,conf/keys}(dati, secrets, cert TLS)/var/log/xiquil/(log applicazione + healthcheck)/var/backups/xiquil/(dump pre-update / pre-uninstall)
- Copia file applicazione in
/usr/local/opt/xiquil/ - Crea venv Python e installa dipendenze:
- Prepende
$PG_BIN_DIRalPATHdurantepip install— necessario perchépsycopgcercapg_configper compilare contro libpq, e macOS non ha libpq di sistema. Senza questo step, l’install fallisce su sorgenti che non hanno wheel binari pre-compilati per la combinazione Python+arch corrente - Installa
rumps(specifico macOS) per l’icona menubar
- Prepende
- Imposta ownership
_xiquil:_xiquilsuINSTALL_DIR,DATA_DIR,LOG_DIR,BACKUP_DIR(parità con Linux — permette all’auto-update di sovrascrivere i file applicativi senza prompt admin) - Crea database, ruolo, verifica connessione (vedi sezione 3)
- Scrive
/Library/Application Support/XIQUIL/data/conf/xiquil.envcon tutti i parametri + markerPOSTGRES_INSTALLATION+POSTGRES_BIN_DIR - Esegue migrazioni Alembic — output: “Esecuzione migrazioni Alembic in corso… Può richiedere diversi minuti, non interrompere. Log live: /var/log/xiquil/app-.log”*
- Crea l’utente admin via
python -m app.cli setup --email ... --password ... - Installa
/Library/LaunchDaemons/com.xiquil.server.plist(root:wheel 644— obbligatorio per launchd) e falaunchctl bootstrap system <plist>. Pollalaunchctl printper 10s dopobootoutper evitare la race “Input/output error 5” nota su Sonoma 14.x - Installa CLI wrapper
/usr/local/bin/xiquil(vedi sezione dedicata) - Crea il bundle launcher
/Applications/XIQUIL.app/(vedi sezione dedicata) - Installa LaunchAgent menubar in
~/Library/LaunchAgents/com.xiquil.menubar.plistper l’utente che ha invocatosudo(NON in/Library/LaunchAgents/— la menubar è personale, gira nel session utente) - Healthcheck post-install (vedi sezione dedicata)
Up-and-running checklist finale
Sezione intitolata “Up-and-running checklist finale”Quando il healthcheck passa tutti e 5 i controlli, lo script stampa un banner verde con 6 bullet:
═══════════════════════════════════════════ XIQUIL è operativo: - LaunchDaemon: caricato (com.xiquil.server) - Backend: raggiungibile - Database: connesso - Backup pre-update: /var/backups/xiquil/ - URL: https://localhost:8443 - Launcher: /Applications/XIQUIL.app═══════════════════════════════════════════Lo script apre automaticamente il browser sull’URL via open (eseguito come $SUDO_USER, non come root). Se il healthcheck fallisce, banner giallo con l’exit code e l’azione consigliata, e ritorna l’exit code (utile per CI/Ansible).
Healthcheck post-install (cross-platform)
Sezione intitolata “Healthcheck post-install (cross-platform)”desktop/healthcheck.py è lo stesso script usato anche su Windows e Linux (cross-platform Python stdlib). Esegue 5 controlli sequenziali con timeout 120s:
| # | Controllo | Strumento macOS | Exit code se fallisce |
|---|---|---|---|
| 1 | Servizio registrato | launchctl print system/com.xiquil.server | 2 |
| 2 | Servizio raggiunge state = running | poll launchctl print ogni 2s | 3 (+ tail di /var/log/xiquil/xiquil-daemon.err.log) |
| 3 | Porta TCP bound su 127.0.0.1 | socket.create_connection | 4 |
| 4 | HTTPS GET /api/system/version → 200 | urllib + trust-all SSL | 1 (soft warn) |
| 5 | HTTPS GET /health → 200 con database: "connected" | come sopra, parse JSON | 5 |
Lo script di install mappa ogni exit code a un messaggio italiano colorato che ti dice esattamente dove cercare. Esempio per exit 5:
[ERROR] Backend raggiungibile ma database non connesso[ERROR] Cause comuni: password DB errata, PostgreSQL non in esecuzione, porta DB diversa da quella in /Library/Application Support/XIQUIL/data/conf/xiquil.env[ERROR] Diagnostica: tail /var/log/xiquil/app-*.logIl healthcheck scrive un log persistente in /var/log/xiquil/healthcheck-YYYYMMDD_HHMMSS.log. Su exit 3 (servizio non running) include automaticamente il tail di /var/log/xiquil/xiquil-daemon.err.log (lo stderr catturato da launchd).
Lanciarlo manualmente in qualsiasi momento:
xiquil health# Equivalente a:sudo /usr/local/opt/xiquil/venv/bin/python /usr/local/opt/xiquil/desktop/healthcheck.py --port 8443 --timeout 30CLI wrapper xiquil
Sezione intitolata “CLI wrapper xiquil”Lo script bash installato in /usr/local/bin/xiquil espone i comandi più comuni con sintassi semplificata. È un thin layer su launchctl/tail/open/healthcheck.py. Auto-eleva via sudo solo per i comandi privileged (start/stop/restart). I read-only non chiedono mai password.
| Comando | Azione | Sudo? |
|---|---|---|
xiquil status | Banner stato servizio + URL applicazione + estratto launchctl print | No |
xiquil start | launchctl bootstrap system <plist> (o kickstart -k se già caricato) | Sì (auto-prepende) |
xiquil stop | launchctl bootout system/com.xiquil.server | Sì |
xiquil restart | launchctl kickstart -k | Sì |
xiquil logs | tail -n 50 -F /var/log/xiquil/xiquil-daemon.{out,err}.log (live) | No |
xiquil logs 200 | tail con N righe iniziali specificate | No |
xiquil open | open https://localhost:<porta> (porta letta da env) | No |
xiquil health | Esegue healthcheck.py con la porta giusta | No |
xiquil version | cat /usr/local/opt/xiquil/VERSION | No |
xiquil help | Elenco comandi (default se nessun arg) | No |
Esempi pratici:
xiquil status # "● XIQUIL is running (https://hostname:8443)"xiquil restart # auto-sudoxiquil logs # tail live -F su out + errxiquil logs 500 # ultime 500 righe + seguixiquil health # diagnostica completa, exit code 0-5xiquil open # apre il browserMenubar status icon (rumps)
Sezione intitolata “Menubar status icon (rumps)”Sulla barra dei menu di macOS appare un’icona testuale “X” che riflette lo stato del servizio:
| Glyph | Stato |
|---|---|
X | Servizio in esecuzione (state = running) |
X· | Servizio caricato ma non running, o non caricato |
X… | Avvio / arresto / riavvio in corso |
X? | Stato sconosciuto (errore launchctl) |
Cliccando l’icona si apre un menu a tendina con le stesse azioni del CLI wrapper:
- Apri nel browser — apre l’URL HTTPS configurato
- Avvia / Arresta / Riavvia servizio — attiva un dialog admin di macOS (
do shell script ... with administrator privileges) per autenticare le operazionilaunchctl bootstrap/bootout/kickstartche richiedono root. Dopo conferma, il dialog si chiude e l’azione viene eseguita - Apri cartella log — apre
/var/log/xiquil/in Finder - Apri cartella dati — apre
/Library/Application Support/XIQUIL/data/in Finder - Esci — termina il processo menubar (NON arresta il servizio)
L’icona aggiorna lo stato ogni 10 secondi tramite rumps.Timer (callback sul main thread Cocoa, niente race condition con AppKit).
Architettura LaunchAgent vs LaunchDaemon
Sezione intitolata “Architettura LaunchAgent vs LaunchDaemon”XIQUIL usa due plist launchd con scopi diversi:
| Componente | Tipo | Path | User | Quando parte |
|---|---|---|---|---|
| Backend FastAPI | LaunchDaemon | /Library/LaunchDaemons/com.xiquil.server.plist | _xiquil (system) | Al boot, prima del login |
| Menubar (rumps) | LaunchAgent | ~/Library/LaunchAgents/com.xiquil.menubar.plist | utente corrente | Al login utente |
Questa è la separazione corretta secondo le convenzioni Apple: il backend è un servizio di sistema (vive a prescindere da chi è loggato); la menubar è una UI personale (vive solo nella sessione dell’utente che l’ha installata).
Se più utenti usano lo stesso Mac e tutti vogliono la menubar, ognuno deve ricopiarsi il plist:
cp /usr/local/opt/xiquil/desktop/macos/com.xiquil.menubar.plist ~/Library/LaunchAgents/launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/com.xiquil.menubar.plist“Esci” non riavvia la menubar fino al login successivo
Sezione intitolata ““Esci” non riavvia la menubar fino al login successivo”Il LaunchAgent ha KeepAlive = { SuccessfulExit = false }: respawn solo su crash, non quando l’utente seleziona “Esci”. Per riavviarla manualmente nello stesso login:
launchctl kickstart -k "gui/$(id -u)/com.xiquil.menubar"Launcher /Applications/XIQUIL.app
Sezione intitolata “Launcher /Applications/XIQUIL.app”In /Applications/ viene creata un’app drag-friendly chiamata XIQUIL che è semplicemente un launcher: doppio-click apre https://localhost:<porta> nel browser predefinito. Il backend non è dentro l’app bundle — il backend è il LaunchDaemon com.xiquil.server registrato in /Library/LaunchDaemons/.
Struttura del bundle:
/Applications/XIQUIL.app/├── Contents/│ ├── Info.plist # CFBundleIdentifier, version, app metadata│ ├── MacOS/│ │ └── xiquil # Shell script: exec /usr/bin/open <APP_URL>│ └── Resources/│ └── xiquil.png # Logo (se presente)L’URL è sostituito a install-time in Info.plist (chiave XQAppURL) e nello script launcher. Se cambi APP_PORT in xiquil.env, devi aggiornare il bundle (rilancia install.sh o modifica manualmente il path nello script).
Aggiornamento (upgrade)
Sezione intitolata “Aggiornamento (upgrade)”Due strade.
Manuale (riesegue install.sh):
VERSION=X.Y.Zcurl -L -O "https://github.com/JustVitLab/xiquil/releases/download/v${VERSION}/xiquil-${VERSION}-macos-arm64.tar.gz"tar xzf "xiquil-${VERSION}-macos-arm64.tar.gz"cd "xiquil-${VERSION}"sudo bash desktop/macos/install.shLo script rileva l’installazione esistente leggendo /Library/Application Support/XIQUIL/data/conf/xiquil.env e procede in modalità upgrade: bootout LaunchDaemon + kill processi residui, sovrascrive i file, riapplica le migrazioni, ricarica.
Automatica (dal pannello admin web):
XIQUIL include un updater integrato (desktop/updater.py). Quando una nuova versione è disponibile (notification aggiornamento_disponibile agli admin), il pannello “Aggiornamenti” può triggerare l’upgrade da browser. Su macOS esegue:
- Backup pre-update (best-effort):
pg_dump→/var/backups/xiquil/pre_update_YYYYMMDD_HHMMSS.dump. Cercapg_dumpsu PATH, poi nei path noti (Homebrew, Postgres.app, EDB) launchctl bootout system/com.xiquil.server+ polling 30s +pkill -9insurance sui residual python sotto/usr/local/opt/xiquil- Estrae il tarball su
/usr/local/opt/xiquil/contar xzf --strip-components=1 --no-same-owner - Aggiorna le dipendenze:
pip install -r requirements.txt launchctl bootstrap system /Library/LaunchDaemons/com.xiquil.server.plist(le migrazioni partono innative_startupprima del bind della porta)
Il backup pre-update è sempre best-effort: se PG non è raggiungibile o le credenziali non sono valide, viene loggato un warning e l’update procede comunque.
Disinstallazione
Sezione intitolata “Disinstallazione”sudo bash /usr/local/opt/xiquil/desktop/macos/uninstall.shCosa fa sempre:
- Backup precauzionale del database in
/var/backups/xiquil/pre_uninstall_YYYYMMDD_HHMMSS.dump(best-effort: cercapg_dumpcon la stessa precedenza dell’updater) launchctl bootout system/com.xiquil.server+ polling stop +pkill -9sui residual python- Rimuove il plist
/Library/LaunchDaemons/com.xiquil.server.plist - Bootout + rimozione del LaunchAgent menubar del primo utente non-root rilevato (via
SUDO_USERostat -fsui/Users/) - Elimina
/Applications/XIQUIL.app/ - Elimina
/usr/local/bin/xiquil(CLI wrapper) - Elimina
/usr/local/opt/xiquil/
Cosa chiede esplicitamente (default NO):
- Eliminare il database
xiquil+ ruoloxiquil_admin? Solo se confermi. Locale: usapsqlcomepostgressuperuser (su EDB) o come l’utente che possiede il cluster (Homebrew/Postgres.app). Remoto: skip (servirebbe accesso al server remoto). - Eliminare l’utente di sistema
_xiquil? Default NO. Usadscl . -delete /Users/_xiquil.
Cosa NON fa mai automaticamente:
- PostgreSQL non viene rimosso. Potrebbe essere usato da altre applicazioni sul tuo sistema. Lo script stampa i comandi per la rimozione manuale, adattati alla sorgente rilevata in
POSTGRES_INSTALLATION:- Homebrew: brew uninstall postgresql@18brew services stop postgresql@18- Postgres.app: trascina /Applications/Postgres.app nel Cestino(i dati restano in ~/Library/Application Support/Postgres)- EDB installer: esegui /Library/PostgreSQL/18/uninstall-postgres.app /Library/Application Support/XIQUIL/(dati, conf, certs) conservato sempre — incluso il dump pre-uninstall appena creato. Per re-install futuro o forensics.
Il summary finale ricorda i path conservati e il comando per la rimozione totale (irreversibile):
sudo rm -rf "/Library/Application Support/XIQUIL" /var/log/xiquil /var/backups/xiquilServizio LaunchDaemon
Sezione intitolata “Servizio LaunchDaemon”Il file /Library/LaunchDaemons/com.xiquil.server.plist:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict> <key>Label</key> <string>com.xiquil.server</string>
<key>UserName</key> <string>_xiquil</string> <key>GroupName</key> <string>_xiquil</string>
<key>ProgramArguments</key> <array> <string>/usr/local/opt/xiquil/venv/bin/python</string> <string>-m</string> <string>desktop.native_startup</string> </array>
<key>WorkingDirectory</key> <string>/usr/local/opt/xiquil/backend</string>
<key>EnvironmentVariables</key> <dict> <key>NATIVE_MODE</key> <string>1</string> <key>PYTHONPATH</key> <string>/usr/local/opt/xiquil/backend:/usr/local/opt/xiquil</string> <key>PYTHONUNBUFFERED</key> <string>1</string> </dict>
<key>StandardOutPath</key> <string>/var/log/xiquil/xiquil-daemon.out.log</string> <key>StandardErrorPath</key> <string>/var/log/xiquil/xiquil-daemon.err.log</string>
<key>RunAtLoad</key> <true/> <key>KeepAlive</key> <dict> <key>SuccessfulExit</key> <false/> </dict> <key>ThrottleInterval</key> <integer>10</integer></dict></plist>Hardening applicato:
| Direttiva | Effetto |
|---|---|
UserName / GroupName = _xiquil | Drop privileges all’avvio: niente root, niente shell, NFSHomeDirectory ristretta |
KeepAlive = SuccessfulExit:false | Respawn solo su crash, mai su exit pulito (evita loop) |
ThrottleInterval = 10 | Minimo 10s fra restart consecutivi |
StandardErrorPath | stderr catturato in /var/log/xiquil/xiquil-daemon.err.log per diagnostica |
Accesso dalla rete locale (LAN)
Sezione intitolata “Accesso dalla rete locale (LAN)”Per accedere da altri computer della LAN:
-
Modifica
/Library/Application Support/XIQUIL/data/conf/xiquil.env:Terminal window sudo nano "/Library/Application Support/XIQUIL/data/conf/xiquil.env"Imposta:
Terminal window APP_HOST=0.0.0.0ALLOWED_HOSTS=localhost,nome-mac.local,192.168.1.50 -
macOS ha due livelli di firewall, entrambi devono permettere il traffico:
Application Firewall (Impostazioni di Sistema → Rete → Firewall):
- Se il firewall è ON, aggiungi
python(quello del venv:/usr/local/opt/xiquil/venv/bin/python) alle app autorizzate, oppure disabilita la modalità “Block all incoming connections” che blocca anche connessioni LAN.
PF (Packet Filter) — di solito disabilitato di default. Se lo hai attivato manualmente (raro), aggiungi una regola per la porta 8443.
- Se il firewall è ON, aggiungi
-
Riavvia il servizio:
Terminal window xiquil restart
Da un altro device, apri https://192.168.1.50:8443 (o la porta configurata).
Percorsi dei file
Sezione intitolata “Percorsi dei file”| Contenuto | Percorso |
|---|---|
| Applicazione | /usr/local/opt/xiquil/ |
| Ambiente Python (venv) | /usr/local/opt/xiquil/venv/ |
| Backend Python | /usr/local/opt/xiquil/backend/ |
| Frontend compilato | /usr/local/opt/xiquil/frontend/dist/ |
| Healthcheck (cross-platform) | /usr/local/opt/xiquil/desktop/healthcheck.py |
| Configurazione | /Library/Application Support/XIQUIL/data/conf/xiquil.env |
| Certificati TLS | /Library/Application Support/XIQUIL/data/certs/ |
| Upload utente | /Library/Application Support/XIQUIL/data/uploads/ |
| Log applicazione (rotazione giornaliera) | /var/log/xiquil/app-YYYY-MM-DD.log |
| Log daemon (stderr/stdout launchd) | /var/log/xiquil/xiquil-daemon.{out,err}.log |
| Log healthcheck | /var/log/xiquil/healthcheck-*.log |
| Log installer | /var/log/xiquil-install.log |
| Log uninstaller | /var/log/xiquil-uninstall.log |
| Log menubar | ~/Library/Logs/XIQUIL/menubar.log |
| Backup database | /var/backups/xiquil/{pre_update,pre_uninstall}_*.dump |
| LaunchDaemon plist | /Library/LaunchDaemons/com.xiquil.server.plist |
| LaunchAgent menubar plist | ~/Library/LaunchAgents/com.xiquil.menubar.plist |
| CLI wrapper | /usr/local/bin/xiquil |
| Launcher Finder | /Applications/XIQUIL.app |
Comandi utili
Sezione intitolata “Comandi utili”# Wrapper xiquil (consigliato)xiquil status # banner stato + URLxiquil restart # auto-sudoxiquil logs # tail live -Fxiquil logs 200 # ultime 200 righe + seguixiquil health # diagnostica completa exit 0-5xiquil open # apre il browserxiquil version
# launchctl diretto (equivalenti)sudo launchctl print system/com.xiquil.serversudo launchctl kickstart -k system/com.xiquil.servertail -F /var/log/xiquil/xiquil-daemon.err.log
# Quale processo tiene una portasudo lsof -nP -iTCP:8443 -sTCP:LISTENsudo lsof -nP -iTCP:5432 -sTCP:LISTEN
# Healthcheck manuale dettagliatosudo /usr/local/opt/xiquil/venv/bin/python \ /usr/local/opt/xiquil/desktop/healthcheck.py --port 8443 --timeout 30
# CLI utenti applicativi (lo eseguiamo come _xiquil)sudo -u _xiquil NATIVE_MODE=1 \ PYTHONPATH=/usr/local/opt/xiquil/backend:/usr/local/opt/xiquil \ /usr/local/opt/xiquil/venv/bin/python -m app.cli list-users
sudo -u _xiquil NATIVE_MODE=1 \ PYTHONPATH=/usr/local/opt/xiquil/backend:/usr/local/opt/xiquil \
# Modifica config + restartsudo nano "/Library/Application Support/XIQUIL/data/conf/xiquil.env"xiquil restart
# Backup manuale del database (oltre a quelli automatici dell'app)sudo -u _xiquil pg_dump -h 127.0.0.1 -U xiquil_admin -d xiquil \ -Fc -f "/var/backups/xiquil/manual_$(date +%Y%m%d_%H%M%S).dump"
# Reload del menubar (utente non-root)launchctl kickstart -k "gui/$(id -u)/com.xiquil.menubar"Risoluzione problemi
Sezione intitolata “Risoluzione problemi”xiquil status dice “not loaded” o “loaded but not running”
Sezione intitolata “xiquil status dice “not loaded” o “loaded but not running””# Cosa dice launchd (richiede sudo per il dettaglio completo)sudo launchctl print system/com.xiquil.server
# Tail dello stderr del daemon (errori uvicorn / migration / cert)tail -100 /var/log/xiquil/xiquil-daemon.err.log
# Log applicativo recenti (Python logging)tail -100 /var/log/xiquil/app-*.log
# PG attivo? (Homebrew)brew services list | grep postgresql
# PG attivo? (qualsiasi)sudo lsof -nP -iTCP:5432 -sTCP:LISTENbootstrap ritorna “Input/output error 5” (Sonoma)
Sezione intitolata “bootstrap ritorna “Input/output error 5” (Sonoma)”Race nota di launchd su macOS 14.x: bootstrap immediatamente dopo bootout fallisce. L’installer e il CLI wrapper aggiungono già polling automatico, ma se lo stai facendo a mano:
sudo launchctl bootout system/com.xiquil.server# Aspetta che 'launchctl print' ritorni non-zerowhile sudo launchctl print system/com.xiquil.server &>/dev/null; do sleep 0.5; donesudo launchctl bootstrap system /Library/LaunchDaemons/com.xiquil.server.plistxiquil health esce con exit code 5 (DB non connesso)
Sezione intitolata “xiquil health esce con exit code 5 (DB non connesso)”# Log app per l'errore SQLAlchemy precisotail -100 /var/log/xiquil/app-*.log
# Test diretto della connessione con le credenziali del file envENV_FILE="/Library/Application Support/XIQUIL/data/conf/xiquil.env"DB_USER=$(grep -E '^POSTGRES_USER=' "$ENV_FILE" | cut -d= -f2-)DB_PASS=$(grep -E '^POSTGRES_PASSWORD=' "$ENV_FILE" | cut -d= -f2-)DB_NAME=$(grep -E '^POSTGRES_DB=' "$ENV_FILE" | cut -d= -f2-)DB_PORT=$(grep -E '^POSTGRES_PORT=' "$ENV_FILE" | cut -d= -f2-)PSQL=$(grep -E '^POSTGRES_BIN_DIR=' "$ENV_FILE" | cut -d= -f2-)/psqlPGPASSWORD="$DB_PASS" "$PSQL" -h 127.0.0.1 -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1"Se il psql funziona ma il backend no: probabile mismatch fra quello che l’app legge e quello che pensi sia in env.
pip install psycopg fallisce con “pg_config not found”
Sezione intitolata “pip install psycopg fallisce con “pg_config not found””Significa che durante install.sh non era stato rilevato un PG_BIN_DIR valido. Controlla:
# Quale Postgres è installato?brew --prefix postgresql@18 2>/dev/nullls /Applications/Postgres.app/Contents/Versions/ 2>/dev/nullls /Library/PostgreSQL/ 2>/dev/null
# Forza un path manualmente e riesegui pip installexport PATH="/opt/homebrew/opt/postgresql@18/bin:$PATH"sudo /usr/local/opt/xiquil/venv/bin/pip install -r /usr/local/opt/xiquil/backend/requirements.txtPermessi negati sui file /Library/Application Support/XIQUIL/
Sezione intitolata “Permessi negati sui file /Library/Application Support/XIQUIL/”Tipicamente succede dopo un chmod -R accidentale o un restore manuale dei dati:
sudo chown -R _xiquil:_xiquil "/Library/Application Support/XIQUIL" /var/log/xiquil /var/backups/xiquilsudo chown -R _xiquil:_xiquil /usr/local/opt/xiquilsudo chmod 750 "/Library/Application Support/XIQUIL/data/conf" /var/log/xiquilxiquil restartLa menubar non appare al login
Sezione intitolata “La menubar non appare al login”# Verifica il LaunchAgentls -l ~/Library/LaunchAgents/com.xiquil.menubar.plistlaunchctl print "gui/$(id -u)/com.xiquil.menubar" 2>&1 | head -20
# Log della menubar (solitamente in ~/Library/Logs/XIQUIL/)tail -50 ~/Library/Logs/XIQUIL/menubar.log# Fallback: logs di launchdtail -50 /tmp/xiquil-menubar.err.logSe manca il plist: ricaricalo a mano (per esempio dopo aver rimosso e reinstallato XIQUIL su un altro account utente):
cp /usr/local/opt/xiquil/desktop/macos/com.xiquil.menubar.plist ~/Library/LaunchAgents/launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/com.xiquil.menubar.plistSe rumps non è nel venv (errore ImportError: rumps):
sudo /usr/local/opt/xiquil/venv/bin/pip install rumpslaunchctl kickstart -k "gui/$(id -u)/com.xiquil.menubar"Voglio rimuovere completamente XIQUIL incluso PostgreSQL
Sezione intitolata “Voglio rimuovere completamente XIQUIL incluso PostgreSQL”In uninstall.sh, conferma il drop del database; poi a mano:
# Rimuovi PostgreSQL (impatta tutto il sistema!)# Homebrewbrew services stop postgresql@18brew uninstall postgresql@18
# Postgres.app: trascina nel cestino + rimuovi datirm -rf "$HOME/Library/Application Support/Postgres"
# EDBsudo /Library/PostgreSQL/18/uninstall-postgres.app/Contents/MacOS/installbuilder.sh
# Pulizia totale dei dati XIQUILsudo rm -rf "/Library/Application Support/XIQUIL" /var/log/xiquil /var/backups/xiquilGatekeeper blocca l’apertura di XIQUIL.app
Sezione intitolata “Gatekeeper blocca l’apertura di XIQUIL.app”In condizioni normali non succede (l’app è creata localmente da install.sh, niente quarantine xattr). Se invece hai zippato e ricopiato il bundle, oppure scaricato da Safari un bundle pre-confezionato:
# Rimuovi la quarantine ricorsivamentexattr -dr com.apple.quarantine /Applications/XIQUIL.app
# Verificaxattr /Applications/XIQUIL.app# Output atteso: nessun com.apple.quarantineIl browser mostra solo JSON {"app":"XIQUIL","status":"running",...}
Sezione intitolata “Il browser mostra solo JSON {"app":"XIQUIL","status":"running",...}”Stai visitando la root del backend invece della SPA React. Vai su https://localhost:<porta>/login (o /setup per la prima configurazione). Versioni nativetest.12+ rendono / la SPA in native mode (gestito in backend/app/main.py).