SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-28

Mailcow su VPS: email self-hosted accettata da Gmail

Verifica la porta 25 prima di installare mailcow: se è bloccata, i messaggi restano in coda. Configura poi il DNS per evitare l’errore Gmail 550 5.7.25 sul PTR.

Cosa stai creando

Un server di posta completo su un server di tua proprietà: SMTP per inviare e ricevere messaggi, IMAP per mantenere sincronizzati telefono e laptop, un client webmail e un filtro antispam che assegna un punteggio a ogni messaggio in entrambe le direzioni. mailcow-dockerized raggruppa Postfix, Dovecot, Rspamd, la webmail SOGo, MariaDB, Redis e un client ACME in un unico stack Docker Compose, quindi il software non è l’aspetto più complesso. Lo avrai in esecuzione in mezz’ora.

La parte difficile è tutto ciò che lo circonda. La posta elettronica è l’unico servizio per cui il resto di Internet diffida attivamente di un server appena configurato, e la differenza tra «funziona» e «Gmail elimina silenziosamente ogni messaggio» dipende da quattro record DNS e da un’impostazione relativa alla reputazione dell’indirizzo IP che potresti non controllare completamente. Leggi i prerequisiti riportati di seguito prima di noleggiare qualsiasi risorsa. Se, dopo averli letti, decidi che il lavoro necessario per costruire una buona reputazione non vale la pena, è una scelta legittima: la nostra panoramica di ciò che vale davvero la pena eseguire in self-hosting nel 2026 inserisce la posta elettronica nella categoria «solo se fai sul serio» proprio per questi motivi.

I prerequisiti sono il progetto

Se ne manca anche solo uno, invierai messaggi che non arriveranno mai. In ordine approssimativo di frequenza con cui causano problemi:

La porta in uscita 25 deve essere aperta. Il server consegna i messaggi a Gmail e Microsoft tramite TCP sulla porta 25. Molti provider VPS e cloud bloccano per impostazione predefinita la porta 25 in uscita per contrastare lo spam. Il blocco è silenzioso: all'avvio non viene segnalato alcun errore, tutto sembra funzionare e i messaggi restano semplicemente accodati per sempre. Verifica la porta prima di installare qualsiasi componente. Se è bloccata, l'unica soluzione è aprire un ticket al supporto e chiedere al provider di abilitarla. Alcuni provider lo fanno per gli account più vecchi, altri non lo consentono mai.

Un indirizzo IP pulito, con una reputazione utilizzabile. Gli indirizzi IP VPS riciclati si trovano spesso già nelle blocklist a causa dello spam inviato dal precedente assegnatario. Controlla il tuo indirizzo con un servizio come la ricerca Spamhaus o mxtoolbox prima di procedere. Se l'indirizzo è presente in una blocklist, riceverai rifiuti che non puoi risolvere intervenendo sul codice.

Il controllo del DNS e un record PTR corretto. Devi poter aggiungere record alla zona del tuo dominio e devi configurare il DNS inverso (PTR) dell'indirizzo IP del server in modo che punti al nome host di posta. Il PTR quasi mai viene configurato nel pannello DNS: è gestito dal proprietario dell'indirizzo IP. Di conseguenza, va impostato nel pannello di controllo del provider VPS o tramite ticket.

6 GiB di RAM e 2 vCPU sono il minimo consigliato per lavorare senza problemi. Il requisito minimo dichiarato da mailcow per un'installazione privata è 6 GiB di RAM più 1 GiB di swap. Quando il servizio viene utilizzato da alcuni utenti, sono consigliati 8 GiB. Al di sotto di circa 2.5 GiB, generate_config.sh propone di disabilitare lo scanner antivirus ClamAV, per evitare che il kernel inizi a terminare i container. Per iniziare, assegna 20 GB di spazio SSD.

Un nome DNS, non un semplice indirizzo IP. Scegli un nome host come mail.example.com. Questo unico nome diventa il tuo MAILCOW_HOSTNAME, il subject del certificato TLS, la destinazione del PTR e il banner SMTP. Usalo in modo coerente ovunque.

Passaggio 1: verificare che la porta 25 in uscita sia aperta

Esegui prima questo controllo. Se non supera questo test, tutto il resto è inutile. Dal VPS appena creato, prova ad aprire una sessione SMTP con un server di posta reale:

sudo apt update && sudo apt install -y netcat-openbsd
nc -vz -w 5 gmail-smtp-in.l.google.com 25

Se la connessione funziona, il risultato è immediato:

Connection to gmail-smtp-in.l.google.com (142.250.x.x) 25 port [tcp/smtp] succeeded!

