Docs / Fixes
PowerMTA: port 25 already in use — how to fix it
The error means another mail server already holds TCP port 25, so PowerMTA can't bind it. Find the process with sudo ss -lntp | grep ':25 ', then stop and disable the conflicting MTA (usually Postfix, sometimes Exim or sendmail) — or bind PowerMTA to a submission port like 2525. Confirm exactly one process owns 25, then start PowerMTA.
When PowerMTA fails to start with "SMTP TCP port already in use" or a bind error on port 25, the cause is almost never PowerMTA — it's that another mail server is already listening on that port. Two MTAs can't share it. This page finds the culprit and frees the port the right way — and covers the less obvious version, where the conflict is inside one mail server’s own config rather than between two programs.
Why two MTAs can’t share port 25
A TCP port is held by exactly one listening socket per address. When PowerMTA tries to bind 0.0.0.0:25
and another process already has it, the kernel refuses with address already in use — there’s no sharing
and no queue, the second program simply fails to start. That’s by design: port 25 is the well-known SMTP port, and
a server has to know unambiguously which process receives mail on it.
The reason this bites so often is that most Linux installs ship a mail server already running. AlmaLinux, Rocky and Debian/Ubuntu commonly start Postfix on port 25 for local and system mail; cPanel boxes run Exim; older systems carry sendmail. So the moment you install PowerMTA or KumoMTA to send at volume, you have two mail servers wanting the same port, and the newcomer loses the race. The fix is never to force a share — it’s to decide which one owns port 25 and arrange the other around it.
Find what holds port 25
List the process bound to the port:
sudo ss -lntp | grep ':25 '
# or
sudo lsof -i :25 You'll typically see master (Postfix), exim, or sendmail. Confirm which service it is:
systemctl status postfix exim sendmail 2>/dev/null | grep -E 'Loaded|Active|^●' Read the output properly
Two details trip people up. First, check both address families: a process can hold IPv4 0.0.0.0:25,
IPv6 [::]:25, or a single bound IP. Listing only one can hide the real owner, so prefer ss
or lsof over an incomplete netstat -ln, which famously shows nothing useful in some of
these cases. If ss still shows nothing but the bind keeps failing, try sudo fuser 25/tcp,
which names the PID directly.
Second, read the process name, not the port alone. master is Postfix; exim and
sendmail are themselves. Map the PID back to its service so you disable the right thing rather than
killing a child process that a supervisor immediately respawns:
sudo ss -lntp | grep ':25 '
# PID → service
systemctl status $(sudo ss -lntp | grep -oP 'pid=\K[0-9]+' | head -1) 2>/dev/null | head -3 The hidden case: a duplicate in master.cf
Sometimes the conflict isn’t two programs — it’s one. If Postfix itself fails with
bind 0.0.0.0 port 25: Address already in use while nothing else holds the port, the usual cause is a
duplicate listener in /etc/postfix/master.cf: two smtp inet lines that both try to bind
25. Control panels and bad merges are common sources. Open the file, find the repeated smtp inet n - n - -
smtpd entries, and comment out the duplicate so only one remains:
# /etc/postfix/master.cf — keep ONE smtp inet line
smtp inet n - n - - smtpd
#smtp inet n - n - - smtpd <- duplicate, comment out Then sudo postfix check and reload. This is worth ruling out before you go hunting for a second MTA that isn’t there.
Free the port
If PowerMTA should own outbound (the usual case for volume sending), stop and disable the conflicting MTA so it won't return on reboot:
# Postfix (most common)
sudo systemctl stop postfix
sudo systemctl disable postfix
# Exim / sendmail if present
sudo systemctl stop exim sendmail
sudo systemctl disable exim sendmail If you still need local mail delivery on the box, instead of disabling Postfix you can bind it to localhost only (set inet_interfaces = loopback-only in main.cf) so it stays off the public port 25.
Alternative: run PowerMTA on a submission port
If another MTA must keep port 25, don't fight it — give PowerMTA its own listener. Configure PowerMTA's SMTP listener on a port like 2525 and point your application or MailWizz relay at it. See the CyberPanel integration for the panel-specific version of this trade-off.
Confirm and start
Make sure exactly one process (or none, before you start PowerMTA) holds the port, then start and verify:
sudo ss -lntp | grep ':25 ' # should be clear, or show pmta after start
sudo /etc/init.d/pmta start # or: systemctl start pmta
pmta show status Decide who owns port 25
Before touching anything, make the architectural call, because it determines which fix you apply. For high-volume outbound, your sending engine — PowerMTA or KumoMTA — should own port 25, since that’s the engine doing the work that matters and the one whose throttling, pools and reputation you’re managing. Postfix, Exim or sendmail then either steps aside entirely or is confined to local/system mail. The opposite arrangement — keeping the default MTA on 25 and relaying to your sender on another port — is valid too, and sometimes necessary on a managed or panel-controlled box you don’t fully own.
The wrong move is to repeatedly kill whichever process you find and start yours in the gap. It “works” until the next reboot or the next time a supervisor restarts the other MTA, and then you’re back to a flapping listener and intermittent failures. Decide ownership once, make it persistent, and the conflict stops recurring.
Coexistence patterns
There are four clean ways to resolve it, in rough order of how often they’re the right answer:
- Disable the other MTA. If nothing on the box needs local mail, stop and disable Postfix/Exim/sendmail so the sending engine owns 25 cleanly. Simplest and most common.
- Confine the other MTA to loopback. If you still need local/system mail (cron output, alerts), set
inet_interfaces = loopback-onlyin Postfix’smain.cf. It keeps delivering locally on 127.0.0.1 and leaves the public port 25 free. - Bind each MTA to specific IPs. On a multi-IP server you can give the default MTA one address and the sending engine others, so neither claims
0.0.0.0. Postfix usesinet_interfaces/ per-transportsmtp_bind_address; the sending engine binds its own set. - Relocate the sending engine. If the other MTA must keep 25, point PowerMTA or KumoMTA at a submission-style port like
2525and relay your apps to it. Least common, but the escape hatch when you don’t control the box.
Whichever you pick, make it survive a reboot — a disabled service, a saved config, a persistent bind —
so the resolution holds rather than working only until the next restart.
Stale binds, TIME_WAIT and SELinux
Occasionally the port appears taken when no live MTA holds it. A process that just crashed or restarted can leave a
socket briefly in TIME_WAIT, so a retry a few seconds later succeeds. A leftover or zombie daemon may
still hold the descriptor — find it with sudo fuser 25/tcp and stop it properly rather than spawning
another. And on SELinux-enforcing systems, a bind can be denied at the policy layer even though the port is free;
check the audit log (ausearch -m avc -ts recent) if the process insists it can’t bind a port nothing
else is using. These are the edge cases behind “nothing is on 25 but it still won’t bind.”
Make sure the fix survives a reboot
The most common way this problem “comes back” is a fix that only held until the next restart. If you stopped the
other MTA but didn’t disable it, systemd will start it again on boot and reclaim port 25 before your
sending engine comes up. So confirm the state is persistent: the conflicting service shows disabled under
systemctl is-enabled, any main.cf or master.cf change is saved, and your
engine’s service is enabled to start on boot. Then actually reboot once and re-check the listener — a fix you
haven’t tested across a restart isn’t finished.
systemctl is-enabled postfix # should say: disabled (or masked)
sudo ss -lntp | grep ':25 ' # after reboot: only your engine Is it actually outbound 25 being blocked?
It’s worth being precise, because two different problems wear similar language. “Port 25 already in use” is a local bind conflict — something on your own box holds the port. A blocked outbound port 25 is the opposite: your engine binds locally just fine, but the provider’s network won’t let connections leave on port 25, so deliveries time out instead. Many clouds block outbound 25 by default to fight spam.
Test which one you have by trying to reach a remote mail server on 25 from your box:
nc -vz gmail-smtp-in.l.google.com 25
# open → outbound 25 works; succeeded means it’s a local bind issue, not the network
# timeout/refused → outbound 25 is blocked by your provider If outbound is blocked, no local fix helps — you need the provider to open port 25 (often a support request and a use-case justification), or you relay through an authorized smart host on a permitted port. The connection-timed-out fix covers diagnosing that path in full; this page is specifically about the local bind conflict.
A worked example, start to finish
Here’s the whole flow on a fresh AlmaLinux box where Postfix has port 25 and you want PowerMTA to own it for outbound, with no need for local mail. First, confirm the holder and identify it; then disable it; then verify the port is free; then start your engine and check it bound cleanly:
# 1. who has port 25?
sudo ss -lntp | grep ':25 '
# LISTEN ... 0.0.0.0:25 ... users:(("master",pid=812,...)) → Postfix
# 2. stop and disable it so it stays gone after reboot
sudo systemctl stop postfix
sudo systemctl disable postfix
# 3. confirm 25 is now free
sudo ss -lntp | grep ':25 ' # no output = clear
# 4. start the engine and verify it owns 25
sudo systemctl start pmta
sudo ss -lntp | grep ':25 ' # now shows pmta
pmta show status
If you needed Postfix for local system mail, you’d replace step 2 with inet_interfaces = loopback-only
in main.cf and a reload, leaving Postfix on 127.0.0.1 and the public 25 free for the engine. On KumoMTA
the only difference is step 4 — you start and check the KumoMTA service instead — because the conflict and the
resolution are identical regardless of which engine takes the port.
Mistakes to avoid
A few habits turn a five-minute fix into a recurring headache. Killing instead of disabling is the
big one — kill or systemctl stop without disable frees the port until the
next boot, then the conflict silently returns. Forcing two binds by trying to make both MTAs listen
on 0.0.0.0:25 never works; the port has one owner per address, full stop. Editing the wrong
file is common too: changing main.cf when the duplicate is in master.cf, or vice
versa, leaves the real cause untouched.
And the costliest mistake is misreading the problem entirely — spending an hour freeing a local bind when the real issue is the provider blocking outbound 25, or the reverse. Run the one-line outbound test early so you know which of the two you’re solving before you change anything. Diagnose first, decide ownership once, make it persistent, and verify across a reboot: do those four and the error doesn’t come back.
Sanity-check the listener
Once your engine owns port 25, do a quick two-part check before you trust it. First confirm it’s actually listening where you expect — not merely running as a service, but genuinely bound to the right address and the right port — and that it actually answers SMTP when something connects. A local banner check is enough to prove the socket is live and the engine is the thing answering on it:
# is the engine bound and answering on 25?
sudo ss -lntp | grep ':25 '
printf 'QUIT\r\n' | nc -w3 127.0.0.1 25 # expect a 220 SMTP banner, then 221 Second, send one real test through the engine to a seed inbox and read the headers to confirm it left correctly and authenticated. If the banner check passes but the test message never arrives, you’ve almost certainly crossed into the outbound-blocked case above rather than the bind conflict — the listener is fine, the network path isn’t. Separating those two checks (does it bind and answer locally? does mail actually leave?) tells you in under a minute which half of the problem you’re in, and keeps you from spending time “fixing” a local bind that was never the actual issue.
The bottom line
“Port 25 already in use” is almost never a problem with your sending engine — it’s a pre-existing mail server, or
occasionally a duplicate line in Postfix’s own config, holding the port first. Find what holds it with
ss, lsof or fuser; decide deliberately which MTA should own port 25; then
disable, confine or relocate the other so the decision is persistent. Rule out the duplicate master.cf
case if nothing else seems to hold the port, and don’t confuse a local bind conflict with a provider blocking
outbound 25 — they look alike and need opposite fixes.
Done once and made persistent, this is a five-minute fix that stays fixed. If you’d rather not work through it on a production box — or you want the whole stack installed with the port arrangement, authentication and listeners set up correctly from the start — our setup service does exactly that on your own server and license, and the Auto PMTA Configurator handles the coexistence automatically when it builds the stack.
Frequently asked questions
What process usually holds port 25 on a fresh server? +
Postfix. Most AlmaLinux, Rocky and Ubuntu installs ship Postfix listening on port 25 for local mail. Exim (common on cPanel boxes) and the legacy sendmail are the other usual suspects. Whichever it is, two mail servers cannot both bind port 25.
Can PowerMTA and Postfix run on the same server? +
Yes, but not both on port 25. Decide which one owns outbound: for volume sending, let PowerMTA bind 25 and either disable Postfix or restrict it to localhost for local mail. Alternatively keep Postfix on 25 and run PowerMTA on a submission port (e.g. 2525) that your applications relay to.
I stopped Postfix but still get 'port already in use'. +
Something else is holding it. Re-run sudo ss -lntp | grep ':25 ' to see the actual process — it may be Exim, sendmail, or a leftover daemon. Also confirm the service didn't restart (disable it rather than only stopping it), and check SELinux isn't blocking PowerMTA from binding.
My host blocks outbound port 25 entirely — is that the same problem? +
No, that's a different issue. 'Port 25 already in use' is a local bind conflict. If your cloud provider blocks outbound port 25 (many do by default), PowerMTA can bind it locally but mail still won't leave. Ask the provider to open outbound 25, or relay through an authorized smart host.
ss and lsof show nothing on port 25, but the bind still fails. Why? +
A few possibilities. Check IPv6 as well as IPv4 (a process may hold [::]:25), try sudo fuser 25/tcp which names the PID when ss misses it, and rule out a duplicate smtp inet line in Postfix’s master.cf — that makes Postfix conflict with itself. A stale socket in TIME_WAIT from a process that just exited can also briefly hold it; wait a few seconds and retry. Finally, on SELinux systems confirm the policy isn’t blocking the bind.
Does this apply to KumoMTA as well as PowerMTA? +
Yes. Any MTA that sends on port 25 will hit the same conflict with a pre-installed Postfix, Exim or sendmail. The diagnosis (find the holder) and the resolution (decide ownership, disable or relocate the other, or bind per-IP) are identical whether the sending engine is PowerMTA or KumoMTA.
Is it safe to just disable Postfix? +
Usually yes, if nothing on the box relies on it for local or system mail (cron output, alerts). If something does, don’t disable it — restrict it to loopback with inet_interfaces = loopback-only so it keeps handling local mail without touching the public port 25, and let your sending engine own 25. Disable only when you’re sure local delivery isn’t needed.
Related