Operations 19 min read

How to Build a High‑Availability Discuz Forum with NFS, PHP‑FPM, and Dual Web Servers

This guide walks through the complete setup of a load‑balanced Discuz forum using NFS for shared storage, MySQL, PHP‑FPM, and Apache across two front‑end web servers, covering NFS fundamentals, security, configuration files, and step‑by‑step commands for each component.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
How to Build a High‑Availability Discuz Forum with NFS, PHP‑FPM, and Dual Web Servers

NFS Overview

1. NFS (Network File System) is a file‑sharing protocol implemented in the Unix kernel.

2. Origin The protocol was originally developed by Sun Microsystems; versions include NFSv1, v2, v3, and v4, with v4 adding Kerberos authentication.

3. RPC NFS operates over Remote Procedure Call (RPC). The client sends a request to the rpcbind daemon (listening on 111/tcp and 111/udp), which forwards it via socket communication to the server’s rpc.mountd (listening on 2049/tcp and 2049/udp). The server processes the request and returns the result.

NFS RPC diagram
NFS RPC diagram

4. Security Settings Native NFS only supports IP‑based authentication. NFSv4 can use NIS or Kerberos for stronger authentication.

5. Installation Install the nfs-utils package; NFS functionality is provided by the kernel, so only the utilities are needed.

6. Key Daemons

mountd – handles mount requests and client authentication.

nfsd – performs file read/write operations.

idmapd – maps user IDs between client and server.

7. /etc/exports Configuration

Export format:

/var/www/htdocs/Discuz/upload 192.168.98.128/24(rw,async,no_root_squash) 192.168.98.129/24(rw,async,no_root_squash)

Export options include: rw – read/write. async – asynchronous writes. sync – synchronous writes. root_squash – maps remote root to nfsnobody. no_root_squash – disables root squashing. all_squash – maps all users to anonymous UID/GID. anonuid, anongid – set anonymous UID/GID.

8. Useful Commands showmount -e SERVER_IP – list exported file systems from a client. showmount -d – show which exports are currently mounted on the server. showmount -a – display all active mount sessions. exportfs -a – re‑export all directories without restarting the service. exportfs -ra – re‑export after changes. exportfs -ua – unexport all directories. exportfs -v – verbose output.

9. Fixing Random Port Issues The mountd daemon may listen on a random port, potentially conflicting with other services (e.g., port 80). To lock the port, add the following line to /etc/sysconfig/nfs:

MOUNTD_PORT=892

Practical Deployment: Dual Web Servers + PHP‑FPM + NFS + MySQL for Discuz

The architecture consists of five services across four hosts:

Two front‑end Apache servers (httpd1 and httpd2) with the same domain name but different IPs for simple load balancing.

A PHP‑FPM server that receives reverse‑proxy requests from the front‑ends; the NFS server exports the Discuz installation directory to the front‑ends.

A MySQL server providing the database backend for Discuz.

Step 1 – MySQL Server (192.168.98.131)

Install MySQL from binary, create a dedicated user/group, set up LVM, format and mount the logical volume, and initialize the data directory:

# tar -xf mysql-5.6.25-linux-glibc2.5-x86_64.tar.gz -C /usr/local
# ln -s /usr/local/mysql-5.6.25-linux-glibc2.5-x86_64 /usr/local/mysql
# groupadd -r mysql
# useradd -g mysql -r -s /sbin/nologin mysql
# fdisk /dev/sdb
# pvcreate /dev/sdb1
# vgcreate database /dev/sdb1
# lvcreate -L 6G -n mysqlData database
# mkfs.ext4 /dev/database/mysqlData
# mkdir -p /data/mysqlData
# echo "/dev/database/mysqlData /data/mysqlData ext4 defaults,acl 0 0" >> /etc/fstab
# mount -a

Initialize the database and configure my.cnf:

# /usr/local/mysql/mysql_install_db --basedir=/usr/local/mysql --datadir=/data/mysqlData --user=mysql
# cp /usr/local/mysql/my.cnf /etc/
[mysqld]
   datadir=/data/mysqlData
   basedir=/usr/local/mysql
   user=mysql
# cp /usr/local/mysql/mysql.server /etc/rc.d/init.d/mysqld
# service mysql start

Create the Discuz database and user, then grant privileges:

DROP USER 'root'@'playground3';
DROP USER 'root'@'::1';
DROP USER ''@'localhost';
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('root');
CREATE USER 'discuz'@'192.168.98.130' IDENTIFIED BY 'discuz';
CREATE DATABASE discuzData;
GRANT ALL ON discuzData.* TO 'discuz'@'192.168.98.130';
FLUSH PRIVILEGES;

Test the connection from the PHP‑FPM host:

# mysql -u'discuz' -h'192.168.98.131' -pdiscuz

Step 2 – PHP‑FPM Server (192.168.98.130)

Compile and install PHP with required extensions, then install XCache:

# tar -xf php.tar.gz
# cd php-5.3.27
# ./configure --prefix=/usr/local/php --with-mysql=mysqlnd --with-openssl --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --enable-mbstring --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml --enable-sockets --enable-fpm --with-mcrypt --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --with-bz2
# make && make install
# cp php.ini-production /etc/php.ini

Install XCache:

# tar -xf xcache-3.2.0.tar.gz
# cd xcache-3.2.0
# /usr/local/php/bin/phpize
# ./configure --enable-xcache --with-php-config=/usr/local/php/bin/php-config
# make && make install

Configure PHP‑FPM init script and service:

# cp sapi/fpm/init.d.php-fpm /etc/rc.d/init.d/php-fpm
# chmod +x /etc/rc.d/init.d/php-fpm
# chkconfig --add php-fpm
# chkconfig php-fpm on

Adjust /usr/local/php/etc/php-fpm.conf (example values):

pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 8
pid = /usr/local/php/var/run/php-fpm.pid
# service php-fpm start

Step 3 – NFS Server (192.168.98.130)

Install NFS utilities and RPC bind:

# yum -y install nfs-utils
# yum -y install rpcbind

Create the export directory and add it to /etc/fstab:

# mkdir -p /var/www/htdocs/Discuz/upload
# echo "/dev/sdb1 /var/www/htdocs/Discuz/upload ext4 defaults,acl 0 0" >> /etc/fstab
# mount -a

Configure /etc/exports to share the directory with the two web servers:

/var/www/htdocs/Discuz/upload 192.168.98.128/24(rw,async,no_root_squash,no_subtree_check) 192.168.98.129/24(rw,async,no_root_squash,no_subtree_check)

Lock the mountd port: # echo "MOUNTD_PORT=892" >> /etc/sysconfig/nfs Start NFS services: # service nfs start Expected output shows all daemons started successfully.

Step 4 – Front‑End Apache Servers (192.168.98.128 & 192.168.98.129)

Install APR, APR‑util, and compile Apache 2.4.16:

# tar xf apr-1.5.2.tar.gz && cd apr-1.5.2 && ./configure --prefix=/usr/local/apr && make && make install
# tar xf apr-util-1.5.4.tar.gz && cd apr-util-1.5.4 && ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr && make && make install
# tar -xf httpd-2.4.16.tar.gz && cd httpd-2.4.16 && ./configure --prefix=/usr/local/httpd24 --sysconfdir=/etc/httpd24 --enable-so --enable-ssl --enable-cgi --enable-rewrite --with-zlib --with-pcre --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util --enable-modules=most --enable-mpms-shared=all --with-mpm=event && make && make install

Create an init script (copy from the distribution, make executable, and add to chkconfig).

Configure the virtual host to serve the shared Discuz directory and proxy PHP requests to the PHP‑FPM server:

<VirtualHost *:80>
    DocumentRoot "/var/www/htdocs/Discuz/upload"
    ServerName www.discuz.com
    ProxyRequests Off
    ProxyPassMatch ^/(.*\.php)$ fcgi://192.168.98.130:9000/var/www/htdocs/Discuz/upload/$1
    <Directory "/var/www/htdocs/Discuz/upload">
        Options None
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>
# service httpd24 start

Step 5 – Install Discuz Forum and Test

On a Windows client, edit C:\Windows\System32\drivers\etc\hosts to map both web‑server IPs to the domain:

192.168.98.128   www.discuz.com
192.168.98.129   www.discuz.com

Open a browser, navigate to http://www.discuz.com, and follow the installation wizard, using the MySQL credentials created earlier.

After installation, upload an image while one web server is down; then bring the other server back online. The image remains accessible, confirming that NFS‑based load balancing works correctly.

Discuz installation page
Discuz installation page
Load‑balanced image access
Load‑balanced image access
Final verification
Final verification
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

load balancingmysqlNFSphp-fpmDiscuz
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.