Se la porta è bloccata, il comando resta in attesa per tutti i cinque secondi e poi restituisce un errore:

nc: connect to gmail-smtp-in.l.google.com port 25 (tcp) timed out: Operation now in progress

Il timeout indica il blocco. Si tratta di un filtro di rete applicato dal provider, non del firewall del server. Nessuna modifica locale può risolvere il problema. Apri un ticket con questo testo: "Please enable outbound TCP port 25 for my VPS at <IP>; I am running a legitimate mail server." Non installare mailcow finché il comando non restituisce "succeeded". La porta 25 in ingresso, usata dagli altri server per raggiungere il tuo, segue un percorso separato ed è generalmente aperta. Sono le connessioni in uscita a essere limitate dai provider.

Passaggio 2: configurare ora i record DNS

Le modifiche DNS richiedono tempo per propagarsi, quindi pubblica tutti i record possibili prima dell'installazione. Supponiamo che il tuo dominio sia example.com, che il tuo host di posta sia mail.example.com e che l'indirizzo IP sia 10.0.0.10. Nella tua zona DNS, crea:

mail.example.com.        A      10.0.0.10
mail.example.com.        AAAA   2001:db8::10          ; only if you have IPv6
example.com.             MX  10 mail.example.com.
example.com.             TXT    "v=spf1 mx -all"
_dmarc.example.com.      TXT    "v=DMARC1; p=none; rua=mailto:postmaster@example.com"

Il record SPF indica che «solo il mio MX può inviare messaggi per questo dominio; tutti gli altri devono essere rifiutati». Imposta DMARC su p=none per iniziare, così puoi monitorare i report senza rifiutare i tuoi messaggi; passa a p=quarantine e poi a p=reject quando avrai verificato l'allineamento. Mancano volutamente due record: DKIM, che mailcow genera per te nel passaggio 6, e PTR, che devi configurare ora nel pannello del provider.

Imposta il PTR (DNS inverso) di 10.0.0.10 su mail.example.com, il valore esatto di MAILCOW_HOSTNAME. Questo è il record che viene dimenticato più spesso e i principali provider rifiutano i messaggi quando manca o è errato. Se il pannello non dispone di un campo rDNS, apri un ticket.

Passaggio 3: installare Docker

mailcow richiede Docker Engine con il plugin Compose v2. Utilizza lo script ufficiale di Docker invece del pacchetto docker.io di Ubuntu, che non include alcun plugin Compose:

curl -fsSL https://get.docker.com | sudo sh
sudo docker compose version

Dovresti visualizzare una riga Docker Compose version v2.x. Se docker compose version restituisce docker: 'compose' is not a docker command, Docker Engine è installato, ma il plugin Compose non lo è. Installa il plugin dal repository di Docker, esegui di nuovo lo script precedente oppure consulta la nostra guida di base a Docker Compose, che installa entrambi dal repository apt ufficiale di Docker.

Passaggio 4: clonare mailcow e generare la configurazione

cd /opt
sudo git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
umask
sudo ./generate_config.sh

Verifica che umask restituisca prima 0022: mailcow non esegue la build con una maschera di file non pari, mentre una shell root appena avviata su Ubuntu 24.04 imposta già 0022. Lo script chiede quindi l'unico dato realmente importante: il nome host completo. Inserisci mail.example.com; il valore deve corrispondere esattamente ai record A e PTR. Lo script scrive mailcow.conf, l'unico file d'ambiente letto dall'intero stack. Aprilo se devi modificare le porte web (HTTP_PORT, HTTPS_PORT) o disabilitare ClamAV su un server con poca memoria:

MAILCOW_HOSTNAME=mail.example.com
HTTP_PORT=80
HTTPS_PORT=443
SKIP_CLAMD=n          # set to y to drop the virus scanner on a <2.5 GiB box

SKIP_FTS=y è l'altra impostazione utile su un server con poca RAM: la ricerca full-text è il secondo componente che consuma più memoria, secondo la documentazione di mailcow, e disabilitarla comporta soltanto la perdita della ricerca nel corpo dei messaggi nella webmail.

Mantieni HTTP_PORT=80 e HTTPS_PORT=443, a meno che sul server non siano già occupate da un altro servizio: il client ACME integrato di mailcow deve poter raggiungere la porta 80 da Internet per ottenere il certificato. Per questo non devi eseguire una configurazione separata con nginx-plus-Certbot sullo stesso server: mailcow emette e rinnova internamente i propri certificati TLS, mentre un secondo servizio in ascolto sulle porte 80/443 ne impedirebbe il funzionamento. Lo stesso vale per qualsiasi altro servizio che richieda un front end web pubblico. Una configurazione come Halcyon che trasforma una libreria Jellyfin in un videonoleggio degli anni 90, che si aspetta un proprio reverse proxy sulla porta 443, deve quindi essere eseguita su un altro host. Fa eccezione un servizio che non richieda mai una porta web pubblica: un relay RustDesk self-hosted resta in ascolto soltanto sull'intervallo 21115-21119, quindi può condividere il server, purché rimanga una quantità sufficiente di banda disponibile.

