Databases

Install Apache, MariaDB, and PHP (LAMP) on Void Linux

Void Linux handles services differently from most distros. There’s no systemd here. Runit manages everything, and the package manager (xbps) is fast and minimal. Setting up a LAMP stack on Void takes about 10 minutes once you know the right steps, but a few configuration details will trip you up if you follow generic guides written for Debian or Fedora.

Original content from computingforgeeks.com - post 83703

This guide installs Apache, MariaDB and PHP on Void Linux from the official xbps repositories, with real commands and output, then covers two practical scenarios: a PHP application talking to MariaDB, and Apache virtual hosts for several sites. We also show how to confirm that the PHP build answering your web requests is patched against PHP2Shell, because the meta package names hide which PHP branch you actually run. The install path and the runit service handling described here were checked against Void’s current glibc repository in October 2026, which now installs PHP 8.5.12 by default.

Prerequisites

  • A running Void Linux system (glibc variant recommended for maximum compatibility)
  • Root or sudo access
  • Tested on: Void Linux x86_64 (glibc) with Apache 2.4.69, MariaDB 12.3.2 and PHP 8.5.12

Update the System

Start by updating the xbps package manager itself, then pull in all available updates. Void requires updating xbps separately before a full system upgrade, and the -S flag matters here: it syncs the repository index first, so xbps compares against what the mirror serves today rather than whatever index the installer left behind.

sudo xbps-install -Su xbps

Once xbps is current, run a full system update:

sudo xbps-install -Syu

If the upgrade replaced the kernel or core libraries, reboot before going further so the services you are about to enable start against the new versions.

Install Apache Web Server

Install Apache from the Void repos:

sudo xbps-install -y apache

Void Linux uses runit instead of systemd. To enable a service, you create a symlink from /etc/sv/ to /var/service/. This both enables the service at boot and starts it immediately.

sudo ln -s /etc/sv/apache /var/service/apache

Give it a couple of seconds, then verify Apache is running:

sudo sv status apache

The output should show the service with a PID and uptime:

run: apache: (pid 168) 2s; run: log: (pid 167) 2s

Confirm the installed version:

httpd -v

You should see Apache 2.4.69 or later:

Server version: Apache/2.4.69 (Unix)
Server built:   Oct 12 2026 02:05:31

Apache’s default document root on Void Linux is /srv/www/apache, not /var/www/html like on Debian or RHEL. The main configuration file lives at /etc/apache/httpd.conf.

Install MariaDB

Void ships MariaDB as its MySQL-compatible database, and the current package is the 12.3 series. Install it:

sudo xbps-install -y mariadb

Enable and start the MariaDB service through runit:

sudo ln -s /etc/sv/mysqld /var/service/mysqld

Wait a few seconds for MariaDB to initialize, then check its status:

sudo sv status mysqld

A healthy service looks like this:

run: mysqld: (pid 367) 10s; run: log: (pid 366) 10s

One thing to note: MariaDB 11 and newer have deprecated the mysql command in favor of mariadb. Both still work for now, but you’ll see deprecation warnings if you use the old name. The article uses mariadb throughout.

Secure the Installation

Run the interactive security script to set a root password, remove anonymous users, and drop the test database:

sudo mariadb-secure-installation

Answer the prompts as follows (press Enter for the default where shown):

Enter current password for root (enter for none): [Enter]
Switch to unix_socket authentication [Y/n]: Y
Change the root password? [Y/n]: Y
New password: ********
Re-enter new password: ********
Remove anonymous users? [Y/n]: Y
Disallow root login remotely? [Y/n]: Y
Remove test database and access to it? [Y/n]: Y
Reload privilege tables now? [Y/n]: Y

Verify you can log in with the new password:

mariadb -u root -p -e "SELECT VERSION();"

The output confirms MariaDB 12.3.2:

+----------------+
| VERSION()      |
+----------------+
| 12.3.2-MariaDB |
+----------------+

With the database answering and the root account locked down, PHP is the last piece of the stack.

