8.2.25 Poste.io — Deploying a Mail Server

The Host Banner Poste.io

Poste.io simplifies deploying a full-featured mail server: SMTP/IMAP/POP3, web admin, webmail, anti-spam/antivirus. This article addresses: correct networking and ports, issuing a TLS certificate, configuring DNS records (MX, SPF, DKIM, DMARC), reverse zone (rDNS/PTR) and basic diagnostics. We rely on the project’s current recommendations: Docker host network, the list of ports to open, rDNS and DNS requirements, and Poste.io environment parameters.

Server preparation

Requirements

Environment variables

The article uses placeholders (replace with your own values):

  • SERVER_IP — public IP of the server
  • DOMAIN_NAME — root domain (example: example.com)
  • MAIL_HOSTNAME — A record of the mail host (example: mail.example.com)
  • TIMEZONE — system timezone (example: Europe/Kyiv)
  • DATA_DIR — data directory on the host (example: /srv/poste/data)
  • ADMIN_EMAIL — your admin email (you will create it in the admin panel)

Installation

Prepare Docker and Compose

Install Docker and Compose in the usual way (if not already installed). See the full guide in our article: Docker and Docker Compose.

Check versions:

Check Docker/Composer
docker --version
docker-composer version

docker --version

Create the data directory

First, create a directory for data and grant permissions:

Create data directory
sudo mkdir -p DATA_DIR
sudo chown -R $USER:$USER DATA_DIR

Create data directory

Note: all mail data, logs and configs live in /data inside the container. We will mount DATA_DIR there to simplify backups.

Prepare docker-compose.yml

Create a Compose file with the recommended host network (correct outgoing IPs, simple firewall, IPv6 readiness):

docker-compose.yml
version: "3.8"

services:
  poste:
    image: analogic/poste.io:2
    container_name: poste
    hostname: MAIL_HOSTNAME
    restart: unless-stopped
    network_mode: host              # recommended mode
    environment:
      - TZ=TIMEZONE
      # If proxying through external Nginx/Traefik you can disable HTTPS redirect:
      # - HTTPS=OFF
      # Additionally, if RAM is tight (not recommended for production):
      # - DISABLE_CLAMAV=TRUE
      # - DISABLE_RSPAMD=TRUE
      # Integration if needed:
      # - ELASTICSEARCH=127.0.0.1:9200
    volumes:
      - DATA_DIR:/data

Alternative without host network: instead of network_mode: host you can use ports: and map 25, 80, 110, 143, 443, 465, 587, 993, 995 and, if needed, 4190 (Sieve). But the project recommends the host network.

Start the container

Bring the service up and confirm it is running:

Start
docker compose up -d
docker compose ps

docker compose

docker compose ps

Open firewall ports

Allow mail and web ports.

UFW -- allow required ports
sudo ufw allow 25,80,110,143,443,465,587,993,995,4190/tcp
sudo ufw reload
sudo ufw status numbered

UFW

iptables -- allow required ports
sudo iptables -A INPUT -p tcp -m multiport --dports 25,80,110,143,443,465,587,993,995,4190 -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -j DROP

Initial admin login

Open the admin/webmail in a browser at: https://<MAIL_HOSTNAME>. Use the setup wizard to create an administrator, a domain and the first mailbox.

Web ui

After that you will enter the administrative panel:

Administrator creating

Configuring additional features

Sieve filters (port 4190)

Sieve is the standardized server-side mail filtering language (RFC 5228). Rules run on the server before the mail reaches the client: folder sorting, forwarding, auto-replies, anti-spam tags, etc. Editing rules from Roundcube/Thunderbird via ManageSieve (port 4190) is convenient.

Enable management of delivery rules:

ss -lntp | grep :4190 || echo "Open port 4190 (see UFW/iptables above)"

Why this is useful

Unified server-side rules work the same for all clients and devices (unlike local filters in a mail client).

Elasticsearch integration

Elasticsearch is a full-text search and analytics engine. For Poste.io it is useful for aggregating and searching mail events and logs (deliveries, bounces, spam scores, quarantine, etc.), building dashboards and investigating incidents (together with Kibana/OpenSearch). The feature is optional but simplifies monitoring and auditing the mail system.

Add the following line to your docker-compose.yml under environment:

docker-compose.yml
environment:
  - ELASTICSEARCH=127.0.0.1:9200

Data backup

Save critical data from the mounted DATA_DIR:

Backup data directory
docker compose down
tar -C $(dirname DATA_DIR) -czf /root/poste-backup-$(date +%F).tar.gz $(basename DATA_DIR)
docker compose up -d

Verification and testing

View container logs

Check that the service started without critical errors:

Poste.io logs
docker logs -f poste

View container logs

Check listening ports

Ensure the required TCP ports are open and bound to processes:

Check listening ports
ss -lntp | egrep ':25|:80|:110|:143|:443|:465|:587|:993|:995|:4190'

Check listening ports

Quick breakdown of ss -lntp columns

  • LISTEN — socket is waiting for incoming connections
  • Local Address:Port — where the port is bound
  • 0.0.0.0:PORT — listening on all IPv4 interfaces
  • [::]:PORT or *:PORT — listening on all IPv6
  • 127.0.0.1:PORT — available only locally
  • users:(… pid=…) — which process holds the port (name and PID)

Common issues

Error / Symptom Cause Fix Diagnostics
Certificate not issued Port 80 is occupied/closed Free port 80 or proxy /.well-known to Poste.io; retry issuance ss -lntp or grep :80
Messages land in spam Missing/incorrect SPF/DKIM/DMARC, missing rDNS Fix records; request PTR from your provider dig, nslookup, hints in admin UI
Sending to external domains fails Provider blocks port 25 Request unblock / use a smart relay telnet mx.gmail.com 25 from server
Admin UI not reachable over HTTPS Port 443 conflict Free port 443 on the host or use a proxy + HTTPS=OFF + HTTP_PORT/HTTPS_PORT ss -lntp or grep :443
IMAP/POP3 not working Ports / firewall Allow ports in UFW/iptables ufw status, iptables -S

Official documentation and resources

Official documentation