Passaggio 5: avviare lo stack ed effettuare l’accesso

sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps

Il comando pull scarica circa due dozzine di immagini; attendere alcuni minuti. Quando docker compose ps mostra che ogni container è running (oppure healthy), aprire https://mail.example.com in un browser. Le credenziali predefinite dell’amministratore sono: nome utente admin e password moohoo. Cambiare subito la password nell’interfaccia di amministrazione, in Access → Administrators. Se il browser segnala NET::ERR_CERT_AUTHORITY_INVALID, il certificato ACME non è ancora stato emesso. Consultare la sezione sui problemi ACME prima di concludere che la configurazione non funzioni; nei primi uno o due minuti è normale utilizzare un certificato segnaposto autofirmato.

Passaggio 6: aggiungere un dominio, una casella di posta e pubblicare DKIM

Nell'interfaccia di amministrazione, apri la pagina Mail Setup (Configuration → Mail Setup). Nella scheda Domains fai clic su Add domain e inserisci example.com. Quindi, nella sezione Mailboxes, fai clic su Add mailbox per creare you@example.com con una password. La casella è già operativa e raggiungibile tramite IMAP.

Ora configura la chiave DKIM. Vai a Configuration → ARC/DKIM keys. mailcow potrebbe avere già generato una chiave quando hai aggiunto il dominio. In caso contrario, generala nella stessa sezione. Seleziona il dominio, mantieni il selettore dkim, scegli 2048-bit e fai clic su Add. Copia il lungo valore TXT visualizzato e pubblicalo come:

dkim._domainkey.example.com.  TXT  "v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqh...long-key...QAB"

La pagina Domains di mailcow contiene un pulsante DNS che elenca tutti i record richiesti e mostra un segno di spunta verde o una croce rossa in base a ciò che è effettivamente pubblicato. Usala come checklist e assicurati che ogni riga sia verde prima di verificare la recapitalità. Se la riga DKIM resta rossa dopo la pubblicazione, in genere la chiave è stata suddivisa in modo errato tra più parti TXT. Una chiave a 2048 bit supera il limite di 255 caratteri per una singola stringa TXT. Incollala quindi come un unico valore logico e lascia che sia il provider DNS a suddividerla in più parti.

Passaggio 7: verifica della deliverability e raggiungi 10/10

Vai su mail-tester.com, copia l'indirizzo casuale visualizzato e inviagli un messaggio dalla nuova casella. Accedi a SOGo webmail all'indirizzo https://mail.example.com/SOGo e invialo da lì. Quindi fai clic su "Then check your score".

Punta a 10/10. Le detrazioni più comuni e le relative cause sono:

  • SPF non allineato: il record MX/SPF è assente oppure l'IP di invio non è incluso. Verifica nuovamente il record SPF TXT.
  • La firma DKIM non viene verificata: il record TXT dkim._domainkey è assente, la propagazione non è ancora completata oppure il contenuto è alterato. È l'errore più comune.
  • PTR assente o non corrispondente: il DNS inverso non risolve in mail.example.com. Correggilo presso il provider.
  • IP presente in una blocklist: la reputazione precedente dell'IP. Richiedi la rimozione dalla lista oppure chiedi un IP con una reputazione migliore.

Non inviare messaggi reali a Gmail o Outlook finché il punteggio non è 10/10. Un punteggio basso associato a un IP nuovo può far contrassegnare il tuo dominio già dal primo giorno.

Passaggio 8: connettere un client di posta reale

Configura Thunderbird, Apple Mail o il telefono con questi parametri. Per tutti, il server è mail.example.com:

  • IMAP: porta 993, SSL/TLS (oppure 143 con STARTTLS)
  • Invio SMTP: porta 465, SSL/TLS (oppure 587 con STARTTLS)
  • Nome utente: l'indirizzo completo, you@example.com
  • Password: la password della casella configurata

Non inviare mai la posta del client tramite la porta 25. Questa porta è riservata alle comunicazioni tra server. mailcow non offre l'invio autenticato su questa porta e il client che la utilizza viene rifiutato. Se il client segnala Relay access denied, sta tentando di inviare tramite la porta 25 oppure senza autenticazione. Configuralo sulla porta 465 o 587 usando le credenziali della casella.