Install PHP with the Apache Module

The php-apache and php-mysql meta packages follow Void’s default PHP branch, which is 8.5 today. Versioned packages for 8.2, 8.3 and 8.4 sit beside it in the repository if an application needs an older branch. Install the Apache SAPI and the MySQL extension together:

sudo xbps-install -y php-apache php-mysql

This pulls in php8.5, php8.5-apache, and php8.5-mysql (which includes both mysqli and PDO MySQL drivers).

Confirm PHP is installed:

php -v

Expected output:

PHP 8.5.12 (cli) (built: Oct 21 2026 15:13:17) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.5.12, Copyright (c) Zend Technologies
    with Zend OPcache v8.5.12, Copyright (c), by Zend Technologies

The OPcache line is expected: PHP 8.5 builds OPcache in and loads it without any ini file, so there is nothing extra to enable for it.

Configure Apache to Use PHP

PHP’s Apache module is not thread-safe on Void, so Apache must use the prefork MPM instead of the default event MPM. Open the Apache configuration file:

sudo vi /etc/apache/httpd.conf

Find the MPM module lines (around line 66) and make these changes:

# Comment out event MPM (not compatible with mod_php)
#LoadModule mpm_event_module /usr/libexec/httpd/mod_mpm_event.so

# Uncomment prefork MPM
LoadModule mpm_prefork_module /usr/libexec/httpd/mod_mpm_prefork.so

Then scroll to the bottom of the file and add the PHP module configuration:

LoadModule php_module /usr/libexec/httpd/modules/libphp.so
Include /etc/apache/extra/php_module.conf

The libphp.so symlink is managed by xbps-alternatives and points to the active PHP branch (currently libphp8.5.so), so you won’t need to edit this line when PHP gets a point release. The alternative stays on whichever branch was installed first, though. A server built while the default was 8.4 keeps loading libphp8.4.so even after the meta package pulls in 8.5, which we confirmed on a second box. The PHP2Shell section below shows how to see which module Apache loads and how to switch branches safely.

Test the configuration for syntax errors:

httpd -t

If everything is correct, you’ll see:

Syntax OK

Restart Apache to load the PHP module:

sudo sv restart apache

A restart that prints ok: run: apache with a fresh PID means Apache accepted the new module; a down status instead points back at the httpd -t output.

Enable PHP Extensions

The MySQL extension is installed but not automatically enabled. PHP on Void reads additional config files from /etc/php8.5/conf.d/. Create that directory and enable the extensions:

sudo mkdir -p /etc/php8.5/conf.d

Enable the MySQLi and PDO MySQL extensions:

echo "extension=mysqli.so" | sudo tee /etc/php8.5/conf.d/mysqli.ini
echo "extension=pdo_mysql.so" | sudo tee /etc/php8.5/conf.d/pdo_mysql.ini

Verify the extensions are loaded:

php -m | grep -i mysql

All three MySQL-related modules should appear:

mysqli
mysqlnd
pdo_mysql

Restart Apache once more to pick up the new extensions:

sudo sv restart apache

Apache now loads the MySQL drivers for every request it hands to PHP.

Verify the LAMP Stack

Create a PHP info page to confirm everything works through the web server:

echo '<?php phpinfo(); ?>' | sudo tee /srv/www/apache/info.php

Open http://10.0.1.50/info.php in a browser (use your server’s address). You should see the full PHP information page showing PHP 8.5.12, the Apache 2 Handler server API, and the mysqli section confirming database support is active.

Check that both services are running:

sudo sv status apache mysqld

Both should show run with their PIDs:

run: apache: (pid 928) 8s; run: log: (pid 167) 283s
run: mysqld: (pid 367) 257s; run: log: (pid 366) 257s

Verify both Apache and MariaDB are listening on their expected ports:

ss -tlnp | grep -E '80|3306'

Apache should be on port 80 and MariaDB on port 3306:

LISTEN 0      80           0.0.0.0:3306      0.0.0.0:*   
LISTEN 0      511          0.0.0.0:80        0.0.0.0:*    users:(("httpd",pid=928,fd=3))
LISTEN 0      80              [::]:3306         [::]:*   

Remove the info.php file after verification since it exposes server details:

sudo rm /srv/www/apache/info.php

With the page gone, the stack is working end to end, but one more check belongs here before you put an application on it.

How to check Void’s PHP for PHP2Shell (CVE-2026-109618 and CVE-2026-109619)

PHP2Shell is the name for CVE-2026-109618 and CVE-2026-109619, two critical remote code execution bugs in PHP itself that php.net scored CVSS v4.0 9.2 in its 20 October pre-announcement and fixed on 21 October 2026 in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 (see the PHP security advisory). Void has shipped the fix for every supported branch: its repository already carries php8.5 8.5.12_1, php8.4 8.4.27_1, php8.3 8.3.36_1 and php8.2 8.2.35_1. These are the upstream releases rather than backports, so on Void the package version is the whole check, and a fresh install from this guide is patched once the version check below shows 8.5.12.

Two separate questions matter here. xbps-query answers whether the installed branch packages are at a fixed version, while xbps-alternatives -l -g php-apache and the probe page further down show which libphp Apache actually loads, because the php-apache meta package only names the default branch. Start with the version check:

xbps-query -l | grep -E 'php8\.[0-9]+(-apache|-fpm)?-8'

On our fresh box only the 8.5 branch appeared, at the fixed release:

ii php8.5-8.5.12_1                    HTML-embedded scripting language
ii php8.5-apache-8.5.12_1             HTML-embedded scripting language - Apache SAPI

Compare every line against 8.5.12_1, 8.4.27_1, 8.3.36_1 or 8.2.35_1. A server that followed an older copy of this guide shows php8.4 lines as well, and that is fine once they read 8.4.27_1. A php8.1 line is the real problem: Void ships no fixed php8.1 build, because it removed php8.1 from its package tree as end of life on 21 October and the index still serves the unfixed php8.1-8.1.34_2, so move that application to 8.4 or 8.5 rather than waiting.

On an existing server, upgrade the whole system. Void is a rolling release and partial upgrades are not supported, so sync the index and take everything it offers:

sudo xbps-install -Su

New files on disk do not patch the Apache workers that are already running, because each one keeps the old libphp mapped until it exits. Restart Apache yourself, along with any PHP-FPM service you added later (ls /etc/sv | grep php shows it) and any long-running PHP CLI workers, then read the status:

sudo sv restart apache
sudo sv status apache

The proof is the uptime in seconds after the PID. It must be smaller than the time since the upgrade finished, which shows the process serving requests started after the new package landed:

ok: run: apache: (pid 928) 1s
run: apache: (pid 928) 1s; run: log: (pid 167) 276s

The CLI and Apache can disagree, so ask the web server itself. This small page prints the version and SAPI that answer a real request:

echo '<?php echo PHP_VERSION, " ", PHP_SAPI, PHP_EOL;' | sudo tee /srv/www/apache/version.php
curl -s http://localhost/version.php

A patched mod_php setup answers with the fixed version and apache2handler. The server we built on the old 8.4 branch answered 8.4.27 apache2handler from a similar probe:

8.5.12 apache2handler

If curl is missing, install it with sudo xbps-install -y curl or open the page in a browser. Once you add the virtual hosts from Scenario 2, localhost lands on the first virtual host, so place the file in that site’s document root instead. Delete version.php when you are done, for the same reason you removed info.php.

A server still loading 8.4 is fine as long as it reads 8.4.27, and staying there is a reasonable choice. If you would rather follow the default branch, switch both alternatives groups to 8.5. The catch is the extension files: they live per branch, so mysqli and pdo_mysql stop loading until you recreate the ini files under /etc/php8.5/conf.d/. Our probe answered mysqli=no after the switch alone. Copy the files across in the same step:

sudo xbps-alternatives -s php8.5-apache
sudo xbps-alternatives -s php8.5
sudo mkdir -p /etc/php8.5/conf.d
sudo cp /etc/php8.4/conf.d/*.ini /etc/php8.5/conf.d/
sudo sv restart apache

Load version.php again afterwards. It should now report 8.5.12 apache2handler, and php -m should list mysqli and pdo_mysql again before you delete the probe.

Scenario 1: PHP Application with MariaDB

A LAMP stack by itself doesn’t do much. Here’s how to connect PHP to MariaDB with a working example. First, create a database and user for the application:

mariadb -u root -p

Run these SQL statements inside the MariaDB shell:

CREATE DATABASE appdb;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'AppP@ssw0rd';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Now create a PHP file that connects to MariaDB, creates a table, inserts a row, and reads it back:

sudo vi /srv/www/apache/app.php

Add the following PHP code:

<?php
$conn = new mysqli("localhost", "appuser", "AppP@ssw0rd", "appdb");
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// Create table
$conn->query("CREATE TABLE IF NOT EXISTS messages (
    id INT AUTO_INCREMENT PRIMARY KEY,
    content VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");

// Insert a test record
$conn->query("INSERT INTO messages (content) VALUES ('Hello from PHP on Void Linux')");

// Read back
$result = $conn->query("SELECT * FROM messages ORDER BY id DESC LIMIT 5");
echo "<h2>Messages from MariaDB</h2>";
echo "<table border='1'><tr><th>ID</th><th>Message</th><th>Created</th></tr>";
while ($row = $result->fetch_assoc()) {
    echo "<tr><td>{$row['id']}</td><td>{$row['content']}</td><td>{$row['created_at']}</td></tr>";
}
echo "</table>";
echo "<p>PHP " . phpversion() . " | MariaDB " . $conn->server_info . "</p>";
$conn->close();
?>

Visit http://10.0.1.50/app.php in your browser. You should see a table with the test message, confirming PHP can read from and write to MariaDB. Each page refresh adds another row.

Scenario 2: Apache Virtual Hosts

Hosting multiple sites on one Void Linux server requires Apache virtual hosts. Open the main configuration file:

sudo vi /etc/apache/httpd.conf

Find and uncomment this line to enable virtual host configuration:

Include /etc/apache/extra/httpd-vhosts.conf

Now edit the virtual hosts file:

sudo vi /etc/apache/extra/httpd-vhosts.conf

Replace the example entries with your site configuration:

<VirtualHost *:80>
    ServerName site1.example.com
    DocumentRoot "/srv/www/site1"
    <Directory "/srv/www/site1">
        AllowOverride All
        Require all granted
    </Directory>
    ErrorLog "/var/log/httpd/site1-error.log"
    CustomLog "/var/log/httpd/site1-access.log" common
</VirtualHost>

<VirtualHost *:80>
    ServerName site2.example.com
    DocumentRoot "/srv/www/site2"
    <Directory "/srv/www/site2">
        AllowOverride All
        Require all granted
    </Directory>
    ErrorLog "/var/log/httpd/site2-error.log"
    CustomLog "/var/log/httpd/site2-access.log" common
</VirtualHost>

Create the document roots and log directory:

sudo mkdir -p /srv/www/site1 /srv/www/site2 /var/log/httpd

Add a test page for each site:

echo "<h1>Site 1 on Void Linux</h1>" | sudo tee /srv/www/site1/index.html
echo "<h1>Site 2 on Void Linux</h1>" | sudo tee /srv/www/site2/index.html

Test the configuration and restart Apache:

httpd -t && sudo sv restart apache

Each site now responds to its own hostname on port 80. Point your DNS records (or local /etc/hosts file) to the server’s IP and test both sites independently.

Install Additional PHP Extensions

Most PHP applications need more than the base install. Void provides a solid set of extensions through its repos. Install the most commonly needed ones:

sudo xbps-install -y php-gd php-intl php-sqlite

After installing, each extension needs an ini file in the conf.d directory to be activated:

echo "extension=gd.so" | sudo tee /etc/php8.5/conf.d/gd.ini
echo "extension=intl.so" | sudo tee /etc/php8.5/conf.d/intl.ini
echo "extension=sqlite3.so" | sudo tee /etc/php8.5/conf.d/sqlite3.ini
echo "extension=pdo_sqlite.so" | sudo tee /etc/php8.5/conf.d/pdo_sqlite.ini

Restart Apache and confirm the full module list:

sudo sv restart apache
php -m | sort

Our run listed 38 entries, including gd, intl, mysqli, pdo_mysql, sqlite3, and pdo_sqlite.

Other available extensions you can install the same way include: php-redis, php-ldap, php-pgsql, php-sodium, php-tidy, and php-xsl. Run xbps-query -Rs php- to see the full list.

Runit Service Management Quick Reference

If you’re coming from systemd-based distros, runit’s service management takes some getting used to. Here are the essential commands for managing your LAMP services:

ActionRunit commandsystemd equivalent
Start a servicesv start apachesystemctl start httpd
Stop a servicesv stop apachesystemctl stop httpd
Restart a servicesv restart apachesystemctl restart httpd
Check statussv status apachesystemctl status httpd
Enable at bootln -s /etc/sv/apache /var/service/systemctl enable httpd
Disable at bootrm /var/service/apachesystemctl disable httpd
View logscat /var/log/socklog/apache/*journalctl -u httpd

One key difference: runit starts a service the moment you symlink it to /var/service/. There’s no separate “enable” and “start” step. Removing the symlink stops and disables the service.

Void Linux vs Other Distros: LAMP Differences

If you maintain LAMP stacks across multiple Linux distributions, these are the differences that catch people off guard on Void:

ItemVoid LinuxDebian/UbuntuRHEL/Rocky
Init systemrunitsystemdsystemd
Package managerxbpsaptdnf
Apache document root/srv/www/apache/var/www/html/var/www/html
Apache config/etc/apache/httpd.conf/etc/apache2/apache2.conf/etc/httpd/conf/httpd.conf
PHP config/etc/php8.5/php.ini/etc/php/8.x/apache2/php.ini/etc/php.ini
MariaDB commandmariadbmariadbmariadb
MariaDB servicesv status mysqldsystemctl status mariadbsystemctl status mariadb
SELinux/AppArmorNeitherAppArmorSELinux

Going Further

  • Set up an Nginx reverse proxy with SSL in front of Apache for production deployments
  • Install LAMP on Fedora or Rocky Linux if you need systemd-based service management
  • Consider LAMP on Debian or Ubuntu for production web hosting with broader community support
  • Explore php-fpm (available as xbps-install php-fpm) if you want Apache to use FastCGI instead of mod_php for better memory management under load
  • Install socklog-void (xbps-install socklog-void) for persistent logging, since runit’s default logging is minimal compared to journald

Keep reading

PHP2Shell (CVE-2026-109618, CVE-2026-109619): Check and Patch PHP Php PHP2Shell (CVE-2026-109618, CVE-2026-109619): Check and Patch PHP PHP2Shell on End-of-Life PHP 8.1, 8.0 and 7.4 (WHMCS, ionCube) Php PHP2Shell on End-of-Life PHP 8.1, 8.0 and 7.4 (WHMCS, ionCube) Patch PHP2Shell (CVE-2026-109618) on Ubuntu 26.04 / 24.04 / 22.04 Php Patch PHP2Shell (CVE-2026-109618) on Ubuntu 26.04 / 24.04 / 22.04 Best PL-300 Books for the Power BI Data Analyst Exam Books Best PL-300 Books for the Power BI Data Analyst Exam Best MySQL and MariaDB Books for 2026 Books Best MySQL and MariaDB Books for 2026 How To Install PHP 8.4 on Rocky / AlmaLinux 9|8 AlmaLinux How To Install PHP 8.4 on Rocky / AlmaLinux 9|8

Leave a Comment

Press ESC to close