WebGen Linux Manual

Running a LAMP server

WebGen is a KVM host and workstation first, but it also carries a complete, from-source LAMP stack — Apache, PHP-FPM and MariaDB — plus an ACME client for free TLS. This guide stands up a stock Laravel application at example.com, served over HTTPS on ports 80 and 443. Swap in your own app: the wiring is identical.

The server role is opt-in. None of this is in the base image and nothing listens until you install and enable it — installing the packages does not start a daemon or initialise a database. Do all of this as a normal user with sudo.

1 · What you install

Web serverApache 2.4.68 (httpd, MPM event) — talks to PHP over mod_proxy_fcgi, no mod_php.
PHPPHP 8.5.8 as php-fpm on 127.0.0.1:9000. OPcache is built in. Config in /etc/php.
DatabaseMariaDB 11.8.8 LTS. Socket /run/mysqld/mysqld.sock, config /etc/my.cnf.d/.
TLSacme.sh 3.1.4 — a pure-shell Let’s Encrypt client (no Python, unlike certbot).

The web tier and the data tier are separate groups — install both:

sudo wgpkg update
sudo wgpkg install --group server      # Apache + PHP-FPM + acme.sh (the web tier)
sudo wgpkg install --group database    # your data tier -- see below

The server group is Apache, PHP-FPM and acme.sh. The database group holds every data service — MariaDB, PostgreSQL and Valkey, each split into a client and a server package so a box that only needs a client doesn’t pull a whole daemon. For a classic LAMP app just add MariaDB: sudo wgpkg install mariadb. For image manipulation, queues, or other PHP extensions add the php-extras group. Then pull the app’s toolchain — git and Composer are the usual pair (Composer runs on the PHP you just installed).

2 · The database

The first start initialises the data directory; then create a database and a user for the app.

sudo rc-service mariadb start        # first start runs mariadb-install-db
sudo mariadb <<'SQL'
CREATE DATABASE example CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'example'@'localhost' IDENTIFIED BY 'change-this-password';
GRANT ALL PRIVILEGES ON example.* TO 'example'@'localhost';
FLUSH PRIVILEGES;
SQL

MariaDB ships tuned for a 1-core / 1 GB box (the tiny tier). To scale up, edit /etc/my.cnf.d/webgen.cnf — it carries commented tiny / small / med / large blocks; the knobs that matter most are innodb_buffer_pool_size (the working-set cache) and max_connections. It binds to 127.0.0.1 only, so the database is never exposed to the network by default.

3 · PHP-FPM

PHP-FPM already ships a working pool listening on 127.0.0.1:9000 as the http user, and a production php.ini. The simplest setup is to let the app be owned by that same http user, so no pool edit is needed:

sudo rc-service php-fpm start
If you must run the pool as a different user, add a dedicated pool file at /etc/php/php-fpm.d/<app>.conf — do not edit the stock www.conf. A wgpkg upgrade of PHP overwrites package-shipped configs, which would silently revert your change and break file writes.

4 · Apache → PHP

Load the proxy modules and point a virtual host at the app’s public/ directory, handing .php requests to php-fpm. Add to /etc/httpd/httpd.conf:

LoadModule proxy_module         modules/mod_proxy.so
LoadModule proxy_fcgi_module    modules/mod_proxy_fcgi.so
LoadModule rewrite_module       modules/mod_rewrite.so
LoadModule ssl_module           modules/mod_ssl.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
Include /etc/httpd/extra/example.conf

Then /etc/httpd/extra/example.conf:

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /srv/www/example-app/public
    <Directory /srv/www/example-app/public>
        AllowOverride All
        Require all granted
    </Directory>
    <FilesMatch \.php$>
        SetHandler "proxy:fcgi://127.0.0.1:9000"
    </FilesMatch>
</VirtualHost>

5 · Deploy the Laravel app

Create a stock Laravel app (or clone yours) under /srv/www, install dependencies, set it up, and hand ownership to the http user so PHP can write storage/.

sudo install -d -o $USER -g http /srv/www
cd /srv/www
composer create-project laravel/laravel example-app

cd example-app
cp .env.example .env
# point .env at the database from step 2:
#   DB_CONNECTION=mysql  DB_HOST=127.0.0.1  DB_DATABASE=example
#   DB_USERNAME=example  DB_PASSWORD=change-this-password
#   APP_URL=https://example.com
php artisan key:generate
php artisan migrate --force
php artisan storage:link
php artisan config:cache && php artisan route:cache

sudo chown -R http:http /srv/www/example-app
sudo rc-service apache2 restart
WebGen tracks the latest stable PHP. If a project’s composer.lock caps PHP below 8.5.8, composer install refuses; run composer update once to re-resolve against the installed PHP, then commit the new lock.

6 · Open the firewall

Inbound is denied by default except SSH. Open 80 and 443. In the desktop, Settings → Network → Firewall lists the live rules in a table — click Add allow rule for tcp/80 and tcp/443, then Apply. Headless, edit /etc/nftables.conf:

tcp dport { 80, 443 } accept
# then reload:
sudo nft -f /etc/nftables.conf
sudo rc-service firewall restart

6.1 · The same rules in the Settings app

On the desktop the firewall is a panel, not a file. Settings → Network → Firewall lists the rules in a table — and it reads the live nftables ruleset, so the two ports you just opened (by hand, or by a recipe) appear here too, not just a hardcoded default. Use Add allow rule and the trash icon to change them; Apply writes /etc/nftables.conf and reloads. For this web server it looks like:

SSH (22) stays open so a remote box can’t lock you out; 80 and 443 are the two you added for the web server; everything else falls through to the default Drop.

7 · HTTPS with Let’s Encrypt

With Apache already answering on port 80, issue and install a certificate over the webroot. The --reloadcmd keeps it renewing automatically.

sudo acme.sh --set-default-ca --server letsencrypt
sudo acme.sh --issue -d example.com -w /srv/www/example-app/public --keylength ec-256
sudo acme.sh --install-cert -d example.com --ecc \
     --key-file  /etc/httpd/ssl/example.key \
     --fullchain-file /etc/httpd/ssl/example.crt \
     --reloadcmd "rc-service apache2 reload"

Add the TLS <VirtualHost *:443> (same DocumentRoot and SetHandler as port 80, plus SSLEngine on and the SSLCertificateFile/SSLCertificateKeyFile paths above), and redirect 80→443.

8 · Start at boot

sudo rc-update add mariadb default
sudo rc-update add php-fpm default
sudo rc-update add apache2 default

For Laravel’s queue and scheduler, run php artisan queue:work under a small OpenRC service and add php artisan schedule:run to /etc/cron.d/ (the per-minute driver Laravel expects).

9 · Redeploy

Day to day, pull and refresh caches:

cd /srv/www/example-app
git pull
composer install --no-dev
php artisan migrate --force
php artisan config:cache && php artisan route:cache
sudo rc-service php-fpm reload