Passaggio 9: eseguire il backup di ciò che conta davvero

mailcow include uno script di backup che crea snapshot di ogni volume con stato persistente. Eseguilo su un disco esterno o su una destinazione remota montata:

sudo MAILCOW_BACKUP_LOCATION=/opt/mailcow-backups \
  ./helper-scripts/backup_and_restore.sh backup all

all acquisisce sei elementi. La perdita di uno qualsiasi di questi elementi comporta una perdita di dati: vmail (le caselle di posta effettive), crypt (le chiavi che decrittano vmail, inutilizzabili senza di esso), mysql (il database MariaDB che contiene domini, utenti, alias e impostazioni), redis (lo stato delle code e della cache), rspamd (i dati appresi per classificare spam e posta legittima) e postfix (la coda di posta). Lo script viene eseguito all'interno di un container di supporto e scrive archivi compressi, quindi i backup restano coerenti anche mentre lo stack è in esecuzione. Automatizzalo con un cron job notturno e aggiungi --delete-days 14 per eliminare i set meno recenti. Un cron job che smette di funzionare fallisce senza produrre notifiche. Invia quindi lo stato di uscita dello script a un sistema che controlli davvero; un server ntfy self-hosted richiede un comando curl su una sola riga nella stessa voce cron e invia l'errore al telefono la notte in cui si verifica. Il ripristino usa lo stesso script con restore. Questo comando elenca gli snapshot e consente di scegliere quali ripristinare. Un backup mai sottoposto a un test di ripristino è solo un'ipotesi, non un backup. Esegui almeno una prova a vuoto su una VPS di test.

Passaggio 10, Aggiornamenti pianificati

mailcow si aggiorna tramite il proprio script, che scarica il nuovo codice, esegue la migrazione di mailcow.conf, precarica le immagini e riavvia i container nell’ordine corretto:

cd /opt/mailcow-dockerized
sudo ./update.sh --check   # reports whether an update exists, changes nothing
sudo ./update.sh           # applies it

Esegui prima il backup (Passaggio 9), perché una migrazione dello schema è difficile da annullare. Gli aggiornamenti vengono pubblicati frequentemente e includono correzioni di sicurezza per i demoni esposti a Internet. Non lasciare quindi un server di posta senza aggiornamenti per mesi. Se un aggiornamento lascia un container in stato non integro, sudo docker compose logs --tail=50 <service>-mailcow indica il demone che non è tornato operativo.

Una nota sull’hardening

mailcow esegue un proprio servizio netfilter (netfilter-mailcow) che blocca gli indirizzi IP dai quali provengono numerosi tentativi di accesso sulle porte della posta e della webmail. Il livello di protezione della posta è quindi già configurato. Questo non protegge SSH sull’host stesso, che rimane esposto e continua a ricevere attacchi brute-force. Abbina questa configurazione a Fail2ban che monitora il log di autenticazione SSH e all’accesso consentito solo tramite chiavi. Proteggi l’interfaccia di amministrazione di mailcow con una password robusta e, idealmente, non esporla a Internet oppure rendila accessibile tramite una VPN.

Modalità di errore, con le stringhe esatte

Le code di posta aumentano e i messaggi non vengono mai consegnati. Eseguire sudo docker compose exec postfix-mailcow postqueue -p oppure leggere la coda di posta nell'interfaccia di amministrazione; le voci restano nello stato deferred con:

status=deferred (connect to gmail-smtp-in.l.google.com[142.250.x.x]:25: Connection timed out)

La porta in uscita 25 è bloccata dal provider (Passaggio 1). Nessuna modifica alla configurazione può risolvere il problema: aprire un ticket. Non è un problema di DNS né di TLS; l'indicatore è la parola timed out riferita a un MX remoto sulla porta 25.

Gmail contrassegna tutti i messaggi come spam oppure li rifiuta. Aprire il messaggio in Gmail, selezionare "Show original" e leggere i risultati dell'autenticazione. dkim=fail o dkim=none indica che il record TXT dkim._domainkey manca, è errato o non è ancora stato propagato. Pubblicare di nuovo esattamente il contenuto mostrato dalla pagina ARC/DKIM e attendere il TTL. spf=fail indica che i record SPF/MX non includono il vostro IP. L'allineamento è fondamentale: è sufficiente un solo controllo non superato per finire nello spam.

I grandi provider rifiutano la connessione. I messaggi di mancata consegna o i log di Postfix contengono il rifiuto PTR di Gmail:

