How To Install PostfixAdmin on Fedora 43

Install PostfixAdmin on Fedora 43

Managing a mail server manually gets painful fast. The moment you need to handle more than one domain or a handful of mailboxes, editing flat config files and reloading Postfix for every change stops being practical and starts causing mistakes. That is exactly the problem PostfixAdmin solves. This guide walks you through how to install PostfixAdmin on Fedora 43 from scratch, covering every layer of the stack: Postfix as the mail transfer agent, MariaDB as the database backend, Apache and PHP as the web layer, and PostfixAdmin as the browser-based control panel that ties them all together.

Every step below includes a “WHY” explanation. You will understand what each command actually does to your system, not just copy and paste blindly. That approach saves hours of debugging and makes you a better sysadmin in the process.

What this guide covers:

  • Setting up a fully qualified hostname
  • Installing and configuring Postfix
  • Installing MariaDB and creating the PostfixAdmin database
  • Installing Apache with all required PHP extensions
  • Downloading and deploying PostfixAdmin
  • Writing a secure config.local.php
  • Creating an Apache VirtualHost
  • Configuring SELinux and firewalld (the steps most tutorials skip)
  • Running the web-based setup wizard
  • Verifying your install works end-to-end
  • Troubleshooting the five most common failure points

Prerequisites

Before you run a single command, confirm all of the following are in place.

System requirements:

  • Fedora 43 server (fresh install preferred) with at least 2GB RAM and 20GB disk space
  • Root access or a user account with full sudo privileges
  • A static IP address — dynamic IPs are blacklisted by the majority of receiving mail servers

DNS requirements (critical — configure these before starting):

  • An A record pointing your mail hostname (e.g., mail.yourdomain.com) to your server’s IP
  • An MX record for your domain pointing to mail.yourdomain.com
  • A PTR (reverse DNS) record matching your FQDN — without this, most major mail providers will reject your outbound email as suspected spam

Ports that must be reachable:

  • 25 (SMTP — mail transfer between servers)
  • 80 / 443 (HTTP/HTTPS — PostfixAdmin web interface)
  • 143 / 993 (IMAP / IMAPS)
  • 110 / 995 (POP3 / POP3S)

Knowledge baseline:

  • Basic Linux command-line navigation
  • Familiarity with editing files using nano or vim
  • A domain name you control and can update DNS records for

Step 1: Update Your Fedora 43 System and Set the Hostname

Update All Packages

Start with a clean, fully updated system. Fedora moves fast, and stale packages cause dependency conflicts during installation.

sudo dnf update -y && sudo dnf upgrade -y

WHY: Package updates pull in security patches, updated library versions, and any fixes to packages like openssl or glibc that Postfix and MariaDB depend on at compile time. Installing server software on top of outdated packages is a recipe for subtle, hard-to-diagnose failures.

If a kernel update was included, reboot before continuing:

sudo reboot

WHY the reboot: When a new kernel is installed, the running kernel in memory does not match the installed one. Some services including network drivers behave differently or fail to load until the new kernel is active.

Install Utility Packages

sudo dnf install wget nano net-tools -y

Set Your Fully Qualified Domain Name (FQDN)

sudo hostnamectl set-hostname mail.yourdomain.com

Open /etc/hosts and add your server’s IP alongside its hostname:

sudo nano /etc/hosts

Add this line (replace with your actual IP and domain):

YOUR_SERVER_IP   mail.yourdomain.com   mail

Confirm the FQDN is set correctly:

hostname -f

Expected output:

mail.yourdomain.com

WHY set the FQDN now: Postfix reads the hostname at startup and embeds it in SMTP banners, Received headers, and bounce messages. If hostname -f returns something like localhost.localdomain, receiving servers will flag your outbound mail as spoofed or misconfigured. Fix this first so everything downstream uses the correct identity.

Step 2: Install and Configure Postfix on Fedora 43

Install Postfix

Fedora 43 may include Postfix by default, but run the install command anyway to confirm you have the latest version:

sudo dnf install postfix postfix-mysql -y

WHY postfix-mysql: This adds the MySQL/MariaDB lookup table support to Postfix. Without it, Postfix cannot query your MariaDB database for virtual domain and mailbox information later in the setup.

