Building a LEMP stack on Artix means installing nginx, PHP-FPM, and MariaDB or PostgreSQL from the world repo, then enabling them via your chosen init. This episode covers installation, virtual host configuration, and service activation on OpenRC, runit, s6, and dinit.

Artix isn't just for desktops; it's also a solid server platform. Episode 12 builds the LEMP stack — Linux, nginx, MariaDB, PHP — the components that power the majority of modern websites. You'll install the components from the world repo, configure virtual hosts, and enable all services via your chosen init.
Because this is a series about full control, we won't use automated panels. All configuration is written by hand, and every service is enabled the init-appropriate way — skills you can take straight to production.
nginx is chosen because it's light and fast for static files. Install it along with the service subpackage for your init:
sudo pacman -S nginx nginx-openrcThe nginx-openrc package provides /etc/init.d/nginx. For other inits, use the matching subpackage: nginx-runit, nginx-s6, or nginx-dinit.
Add the PHP processor and database:
sudo pacman -S php php-fpm php-fpm-openrc
sudo pacman -S mariadb mariadb-openrcPHP-FPM runs PHP scripts as a separate service, while MariaDB stores the data. Both also need the service subpackage matching your init.
nginx configuration lives in /etc/nginx/. The main nginx.conf file loads files from /etc/nginx/conf.d/, where you place virtual hosts. Create the web directory and your first virtual host:
sudo mkdir -p /srv/www/example/html
sudo chown -R http:http /srv/www/exampleThe http user is the user running nginx workers on Artix. All web files must be readable by this user.
Write a virtual host file at /etc/nginx/conf.d/example.conf:
server {
listen 80;
server_name example.com;
root /srv/www/example/html;
index index.html index.php;
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
}The location ~ \.php$ block routes PHP requests to the PHP-FPM socket. After writing the file, test the configuration before restarting:
sudo nginx -t
sudo rc-service nginx restartnginx -t validates the syntax of the entire configuration. Never restart a service before this test passes.
PHP-FPM serves PHP scripts through a pool connected to nginx. The default pool is in /etc/php/php-fpm.d/www.conf. Make sure the listen socket matches the nginx configuration:
listen = /run/php-fpm/php-fpm.sock
listen.owner = http
listen.group = httpA socket mismatch between nginx and PHP-FPM is the most common cause of white pages or 502 errors. Note the socket path in both configurations.
Enable the extensions your application needs by uncommenting lines in /etc/php/php.ini or copying extension files from /etc/php/conf.d/. After changing them, restart php-fpm.
Before use, MariaDB needs its data directory initialized and the root user set up:
sudo mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
sudo rc-service mariadb start
sudo mysql_secure_installationmysql_secure_installation guides you through setting the root password and removing anonymous accounts. This step is mandatory before the database goes into production.
Create an application database and user:
sudo mysql -u root -p
CREATE DATABASE appdb;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'a-strong-secret';
GRANT ALL PRIVILEGES ON appdb.* TO 'app'@'localhost';
FLUSH PRIVILEGES;
EXITNever use the same password as the example. Use appdb and app as the database and application user names of your own.
For OpenRC, register all three services in the default runlevel:
rc-update add nginx default
rc-update add php-fpm default
rc-update add mariadb defaultFor other inits, the equivalent pattern:
ln -s /etc/runit/sv/nginx /etc/runit/runsvdir/default/nginx
ln -s /etc/runit/sv/php-fpm /etc/runit/runsvdir/default/php-fpm
ln -s /etc/runit/sv/mariadb /etc/runit/runsvdir/default/mariadbFor s6 use s6-rc with the service database, and for dinit use dinitctl enable. The pattern "install the subpackage, register the service, start the service" applies across all inits.
Once everything is active, test from the ground up:
curl -I http://localhost/
curl -I http://localhost/index.php
mysqladmin -u app -p pingcurl -I http://localhost/index.php shows whether PHP is being processed by PHP-FPM. A 200 response means the stack works; 502 or 404 means a layer is out of sync.
Episode 12 built a full LEMP stack on Artix: nginx as the web server, PHP-FPM to process PHP, MariaDB for the database, all enabled through your chosen init and verified with bottom-up tests.
Key takeaways:
/etc/nginx/conf.d/ and validated with nginx -t.mysql_secure_installation is mandatory after initializing MariaDB.curl -I tests each layer from top to bottom.In the next episode, episode 13, we'll cover firewall: nftables and iptables — basic rules, UFW as a frontend, fail2ban, and strategies for limiting exposed ports.