Rendi configurabili le porte esposte sull'host
Le porte erano legate a 127.0.0.1, quindi l'applicazione non era raggiungibile per IP: andava bene solo accedendo da un dominio via Traefik. Ora interfaccia e porta si decidono separatamente nel .env, per ogni servizio. APP_BIND=0.0.0.0 APP_PORT=8080 app esposta (default) DB_BIND=127.0.0.1 DB_PORT_HOST=3306 database solo da localhost MAILPIT_BIND=127.0.0.1 solo col profilo dev Il database resta su localhost per due motivi: ci si arriva comunque con un tunnel SSH senza esporlo a Internet, e su un host con piu' progetti la 3306 va spesso in conflitto (per questo e' cambiabile con DB_PORT_HOST). Redis non pubblica nulla: non serve da fuori. SESSION_SECURE_COOKIE passa a false come default, perche' ora l'accesso tipico e' in HTTP per IP. Con true il cookie di sessione e' marcato "secure" e il browser non lo rimanda su HTTP: verificato, il login risponde 419 Page Expired e si torna alla schermata di accesso. Il tranello e' che provandolo su localhost non si manifesta, perche' i browser considerano localhost un contesto sicuro: emerge solo accedendo per IP. E' documentato in .env.example insieme al sintomo esatto. Verificato: app raggiungibile dall'IP di rete, porta del database chiusa dall'esterno e aperta da localhost, login e pagine funzionanti via IP. Nota: senza dominio il traffico e' in chiaro. Il README segnala il passaggio a HTTPS come consigliato, con le tre variabili da cambiare. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
62
.env.example
62
.env.example
@@ -20,11 +20,15 @@ APP_ENV=production
|
|||||||
APP_DEBUG=false
|
APP_DEBUG=false
|
||||||
APP_TIMEZONE=Europe/Rome
|
APP_TIMEZONE=Europe/Rome
|
||||||
|
|
||||||
# [OBBLIGATORIA] Deve combaciare ESATTAMENTE col dominio servito, schema
|
# [OBBLIGATORIA] Deve combaciare ESATTAMENTE con l'indirizzo da cui accedi,
|
||||||
# incluso. L'app rifiuta richieste con un Host diverso (protezione contro
|
# schema e porta inclusi. L'app rifiuta richieste con un Host diverso
|
||||||
# l'host header injection): un valore sbagliato da' 400 su tutto.
|
# (protezione contro l'host header injection): un valore sbagliato da' 400
|
||||||
# In locale: http://localhost:8080
|
# su tutto.
|
||||||
APP_URL=https://territori.example.org
|
#
|
||||||
|
# accesso per IP:porta -> http://192.0.2.10:8080
|
||||||
|
# accesso in locale -> http://localhost:8080
|
||||||
|
# dominio con HTTPS -> https://territori.example.org
|
||||||
|
APP_URL=http://192.0.2.10:8080
|
||||||
|
|
||||||
# [OBBLIGATORIA] Genera con: echo "base64:$(openssl rand -base64 32)"
|
# [OBBLIGATORIA] Genera con: echo "base64:$(openssl rand -base64 32)"
|
||||||
# I dati personali dei proclamatori sono cifrati con questa chiave: se la
|
# I dati personali dei proclamatori sono cifrati con questa chiave: se la
|
||||||
@@ -77,8 +81,18 @@ CACHE_STORE=redis
|
|||||||
SESSION_DRIVER=redis
|
SESSION_DRIVER=redis
|
||||||
QUEUE_CONNECTION=redis
|
QUEUE_CONNECTION=redis
|
||||||
|
|
||||||
# true in produzione (HTTPS), false se accedi in HTTP su localhost.
|
# DEVE essere false se accedi in HTTP (tipicamente per IP:porta).
|
||||||
SESSION_SECURE_COOKIE=true
|
#
|
||||||
|
# Con true, il cookie di sessione viene marcato "secure" e il browser non lo
|
||||||
|
# rimanda mai su una connessione HTTP: il login risponde 419 "Page Expired"
|
||||||
|
# e si torna alla schermata di accesso, senza spiegazioni.
|
||||||
|
#
|
||||||
|
# Attenzione: provandolo su http://localhost NON te ne accorgi, perche' i
|
||||||
|
# browser trattano localhost come contesto sicuro. Il problema salta fuori
|
||||||
|
# solo accedendo per IP.
|
||||||
|
#
|
||||||
|
# Mettilo a true quando servirai l'app in HTTPS dietro un dominio.
|
||||||
|
SESSION_SECURE_COOKIE=false
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Posta
|
# Posta
|
||||||
@@ -96,10 +110,32 @@ MAIL_FROM_ADDRESS=noreply@example.org
|
|||||||
MAIL_FROM_NAME="${APP_NAME}"
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Porte
|
# Porte esposte sull'host
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Di default l'app ascolta solo su localhost. In produzione va bene cosi': il
|
# Per ogni servizio decidi separatamente SU QUALE INTERFACCIA ascoltare (_BIND)
|
||||||
# traffico arriva da Traefik sulla rete interna, non da questa porta.
|
# e SU QUALE PORTA (_PORT):
|
||||||
# Per esporla davvero (server senza reverse proxy): APP_PORT=0.0.0.0:8080
|
#
|
||||||
APP_PORT=127.0.0.1:8080
|
# 0.0.0.0 raggiungibile da fuori, cioe' da Internet se il server e'
|
||||||
MAILPIT_UI_PORT=127.0.0.1:8025
|
# pubblico e non c'e' un firewall davanti
|
||||||
|
# 127.0.0.1 solo dalla macchina stessa; da remoto ci arrivi con un
|
||||||
|
# tunnel SSH: ssh -L 8080:127.0.0.1:8080 utente@server
|
||||||
|
|
||||||
|
# --- Applicazione ---
|
||||||
|
# Esposta, cosi' l'app risponde su http://IP-DEL-SERVER:8080
|
||||||
|
# Quando passerai a un dominio con HTTPS, rimetti APP_BIND=127.0.0.1: il
|
||||||
|
# traffico arrivera' dal reverse proxy sulla rete interna e la porta non
|
||||||
|
# servira' piu'.
|
||||||
|
APP_BIND=0.0.0.0
|
||||||
|
APP_PORT=8080
|
||||||
|
|
||||||
|
# --- Database ---
|
||||||
|
# Legato a localhost: per collegare un client grafico (DBeaver, TablePlus)
|
||||||
|
# apri un tunnel: ssh -L 3306:127.0.0.1:3306 utente@server
|
||||||
|
# Se la 3306 e' gia' occupata sull'host, cambia DB_PORT_HOST (es. 3307).
|
||||||
|
# Sconsigliato mettere DB_BIND=0.0.0.0: esporrebbe il database a Internet.
|
||||||
|
DB_BIND=127.0.0.1
|
||||||
|
DB_PORT_HOST=3306
|
||||||
|
|
||||||
|
# --- Mailpit (solo con --profile dev) ---
|
||||||
|
MAILPIT_BIND=127.0.0.1
|
||||||
|
MAILPIT_UI_PORT=8025
|
||||||
|
|||||||
33
README.md
33
README.md
@@ -93,9 +93,13 @@ valori:
|
|||||||
APP_NAME=TerManager2
|
APP_NAME=TerManager2
|
||||||
APP_ENV=production
|
APP_ENV=production
|
||||||
APP_DEBUG=false
|
APP_DEBUG=false
|
||||||
APP_URL=https://territori.tuodominio.it
|
|
||||||
APP_TIMEZONE=Europe/Rome
|
APP_TIMEZONE=Europe/Rome
|
||||||
|
|
||||||
|
# Deve combaciare con l'indirizzo da cui accedi, porta inclusa.
|
||||||
|
# per IP:porta -> http://IP-DEL-SERVER:8080
|
||||||
|
# con dominio -> https://territori.tuodominio.it
|
||||||
|
APP_URL=http://IP-DEL-SERVER:8080
|
||||||
|
|
||||||
# --- Chiavi e password (dal Passo 2) ---
|
# --- Chiavi e password (dal Passo 2) ---
|
||||||
APP_KEY=base64:...
|
APP_KEY=base64:...
|
||||||
DB_PASSWORD=...
|
DB_PASSWORD=...
|
||||||
@@ -121,8 +125,15 @@ INITIAL_ADMIN_NAME=Nome Cognome
|
|||||||
INITIAL_ADMIN_EMAIL=admin@tuodominio.it
|
INITIAL_ADMIN_EMAIL=admin@tuodominio.it
|
||||||
INITIAL_ADMIN_PASSWORD=UnaPasswordSolida
|
INITIAL_ADMIN_PASSWORD=UnaPasswordSolida
|
||||||
|
|
||||||
|
# --- Porte esposte sull'host ---
|
||||||
|
APP_BIND=0.0.0.0 # 127.0.0.1 se ci metti davanti un reverse proxy
|
||||||
|
APP_PORT=8080
|
||||||
|
DB_BIND=127.0.0.1 # database raggiungibile solo via tunnel SSH
|
||||||
|
DB_PORT_HOST=3306
|
||||||
|
|
||||||
# --- Sessioni e log ---
|
# --- Sessioni e log ---
|
||||||
SESSION_SECURE_COOKIE=true
|
# false con accesso HTTP, true solo in HTTPS: vedi .env.example
|
||||||
|
SESSION_SECURE_COOKIE=false
|
||||||
LOG_CHANNEL=stderr
|
LOG_CHANNEL=stderr
|
||||||
LOG_LEVEL=warning
|
LOG_LEVEL=warning
|
||||||
|
|
||||||
@@ -141,7 +152,15 @@ MAIL_FROM_ADDRESS=noreply@tuodominio.it
|
|||||||
> la protezione contro l'host header injection, ed è la causa più comune di
|
> la protezione contro l'host header injection, ed è la causa più comune di
|
||||||
> "pagina che non si apre" al primo deploy.
|
> "pagina che non si apre" al primo deploy.
|
||||||
|
|
||||||
### Passo 4 — Assegna il dominio
|
### Passo 4 — Assegna il dominio (facoltativo)
|
||||||
|
|
||||||
|
Con la configurazione qui sopra l'applicazione risponde gia' su
|
||||||
|
`http://IP-DEL-SERVER:8080`. Questo passo serve solo se vuoi un dominio con
|
||||||
|
HTTPS — **consigliato**, perche' altrimenti password e sessioni viaggiano in
|
||||||
|
chiaro.
|
||||||
|
|
||||||
|
Quando lo fai, cambia anche: `APP_URL=https://tuodominio.it`,
|
||||||
|
`SESSION_SECURE_COOKIE=true` e `APP_BIND=127.0.0.1`.
|
||||||
|
|
||||||
**Domains** → **Add Domain**:
|
**Domains** → **Add Domain**:
|
||||||
|
|
||||||
@@ -237,9 +256,9 @@ docker network create dokploy-network # una volta sola
|
|||||||
# nel .env, per l'uso locale:
|
# nel .env, per l'uso locale:
|
||||||
# APP_URL=http://localhost:8080
|
# APP_URL=http://localhost:8080
|
||||||
# APP_ENV=local
|
# APP_ENV=local
|
||||||
# SESSION_SECURE_COOKIE=false
|
|
||||||
# MAIL_MAILER=smtp MAIL_HOST=mailpit MAIL_PORT=1025
|
# MAIL_MAILER=smtp MAIL_HOST=mailpit MAIL_PORT=1025
|
||||||
# e le tre password a piacere
|
# e le tre password a piacere
|
||||||
|
# (SESSION_SECURE_COOKIE=false e APP_BIND/APP_PORT vanno gia' bene)
|
||||||
|
|
||||||
docker compose --profile dev up -d --build
|
docker compose --profile dev up -d --build
|
||||||
```
|
```
|
||||||
@@ -310,7 +329,11 @@ ridichiara le variabili applicative: le prende dal `.env` così com'è.
|
|||||||
| `APP_DEBUG` | `false` | **Mai `true` in produzione** |
|
| `APP_DEBUG` | `false` | **Mai `true` in produzione** |
|
||||||
| `APP_TIMEZONE` | `Europe/Rome` | Fuso orario |
|
| `APP_TIMEZONE` | `Europe/Rome` | Fuso orario |
|
||||||
| `LOG_LEVEL` | `warning` | `debug` per diagnosticare |
|
| `LOG_LEVEL` | `warning` | `debug` per diagnosticare |
|
||||||
| `SESSION_SECURE_COOKIE` | `true` | `false` solo su HTTP locale |
|
| `SESSION_SECURE_COOKIE` | `false` | `true` solo servendo in HTTPS |
|
||||||
|
| `APP_BIND` | `0.0.0.0` | `127.0.0.1` dietro un reverse proxy |
|
||||||
|
| `APP_PORT` | `8080` | Porta dell'applicazione sull'host |
|
||||||
|
| `DB_BIND` | `127.0.0.1` | Interfaccia della porta MariaDB |
|
||||||
|
| `DB_PORT_HOST` | `3306` | Cambiala se la 3306 e' occupata |
|
||||||
| `INITIAL_ADMIN_EMAIL` | — | Admin creato al primo avvio |
|
| `INITIAL_ADMIN_EMAIL` | — | Admin creato al primo avvio |
|
||||||
| `INITIAL_ADMIN_PASSWORD` | — | Idem |
|
| `INITIAL_ADMIN_PASSWORD` | — | Idem |
|
||||||
| `INITIAL_ADMIN_NAME` | `Amministratore`| Idem |
|
| `INITIAL_ADMIN_NAME` | `Amministratore`| Idem |
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ services:
|
|||||||
# I sorgenti non cambiano dentro un'immagine gia' costruita.
|
# I sorgenti non cambiano dentro un'immagine gia' costruita.
|
||||||
PHP_OPCACHE_VALIDATE_TIMESTAMPS: 0
|
PHP_OPCACHE_VALIDATE_TIMESTAMPS: 0
|
||||||
ports:
|
ports:
|
||||||
# Di default ascolta solo su localhost: in produzione il traffico passa
|
# Interfaccia e porta si decidono separatamente nel .env:
|
||||||
# da Traefik sulla rete interna, non da questa porta. In locale invece
|
# APP_BIND=0.0.0.0 raggiungibile dall'esterno (http://IP:8080)
|
||||||
# apri http://localhost:8080.
|
# APP_BIND=127.0.0.1 solo dalla macchina stessa, per quando il
|
||||||
# Per esporlo davvero: APP_PORT=0.0.0.0:8080 nel .env
|
# traffico arriva da un reverse proxy
|
||||||
- "${APP_PORT:-127.0.0.1:8080}:80"
|
- "${APP_BIND:-0.0.0.0}:${APP_PORT:-8080}:80"
|
||||||
volumes:
|
volumes:
|
||||||
# PDF territori, miniature, log e chiave di fallback.
|
# PDF territori, miniature, log e chiave di fallback.
|
||||||
- storage_data:/var/www/html/storage
|
- storage_data:/var/www/html/storage
|
||||||
@@ -121,6 +121,13 @@ services:
|
|||||||
- --character-set-server=utf8mb4
|
- --character-set-server=utf8mb4
|
||||||
- --collation-server=utf8mb4_unicode_ci
|
- --collation-server=utf8mb4_unicode_ci
|
||||||
- --innodb-buffer-pool-size=256M
|
- --innodb-buffer-pool-size=256M
|
||||||
|
ports:
|
||||||
|
# Legata a localhost: ci arrivi con un client grafico via tunnel SSH
|
||||||
|
# ssh -L 3306:127.0.0.1:3306 utente@server
|
||||||
|
# senza esporre il database a Internet. Per esporlo davvero (sconsigliato)
|
||||||
|
# metti DB_BIND=0.0.0.0 nel .env.
|
||||||
|
# Se la 3306 e' gia' occupata sull'host, cambia DB_PORT_HOST.
|
||||||
|
- "${DB_BIND:-127.0.0.1}:${DB_PORT_HOST:-3306}:3306"
|
||||||
volumes:
|
volumes:
|
||||||
- db_data:/var/lib/mysql
|
- db_data:/var/lib/mysql
|
||||||
networks:
|
networks:
|
||||||
@@ -167,7 +174,7 @@ services:
|
|||||||
profiles: ["dev"]
|
profiles: ["dev"]
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "${MAILPIT_UI_PORT:-127.0.0.1:8025}:8025"
|
- "${MAILPIT_BIND:-127.0.0.1}:${MAILPIT_UI_PORT:-8025}:8025"
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
|
|
||||||
@@ -177,7 +184,8 @@ volumes:
|
|||||||
storage_data:
|
storage_data:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
# Database e Redis restano qui, senza rotta verso l'esterno.
|
# Rete di servizio fra i container. Redis vive solo qui; MariaDB pubblica
|
||||||
|
# anche una porta sull'host, legata a localhost salvo diversa indicazione.
|
||||||
internal:
|
internal:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
# Rete condivisa del Traefik di Dokploy: e' cosi' che il dominio raggiunge
|
# Rete condivisa del Traefik di Dokploy: e' cosi' che il dominio raggiunge
|
||||||
|
|||||||
Reference in New Issue
Block a user