Configure main.cf

Open the primary Postfix configuration file:

sudo nano /etc/postfix/main.cf

Find and set the following directives (replace yourdomain.com with your actual domain throughout):

myhostname = mail.yourdomain.com
mydomain = yourdomain.com
myorigin = $mydomain
inet_interfaces = all
inet_protocols = ipv4
mydestination = $myhostname, localhost.$mydomain, localhost
mynetworks = 127.0.0.0/8
home_mailbox = Maildir/
smtpd_banner = $myhostname ESMTP

WHY inet_interfaces = all: This tells Postfix to listen on every network interface on your server, which is required to accept incoming mail from external senders. The default value localhost means Postfix only accepts mail from the same machine.

WHY set mydestination carefully: This directive lists which domains Postfix delivers mail locally rather than forwarding. If you add your main domain here AND configure virtual domains for it later, Postfix will try to deliver mail twice and reject it. Keep mydestination limited to the hostname and localhost entries shown above.

Enable and Start Postfix

sudo systemctl enable --now postfix

Verify it is running:

sudo systemctl status postfix

Expected output (look for the active (running) line):

● postfix.service - Postfix Mail Transport Agent
     Loaded: loaded (/usr/lib/systemd/system/postfix.service; enabled)
     Active: active (running) since ...

Step 3: Install MariaDB and Create the PostfixAdmin Database

Install MariaDB

sudo dnf install mariadb-server -y

Before starting MariaDB, set the character encoding to utf8mb4. Create a configuration file:

sudo nano /etc/my.cnf.d/charset.cnf

Add the following:

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

[client]
default-character-set = utf8mb4

WHY utf8mb4 before first start: Standard utf8 in MySQL/MariaDB only supports 3-byte characters, which excludes emoji and certain international domain name characters. The utf8mb4 charset supports the full 4-byte Unicode range. Set this before any data is created because converting an existing database to utf8mb4 is significantly more complex.

Now enable and start MariaDB:

sudo systemctl enable --now mariadb

Secure MariaDB

Run the security script to harden your database server:

sudo mysql_secure_installation

When prompted:

  • Set a strong root password
  • Remove anonymous users: Yes
  • Disallow root login remotely: Yes
  • Remove test database: Yes
  • Reload privilege tables: Yes

WHY this matters: A fresh MariaDB install includes an anonymous user account and a test database. These exist for convenience during development, not for production. Leaving them in place means anyone who can reach your database socket can log in without credentials.

Create the PostfixAdmin Database and User

Log into MariaDB as root:

sudo mysql -u root -p

Run the following SQL commands:

CREATE DATABASE postfixadmin CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'postfixadmin'@'localhost' IDENTIFIED BY 'YourStrongPassword123!';
GRANT ALL PRIVILEGES ON postfixadmin.* TO 'postfixadmin'@'localhost';
FLUSH PRIVILEGES;
EXIT;

WHY a dedicated database user: Giving PostfixAdmin access through the MariaDB root account violates the principle of least privilege. If the PostfixAdmin config file is ever exposed, an attacker with root database access can destroy every database on your server, not just the mail data. A scoped user limits the damage to one database.

WHY FLUSH PRIVILEGES: MariaDB caches grant tables in memory. Without flushing, the new user permissions may not activate until the next service restart, causing PostfixAdmin to fail with an “access denied” error even though the SQL commands ran successfully.

Step 4: Install Apache Web Server and PHP with Required Extensions

Install Apache and PHP Modules

sudo dnf install httpd php php-mysqlnd php-mbstring php-imap php-xml php-intl php-json php-gd -y

WHY each PHP extension:

  • php-mysqlnd: The native MySQL driver for PHP. Without this, PostfixAdmin cannot open a connection to MariaDB.
  • php-mbstring: Required for multibyte string operations used when processing international email addresses.
  • php-imap: Validates IMAP mailbox connections during PostfixAdmin’s setup checks.
  • php-xml and php-intl: Required for PostfixAdmin’s internationalization layer and XML-based configuration parsing.
  • php-gd: Handles image generation for CAPTCHA functionality in PostfixAdmin’s user registration flow.

