# TerManager2 Applicazione web per la **gestione dell'assegnazione e rientro di territori** (cartoline), statistiche di percorrenza e campagne speciali per congregazioni. --- ## Indice - [Panoramica](#panoramica) - [Stack tecnologico](#stack-tecnologico) - [Requisiti di sistema](#requisiti-di-sistema) - [Installazione da zero](#installazione-da-zero) - [Configurazione](#configurazione) - [Migrazione su nuovo server](#migrazione-su-nuovo-server) - [Comandi utili](#comandi-utili) - [Troubleshooting](#troubleshooting) - [Struttura del progetto](#struttura-del-progetto) - [Funzionalità principali](#funzionalità-principali) - [Ruoli e permessi (RBAC)](#ruoli-e-permessi-rbac) - [Sicurezza e GDPR](#sicurezza-e-gdpr) - [Modello dati](#modello-dati) - [Regole di business](#regole-di-business) - [Produzione](#produzione) - [Licenza](#licenza) --- ## Panoramica **TerManager2** gestisce: - **Territori** (cartoline) con PDF allegato, stato dinamico (in reparto / assegnato / da rientrare / prioritario / inattivo), zona e tipologia. - **Proclamatori** (assegnatari) con dati personali **cifrati a livello di colonna** nel database (AES-256-CBC tramite `APP_KEY`). - **Assegnazioni** con data assegnazione/rientro, anno teocratico, conteggio opzionale in campagna. - **Campagne** (periodi speciali) con percentuali di percorrenza in tempo reale. - **Dashboard** con media mensile di percorrenza, campagna attiva, e tre liste rapide (da assegnare, prioritari, da rientrare). - **Registro** delle assegnazioni filtrabile per anno teocratico, zona, stato. - **Audit Log** completo di tutte le azioni utente con diff before/after. --- ## Stack tecnologico | Componente | Tecnologia | |------------------|-----------------------------------------------| | **Framework** | Laravel 11.x | | **PHP** | 8.3-FPM | | **UI** | Livewire 3.5 + TailwindCSS 4.0 + Alpine.js | | **Database** | MariaDB 11 | | **Cache/Session**| Redis 7 (Alpine) | | **Web Server** | Nginx 1.25 (Alpine) | | **Auth** | Laravel Breeze 2.0 | | **RBAC** | spatie/laravel-permission 6.4 | | **Audit Trail** | spatie/laravel-activitylog 4.8 | | **Asset Build** | Vite 6.0 + @tailwindcss/vite | | **Node.js** | 20 LTS (nel container PHP) | | **Mail (dev)** | Mailpit | | **Container** | Docker Compose (6 servizi) | --- ## Requisiti di sistema - **Docker** >= 24.0 e **Docker Compose** >= 2.20 - **Git** per clonare il repository - **Porte libere** (configurabili nel `.env`): | Porta | Servizio | Variabile `.env` | |---------|-------------------------|-------------------| | `8080` | Applicazione web (Nginx)| `APP_PORT` | | `1025` | SMTP Mailpit | `MAIL_PORT` | | `8025` | UI Mailpit | `MAILPIT_UI_PORT` | > MariaDB (`3306`) e Redis (`6379`) non espongono porte sull'host: sono accessibili solo dalla rete interna Docker. --- ## Installazione da zero ### Passo 1 — Clona il repository ```bash git clone termanager2 cd termanager2 ``` ### Passo 2 — Crea il file `.env` ```bash cp .env.example .env ``` ### Passo 3 — Configura le variabili obbligatorie Apri `.env` con un editor e imposta **almeno** queste variabili: ```bash nano .env ``` ```dotenv # --- Credenziali admin iniziale (OBBLIGATORIE al primo avvio) --- INITIAL_ADMIN_NAME="Mario Rossi" INITIAL_ADMIN_EMAIL=admin@esempio.it INITIAL_ADMIN_PASSWORD=UnaPasswordSicura123 # --- URL dell'applicazione (adatta al tuo dominio/IP) --- APP_URL=http://localhost:8080 ASSET_URL=http://localhost:8080 # --- Password database (cambia i default in produzione!) --- DB_PASSWORD=una_password_sicura DB_ROOT_PASSWORD=una_root_password_sicura REDIS_PASSWORD=una_redis_password_sicura ``` > **Importante**: `INITIAL_ADMIN_NAME`, `INITIAL_ADMIN_EMAIL` e `INITIAL_ADMIN_PASSWORD` sono obbligatorie. > Se mancano e il database è vuoto, il container si avvia ma mostra un warning e non potrai accedere. ### Passo 4 — Imposta i permessi Il container PHP gira con UID/GID `1000`. I file devono appartenere a questo utente: ```bash # Crea le cartelle necessarie mkdir -p storage/app/public \ storage/framework/cache/data \ storage/framework/sessions \ storage/framework/views \ storage/logs \ bootstrap/cache # Imposta proprietario e permessi sudo chown -R 1000:1000 . chmod -R 775 storage bootstrap/cache ``` ### Passo 5 — Avvia i container (primo avvio) ```bash docker compose up -d --build ``` Questo comando: 1. **Costruisce** le immagini Docker (PHP + Nginx) 2. **Avvia** 6 servizi: `app`, `nginx`, `queue-worker`, `mariadb`, `redis`, `mailpit` 3. L'entrypoint del container `app` esegue automaticamente: - Copia `.env.example` → `.env` (se mancante) - Installa le dipendenze Composer (`vendor/`) - Genera `APP_KEY` (se vuota) e la salva in `storage/app/.app_key` - Installa le dipendenze NPM (`node_modules/`) - Compila gli asset frontend CSS/JS (`public/build/`) - Crea il symlink `public/storage` → `storage/app/public` - Esegue le migrazioni database - Esegue il seed iniziale (ruoli e permessi) - Crea l'account admin iniziale - Mette in cache config, routes e views ### Passo 6 — Verifica che tutto funzioni ```bash # Controlla che tutti i container siano "healthy" docker compose ps ``` Output atteso — tutti i container devono essere `Up` (e `healthy` dove previsto): ``` NAME STATUS PORTS termanager2_app Up (healthy) 9000/tcp termanager2_nginx Up 0.0.0.0:8080->80/tcp termanager2_queue Up 9000/tcp termanager2_db Up (healthy) 3306/tcp termanager2_redis Up (healthy) 6379/tcp termanager2_mail Up 0.0.0.0:1025->1025/tcp, 0.0.0.0:8025->8025/tcp ``` Se un container non è healthy, controlla i log: ```bash # Log del container app (il più importante) docker compose logs app --tail=100 # Log di tutti i container docker compose logs --tail=50 ``` ### Passo 7 — Accedi all'applicazione Apri il browser su: **http://localhost:8080** (o la porta configurata in `APP_PORT`) Accedi con le credenziali impostate in `INITIAL_ADMIN_EMAIL` e `INITIAL_ADMIN_PASSWORD`. --- ## Configurazione ### Variabili d'ambiente principali (`.env`) | Variabile | Default | Descrizione | |-----------------------|----------------------|------------------------------------------| | `APP_KEY` | (auto-generata) | Chiave AES-256 per cifratura dati. **Mai condividere.** Viene generata automaticamente al primo avvio | | `APP_URL` | da `.env.example` | URL completo dell'applicazione (es. `https://miodominio.it`) | | `ASSET_URL` | da `.env.example` | URL base per gli asset CSS/JS (normalmente uguale a `APP_URL`) | | `APP_PORT` | `8080` | Porta host su cui Nginx espone l'app | | `APP_ENV` | `local` | Ambiente: `local` (sviluppo) o `production` | | `APP_DEBUG` | `true` | Mostra errori dettagliati. **Impostare `false` in produzione** | | `SEED_DEV_DATA` | `false` | Se `true`, il seed include dati demo di test | | `RUN_DB_SEED_ON_FIRST_START` | `true` | Se `true`, esegue il seed automatico solo al primo avvio | | `ENSURE_INITIAL_ADMIN_ON_EMPTY_DB` | `true` | Se `true`, crea admin iniziale quando non esistono utenti | | `INITIAL_ADMIN_NAME` | (vuoto) | Nome dell'admin iniziale — **obbligatorio al primo avvio** | | `INITIAL_ADMIN_EMAIL` | (vuoto) | Email dell'admin iniziale — **obbligatorio al primo avvio** | | `INITIAL_ADMIN_PASSWORD` | (vuoto) | Password dell'admin iniziale (min 8 caratteri) — **obbligatorio al primo avvio** | | `DB_DATABASE` | `termanager2` | Nome database MariaDB | | `DB_USERNAME` | `termanager2` | Utente database | | `DB_PASSWORD` | `secret` | Password database — **cambiare in produzione** | | `DB_ROOT_PASSWORD` | `rootsecret` | Password root MariaDB — **cambiare in produzione** | | `REDIS_PASSWORD` | `redissecret` | Password Redis — **cambiare in produzione** | | `MAIL_PORT` | `1025` | Porta SMTP (Mailpit in dev, SMTP reale in prod) | | `MAILPIT_UI_PORT` | `8025` | Porta UI Mailpit per debug email | ### Configurazione applicativa Dopo il primo accesso, la configurazione si gestisce dalla sezione **Impostazioni** nel menu (solo Amministratore): - Nome congregazione - Soglia mesi per priorità automatica territori - Soglia giorni per "da rientrare" - Retention giorni audit log ### Credenziali iniziali Le credenziali admin non sono hardcoded. Al primo avvio devi impostare nel `.env`: - `INITIAL_ADMIN_NAME` - `INITIAL_ADMIN_EMAIL` - `INITIAL_ADMIN_PASSWORD` Se il database è vuoto e queste variabili non sono valorizzate, il container `app` mostra un warning e non verrà creato l'account admin. --- ## Migrazione su nuovo server Quando sposti TerManager2 su un nuovo server, segui questa procedura: ### 1. Copia i file sul nuovo server ```bash # Dal vecchio server: crea un archivio (escludi vendor, node_modules e volumi Docker) tar czf termanager2-backup.tar.gz \ --exclude='vendor' \ --exclude='node_modules' \ --exclude='public/build' \ --exclude='.git' \ termanager2/ # Copia sul nuovo server scp termanager2-backup.tar.gz utente@nuovo-server:/home/utente/Docker/ # Sul nuovo server: estrai cd /home/utente/Docker tar xzf termanager2-backup.tar.gz cd termanager2 ``` ### 2. Verifica il file `.env` ```bash # Controlla che .env esista e contenga i valori corretti cat .env # Adatta APP_URL e ASSET_URL al nuovo dominio/IP nano .env ``` > **Critico**: se il nuovo server ha un URL/IP diverso, aggiorna `APP_URL` e `ASSET_URL`. ### 3. Imposta i permessi ```bash sudo chown -R 1000:1000 . chmod -R 775 storage bootstrap/cache ``` ### 4. Ricostruisci e avvia ```bash docker compose up -d --build ``` ### 5. Forza la ricompilazione degli asset Se la pagina appare senza stile (CSS mancante), ricompila gli asset: ```bash # Ricompila CSS e JS dentro il container docker compose exec -u root app bash -c "npm install --no-audit --no-fund && npm run build" # Correggi i permessi dei file generati docker compose exec -u root app chown -R 1000:1000 public/build node_modules ``` ### 6. (Opzionale) Ripristina il database Se hai un dump SQL dal vecchio server: ```bash # Copia il dump nel container MariaDB docker cp backup.sql termanager2_db:/tmp/backup.sql # Importa il dump docker compose exec mariadb mysql -u root -p"$(grep DB_ROOT_PASSWORD .env | cut -d= -f2)" termanager2 < /tmp/backup.sql # Esegui le eventuali migrazioni mancanti docker compose exec app php artisan migrate --force # Pulisci la cache docker compose exec app php artisan optimize:clear ``` --- ## Struttura del progetto ``` TerManager2/ ├── app/ │ ├── Console/Commands/ # AuditCleanup (pulizia log schedulata) │ ├── Http/Middleware/ # Middleware HTTP applicativi │ ├── Livewire/ │ │ ├── Assegnazioni/ # Assegna, Rientra │ │ ├── Auth/ # Login │ │ ├── Campagne/ # Index, Create, Edit, Show │ │ ├── Proclamatori/ # Index, Create, Edit, Show, Cestino │ │ ├── Settings/ # SettingsEdit, ZoneIndex, TipologieIndex │ │ ├── Territori/ # Index, Create, Edit, Show, Cestino │ │ ├── AuditLog.php # Log attività (filtri, diff) │ │ ├── Home.php # Dashboard │ │ └── Registro.php # Registro assegnazioni │ ├── Models/ # 8 modelli Eloquent │ └── Providers/ # AppServiceProvider (Gate admin) ├── bootstrap/ # app.php (middleware), providers.php ├── config/ # app, auth, database, session ├── database/ │ ├── migrations/ # 10 migrazioni ordinate │ └── seeders/ # Roles, Dev, Database seeders ├── docker/ │ ├── nginx/default.conf # Vhost con security headers │ └── php/ │ ├── Dockerfile # PHP 8.3-FPM + estensioni + Composer + Node 20 │ └── php.ini # 64M upload, opcache, Europe/Rome ├── public/index.php # Entry point Laravel ├── resources/ │ ├── css/app.css # TailwindCSS 4 import │ ├── js/ # app.js, bootstrap.js (Axios) │ └── views/ │ ├── components/layouts/ # app.blade.php (sidebar), guest.blade.php │ └── livewire/ # Tutte le viste dei componenti ├── routes/ │ ├── web.php # Tutte le rotte con permessi │ └── console.php # Schedule audit:cleanup daily ├── .env.example # Template configurazione ├── artisan # CLI Laravel ├── composer.json # Dipendenze PHP ├── docker-compose.yml # 5 servizi (app, nginx, mariadb, redis, mailpit) ├── package.json # Dipendenze Node (Vite, TailwindCSS) └── vite.config.js # Vite + Laravel plugin + TailwindCSS plugin ``` --- ## Funzionalità principali ### Dashboard (Home) - Anno teocratico corrente (auto-creato se mancante, Set→Ago) - Media mensile di percorrenza (territori rientrati / mesi trascorsi) - Campagna attiva con barra di progresso percentuale - Tre liste rapide con azione diretta: - **Da assegnare**: territori in reparto, ordinati per priorità - **Prioritari**: flag manuale O soglia automatica (la soglia vince sempre) - **Da rientrare**: assegnazioni oltre la soglia giorni configurata ### Territori - CRUD completo con upload/sostituzione PDF - Filtri per zona, tipologia, stato (in_reparto, assegnato, da_rientrare, inattivo) - Badge di stato colorati + indicatore priorità (Manuale/Automatico) - Dettaglio con PDF viewer inline e storico assegnazioni per anno teocratico - Toggle attivo/inattivo e prioritario - Soft delete con cestino (ripristino o eliminazione definitiva) ### Proclamatori - CRUD con campi nome/cognome **cifrati nel DB** (AES-256-CBC) - Ricerca in-memory (necessaria per campi cifrati, ottimizzata per < 200 record) - Conteggio territori attualmente assegnati - Toggle attivo/inattivo - **Anonimizzazione GDPR** (sostituzione dati con placeholder irreversibile) - Soft delete con cestino ### Assegnazione / Rientro - Selezione territorio disponibile + proclamatore attivo - Data assegnazione con auto-detection anno teocratico - Validazione: territorio non già assegnato, entrambi attivi - Rientro con calcolo automatico giorni - **Prompt retroattivo campagna**: se l'assegnazione ricade nel range di una campagna, viene chiesto se conteggiare il rientro ### Campagne - CRUD con date inizio/fine e descrizione - Stato automatico (Attiva/Futura/Conclusa) - Percentuale percorrenza in tempo reale (conteggiati / totali assegnati nel range) - Dettaglio con lista territorio-per-territorio dei conteggiati ### Registro Assegnazioni - Filtri: anno teocratico, zona, stato (aperte/chiuse), ricerca testo - Colonne: territorio, proclamatore, date, giorni, campagna ### Audit Log - Log automatico su tutti i modelli (spatie/laravel-activitylog) - Log manuale per eventi di flusso (assign, return, login, logout) - Filtri per utente, tipo evento, ricerca testo - Dettaglio con diff before/after (properties JSON espanso) - Pulizia automatica schedulata (`audit:cleanup` — retention configurabile) ### Impostazioni - Nome congregazione - Soglia mesi priorità automatica - Soglia giorni per "da rientrare" - Retention giorni audit log ### XML Exchange - Conversione dump SQL legacy in XML compatibile con TerManager2 - Import XML nell'app (sostituzione dati gestionali: impostazioni, zone, tipologie, proclamatori, territori, anni, campagne, assegnazioni) - Export XML dei dati correnti ### Zone e Tipologie - CRUD inline (aggiungi, rinomina, attiva/disattiva, elimina) - Protezione: non eliminabile se ha territori associati --- ## Ruoli e permessi (RBAC) Tre ruoli con permessi granulari gestiti da **spatie/laravel-permission**: | Permesso | Amministratore | Assistente | Operatore | |---------------------|:--------------:|:----------:|:---------:| | `settings.manage` | ✅ | | | | `territori.manage` | ✅ | | | | `proclamatori.manage`| ✅ | ✅ | | | `campagne.manage` | ✅ | ✅ | | | `territori.assign` | ✅ | ✅ | ✅ | | `territori.return` | ✅ | ✅ | ✅ | | `registro.view` | ✅ | ✅ | | | `registro.export` | ✅ | | | | `audit.view` | ✅ | | | | `audit.export` | ✅ | | | L'amministratore ha un bypass completo via `Gate::before` nel `AppServiceProvider`. Il menu sidebar mostra solo le voci per cui l'utente ha permesso. --- ## Sicurezza e GDPR ### Sicurezza - **Cifratura a riposo**: nome e cognome proclamatori cifrati con `encrypted` cast (AES-256-CBC via `APP_KEY`) - **Password**: hash bcrypt (standard Laravel) - **RBAC**: middleware `permission:` su ogni rotta - **CSRF**: token integrato in tutti i form Livewire - **Rate limiting**: login con throttle configurabile - **Security headers**: X-Frame-Options, X-Content-Type-Options, X-XSS-Protection (via Nginx) - **Sessioni**: Redis con cookie `termanager2_session` (httpOnly, secure in produzione) ### GDPR - **Minimizzazione**: solo nome, cognome e stato attivo per i proclamatori - **Cifratura a riposo**: dati illeggibili con accesso diretto al DB - **Audit trail**: log completo di tutte le operazioni sui dati - **Diritto all'oblio**: metodo `anonimizza()` sul Proclamatore (sostituisce dati con placeholder) - **Retention**: pulizia automatica dei log audit oltre il periodo configurato - **Ruoli e autorizzazioni**: accesso ai dati solo per chi ha permessi specifici - **No log di dati sensibili**: l'audit log registra `proclamatore_id` ma non nome/cognome in chiaro nei `properties` --- ## Modello dati ### Tabelle principali (10 migrazioni) | Tabella | Descrizione | |-------------------|--------------------------------------------------------------| | `users` | Utenti app con auth standard Laravel | | `settings` | Configurazione singleton (congregazione, soglie, retention) | | `zone` | Zone territoriali (id, nome, attivo) | | `tipologie` | Tipologie territorio (id, nome, attivo) | | `proclamatori` | Assegnatari con nome/cognome cifrati, soft delete | | `territori` | Cartoline con zona, tipologia, PDF, soft delete | | `anni_teocratici` | Periodi Set→Ago con label univoca | | `campagne` | Periodi speciali con date e descrizione | | `assegnazioni` | Join territorio↔proclamatore con date, anno, campagna | | `activity_log` | Audit trail (spatie/laravel-activitylog) | ### Indici e vincoli - `territori.numero` — UNIQUE - `anni_teocratici.label` — UNIQUE - `assegnazioni(territorio_id, returned_at)` — INDEX composito - `assegnazioni(proclamatore_id, returned_at)` — INDEX composito - `assegnazioni(anno_teocratico_id)` — INDEX - FK con `RESTRICT` su territorio e proclamatore (protezione integrità) --- ## Regole di business ### Anno teocratico - **Settembre → Agosto**: se mese ≥ 9 → anno = `corrente/corrente+1`; se mese ≤ 8 → anno = `corrente-1/corrente` - Creato automaticamente se non esiste (metodo `AnnoTeocratico::perData()`) - L'assegnazione conta per l'anno determinato dalla **data di assegnazione** ### Stato territorio (calcolato dinamicamente) - **in_reparto**: attivo, nessuna assegnazione aperta - **assegnato**: ha assegnazione con `returned_at = null` - **da_rientrare**: assegnato da più giorni della soglia configurata - **inattivo**: `attivo = false` ### Priorità - **Manuale**: flag `prioritario = true` impostato dall'admin - **Automatica**: nessuna assegnazione negli ultimi N mesi (soglia configurabile) - La soglia automatica **vince sempre** sul flag manuale (l'admin può aggiungere ma non rimuovere se la soglia scatta) ### Campagne — percentuale percorrenza - **Denominatore**: tutti i territori assegnati nel range della campagna - **Numeratore**: assegnazioni conteggiate in campagna (`counted_in_campaign = true`) - Il prompt retroattivo appare al rientro se l'assegnazione è nel range di una campagna --- ## Comandi utili ### Gestione container ```bash # Avviare i container (dopo il primo build) docker compose up -d # Avviare con ricostruzione immagini (dopo modifiche a Dockerfile o dipendenze) docker compose up -d --build # Fermare i container (i dati persistono nei volumi) docker compose down # Fermare e CANCELLARE tutti i dati (database, redis, uploads) docker compose down -v --remove-orphans # Stato dei container docker compose ps # Log in tempo reale (tutti i container) docker compose logs -f # Log di un singolo container docker compose logs app --tail=100 docker compose logs nginx --tail=100 docker compose logs mariadb --tail=100 # Riavviare un singolo container docker compose restart app ``` ### Shell interattiva ```bash # Shell nel container app (come utente 1000) docker compose exec app bash # Shell nel container app come root (per operazioni di sistema) docker compose exec -u root app bash # Shell nel container MariaDB docker compose exec mariadb mysql -u root -p ``` ### Laravel / Artisan ```bash # Eseguire migrazioni docker compose exec app php artisan migrate --force # Seed del database docker compose exec app php artisan db:seed --force # Pulizia manuale audit log docker compose exec app php artisan audit:cleanup # Cache configurazione (produzione) docker compose exec app php artisan config:cache docker compose exec app php artisan route:cache docker compose exec app php artisan view:cache # Svuotare TUTTA la cache docker compose exec app php artisan optimize:clear ``` ### Asset frontend (CSS/JS) ```bash # Compilare asset per produzione docker compose exec -u root app bash -c "npm install --no-audit --no-fund && npm run build" docker compose exec -u root app chown -R 1000:1000 public/build node_modules # Compilare asset per sviluppo (hot reload, richiede porta 5173 libera) docker compose exec app npm run dev ``` ### Backup e ripristino database ```bash # Backup del database (sostituisci le credenziali) docker compose exec mariadb mysqldump -u root -prootsecret termanager2 > backup_$(date +%Y%m%d).sql # Ripristino da backup docker compose exec -T mariadb mysql -u root -prootsecret termanager2 < backup_20250101.sql docker compose exec app php artisan migrate --force docker compose exec app php artisan optimize:clear ``` --- ## Troubleshooting ### La pagina appare senza stile (CSS mancante) **Sintomo**: la pagina di login appare con testo non formattato, senza colori né layout. **Causa**: il file CSS compilato manca da `public/build/assets/`. Succede tipicamente dopo una migrazione su nuovo server. **Soluzione**: ```bash # Ricompila gli asset come root (evita problemi di permessi) docker compose exec -u root app bash -c "npm install --no-audit --no-fund && npm run build" # Correggi i permessi docker compose exec -u root app chown -R 1000:1000 public/build node_modules ``` ### Il container `app` non diventa healthy **Sintomo**: `docker compose ps` mostra `app` come `starting` o `unhealthy`. **Cosa controllare**: ```bash # Guarda i log per capire dove si blocca docker compose logs app --tail=200 ``` Cause comuni: - **MariaDB non pronto**: l'entrypoint ripete il tentativo 10 volte. Attendi qualche secondo. - **Credenziali admin mancanti**: se `ENSURE_INITIAL_ADMIN_ON_EMPTY_DB=true` e le variabili `INITIAL_ADMIN_*` sono vuote, il container mostra un warning. - **Errore di permessi**: esegui `sudo chown -R 1000:1000 .` sulla cartella del progetto. ### Errore "Permission denied" su storage o bootstrap/cache ```bash sudo chown -R 1000:1000 storage bootstrap/cache chmod -R 775 storage bootstrap/cache ``` ### La `APP_KEY` è cambiata e i dati cifrati non sono leggibili La `APP_KEY` viene salvata in `storage/app/.app_key` per persistere tra i riavvii. Se perdi questo file: - I **nomi e cognomi dei proclamatori** (cifrati con AES-256) diventano illeggibili - Le **sessioni** vengono invalidate **Prevenzione**: dopo il primo avvio, salva il valore di `APP_KEY` dal file `.env` in un luogo sicuro. ### Errore npm "EACCES" o "vite: not found" ```bash # Installa le dipendenze npm come root docker compose exec -u root app npm install --no-audit --no-fund # Verifica che vite sia installato docker compose exec app ls node_modules/.bin/vite # Compila come root docker compose exec -u root app npm run build # Poi correggi i permessi docker compose exec -u root app chown -R 1000:1000 public/build node_modules ``` ### Reset completo (ripartire da zero) > **Attenzione**: questo cancella il database, i file Redis e tutti i dati applicativi. ```bash docker compose down -v --remove-orphans sudo chown -R 1000:1000 . rm -rf node_modules public/build vendor storage/app/.app_key storage/framework/.runtime_db_seeded docker compose up -d --build ``` --- ## Produzione ### Checklist deploy in produzione 1. **Variabili d'ambiente** — modifica nel `.env`: ```dotenv APP_ENV=production APP_DEBUG=false APP_URL=https://tuodominio.it ASSET_URL=https://tuodominio.it ``` 2. **Password sicure** — cambia TUTTI i default: ```dotenv DB_PASSWORD= DB_ROOT_PASSWORD= REDIS_PASSWORD= ``` 3. **HTTPS** — configura un reverse proxy (Traefik, Nginx, Caddy) con certificato SSL/TLS davanti alla porta `APP_PORT` 4. **Cache** — al primo avvio viene fatto automaticamente dall'entrypoint, ma dopo modifiche: ```bash docker compose exec app php artisan config:cache docker compose exec app php artisan route:cache docker compose exec app php artisan view:cache ``` 5. **Backup** — programma backup regolari del database: ```bash # Cron job giornaliero (esempio) 0 2 * * * cd /path/to/termanager2 && docker compose exec -T mariadb mysqldump -u root -prootsecret termanager2 | gzip > /backups/termanager2_$(date +\%Y\%m\%d).sql.gz ``` 6. **APP_KEY** — salva il valore di `APP_KEY` dal `.env` in un luogo sicuro (password manager, vault). Senza di essa i dati cifrati dei proclamatori sono irrecuperabili. 7. **Mailpit** — in produzione rimuovi il servizio `mailpit` dal `docker-compose.yml` e configura un server SMTP reale: ```dotenv MAIL_MAILER=smtp MAIL_HOST=smtp.tuoprovider.it MAIL_PORT=587 MAIL_USERNAME=utente@tuodominio.it MAIL_PASSWORD=password-smtp MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=noreply@tuodominio.it ``` --- ## Licenza Progetto privato — tutti i diritti riservati.