550-5.7.25 [10.0.0.10] The IP address sending this message does not have a PTR
550-5.7.25 record setup, or the corresponding forward DNS entry does not match
550 5.7.25 the sending IP. As a policy, Gmail does not accept messages from IPs
550 5.7.25 with missing PTR records.

Il codice 550 5.7.25 indica che il DNS inverso manca o non corrisponde. Impostare presso il provider il PTR dell'IP su mail.example.com (Passaggio 2). I record forward (A) e reverse (PTR) devono corrispondere e devono indicare lo stesso host con cui mailcow si presenta agli altri server.

Il browser mostra un avviso relativo al certificato che non scompare. Il container acme-mailcow non è riuscito a ottenere un certificato valido. Controllarne il log:

sudo docker compose logs acme-mailcow | tail -n 40

Una riga come Cannot validate any hostnames, skipping Let's Encrypt for 1 hour. o un errore della challenge indica che la porta 80 non è raggiungibile da Internet oppure che il record A non punta a questo server. Verificare che mail.example.com risolva verso il server, aprire le porte 80 e 443 attraverso eventuali firewall dell'host e assicurarsi che nessun altro processo sia in ascolto su queste porte. Dopo aver corretto la causa, riavviare il client con sudo docker compose restart acme-mailcow invece di attendere il back-off di un'ora.

FAQ

Il self-hosting della posta elettronica conviene davvero?

Se vuoi la proprietà dei dati, alias illimitati e il pieno controllo, sì: mailcow offre uno stack professionale al prezzo di un VPS. Tuttavia, la deliverability richiede attività costante: reputazione dell'IP, allineamento DNS e monitoraggio delle blocklist non finiscono mai del tutto. Per un indirizzo aziendale mission-critical, quando un solo giorno nella cartella spam di qualcuno può costarti caro, un provider gestito è la scelta più pragmatica. Scegli il self-hosting quando attribuisci più valore al controllo che alla comodità e sei disposto a gestirlo concretamente. Se in realtà vuoi soltanto che i tuoi dati non si trovino sui server di qualcun altro, senza che la posta elettronica sia l'obiettivo specifico, inizia da un servizio sul quale gli altri non hanno voce in capitolo: una libreria fotografica non presenta alcun problema di deliverability e il nostro confronto tra PhotoPrism e Immich illustra i requisiti minimi di RAM e i comandi di backup per quella configurazione sullo stesso tipo di VPS.

Come posso sapere se la porta in uscita 25 è bloccata?

Esegui nc -vz -w 5 gmail-smtp-in.l.google.com 25 dal server. Il messaggio "succeeded!" indica che la porta è aperta; un timed out dopo l'attesa indica che il provider la blocca. Questa è la causa più comune per cui un server self-hosted riesce a ricevere posta ma non a inviarla. L'unica soluzione è chiedere al provider di aprire la porta: nessuna impostazione locale può modificarne il blocco.

Perché i miei messaggi finiscono ancora nella cartella spam di Gmail?

Quasi sempre la causa è una catena di autenticazione non configurata correttamente. In Gmail, usa "Show original" e cerca spf=pass, dkim=pass e dmarc=pass. Un dkim=fail indica un record TXT dkim._domainkey mancante o modificato in modo errato; anche una mancata corrispondenza del PTR o un IP nuovo privo di cronologia di invio penalizzano la reputazione. Prima porta mail-tester.com a 10/10, quindi aumenta gradualmente il volume sull'IP, iniziando con pochi messaggi al giorno e incrementandolo nel tempo, invece di inviare grandi quantità già dal primo giorno.

Che cosa devo includere esattamente nel backup?

Esegui backup_and_restore.sh backup all e conserva l'intero set fuori dal server. Include vmail, cioè le caselle di posta; crypt, cioè le chiavi che le decrittografano; il database MariaDB, con domini, utenti, alias e impostazioni; Redis; i dati appresi da Rspamd; e la coda di Postfix. Il volume crypt è quello che spesso viene trascurato: senza di esso, il backup di vmail contiene dati cifrati illeggibili. Esegui almeno una volta un ripristino su un server di prova.

Posso eseguire mailcow su un VPS da 2 GB?

Non in modo affidabile. generate_config.sh propone di disabilitare ClamAV al di sotto di circa 2.5 GiB, ma anche in questo caso Rspamd, ClamAV, Dovecot e MariaDB competono per la memoria. Con un carico reale si verificheranno quindi uso della swap e terminazioni per OOM. Considera 6 GiB più 1 GiB di swap il requisito minimo per un'installazione stabile per un singolo utente. Passa a 8 GiB non appena il servizio viene utilizzato da più di un paio di persone.