WHY Apache over Nginx here: Apache handles PostfixAdmin’s .htaccess rewrite rules natively through mod_rewrite. Nginx requires additional FastCGI pass configuration to achieve the same result. For a PostfixAdmin-only setup, Apache is the simpler and less error-prone choice.

Adjust PHP Settings

Open the PHP configuration file:

sudo nano /etc/php.ini

Find and update these values:

memory_limit = 128M
upload_max_filesize = 20M
post_max_size = 20M
max_execution_time = 300
date.timezone = Asia/Jakarta

Replace Asia/Jakarta with your server’s actual timezone.

Enable and Start Apache

sudo systemctl enable --now httpd

Step 5: Download, Deploy, and Configure PostfixAdmin

Download PostfixAdmin from GitHub

PostfixAdmin is not available in Fedora’s default package repositories. Download it directly from the official GitHub releases page:

cd /var/www/html
sudo wget https://github.com/postfixadmin/postfixadmin/archive/refs/tags/postfixadmin-3.3.15.tar.gz
sudo tar -xzf postfixadmin-3.3.15.tar.gz
sudo ln -s postfixadmin-postfixadmin-3.3.15 postfixadmin

WHY use a symlink: The symlink postfixadmin points to the versioned directory. When you upgrade to a newer PostfixAdmin release in the future, you extract the new version alongside the old one and update the symlink to point at it. Your Apache config does not need to change at all.

Create the templates_c Directory

sudo mkdir -p /var/www/html/postfixadmin/templates_c

WHY this directory is required: PostfixAdmin uses the Smarty PHP templating engine. Smarty compiles your HTML templates into PHP files the first time they are requested and stores those compiled files in templates_c for faster loading on subsequent requests. Without this directory, PostfixAdmin throws a fatal error immediately on first page load.

Set File Ownership and Permissions

sudo chown -R apache:apache /var/www/html/postfixadmin
sudo chmod -R 755 /var/www/html/postfixadmin
sudo chmod -R 775 /var/www/html/postfixadmin/templates_c

WHY apache:apache ownership: The Apache web server on Fedora runs as the apache user. If PostfixAdmin files are owned by root, Apache cannot write compiled templates to templates_c and cannot create or update configuration caches. The result is a broken interface with cryptic permission-denied errors in /var/log/httpd/error_log.

Create the Local Configuration File

Do not edit config.inc.php directly. Instead, create config.local.php, which PostfixAdmin merges on top of the defaults:

sudo nano /var/www/html/postfixadmin/config.local.php

Add the following content:

<?php
$CONF['configured'] = true;
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfixadmin';
$CONF['database_password'] = 'YourStrongPassword123!';
$CONF['database_name'] = 'postfixadmin';
$CONF['mail_server'] = 'localhost';
$CONF['encrypt'] = 'dovecot:SHA512-CRYPT';
$CONF['dovecotpw'] = '/usr/bin/doveadm pw';
$CONF['domain_path'] = 'NO';
$CONF['domain_in_mailbox'] = 'YES';
$CONF['fetchmail'] = 'NO';

WHY config.local.php instead of editing the original: PostfixAdmin’s upstream developers designed this separation intentionally. When you upgrade PostfixAdmin, the new release overwrites config.inc.php with updated defaults. Your local file remains untouched because the upgrade does not know it exists. This pattern prevents you from losing your database credentials or custom settings during every upgrade.

WHY $CONF['configured'] = true: This flag is a deliberate safety lock in PostfixAdmin’s code. The application will not process any requests or display the setup wizard until this is explicitly set. It prevents partial or accidental configurations from silently running on a server.

WHY dovecot:SHA512-CRYPT for password encryption: MD5 password hashing has been broken since 2004. SHA512-CRYPT is the current Dovecot-compatible standard. It is computationally expensive to brute-force, which matters because your mail users’ passwords will be stored in this database.

Step 6: Configure Apache VirtualHost for PostfixAdmin

Create a dedicated Apache configuration file for PostfixAdmin:

sudo nano /etc/httpd/conf.d/postfixadmin.conf

Add the following:

<VirtualHost *:80>
    ServerName mail.yourdomain.com
    DocumentRoot /var/www/html/postfixadmin/public

    <Directory /var/www/html/postfixadmin/public>
        Options FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog /var/log/httpd/postfixadmin-error.log
    CustomLog /var/log/httpd/postfixadmin-access.log combined
</VirtualHost>

WHY DocumentRoot points to /public: PostfixAdmin 3.x restructured its directory layout so that only the public/ subdirectory is meant to be web-accessible. Files above that directory, including config.local.php which contains your MariaDB password, live outside the web root. Pointing Apache at the public/ subdirectory means those sensitive files are never reachable through a browser, even if file permissions are misconfigured.

WHY AllowOverride All: PostfixAdmin ships with .htaccess files that control URL routing. With AllowOverride None (the Apache default for security), those .htaccess rules are completely ignored and every page beyond the root returns a 404 error.

Restart Apache to load the new configuration:

sudo systemctl restart httpd

Step 7: Configure Firewalld and SELinux

This step is the most frequently skipped part of any Fedora mail server tutorial, and skipping it is responsible for the majority of failed installations.

Configure Firewalld

Open the necessary ports:

sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --add-service=smtp --permanent
sudo firewall-cmd --add-service=imap --permanent
sudo firewall-cmd --add-service=pop3 --permanent
sudo firewall-cmd --reload

Confirm the active rules:

sudo firewall-cmd --list-all

WHY: Fedora 43 enables firewalld by default with a restrictive policy that blocks all inbound traffic except SSH. Without explicitly opening these ports, external mail clients cannot connect to Postfix or the PostfixAdmin web interface, even if both services are running and correctly configured.

Configure SELinux Booleans

sudo setsebool -P httpd_can_network_connect_db 1
sudo setsebool -P httpd_can_sendmail 1
sudo setsebool -P httpd_can_network_connect 1

WHY httpd_can_network_connect_db is critical: Fedora 43 ships with SELinux in Enforcing mode. Without this boolean, SELinux silently blocks Apache from making TCP connections to MariaDB. PostfixAdmin will display a database connection error that looks exactly like wrong credentials or a typo in config.local.php, when the real cause is an SELinux access vector cache denial. This is the number one reason people on StackOverflow say PostfixAdmin “doesn’t work on Fedora/CentOS/RHEL.” Ubuntu and Debian tutorials never mention this because those distros default to AppArmor, which does not enforce the same restriction.

You can confirm SELinux is making denials by checking:

sudo grep "denied" /var/log/audit/audit.log | grep httpd

The -P flag in setsebool -P makes the change persistent across reboots.

Step 8: Run the PostfixAdmin Web Setup Wizard

Open a browser and navigate to:

http://mail.yourdomain.com/setup.php

What the Setup Wizard Checks

The wizard runs a requirements checklist before doing anything else. All items must show a green checkmark before you proceed:

  • PHP version compatibility
  • All required PHP extensions loaded
  • Database connection successful
  • templates_c directory writable
  • config.local.php present with $CONF['configured'] = true

If any item is red, fix it before continuing. The most common red items are a missing PHP extension (recheck your dnf install command) or a templates_c permission problem.

Generate and Store the Setup Password Hash

Type a strong setup password into the field on the wizard page and click Generate password hash. The page will display a hash string that looks like:

$2y$10$abcdefghijklmnopqrstuvwxyz123456789...

Copy that entire string. Open config.local.php and add:

sudo nano /var/www/html/postfixadmin/config.local.php
$CONF['setup_password'] = 'paste_your_hash_here';

WHY this hash exists: The setup page can create administrator accounts with full control over your mail server. Without a password hash protecting it, any visitor to setup.php could create their own admin account. This design forces you to prove you have write access to config.local.php before you can use the setup wizard.

Create Your Superadmin Account

Return to setup.php, enter your setup password, and complete the form to create the first superadmin account. Use an email address and a strong, unique password that is different from both your database password and your setup password.

After the account is created, restrict access to setup.php:

sudo chmod 440 /var/www/html/postfixadmin/public/setup.php

WHY restrict setup.php after setup: Leaving it fully accessible after installation means a logged-in attacker or a misconfigured server could allow unauthorized users to create rogue administrator accounts. Chmod 440 prevents Apache from executing it while keeping it readable for future reference.

