Introduction
A FEMP Stack (FreeBSD, Nginx, MySQL, PHP) is a combination of FOSS software that can be used together in order to host dynamic websites and Content Management Systems such as Wordpress or Joomla.
This guide will help with the installation and configuration of a FEMP stack on FreeBSD 14.
Prerequisites
- A server with FreeBSD
- Access to the root user or a user with sudo permissions
Step 1 - Updating FreeBSD
By default, FreeBSD does not come with the pkg package manager, but comes with a tool to bootstrap it. If FreeBSD asks to install it, answer 'Yes'.
It is best to update the system beforehand to ensure you are getting the latest packages when installing the FEMP stack. You can do this by running the following command:
sudo pkg update ; sudo pkg upgradeThis will update the repositories of pkg, and then upgrade any installed packages that you may have.
Step 2 - Installing Nginx
To install Nginx, the web server we are using for this tutorial, use the following command:
sudo pkg install nginx
nginx -vBefore we can start nginx to test that it is working, we need to enable it to start on boot.
You can do this by appending nginx_enable="YES" to the end of /etc/rc.conf.
echo 'nginx_enable="YES"' | sudo tee -a /etc/rc.conf
sudo service nginx start
sudo service nginx statusTest that it is working by going to your IP address in a web browser. You can check your server's IP address by running curl -4 https://ip.hetzner.com, or by checking your control panel.
http://203.0.113.1/You should see something like this:
Step 3 - Installing PHP
Next, we need to install and configure PHP, which we'll be using to process PHP requests from nginx.
-
Check which versions are available:
You can use either
awkorgrep.sudo pkg search ^php[0-9] | awk -F'-' 'NF==2 {print $0}' sudo pkg search ^php[0-9] | grep -E '^php[0-9]+-[0-9]+\.[0-9]+\.[0-9]+' -
Install the latest version and some modules:
sudo pkg install php83 php83-mysqli php83-curl php83-gd php83-intl php83-mbstring php83-xml php83-zip php -v -
Like before, we need to enable it to start on boot before we can start the service.
echo 'php_fpm_enable="YES"' | sudo tee -a /etc/rc.conf
Before we can start it, we need to make a few changes to the configuration file /usr/local/etc/php-fpm.d/www.conf
cd /usr/local/etc/
sudo vi php-fpm.d/www.confLook for the line:
listen = 127.0.0.1:9000Replace it with the following, so that PHP listens under an unix socket:
listen = /var/run/php-fpm.sockFurther down in the file, look for these lines:
;listen.owner = www
;listen.group = www
;listen.mode = 0660Uncomment them to change the unix socket owner to be the same as the nginx user:
listen.owner = www
listen.group = www
listen.mode = 0660After you have completed that, save and close the file.
You need to create a php.ini file. You can use the example file php.ini-production with a slight modification for security:
Assuming you are still in /usr/local/etc/:
sudo cp php.ini-production php.ini
sudo sed -i -E 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' php.iniThen finally, start the PHP service.
sudo service php-fpm start
sudo service php-fpm statusStep 3.1 - Configuring Nginx to use PHP
Nginx and PHP are both enabled now, however we need to configure Nginx to be aware of PHP, and to use it to process .php pages.
Open the file /usr/local/etc/nginx/nginx.conf in a text editor:
sudo vi /usr/local/etc/nginx/nginx.confFind the following in the file (commented out parts are removed):
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /usr/local/www/nginx;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/www/nginx-dist;
}
}
}The following changes need to be made to the nginx.conf file:
- Replace
localhostunderserver_namewith your server's domain or IP address. - Remove the
location /block. - Add
index.phpunderindex. - Edit nginx root directory to
/var/www/html/. - Configure nginx for PHP processing.
Your nginx.conf file should look something like this:
server {
listen 80;
server_name example.com;
root /var/www/html;
index index.php index.html index.htm;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/www/nginx-dist;
}
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
try_files $uri $document_root$fastcgi_script_name =404;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}If your server uses IPv6, add the following line under
listen 80;listen [::]:80;
Then finally, create the nginx root directory, symlink the default nginx index.html page, and restart nginx.
sudo mkdir -p /var/www/html/
sudo ln -s /usr/local/www/nginx-dist/index.html /var/www/html/
sudo nginx -t
sudo service nginx restart
sudo service nginx statusGoing to your server's domain or IP address, should still return the Welcome to nginx! page from before.
To test if PHP is working, create a file under /var/www/html/phpinfo.php with the following content:
<?php phpinfo(); ?>Then, visit the test page you created at your server's IP address/domain.
http://example.com/phpinfo.phpIt should return a page like this:
It is best to delete the file afterwards for security, as it can expose information about your PHP install to anyone.
sudo rm /var/www/html/phpinfo.phpStep 4 - Installing MySQL (MariaDB)
Now that we have Nginx and PHP setup and working together, the only thing left that we need to install and configure is MySQL.
-
Check which versions are available:
We'll be using a community maintained drop-in replacement to MySQL, MariaDB; which is fully compatible with applications targeting MySQL.
sudo pkg search '^mariadb[0-9]+-server' | grep -E '^mariadb[0-9]+-server-[0-9]+\.[0-9]+\.[0-9]+' sudo pkg search '^mariadb[0-9]+-client' | grep -E '^mariadb[0-9]+-client-[0-9]+\.[0-9]+\.[0-9]+' -
Install the latest version:
sudo pkg install mariadb114-server mariadb114-client sudo pkg info -x mariadb114-server sudo pkg info -x mariadb114-client -
Like before, we need to enable the service to start on boot before we can start the service.
echo 'mysql_enable="YES"' | sudo tee -a /etc/rc.conf -
Add a configuration file
sudo cp /usr/local/etc/mysql/my.cnf.sample /usr/local/etc/mysql/my.cnf -
Start the service
sudo service mysql-server start sudo service mysql-server status
Next, we need to secure the MariaDB installation.
sudo mysql_secure_installationEnter current password for root (enter for none):Since we are setting up MariaDB for the first time, the root account does not have a password, so just press the "ENTER" key here.
Enable unix_socket authentication? [Y/n]Like before, press the "ENTER" key to answer yes to use unix_socket authentication.
Set root password? [Y/n]Press the "ENTER" key here to answer yes, and then enter a secure password for your MariaDB root user.
Remove anonymous users? [Y/n]
Disallow root login remotely? [Y/n]
Remove test database and access to it? [Y/n]
Reload privilege tables now? [Y/n]The last few questions you can just use the defaults by pressing the "ENTER" key, as they are sane defaults that the installer uses.
MariaDB already uses the changes we made, so there is no need to restart it.
Conclusion
Congrats! You should now have a fully working FEMP stack on your FreeBSD server, using Nginx to host webpages, PHP to process dynamic web pages, and using MySQL (MariaDB) to store data. These together are the basis for many different web apps, some examples include: Wordpress, Gitea, Joomla, and many more.