Salta ai contenuti

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.

  • 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 suggerisce brew 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)
  • 2 GB RAM minimo (4 GB raccomandati)
  • 800 MB di spazio disco
  • Privilegi admin (l’installer richiede sudo)

Vai su Releases di GitHub e scarica il tarball corretto per la tua architettura:

Terminal window
# Sostituisci X.Y.Z con la versione desiderata
VERSION=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}"

Avvia lo script come root:

Terminal window
sudo bash desktop/macos/install.sh

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, offre xcode-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:

#SorgentePath tipicoMarker
1Homebrew postgresql@18/opt/homebrew/opt/postgresql@18/bin/ (Apple Silicon) o /usr/local/opt/postgresql@18/bin/ (Intel)homebrew
2Postgres.app/Applications/Postgres.app/Contents/Versions/<ver>/bin/postgres_app
3EDB installer/Library/PostgreSQL/<ver>/bin/edb
4Server remotoinserito nei prompt successiviremote

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

CampoDefaultNote
HostlocalhostCambia per DB remoto. Marker → remote se non locale
Porta5432
Nome databasexiquil
Utente proprietarioxiquil_admin
Password applicativoautogenerata24 caratteri base64. Scritta in xiquil.env

Se il DB è locale, lo script:

  • Crea il role con CREATE ROLE xiquil_admin WITH LOGIN PASSWORD '...' (idempotente: usa ALTER ROLE se 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

CampoDefaultNote
Indirizzo di ascolto127.0.0.10.0.0.0 per LAN. Cambia anche ALLOWED_HOSTS
Porta HTTPS8443Su macOS evitiamo 443 (collide con AirPlay Receiver e richiede root)
Hostname consentitilocalhost,$(hostname)Aggiungi IP LAN se accedi da altri PC
Fuso orarioEurope/RomeFormato IANA

5. Account amministratore (solo prima installazione)

CampoNote
EmailEmail del primo admin
PasswordMin 8 caratteri, confermata

In ordine, durante “Installazione in corso”:

  1. Verifica root, macOS, Xcode CLT, Python ≥ 3.11
  2. Se upgrade: launchctl bootout system/com.xiquil.server + polling 30s + pkill -9 -f /usr/local/opt/xiquil.*native_startup insurance
  3. Rileva PostgreSQL (Homebrew/Postgres.app/EDB) o offre install via Homebrew (con sonda porta 5432)
  4. Crea utente di sistema _xiquil via dscl (UID assegnato nel range 250–299, gruppo dedicato _xiquil, shell /usr/bin/false, hidden)
  5. 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)
  6. Copia file applicazione in /usr/local/opt/xiquil/
  7. Crea venv Python e installa dipendenze:
    • Prepende $PG_BIN_DIR al PATH durante pip install — necessario perché psycopg cerca pg_config per 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
  8. Imposta ownership _xiquil:_xiquil su INSTALL_DIR, DATA_DIR, LOG_DIR, BACKUP_DIR (parità con Linux — permette all’auto-update di sovrascrivere i file applicativi senza prompt admin)
  9. Crea database, ruolo, verifica connessione (vedi sezione 3)
  10. Scrive /Library/Application Support/XIQUIL/data/conf/xiquil.env con tutti i parametri + marker POSTGRES_INSTALLATION + POSTGRES_BIN_DIR
  11. Esegue migrazioni Alembic — output: “Esecuzione migrazioni Alembic in corso… Può richiedere diversi minuti, non interrompere. Log live: /var/log/xiquil/app-.log”*
  12. Crea l’utente admin via python -m app.cli setup --email ... --password ...
  13. Installa /Library/LaunchDaemons/com.xiquil.server.plist (root:wheel 644 — obbligatorio per launchd) e fa launchctl bootstrap system <plist>. Polla launchctl print per 10s dopo bootout per evitare la race “Input/output error 5” nota su Sonoma 14.x
  14. Installa CLI wrapper /usr/local/bin/xiquil (vedi sezione dedicata)
  15. Crea il bundle launcher /Applications/XIQUIL.app/ (vedi sezione dedicata)
  16. Installa LaunchAgent menubar in ~/Library/LaunchAgents/com.xiquil.menubar.plist per l’utente che ha invocato sudo (NON in /Library/LaunchAgents/ — la menubar è personale, gira nel session utente)
  17. Healthcheck post-install (vedi sezione dedicata)

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).

desktop/healthcheck.py è lo stesso script usato anche su Windows e Linux (cross-platform Python stdlib). Esegue 5 controlli sequenziali con timeout 120s:

#ControlloStrumento macOSExit code se fallisce
1Servizio registratolaunchctl print system/com.xiquil.server2
2Servizio raggiunge state = runningpoll launchctl print ogni 2s3 (+ tail di /var/log/xiquil/xiquil-daemon.err.log)
3Porta TCP bound su 127.0.0.1socket.create_connection4
4HTTPS GET /api/system/version → 200urllib + trust-all SSL1 (soft warn)
5HTTPS GET /health → 200 con database: "connected"come sopra, parse JSON5

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-*.log

Il 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:

Terminal window
xiquil health
# Equivalente a:
sudo /usr/local/opt/xiquil/venv/bin/python /usr/local/opt/xiquil/desktop/healthcheck.py --port 8443 --timeout 30

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.

ComandoAzioneSudo?
xiquil statusBanner stato servizio + URL applicazione + estratto launchctl printNo
xiquil startlaunchctl bootstrap system <plist> (o kickstart -k se già caricato)Sì (auto-prepende)
xiquil stoplaunchctl bootout system/com.xiquil.serverSì
xiquil restartlaunchctl kickstart -kSì
xiquil logstail -n 50 -F /var/log/xiquil/xiquil-daemon.{out,err}.log (live)No
xiquil logs 200tail con N righe iniziali specificateNo
xiquil openopen https://localhost:<porta> (porta letta da env)No
xiquil healthEsegue healthcheck.py con la porta giustaNo
xiquil versioncat /usr/local/opt/xiquil/VERSIONNo
xiquil helpElenco comandi (default se nessun arg)No

Esempi pratici:

Terminal window
xiquil status # "● XIQUIL is running (https://hostname:8443)"
xiquil restart # auto-sudo
xiquil logs # tail live -F su out + err
xiquil logs 500 # ultime 500 righe + segui
xiquil health # diagnostica completa, exit code 0-5
xiquil open # apre il browser

Sulla barra dei menu di macOS appare un’icona testuale “X” che riflette lo stato del servizio:

GlyphStato
XServizio 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 operazioni launchctl bootstrap/bootout/kickstart che 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).

XIQUIL usa due plist launchd con scopi diversi:

ComponenteTipoPathUserQuando parte
Backend FastAPILaunchDaemon/Library/LaunchDaemons/com.xiquil.server.plist_xiquil (system)Al boot, prima del login
Menubar (rumps)LaunchAgent~/Library/LaunchAgents/com.xiquil.menubar.plistutente correnteAl 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:

Terminal window
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:

Terminal window
launchctl kickstart -k "gui/$(id -u)/com.xiquil.menubar"

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).

Due strade.

Manuale (riesegue install.sh):

Terminal window
VERSION=X.Y.Z
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"
cd "xiquil-${VERSION}"
sudo bash desktop/macos/install.sh