Step 9: Verify Your PostfixAdmin Installation

Log into the PostfixAdmin interface at:

http://mail.yourdomain.com/

Use the superadmin credentials you just created. Once inside:

  1. Navigate to Domain List and add a test domain (e.g., testdomain.com).
  2. Go to Mailbox and create a test virtual mailbox (e.g., test@testdomain.com).
  3. Confirm the mailbox appears in the list.

Test Postfix Mail Acceptance

Install swaks for CLI mail testing:

sudo dnf install swaks -y

Send a test message to your new virtual mailbox:

swaks --to test@testdomain.com --server localhost

Expected output:

-> EHLO mail.yourdomain.com
<- 250-mail.yourdomain.com
...
-> MAIL FROM:<>
<- 250 2.1.0 Ok
-> RCPT TO:<test@testdomain.com>
<- 250 2.1.5 Ok

WHY test before going live: You do not want to discover a misconfigured mydestination or a missing database grant after your MX records are already pointing real mail at this server. Test locally first with swaks, then update your DNS records.

Check Postfix logs for any errors:

sudo journalctl -u postfix -f

Troubleshooting Common Issues

Error: “Database connection failed” on setup.php

Cause: Either incorrect credentials in config.local.php or SELinux is blocking Apache from connecting to MariaDB.

Fix:

# Check SELinux boolean
sudo getsebool httpd_can_network_connect_db

# If it returns "off", enable it
sudo setsebool -P httpd_can_network_connect_db 1

# Then verify database credentials directly
mysql -u postfixadmin -p postfixadmin

Error: PostfixAdmin Pages Return 404

Cause: AllowOverride is not set to All in your Apache VirtualHost, so .htaccess routing rules are being ignored.

Fix: Confirm your VirtualHost in /etc/httpd/conf.d/postfixadmin.conf contains AllowOverride All, then restart Apache:

sudo systemctl restart httpd

Error: “templates_c is not writable”

Cause: The templates_c directory is owned by root or has permissions that block the apache user.

Fix:

sudo chown -R apache:apache /var/www/html/postfixadmin/templates_c
sudo chmod -R 775 /var/www/html/postfixadmin/templates_c

Error: Mail Rejected by External Servers (“550 Permanent Failure”)

Cause: Missing PTR (reverse DNS) record, or your IP is on a blocklist due to a missing SPF record.

Fix: Contact your VPS or hosting provider to set a PTR record matching your FQDN. Add an SPF TXT record to your domain’s DNS:

v=spf1 mx a ip4:YOUR_SERVER_IP ~all

Error: Postfix “Relay Access Denied” for Your Own Domain

Cause: The domain you created in PostfixAdmin is listed in mydestination inside /etc/postfix/main.cf. This creates a conflict between local delivery and virtual mailbox delivery.

Fix: Remove your virtual domain from mydestination. That directive should only contain your hostname and localhost entries:

sudo nano /etc/postfix/main.cf
# Set to:
# mydestination = $myhostname, localhost.$mydomain, localhost
sudo systemctl restart postfix

Congratulations! You have successfully installed PostfixAdmin. Thanks for using this tutorial for installing the latest version of PostfixAdmin on Fedora 43 Linux. For additional help or useful information, we recommend you check the official PostfixAdmin website.

VPS Manage Service Offer
If you don’t have time to do all of this stuff, or if this is not your area of expertise, we offer a service to do “VPS Manage Service Offer”, starting from $10 (Paypal payment). Please contact us to get the best deal!
r00t is a Linux Systems Administrator and open-source advocate with over ten years of hands-on experience in server infrastructure, system hardening, and performance tuning. Having worked across distributions such as Debian, Arch, RHEL, and Ubuntu, he brings real-world depth to every article published on this blog. r00t writes to bridge the gap between complex sysadmin concepts and practical, everyday application — whether you are configuring your first server or optimizing a production environment. Based in New York, US, he is a firm believer that knowledge, like open-source software, is best when shared freely. "Linux is not just an operating system. It is a philosophy — and the terminal is where that philosophy comes to life."

Related Posts