# How to Install Apache, MySQL, PHP (FAMP Stack) on FreeBSD 14.0

## Introduction

FreeBSD, Apache, MySQL, and PHP (FAMP stack) is a collection of open-source software applications that manage the runtime and development of dynamic web applications on a server. Apache works as a web server to delivers web application files while MySQL functions as the database backend, and PHP processes dynamic web application contents.

This article explains how to install the Apache, MySQL, and PHP (FAMP) stack on FreeBSD 14.0 and deliver dynamic web applications on your server.

## Prerequisites

Before you begin:

- Deploy a [FreeBSD 14.0](https://www.vultr.com/servers/freebsd) instance on Vultr.
- Create a new [domain **A** record pointing to the instance IP address](https://docs.vultr.com/introduction-to-vultr-dns). For example, `app.example.com`.
- Access the server [using SSH](https://docs.vultr.com/how-to-use-ssh-with-vultr-servers).
- Create a non-root user with sudo privileges and switch to the user.
- [Update the server](https://docs.vultr.com/how-to-update-a-vultr-cloud-server).

## Install Apache

Apache is available in the default repositories on FreeBSD 14.0 with the latest package information. Follow the steps below to install the latest Apache web server package and enable the application to run on your server.

1. Update the server packages catalog.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-1">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo pkg update
    ```
    
    <div class="code-block"><div id="bkmrk-"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-1">Explain Code</button></div>
2. Install Apache on your server.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-2">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo pkg install -y apache24
    ```
    
    <div class="code-block"><div id="bkmrk--1"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-2">Explain Code</button></div>
3. Verify that Apache is installed on your server.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-3">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ apachectl -v
    ```
    
    <div class="code-block"><div id="bkmrk--2"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-3">Explain Code</button></div>Output:
    
    ```
    Server version: Apache/2.4.59 (FreeBSD)
    Server built:   unknown
    ```
4. Enable Apache to automatically start at boot.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-4">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service apache24 enable
    ```
    
    <div class="code-block"><div id="bkmrk--3"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-4">Explain Code</button></div>
5. Start the Apache web server.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-5">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service apache24 start
    ```
    
    <div class="code-block"><div id="bkmrk--4"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-5">Explain Code</button></div>
6. View the Apache service status and verify that the web server is running.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-6">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service apache24 status
    ```
    
    <div class="code-block"><div id="bkmrk--5"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-6">Explain Code</button></div>Output:
    
    ```
    apache24 is running as pid 2536.
    ```
7. Access your server IP address using a web browser such as Chrome and verify that the default Apache virtual host web page displays.
    
    ```
    http://SERVER-IP
    ```
    
    ![Default Apache webpage](https://docs.vultr.com/public/doc-assets/1873/417147e3ea214c4e.png)

## Install MySQL

MySQL is available in the default FreeBSD 14.0 repositories with multiple versions. Follow the steps below to install the latest MySQL database server version and enable it to run on your server.

1. Search all MySQL versions available in the default FreeBSD repositories.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-7">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo pkg search mysql
    ```
    
    <div class="code-block"><div id="bkmrk--6"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-7">Explain Code</button></div>Output:
    
    ```
    ...
    mysql80-client-8.0.35          Multithreaded SQL database (client)
    mysql80-server-8.0.35_1        Multithreaded SQL database (server)
    mysql81-client-8.1.0           Multithreaded SQL database (client)
    mysql81-server-8.1.0           Multithreaded SQL database (server)
    ...
    ```
2. Install the latest MySQL server and client packages.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-8">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo pkg install mysql81-server mysql81-client
    ```
    
    <div class="code-block"><div id="bkmrk--7"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-8">Explain Code</button></div>
3. View the installed MySQL version on your server.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-9">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ mysql --version
    ```
    
    <div class="code-block"><div id="bkmrk--8"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-9">Explain Code</button></div>Output:
    
    ```
    mysql  Ver 8.1.0 for FreeBSD14.0 on amd64 (Source distribution)
    ```
4. Enable the MySQL server to automatically start at boot.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-10">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service mysql enable
    ```
    
    <div class="code-block"><div id="bkmrk--9"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-10">Explain Code</button></div>Output:
    
    ```
    mysql enabled in /etc/rc.conf
    ```
5. Start the MySQL database server.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-11">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service mysql-server start
    ```
    
    <div class="code-block"><div id="bkmrk--10"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-11">Explain Code</button></div>
6. View the MySQL server status and verify that it's running.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-12">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service mysql-server status
    ```
    
    <div class="code-block"><div id="bkmrk--11"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-12">Explain Code</button></div>Output:
    
    ```
    mysql is running as pid 3266.
    ```
7. Start the MySQL secure installation script.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-13">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo mysql_secure_installation
    ```
    
    <div class="code-block"><div id="bkmrk--12"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-13">Explain Code</button></div>
    - Enter <kbd class="key">Y</kbd> when prompted to enable the **VALIDATE PASSWORD** component and set strict password policies on the database server.
    
    ```
    VALIDATE PASSWORD COMPONENT can be used to test passwords
    and improve security. It checks the strength of password
    and allows the users to set only those passwords which are
    secure enough. Would you like to setup VALIDATE PASSWORD component?
    
    Press y|Y for Yes, any other key for No: Y
    ```
    
    
    - Enter your desired password strength level to enable on your server. For example, enter <kbd class="key">2</kbd> to require strong passwords with mixed characters.
    
    ```
    There are three levels of password validation policy:
    
    LOW    Length >= 8
    MEDIUM Length >= 8, numeric, mixed case, and special characters
    STRONG Length >= 8, numeric, mixed case, special characters and dictionary        file
    
    Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG:
    ```
    
    
    - Enter a new strong password to assign the `root` database user.
    
    ```
    Please set the password for root here.
    
    New password: 
    ```
    
    
    - Repeat the password and verify the estimated password strength.
    
    ```
    Re-enter new password: 
    
    Estimated strength of the password: 8
    ```
    
    
    - Enter <kbd class="key">Y</kbd> when prompted to validate and continue with the new user password.
    
    ```
    Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : 
    ```
    
    
    - Enter <kbd class="key">Y</kbd> and press <kbd class="key">Enter</kbd> to remove anonymous database users on your server.
    
    ```
    Remove anonymous users? (Press y|Y for Yes, any other key for No) : 
    ```
    
    
    - Enter <kbd class="key">Y</kbd> when prompted to disable remote access to your database server using the root user account.
    
    ```
    Disallow root login remotely? (Press y|Y for Yes, any other key for No) : 
    ```
    
    
    - Enter <kbd class="key">Y</kbd> when prompted to remove the test databases on your server.
    
    ```
    `Remove test database and access to it? (Press y|Y for Yes, any other key for No) : 
    ```
    
    
    - Enter <kbd class="key">Y</kbd> and press <kbd class="key">Enter</kbd> to reload the MySQL privilege tables and apply your configuration changes.
    
    ```
    Reload privilege tables now? (Press y|Y for Yes, any other key for No) : 
    ```
8. Restart the MySQL database server to apply changes.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-14">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service mysql-server restart
    ```
    
    <div class="code-block"><div id="bkmrk--13"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-14">Explain Code</button></div>

## Install PHP and Configure PHP-FPM

PHP is available in the default FreeBSD repositories and includes the PHP-FPM package that manages connection requests using pool configurations on your server. Follow the steps below to install the latest PHP version on your server.

1. Search all available PHP packages in the default FreeBSD repositories.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-15">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ pkg search php | egrep '^php[0-9]+-[0-9]'
    ```
    
    <div class="code-block"><div id="bkmrk--14"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-15">Explain Code</button></div>Output:
    
    ```
    php81-8.1.29                   PHP Scripting Language (8.1.X branch)
    php82-8.2.18                   PHP Scripting Language (8.2.X branch)
    php83-8.3.6                    PHP Scripting Language (8.3.X branch)
    ```
2. Install the latest PHP package. For example, PHP version `8.3`.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-16">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo apt install php83
    ```
    
    <div class="code-block"><div id="bkmrk--15"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-16">Explain Code</button></div>
3. Install common PHP modules required to enable application functionalities.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-17">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo pkg install -y  php83-mysqli php83-curl php83-zip php83-gd php83-xml php83-mbstring
    ```
    
    <div class="code-block"><div id="bkmrk--16"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-17">Explain Code</button></div>
4. View the installed PHP version on your server..
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-18">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ php -v
    ```
    
    <div class="code-block"><div id="bkmrk--17"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-18">Explain Code</button></div>Output:
    
    ```
    PHP 8.3.6 (cli) (built: Jun 20 2024 02:08:30) (NTS)
    Copyright (c) The PHP Group
    Zend Engine v4.3.6, Copyright (c) Zend Technologies
    ```
5. View the installed PHP-FPM version on your server.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-19">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ php-fpm -v
    ```
    
    <div class="code-block"><div id="bkmrk--18"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-19">Explain Code</button></div>Output:
    
    ```
    PHP 8.3.6 (fpm-fcgi) (built: Jun 20 2024 02:08:43)
    Copyright (c) The PHP Group
    Zend Engine v4.3.6, Copyright (c) Zend Technologies
    ```
6. Enable PHP-FPM to automatically start at boot.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-20">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service php-fpm enable
    ```
    
    <div class="code-block"><div id="bkmrk--19"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-20">Explain Code</button></div>
7. View the PHP-FPM service status and verify that it's running.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-21">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service php-fpm status
    ```
    
    <div class="code-block"><div id="bkmrk--20"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-21">Explain Code</button></div>Output:
    
    ```
    php_fpm is running as pid 2558.
    ```

## Configure Apache with PHP-FPM

Apache uses the `mod_proxy` and `mod_proxy_fcgi` modules to process FastCGI requests and connect to the PHP-FPM service. Follow the steps below to enable the required Apache modules and forward all PHP application requests to the PHP-FPM service port `9000`.

1. Open the default PHP-FPM pool configuration file using a text editor such as the Easy Editor (`ee`).
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-22">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo ee /usr/local/etc/php-fpm.d/www.conf
    ```
    
    <div class="code-block"><div id="bkmrk--21"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-22">Explain Code</button></div>
    - Find the `user` and `group` directives and verify that PHP-FPM runs with the web server user profile `www`.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">ini</span><button class="copy-button" data-code-id="code-block-23">Copy</button></div><div><div class="highlight"></div></div></div>```
    user = www
    group = www
    ```
    
    <div class="code-block"><div id="bkmrk--22"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-23">Explain Code</button></div>
    - Find the `listen` directive and verify that PHP-FPM listens for connection requests on the localhost port `9000`.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">ini</span><button class="copy-button" data-code-id="code-block-24">Copy</button></div><div><div class="highlight"></div></div></div>```
    listen = 127.0.0.1:9000
    ```
    
    <div class="code-block"><div id="bkmrk--23"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-24">Explain Code</button></div>Save and close the file.
2. Run the following command to enable the `mod_proxy` and `mod_proxy_fcgi` Apache modules on your server.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-25">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo sed -i '' -e 's/^#LoadModule proxy_module libexec\/apache24\/mod_proxy.so/LoadModule proxy_module libexec\/apache24\/mod_proxy.so/' -e 's/^#LoadModule proxy_fcgi_module libexec\/apache24\/mod_proxy_fcgi.so/LoadModule proxy_fcgi_module libexec\/apache24\/mod_proxy_fcgi.so/' /usr/local/etc/apache24/httpd.conf
    ```
    
    <div class="code-block"><div id="bkmrk--24"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-25">Explain Code</button></div>The above command uncomments the following Apache configuration directives to enable the modules on your server.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">apacheconf</span><button class="copy-button" data-code-id="code-block-26">Copy</button></div><div><div class="highlight"></div></div></div>```
    LoadModule proxy_module libexec/apache24/mod_proxy.so
    LoadModule proxy_fcgi_module libexec/apache24/mod_proxy_fcgi.so
    ```
    
    <div class="code-block"><div id="bkmrk--25"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-26">Explain Code</button></div>
3. Open the main Apache configuration file.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-27">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo ee /usr/local/etc/apache24/httpd.conf
    ```
    
    <div class="code-block"><div id="bkmrk--26"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-27">Explain Code</button></div>
4. Add the following configurations at the end of the file to forward all PHP file requests to the PHP-FPM port `9000`.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">apacheconf</span><button class="copy-button" data-code-id="code-block-28">Copy</button></div><div><div class="highlight"></div></div></div>```
    <FilesMatch "\.php$">
        SetHandler "proxy:fcgi://127.0.0.1:9000"
    </FilesMatch>
    ```
    
    <div class="code-block"><div id="bkmrk--27"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-28">Explain Code</button></div>Save and close the file.
5. Test the Apache configuration for errors.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-29">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo apachectl configtest
    ```
    
    <div class="code-block"><div id="bkmrk--28"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-29">Explain Code</button></div>Your output should look like the one below when the test is successful:
    
    ```
    Performing sanity check on apache24 configuration:
    AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message
    Syntax OK
    ```
6. Restart PHP-FPM to apply changes.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-30">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service php-fpm restart
    ```
    
    <div class="code-block"><div id="bkmrk--29"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-30">Explain Code</button></div>
7. Restart Apache to apply the configuration changes.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-31">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service apache24 restart
    ```
    
    <div class="code-block"><div id="bkmrk--30"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-31">Explain Code</button></div>

## Test the Installation

1. Log in to the MySQL database server using the `root` user and password you set earlier.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-32">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ mysql -u root -p
    ```
    
    <div class="code-block"><div id="bkmrk--31"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-32">Explain Code</button></div>
2. Create a new sample database `exampledb`.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">sql</span><button class="copy-button" data-code-id="code-block-33">Copy</button></div><div><div class="highlight"></div></div></div>```
    mysql> create database exampledb;
    ```
    
    <div class="code-block"><div id="bkmrk--32"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-33">Explain Code</button></div>
3. Create a new database user such as `dbadmin` with a strong password.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">sql</span><button class="copy-button" data-code-id="code-block-34">Copy</button></div><div><div class="highlight"></div></div></div>```
    mysql> create user 'dbadmin'@'localhost' IDENTIFIED BY 'strong@@password25Bb';
    ```
    
    <div class="code-block"><div id="bkmrk--33"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-34">Explain Code</button></div>
4. Grant the `dbadmin` user full privileges to the `exampledb` database.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">sql</span><button class="copy-button" data-code-id="code-block-35">Copy</button></div><div><div class="highlight"></div></div></div>```
    mysql> GRANT ALL PRIVILEGES ON exampledb.* TO 'dbadmin'@'localhost';
    ```
    
    <div class="code-block"><div id="bkmrk--34"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-35">Explain Code</button></div>
5. Flush the MySQL privileges table to apply changes.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">sql</span><button class="copy-button" data-code-id="code-block-36">Copy</button></div><div><div class="highlight"></div></div></div>```
    mysql> FLUSH PRIVILEGES;
    ```
    
    <div class="code-block"><div id="bkmrk--35"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-36">Explain Code</button></div>
6. Switch to the sample database `exampledb`.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">sql</span><button class="copy-button" data-code-id="code-block-37">Copy</button></div><div><div class="highlight"></div></div></div>```
    mysql> use exampledb;
    ```
    
    <div class="code-block"><div id="bkmrk--36"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-37">Explain Code</button></div>
7. Create a new sample table `exampletable` with the following columns to store integer and string values.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">sql</span><button class="copy-button" data-code-id="code-block-38">Copy</button></div><div><div class="highlight"></div></div></div>```
    mysql> CREATE TABLE exampletable (id INT AUTO_INCREMENT PRIMARY KEY, messages VARCHAR(255) NOT NULL);
    ```
    
    <div class="code-block"><div id="bkmrk--37"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-38">Explain Code</button></div>The above SQL statement creates a new table with the columns: `id` that stores numeric data, and `messages` that stores mixed characters.
8. Insert sample data into the table. For example, `Greetings from Vultr`.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">sql</span><button class="copy-button" data-code-id="code-block-39">Copy</button></div><div><div class="highlight"></div></div></div>```
    mysql> INSERT INTO exampletable (messages) VALUES ('Greetings from Vultr');
    ```
    
    <div class="code-block"><div id="bkmrk--38"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-39">Explain Code</button></div>
9. Exit the MySQL database console.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">sql</span><button class="copy-button" data-code-id="code-block-40">Copy</button></div><div><div class="highlight"></div></div></div>```
    mysql> EXIT;
    ```
    
    <div class="code-block"><div id="bkmrk--39"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-40">Explain Code</button></div>
10. Create a new directory to store your web application files. For example, `app.example.com` in the default Apache web root path.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-41">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo mkdir -p /usr/local/www/apache24/app.example.com
    ```
    
    <div class="code-block"><div id="bkmrk--40"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-41">Explain Code</button></div>
11. Create a new sample PHP application file in the directory. For example, `index.php`.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-42">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo ee /usr/local/www/apache24/app.example.com/index.php
    ```
    
    <div class="code-block"><div id="bkmrk--41"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-42">Explain Code</button></div>
12. Add the following contents to the file.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">php</span><button class="copy-button" data-code-id="code-block-43">Copy</button></div><div><div class="highlight"></div></div></div>```
    <?php
    $servername = "localhost";
    $username = "dbadmin";
    $password = "strong@@password25Bb";
    $dbname = "exampledb";
    
    // Connect to the MySQL database
    $conn = new mysqli($servername, $username, $password, $dbname);
    
    // Test the MySQL database connection
    if ($conn->connect_error) {
        die("Database Connection Failed." . $conn->connect_error);
    }
    
    // Fetch a string from exampletable
    $sql = "SELECT messages FROM exampletable";
    $result = $conn->query($sql);
    
    if ($result->num_rows > 0) {
        $row = $result->fetch_assoc();
        echo "<h1 align='center'> <br> <br>" . $row["messages"]. "</h1>";
    
    } else {
        echo "<h1 align='center'> <br> No Data Found.</h1>";
    }
    
    $conn->close();
    ?>
    ```
    
    <div class="code-block"><div id="bkmrk--42"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-43">Explain Code</button></div>Save the file and exit the text editor.
    
    The above PHP application connects to the MySQL database server and queries the `exampledb` database to output values in the `exampledata` column within the `messages` table. The application displays a `Greetings from Vultr` heading when successful or `No Data Found` when unsuccessful.
13. Create a new Apache virtual host configuration file. For example, `app.example.com.conf`.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-44">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo ee /usr/local/etc/apache24/Includes/app.example.com.conf
    ```
    
    <div class="code-block"><div id="bkmrk--43"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-44">Explain Code</button></div>
14. Add the following configurations to the file.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">apacheconf</span><button class="copy-button" data-code-id="code-block-45">Copy</button></div><div><div class="highlight"></div></div></div>```
    <VirtualHost *:80>
        ServerAdmin webmaster@yourdomain.com
        DocumentRoot "/usr/local/www/apache24/app.example.com/"
        ServerName app.example.com
    
        <Directory "/usr/local/www/apache24/app.example.com/">
            Options Indexes FollowSymLinks
            AllowOverride All
            Require all granted
            DirectoryIndex index.php index.html
    
        </Directory>
    
        ErrorLog "/var/log/app.example.com-error.log"
    </VirtualHost>
    ```
    
    <div class="code-block"><div id="bkmrk--44"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-45">Explain Code</button></div>Save the file and exit the text editor.
    
    The above Apache configuration creates a new virtual host that listens for connections using the domain `app.example.com` on the default HTTP port `80`. All PHP requests are forwarded to PHP-FPM on the host port `9000` applied in your main Apache configuration.
15. Test the Apache configuration for errors.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-46">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo apachectl configtest
    ```
    
    <div class="code-block"><div id="bkmrk--45"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-46">Explain Code</button></div>Output:
    
    ```
    Performing sanity check on apache24 configuration:
    AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message
    Syntax OK
    ```
16. Restart Apache to apply the new virtual host configuration.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-47">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service apache24 restart
    ```
    
    <div class="code-block"><div id="bkmrk--46"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-47">Explain Code</button></div>
17. Access your domain using a web browser and verify that you can access the PHP web application.
    
    ```
    http://app.example.com
    ```
    
    ![A Sample PHP web application](https://docs.vultr.com/public/doc-assets/1873/0c0771b0137320db.png)

### Secure the Server

1. Install the Certbot Let's Encrypt client for Apache.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-48">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo pkg install py39-certbot-apache
    ```
    
    <div class="code-block"><div id="bkmrk--47"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-48">Explain Code</button></div>
2. Run the following commands to enable the Apache `mod_rewrite` and `mod_ssl` modules to allow SSL configurations on your web server.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-49">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo sed -i '' 's/#LoadModule rewrite_module libexec\/apache24\/mod_rewrite.so/LoadModule rewrite_module libexec\/apache24\/mod_rewrite.so/' /usr/local/etc/apache24/httpd.conf
    
    $ sudo sed -i '' 's/#LoadModule ssl_module libexec\/apache24\/mod_ssl.so/LoadModule ssl_module libexec\/apache24\/mod_ssl.so/' /usr/local/etc/apache24/httpd.conf
    ```
    
    <div class="code-block"><div id="bkmrk--48"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-49">Explain Code</button></div>The above commands uncomment and enable the following directives in the `/usr/local/etc/apache24/httpd.conf` Apache configuration file:
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">apacheconf</span><button class="copy-button" data-code-id="code-block-50">Copy</button></div><div><div class="highlight"></div></div></div>```
    LoadModule ssl_module libexec/apache24/mod_ssl.so
    LoadModule rewrite_module libexec/apache24/mod_rewrite.so
    ```
    
    <div class="code-block"><div id="bkmrk--49"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-50">Explain Code</button></div>
3. Generate a new SSL certificate for your domain. Replace `app.example.com` with your actual domain.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-51">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo certbot --apache -d app.example.com --agree-tos
    ```
    
    <div class="code-block"><div id="bkmrk--50"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-51">Explain Code</button></div>
4. Test the Certbot SSL certificate automatic renewal process.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-52">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo certbot renew --dry-run
    ```
    
    <div class="code-block"><div id="bkmrk--51"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-52">Explain Code</button></div>Output:
    
    ```
    Account registered.
    Simulating renewal of an existing certificate for app.example.com
    
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Congratulations, all simulated renewals succeeded: 
      /usr/local/etc/letsencrypt/live/app.example.com/fullchain.pem (success)
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ```
5. Restart Apache to apply your SSL configuration changes.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-53">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo service apache24 restart
    ```
    
    <div class="code-block"><div id="bkmrk--52"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-53">Explain Code</button></div>
6. Create a new Packet Filter (`pf`) firewall configuration.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-54">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo ee /etc/pf.conf
    ```
    
    <div class="code-block"><div id="bkmrk--53"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-54">Explain Code</button></div>
7. Add the following configurations to the file. Replace `vtnet0` with your public server interface name.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">ini</span><button class="copy-button" data-code-id="code-block-55">Copy</button></div><div><div class="highlight"></div></div></div>```
    ext_interface = "vtnet0"            # The external server interface
    
    pass quick on lo0 all      # Allow all connections on the loopback interface
    
    # Filter rules
    block in all                # Block incoming unpermitted traffic
    pass out all keep state     # Allow outgoing traffic
    
    pass in on $ext_interface proto tcp from any to any port 22 keep state  # Allow SSH
    pass in on $ext_interface proto tcp from any to any port 80 keep state  # Allow HTTP
    pass in on $ext_interface proto tcp from any to any port 443 keep state # Allow HTTPS
    ```
    
    <div class="code-block"><div id="bkmrk--54"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-55">Explain Code</button></div>Save the file and exit the text editor.
    
    The above firewall configuration enables network connections to the SSH port `22`, HTTP port `80`, and the HTTPS port `443`. In addition, the firewall blocks any other network connections to other ports on your server.
8. Enable the firewall to automatically start at boot.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-56">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo sysrc pf_enable="YES"
    ```
    
    <div class="code-block"><div id="bkmrk--55"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-56">Explain Code</button></div>Output:
    
    ```
    pf_enable: NO -> YES
    ```
9. Load your firewall configuration.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-57">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo pfctl -f /etc/pf.conf
    ```
    
    <div class="code-block"><div id="bkmrk--56"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-57">Explain Code</button></div>
10. Start the Packet Filter firewall.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-58">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo pfctl -e
    ```
    
    <div class="code-block"><div id="bkmrk--57"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-58">Explain Code</button></div>Output:
    
    ```
    pf enabled
    ```
11. View all firewall rules and verify that your SSH, HTTP, and HTTPS ports are available.
    
    <div class="code-block"><div class="code-heading"><span class="lexer-name">console</span><button class="copy-button" data-code-id="code-block-59">Copy</button></div><div><div class="highlight"></div></div></div>```
    $ sudo pfctl -sr
    ```
    
    <div class="code-block"><div id="bkmrk--58"><div class="highlight"></div></div><button class="explain-button" data-code-id="code-block-59">Explain Code</button></div>Output:
    
    ```
    pass quick on lo0 all flags S/SA keep state
    block drop in all
    pass in on vtnet0 proto tcp from any to any port = ssh flags S/SA keep state
    pass in on vtnet0 proto tcp from any to any port = http flags S/SA keep state
    pass in on vtnet0 proto tcp from any to any port = https flags S/SA keep state
    pass out all flags S/SA keep state
    ```
12. Access your domain using HTTPS to verify that your SSL certificate is valid and encrypted by the Apache web server.
    
    ```
    https://app.example.com
    ```

## Conclusion

You have successfully installed the Apache, MySQL, and PHP (FAMP) stack on your FreeBSD 14.0 server. All applications in the stack run collectively on the server to deliver dynamic web applications. You can configure the Apache web server and set up MySQL databases to securely deliver web applications or frameworks such as WordPress on your server.