Lo 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:

  1. Backup pre-update (best-effort): pg_dump → /var/backups/xiquil/pre_update_YYYYMMDD_HHMMSS.dump. Cerca pg_dump su PATH, poi nei path noti (Homebrew, Postgres.app, EDB)
  2. launchctl bootout system/com.xiquil.server + polling 30s + pkill -9 insurance sui residual python sotto /usr/local/opt/xiquil
  3. Estrae il tarball su /usr/local/opt/xiquil/ con tar xzf --strip-components=1 --no-same-owner
  4. Aggiorna le dipendenze: pip install -r requirements.txt
  5. launchctl bootstrap system /Library/LaunchDaemons/com.xiquil.server.plist (le migrazioni partono in native_startup prima 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.

Terminal window
sudo bash /usr/local/opt/xiquil/desktop/macos/uninstall.sh

Cosa fa sempre:

  1. Backup precauzionale del database in /var/backups/xiquil/pre_uninstall_YYYYMMDD_HHMMSS.dump (best-effort: cerca pg_dump con la stessa precedenza dell’updater)
  2. launchctl bootout system/com.xiquil.server + polling stop + pkill -9 sui residual python
  3. Rimuove il plist /Library/LaunchDaemons/com.xiquil.server.plist
  4. Bootout + rimozione del LaunchAgent menubar del primo utente non-root rilevato (via SUDO_USER o stat -f sui /Users/)
  5. Elimina /Applications/XIQUIL.app/
  6. Elimina /usr/local/bin/xiquil (CLI wrapper)
  7. Elimina /usr/local/opt/xiquil/

Cosa chiede esplicitamente (default NO):

  • Eliminare il database xiquil + ruolo xiquil_admin? Solo se confermi. Locale: usa psql come postgres superuser (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. Usa dscl . -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@18
    brew 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):

Terminal window
sudo rm -rf "/Library/Application Support/XIQUIL" /var/log/xiquil /var/backups/xiquil

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:

DirettivaEffetto
UserName / GroupName = _xiquilDrop privileges all’avvio: niente root, niente shell, NFSHomeDirectory ristretta
KeepAlive = SuccessfulExit:falseRespawn solo su crash, mai su exit pulito (evita loop)
ThrottleInterval = 10Minimo 10s fra restart consecutivi
StandardErrorPathstderr catturato in /var/log/xiquil/xiquil-daemon.err.log per diagnostica

Per accedere da altri computer della LAN:

  1. 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.0
    ALLOWED_HOSTS=localhost,nome-mac.local,192.168.1.50
  2. 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.

  3. Riavvia il servizio:

    Terminal window
    xiquil restart

Da un altro device, apri https://192.168.1.50:8443 (o la porta configurata).

ContenutoPercorso
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
Terminal window
# Wrapper xiquil (consigliato)
xiquil status # banner stato + URL
xiquil restart # auto-sudo
xiquil logs # tail live -F
xiquil logs 200 # ultime 200 righe + segui
xiquil health # diagnostica completa exit 0-5
xiquil open # apre il browser
xiquil version
# launchctl diretto (equivalenti)
sudo launchctl print system/com.xiquil.server
sudo launchctl kickstart -k system/com.xiquil.server
tail -F /var/log/xiquil/xiquil-daemon.err.log
# Quale processo tiene una porta
sudo lsof -nP -iTCP:8443 -sTCP:LISTEN
sudo lsof -nP -iTCP:5432 -sTCP:LISTEN
# Healthcheck manuale dettagliato
sudo /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 \
/usr/local/opt/xiquil/venv/bin/python -m app.cli reset-password --email [email protected]
# Modifica config + restart
sudo 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"

xiquil status dice “not loaded” o “loaded but not running”

Sezione intitolata “xiquil status dice “not loaded” o “loaded but not running””
Terminal window
# 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:LISTEN

bootstrap 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:

Terminal window
sudo launchctl bootout system/com.xiquil.server
# Aspetta che 'launchctl print' ritorni non-zero
while sudo launchctl print system/com.xiquil.server &>/dev/null; do sleep 0.5; done
sudo launchctl bootstrap system /Library/LaunchDaemons/com.xiquil.server.plist

xiquil health esce con exit code 5 (DB non connesso)

Sezione intitolata “xiquil health esce con exit code 5 (DB non connesso)”
Terminal window
# Log app per l'errore SQLAlchemy preciso
tail -100 /var/log/xiquil/app-*.log
# Test diretto della connessione con le credenziali del file env
ENV_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-)/psql
PGPASSWORD="$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:

Terminal window
# Quale Postgres è installato?
brew --prefix postgresql@18 2>/dev/null
ls /Applications/Postgres.app/Contents/Versions/ 2>/dev/null
ls /Library/PostgreSQL/ 2>/dev/null
# Forza un path manualmente e riesegui pip install
export PATH="/opt/homebrew/opt/postgresql@18/bin:$PATH"
sudo /usr/local/opt/xiquil/venv/bin/pip install -r /usr/local/opt/xiquil/backend/requirements.txt

Permessi 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:

Terminal window
sudo chown -R _xiquil:_xiquil "/Library/Application Support/XIQUIL" /var/log/xiquil /var/backups/xiquil
sudo chown -R _xiquil:_xiquil /usr/local/opt/xiquil
sudo chmod 750 "/Library/Application Support/XIQUIL/data/conf" /var/log/xiquil
xiquil restart
Terminal window
# Verifica il LaunchAgent
ls -l ~/Library/LaunchAgents/com.xiquil.menubar.plist
launchctl 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 launchd
tail -50 /tmp/xiquil-menubar.err.log

Se manca il plist: ricaricalo a mano (per esempio dopo aver rimosso e reinstallato XIQUIL su un altro account utente):

Terminal window
cp /usr/local/opt/xiquil/desktop/macos/com.xiquil.menubar.plist ~/Library/LaunchAgents/
launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/com.xiquil.menubar.plist

Se rumps non è nel venv (errore ImportError: rumps):

Terminal window
sudo /usr/local/opt/xiquil/venv/bin/pip install rumps
launchctl 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:

Terminal window
# Rimuovi PostgreSQL (impatta tutto il sistema!)
# Homebrew
brew services stop postgresql@18
brew uninstall postgresql@18
# Postgres.app: trascina nel cestino + rimuovi dati
rm -rf "$HOME/Library/Application Support/Postgres"
# EDB
sudo /Library/PostgreSQL/18/uninstall-postgres.app/Contents/MacOS/installbuilder.sh
# Pulizia totale dei dati XIQUIL
sudo rm -rf "/Library/Application Support/XIQUIL" /var/log/xiquil /var/backups/xiquil

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:

Terminal window
# Rimuovi la quarantine ricorsivamente
xattr -dr com.apple.quarantine /Applications/XIQUIL.app
# Verifica
xattr /Applications/XIQUIL.app
# Output atteso: nessun com.apple.quarantine

Il 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).