Loading...

Lab 80: Installing and Configuring Postfix (MTA)

Install and start Postfix as a local Mail Transfer Agent (MTA) so the host can deliver service notifications and cron output. Validate service health, set a basic mail identity, send a test message to the local root mailbox, and confirm the message is actually delivered.

mail services core

Scenario

You need a working local MTA so system-generated mail (cron output, security alerts, logrotate notices, and service notifications) does not disappear silently. This host does not need to relay mail to the internet, but it must deliver mail locally and reliably across reboots.

Operator context

A local MTA is still common in hardened environments. Even without an external relay, local delivery preserves operational signal (alerts, automation output) when something goes wrong.

Objective

  • Install Postfix with the system package manager.
  • Enable and start postfix at boot.
  • Verify service health with systemctl.
  • Set a basic mail identity (local domain/hostname context).
  • Send and verify a test message to root.

Concepts

  • Postfix accepts mail from local processes and delivers it to local mailboxes (or relays it if configured).
  • “Local MTA” does not mean “public mail server.” The default target here is local delivery for system accounts.
  • Verification means checking the service, queue/logs, and the mailbox itself (not just “command ran”).
  • Mail identity (hostname/domain) impacts sender headers and how local mail tools format addresses.

Walkthrough

Step 1 : Install Postfix.
Note

Use the native package manager for your distro. If you are on RHEL-based systems, use dnf (not legacy yum).

Commands
# RHEL / CentOS / Fedora
sudo dnf install -y postfix mailx

# Debian/Ubuntu
sudo apt update
sudo apt install -y postfix bsd-mailx

# Arch
sudo pacman -S postfix mailutils

Postfix provides the MTA. The mail client package provides mail so you can send and read local test mail during validation.

Installing Postfix and mail client... Done.
Step 2 : Enable and start Postfix.
Command
sudo systemctl enable --now postfix

enable ensures it starts on boot; --now starts it immediately so you can verify state.

Created symlink .../multi-user.target.wants/postfix.service → .../postfix.service.
Job for postfix.service started successfully.
Step 3 : Verify service health.
Commands
systemctl status postfix --no-pager
ss -lntp | grep -E ':(25|587)\s' || true

Confirm the unit is active and that Postfix is listening locally. Depending on defaults, you may see port 25 (SMTP) and possibly 587 (submission).

● postfix.service - Postfix Mail Transport Agent
Active: active (running)

LISTEN 0 100 127.0.0.1:25 ... master
Step 4 : Set a basic mail identity (mail domain/hostname context).
Commands
# Set a minimal mailname (common on Debian-based systems)
echo 'example.local' | sudo tee /etc/mailname

# Set Postfix myhostname/mydomain explicitly (works everywhere)
sudo postconf -e 'myhostname=mail01.example.local'
sudo postconf -e 'mydomain=example.local'
sudo postconf -e 'myorigin=$mydomain'

sudo systemctl restart postfix

This establishes predictable sender identity for local mail. Restart Postfix so settings are applied.

postfix/postconf: updated configuration
postfix restarted.
Step 5 : Send a test message to local root.
Command
echo 'Postfix local delivery test' | mail -s 'postfix-test' root

This validates local submission into the MTA. Next you confirm the message lands in root’s mailbox.

Message accepted for delivery.
Step 6 : Verify delivery (mailbox, queue, logs).
Commands
# Read root mail (interactive)
sudo mail -u root

# Check queue (should be empty for local delivery)
mailq

# Check service logs (systemd journal)
sudo journalctl -u postfix --no-pager -n 50

Your “done” signal is: message visible in the root mailbox, queue not building up, and no obvious delivery errors in logs.

# Example: mail shows a new message with subject "postfix-test"
# Example: mailq returns "Mail queue is empty"

Common breakpoints

postfix is running, but mail never arrives

Check mailq for stuck messages, then inspect journalctl -u postfix for local delivery errors. Also confirm you installed a mail client package so you can read local mail.

port 25 is not listening

Re-check the unit state (systemctl status postfix) and whether Postfix is configured for loopback-only binding. If you hardened the host, confirm firewall rules and SELinux context if applicable.

hostname/domain looks wrong in headers

Validate postconf -n output and ensure myhostname, mydomain, and myorigin match your intended identity.

Cleanup checklist

This lab is safe to leave in place if you want local system mail. If you need to revert, stop/disable the service and remove the packages using your distro’s package manager.

Commands
sudo systemctl disable --now postfix
mailq

Reference

  • dnf install postfix mailx: Install Postfix and a local mail client on RHEL-based systems.
  • apt install postfix bsd-mailx: Install Postfix and a local mail client on Debian-based systems.
  • pacman -S postfix mailutils: Install Postfix and a local mail client on Arch.
  • systemctl enable --now postfix: Enable Postfix at boot and start it immediately.
  • systemctl status postfix: Show Postfix unit health and current runtime state.
  • postconf -e 'key=value': Set Postfix configuration values non-interactively.
    • myhostname: Host identity used in mail headers.
    • mydomain: Domain portion for local mail identity.
    • myorigin: Domain appended to locally-posted mail.
  • /etc/mailname: Mail name file used on some systems (commonly Debian-based).
  • mail -s '<subject>' <user>: Send a local message with a subject.
  • mail -u <user>: Read a local user’s mailbox interactively.
  • mailq: Display queued messages waiting for delivery.
  • journalctl -u postfix: View Postfix logs from the systemd journal.
    • -n 50: Show the most recent 50 lines.
    • --no-pager: Print directly to stdout.
  • ss -lntp: List listening TCP sockets and owning processes.
    • -l: listening sockets
    • -n: numeric addresses/ports
    • -t: TCP
    • -p: process info