Multicraft Installation Guide for Rocky Linux 9

by Simone "Giga 123" Vedda

Hi, I'm Simone Vedda, also known as Giga 123, and in this tutorial, I will explain to you how to setup Multicraft on Rocky Linux 9 with phpMyAdmin, MariaDB, FirewallD, SELinux (it must be on in enforcing mode and targeting) and Certbot (for the TLS certificate).
Please notice that this guide has some variables (like ssh_port, mariadb_port and so on; all of them will be listed below) that you can change with anything suitable for you (in this way, you can have non-standard ports to enhance security).
You can download this guide as a TXT file and edit it as you like. Make sure to not change any commands or it might not work. If you wish, you can even set up a Cloudflared instance to have VPN-like access to the Multicraft panel (again it's entirely optional, but I suggest doing it anyway).

Complete list of variables (if you find them in the guide, make sure to substitute the variable with a valid and unused value of your system, whether it'll be a port, a name or an ID number):
SSH port variable: ssh_port
MariaDB port variable: mariadb_port
Name of the Cloudflared tunnel variable: tunnel_name
ID of the CLoudflared tunnel variable: tunnel_id
Link to your project: subdomain.domain.tdl
Name of the Cloudflared subdomain (the subdomain that you will use to connect with ssh): tunnel_subdomain
Name of the domain for your server: domain.tdl (useful for copying the ssh key if generated on the server and for the Apache webserver)
FTP minimum passive port: ftp_min_passive_port
FTP maximum passive port: ftp_max_passive_port
Name for the SFTP user: sftupser (change it as you like)

OPTIONAL: Install Cloudflared plus a private SSH Key (2FA with a VPN-like connection)

* Update the system and remove the unnecessary services *
dnf -y erase cockpit*
dnf -y update
dnf -y install nano wget
dnf -y install firewalld policycoreutils-devel setroubleshoot-server
systemctl enable --now firewalld
firewall-cmd --remove-service=cockpit --permanent
firewall-cmd --remove-service=dhcpv6-client --permanent
firewall-cmd --reload
* Install Cloudflared *
sudo dnf config-manager --add-repo
sudo dnf -y install cloudflared
* Configure Cloudflared *
cloudflared tunnel login

cloudflared tunnel create tunnel_name
(Be sure to copy your tunnel ID)

* Now edit the file as follow *
nano /root/.cloudflared/config.yml

tunnel: tunnel_id
credentials-file: /root/.cloudflared/tunnel_id.json
  enabled: true


  - hostname: subdomain.domain.tdl
    service: ssh://localhost:ssh_port

  - service: http_status:404
* Define a subdomain to connect through ssh *
cloudflared tunnel route dns tunnel_id tunnel_subdomain
* Consifure the SSH server to access through Cloudflared *
nano /etc/ssh/sshd_config

--> ListenAddress

semanage port -a -t ssh_port_t -p tcp ssh_port
systemctl restart sshd
* Configure Cloudflared service *
cloudflared service install
systemctl start cloudflared
firewall-cmd --remove-service=ssh --permanent
firewall-cmd --reload
* Configure the 2FA *

* Use software like PuTTY to generate the key *

! At this moment the best cypher for a usable key is Ed25519 at 255 bits!

* Install the public key on the server *

-- If generated on the server --
ssh-copy-id root@domain.tld

nano /root/.ssh/authorized_keys
Change the host at the end of the line or remove it

-- If generated locally (suggested) --

Copy the content of the key on the authorized_keys file (it must be on one line straight)
mkdir -p /root/.ssh/
nano /root/.ssh/authorized_keys
Now paste the content of the key in this file and save it (remember, it must be on one line)

* Enable the SSH Key *
nano /etc/ssh/sshd_config

#PubkeyAuthentication yes --> PubkeyAuthentication yes
#PasswordAuthentication yes --> PasswordAuthentication yes

Add to the end of the file

Match User root
  AuthenticationMethods publickey,password

systemctl restart sshd
Please note that you can use the same layout to enable how many users you want (also because even with cloudflared and the ssh key it's still not safe to let the root login via SSH)

Now you can Install Multicraft:

* Update the system and erase cockpit *
dnf -y erase cockpit*
dnf -y update
* Install the main functions and FirewallD (the export command is optional, it will set as default editor Nano instead of Vim) *
dnf -y install wget zip unzip git nano firewalld policycoreutils-python-utils policycoreutils-devel setroubleshoot-server rpmdevtools rpm-build tree docker rsync
export VISUAL=nano export EDITOR="$VISUAL"
nano /usr/lib/systemd/system/firewalld.timer

(Copy the content inside the file)

Description=firewalld - dynamic firewall daemon
Conflicts=iptables.service ip6tables.service ebtables.service ipset.service nftables.service

ExecStart=/usr/sbin/firewalld --nofork --nopid $FIREWALLD_ARGS
ExecReload=/bin/kill -HUP $MAINPID
# supress to log debug and error output also to /var/log/messages


* Add the firewall rules (choose a random number to assign to each service (like ssh, mariadb...) *
chmod 644 /usr/lib/systemd/system/firewalld.timer
sudo systemctl start firewalld
sudo systemctl disable firewalld
sudo systemctl enable firewalld.timer
sudo firewall-cmd --set-default-zone=public
sudo firewall-cmd --zone=public --set-target=DROP --permanent
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --zone=public --add-service=ftp --permanent
sudo firewall-cmd --zone=public --add-service=rsyncd --permanent
sudo firewall-cmd --zone=public --remove-service=cockpit --permanent
sudo firewall-cmd --zone=public --add-port=25465/tcp --permanent
sudo firewall-cmd --zone=public --add-port=25465/udp --permanent
sudo firewall-cmd --zone=public --add-port=25565-25575/tcp --permanent
sudo firewall-cmd --zone=public --add-port=25565-25575/udp --permanent
sudo firewall-cmd --zone=public --add-port=19132-19142/tcp --permanent
sudo firewall-cmd --zone=public --add-port=19132-19142/udp --permanent
sudo firewall-cmd --zone=public --add-port=ftp_min_passive_port-ftp_max_passive_port/tcp --permanent
sudo firewall-cmd --zone=public --add-port=ssh_port/tcp --permanent
sudo firewall-cmd --zone=public --add-port=mariadb_port/tcp --permanent
firewall-cmd --reload
* Install PHP *
dnf config-manager --set-enabled crb
dnf install -y
dnf install -y
dnf module reset php -y
dnf -y module install php:remi-8.2
dnf -y install httpd php-common php-fpm php-gd php-mbstring php-ldap php-odbc php-pear php-xml php-xmlrpc php-bcmath php-mysql php-pdo php-mysqlnd tar curl java-1.8.0-openjdk-devel java-11-openjdk-devel java-17-openjdk-devel rsync rsync-daemon libnsl
* Install MariaDB *
chmod +x mariadb_repo_setup
sudo ./mariadb_repo_setup
sudo dnf install perl-DBI libaio libsepol lsof boost-program-options -y
sudo dnf install mariadb-server -y
sudo mysql_install_db
sudo systemctl enable --now mariadb.service
sudo mariadb-secure-installation

(When it asks for the unix_socket authentication [Y/n] just say "n")

nano /etc/my.cnf.d/server.cnf

port = mariadb_port
* Configure the Java default version *
sudo alternatives --config java
* Clean Mariadb and Apache scripts and enable Apache *
rm -rf mariadb_repo_setup
systemctl enable --now httpd
* Edit the PHP settings (make sure to uncomment (toggle the comma ";") *
nano /etc/php.ini

--> upload_max_filesize = maximum_file_size (here you can choose either from M for megabytes or G for gigabytes)
--> max_execution_time = 0 (edit as you like, but I suggest to use a value between 60 and 300 seconds)
--> cgi.fix_pathinfo=0 (always set it to 0 for better security)
--> date.timezone= Time/Zone (edit as you like, I suggest to use your time zone). (example: Europe/Rome)
* Set the time zone *
timedatectl set-timezone Time/Zone (example: Europe/Rome)
* Install phpMyAdmin *
wget -c -O phpMyAdmin-latest-all-languages.tar.gz
tar -zxvf phpMyAdmin-latest-all-languages.tar.gz
rm -rf phpMyAdmin-latest-all-languages.tar.gz
mkdir -p /usr/share/phpMyAdmin
mv phpMyAdmin-*/* /usr/share/phpMyAdmin
cp -pr /usr/share/phpMyAdmin/ /usr/share/phpMyAdmin/
setsebool -P httpd_can_network_connect 1
setsebool -P httpd_can_network_connect_db 1
nano /usr/share/phpMyAdmin/
Make sure to add the blowfish key from here:[insert_php]echo%20$code;[/insert_php]
* Change the localhost setting to (otherwise it won't connect correctly) *
$cfg['Servers'][$i]['host'] = 'localhost'; --> $cfg['Servers'][$i]['host'] = '';
Otherwise, phpMyAdmin will return a user permission error * Add to the bottom of the file the following line *
#$cfg['Servers'][$i]['AllowRoot'] = FALSE;
(This line will tell phpMyAdmin to deny to the root user any login attempt when it's commented out, so without the "#" at the beginning)
mariadb < /usr/share/phpMyAdmin/sql/create_tables.sql -u root -p

mkdir /usr/share/phpMyAdmin/tmp
chmod 777 /usr/share/phpMyAdmin/tmp
chown -R apache:apache /usr/share/phpMyAdmin
chmod 755 /usr/share/phpMyAdmin
sudo nano /etc/php-fpm.d/www.conf

* Edit the file as suggested below *

--> listen = /var/run/php-fpm/www.sock
--> listen.owner = apache
--> = apache
--> user = apache
--> group = apache
--> ;listen.acl_users = apache,nginx (make sure to comment this line with the ";"!)

semanage fcontext -a -t httpd_sys_rw_content_t "/usr/share/phpMyAdmin/"
semanage fcontext -a -t httpd_sys_rw_content_t "/usr/share/phpMyAdmin/tmp(/.*)?"
restorecon -Rv "/usr/share/phpMyAdmin/"
systemctl enable --now php-fpm
chown -R apache:apache /usr/share/phpMyAdmin/
chmod 755 /var/lib/php/session/
nano /etc/httpd/conf.d/phpMyAdmin.conf

(Copy this configuration to the file)

Alias /phpMyAdmin /usr/share/phpMyAdmin
Alias /phpmyadmin /usr/share/phpMyAdmin

<Directory /usr/share/phpMyAdmin/>
   AddDefaultCharset UTF-8

   <IfModule mod_authz_core.c>
     # Apache 2.4
      Require all granted
   <IfModule !mod_authz_core.c>
     # Apache 2.2
     Order Deny,Allow
     Deny from All
     Allow from
     Allow from ::1

<Directory /usr/share/phpMyAdmin/setup/>
   <IfModule mod_authz_core.c>
     # Apache 2.4
       Require all granted
   <IfModule !mod_authz_core.c>
     # Apache 2.2
     Order Deny,Allow
     Deny from All
     Allow from
     Allow from ::1

nano /etc/httpd/conf/httpd.conf

(Now replace all the values with AllowOverride none to AllowOverride all, there should be four lines)

AllowOverride none --> AllowOverride all

chown -R apache:apache /var/lib/php/session/
systemctl restart httpd php-* mariadb
* Now create the multicraft_daemon and multicraft_panel databases and the multicraft user on phpMyAdmin (make sure to grant all permissions to the multicraft user on these two databases) *

* Install Multicraft *
wget -O multicraft.tar.gz
tar xvzf multicraft.tar.gz
cd multicraft
Attention: Make sure to specify that the database is mysql!

* Now clean the downloaded files and edit the multicraft.conf and pid as suggested *
rm -rf /root/multicraft.tar.gz phpMyAdmin-*
wget -O /etc/systemd/system/multicraft.service
chmod 644 /etc/systemd/system/multicraft.service
systemctl daemon-reload
nano /home/minecraft/multicraft/multicraft.conf

--> pidFile = /var/run/multicraft/

nano /etc/systemd/system/multicraft.service

--> PIDFile=/var/run/multicraft/
--> ExecStartPre=/bin/bash -c 'mkdir -p -m 0755 --context=system_u:object_r:var_run_t:s0 /var/run/multicraft && chown -R minecraft: /var/run/multicraft'

semanage fcontext -a -t bin_t /home/minecraft/multicraft/bin/multicraft
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/html/multicraft/protected/config'
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/html/multicraft/protected/config/config.php'
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/html/multicraft/protected/runtime(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/html/multicraft/assets(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t /var/www/html/multicraft/protected/config/server_defaults.php
restorecon -v /var/www/html/multicraft/protected/config/server_defaults.php
restorecon -Rv /home/minecraft/multicraft/
restorecon -Rv /var/www/html/multicraft
systemctl enable --now multicraft
touch /var/log/httpd/multicraft-error.log
touch /var/log/httpd/multicraft-access.log
sudo dnf install certbot python3-certbot-apache -y
nano /home/minecraft/multicraft/multicraft.conf
Now you have to modify the multicraft.conf to allow the connection to the database. The correct syntax is:
database = mysql:host=;port=mariadb_port;dbname=multicraft_daemon
* Create the webserver *
nano /etc/httpd/conf.d/multicraft.conf

<VirtualHost *:80>
    ServerName domain.tld
    ServerAlias domain.tdl
    ServerAdmin example@domain.tld
    DocumentRoot /var/www/html/multicraft

    <Directory /var/www/html/multicraft>
        Options -Indexes +FollowSymLinks
        AllowOverride All

    ErrorLog /var/log/httpd/multicraft-error.log
    CustomLog /var/log/httpd/multicraft-access.log combined

systemctl restart httpd multicraft
* Configure Multicraft *

Access via your domain to the Multicraft panel and proceed to the setup. If you have any doubts, refer to the official setup docs.

After the configuration, make sure you delete the install.php file:
rm -rf /var/www/html/multicraft/install.php

* Install the TLS certificate and schedule a routine as shown *
sudo certbot --apache

systemctl restart httpd
crontab -e

0 0 * * * dnf -y update >/dev/null 2>&1
30 0 * * * /usr/bin/certbot renew > /var/log/letsencrypt/letsencrypt.log
*/5 * * * * chown -R minecraft:minecraft /home/minecraft/multicraft/jar/ /home/minecraft/multicraft/templates/ >/dev/null 2>&1
*/5 * * * * chown -R sftpuser:sftpuser /home/sftpuser/uploads >/dev/null 2>&1
*/5 * * * * chmod 755 /var/lib/php/session >/dev/null 2>&1
*/5 * * * * chmod 664 /home/minecraft/multicraft/jar/ /home/minecraft/multicraft/templates/ >/dev/null 2>&1
0 */3 * * * rm -rf /var/lib/php/session/* >/dev/null 2>&1
* Clean the installation file and edit the timeout to make sure the daemon will run properly within FirewallD *
rm -rf /var/www/html/multicraft/install.php
nano /var/www/html/multicraft/protected/components/Controller.php

Change the timeout to 60 seconds (line 96) --> 'timeout' => 60,
* Configure the TLS encryption with the Multicraft FTP *
nano /home/minecraft/multicraft/multicraft.conf

ftpPasvPorts = ftp_min_passive_port-ftp_max_passive_port
ftps = true
ftpsCertfile =  /etc/letsencrypt/live/domain.tld/fullchain.pem
ftpsKeyfile = /etc/letsencrypt/live/domain.tld/privkey.pem
ftpsForce = true
ftpsCompatMode = false
* Configure the SFTP access *
nano /etc/ssh/sshd_config

Modify the line 123 as follow:

#Subsystem      sftp    /usr/libexec/openssh/sftp-server (comment this line)
Subsystem       sftp    internal-sftp (add this line)

(Add the template at the bottom of the file)

Match User sftpuser
  PasswordAuthentication yes
  ChrootDirectory %h
  ForceCommand internal-sftp
  AllowTcpForwarding no
  X11Forwarding no
Now let's create the user and its home:

First, make sure that the sbin/nologin shell is enabled in the file /etc/shells:
nano /etc/shells
If it's not present, add the line at the bottom: /sbin/nologin

Then save and exit. Now let's create the sftp user:
useradd -s /usr/sbin/nologin sftpuser
chown -R root:sftpuser /home/sftpuser
chmod 755 -R /home/sftpuser
mkdir /home/sftpuser/uploads
chown sftpuser:sftpuser /home/sftpuser/uploads
passwd sftpuser
nano /etc/ssh/sshd_config

Port ssh_port
systemctl restart sshd
* Disable the root access through phpMyAdmin *
nano /usr/share/phpMyAdmin/

--> #$cfg['Servers'][$i]['AllowRoot'] = FALSE; --> $cfg['Servers'][$i]['AllowRoot'] = FALSE;

** FAQ **

- The Multicraft page redirects me to the error ERR_TOO_MANY_REDIRECT

Probably in the folder /var/www/html/multicraft/ there's no install.php or it has not had the correct authorizations, if so you can copy the original downloaded file like this:
cp -p /root/multicraft/panel/install.php /var/www/html/multicraft/install.php

- Is there a way to simplify the link visualization?

Yes just go to /var/www/html/multicraft/protected/config/internal/application.php and edit as shown:

(Remove all the /* and */)
// uncomment the following to enable URLs in the format index.php/server/1
// uncomment the following to hide the index.php part of the URL
And then execute:
systemctl restart multicraft httpd