Guide v6.4 / Updated 2023-11-24 / First published 2023-09-24 / echo (at) screaming (dot) computer
Preface
Over the years while working on various projects, I've often wished for a fully-featured web development environment confined to my local network. This would allow for offline development (before uploading to a public server), and also allow hosting of local projects that are never meant to be online.
This is an update of my previous LAMP setup guide, where we host a LAMP server in an UnRAID VM. Updated to use PHP 8 and replacing MySQL with (open source, drop-in replacement) MariaDB.
Large portions of this guide are unchanged from the previous version.
Note that I will refer to MariaDB as “MySQL” throughout, for consistency with traditional LAMP. MariaDB advertises substantial compatibility with MySQL, and all MySQL commands are aliased to the MariaDB executables.
Please Note: The choice of software and settings are entirely based on what I imagine my personal needs to be, and depend upon my current (possibly flawed) understanding of the software involved. This guide might not be suitable for you, and even if it is, it might contain errors. Proceed at your own discretion.
Content may be updated and expanded over time.... take note of the “Updated” date, above.
Overview
Operating system:
- Linux Mint Xfce 21.2
Server:
- Apache 2.4
- MariaDB 10.11
- PHP 8.2
Additional features:
- phpMyAdmin 5.1
- Samba network file sharing
- Virtual hosts
* version numbers as of this writing
1. User accounts
Once you have completed all steps in this guide, a variety of accounts and users will exist.
Anywhere you see a VARIABLE in this document, substitute your chosen value. To change passwords later, refer to appendix A.
1.1 Linux Users
Linux Mint does not have a separate user named root
. The first user you create during installation gets root privileges; in this guide the primary admin user is VMUSER.
root |
VMPASS | Virtual root user; not a true account |
VMUSER | VMPASS | Primary admin user; has root privileges; member of the www-data usergroup |
1.2 SQL Users
root |
SQLPASS | MySQL administrator; requires local superuser privileges to use |
SQLUSER | SQLPASS | MySQL administrator; used to access phpMyAdmin |
DBUSER | DBPASS | Limited user with permission to manage only the DBNAME database |
You should create separate low-privilege users for accessing your databases from PHP projects, such as DBUSER, above; refer to phpMyAdmin user management, and section 8 of this guide.
1.3 Samba User
SMBUSER | SMBPASS | Used to connect to the network share \\mint-vm\www ; member of the www-data usergroup |
1.4 Linux Usergroups
www-data |
Any member of this group has full R/W access to web files, locally via /var/www or remotely via \\mint-vm\www |
2. UnRAID VM setup
Download a long-term support (LTS) release of Linux Mint Xfce 64-bit
Place the ISO file in UnRAID /mnt/user/isos
UnRAID [VMs] tab → [Add VM] → [Linux]
Name: Linux Mint Xfce
Initial Memory: 8192 MB
Max Memory: 8192 MB
USB Controller: 3.0 (qemu XHCI)
OS Install ISO: [select downloaded ISO file]
Primary vDisk Size: 48G
[Create]
Launch [VNC Remote] from “Linux Mint Xfce” VM dropdown menu
3. Linux installation
From the boot menu, run [Start Linux Mint]
From the desktop, run [Install Linux Mint]
Accept all defaults, then [Install Now]
Your name: Administrator
Your computer's name: mint-vm
Pick a username: VMUSER
Choose a password: VMPASS
Confirm your password: VMPASS
Log in automatically: yes
[Continue]
Wait for installation, then [Restart Now]
“Please remove the installation medium then press enter” → just press enter
Wait for restart
Uncheck [Show this dialog at startup] on Welcome screen, then close it
Open [Update Manager] from the tray
[Edit] menu → [Preferences] → Notifications: set all values to 90 days
Close [Preferences] window
Install all available updates
Open [System Reports] from the tray (warning icon with exclamation mark)
[Ignore this report] for each detected issue
Open [Power Manager] from the tray (lightning bolt icon)
[Display] tab → uncheck [Display power management], set [Blank after] to never
[Security] tab → [Automatically lock the session] → [Never]
Start Menu → All Applications → [Settings Manager]
[Desktop] icon → [Icons] tab → Default Icons: ☑ Removable Devices
Start Menu → All Applications → [Synaptic Package Manager]
[Status] button → [Installed] → Uninstall packages by clicking the checkbox and selecting “Mark for complete removal”
- celluloid
- drawing
- growisofs
- hexchat
- hexchat-common
- hypnotix
- libreoffice-common
- libreoffice-*
- mythes-*
- pix
- pix-data
- rhythmbox
- rhythmbox-data
- thunderbird
- transmission-common
- uno-libs-private
[Apply] button → [Apply]
Start Menu → All Applications → [Session and Startup]
[Application Autostart] tab → Uncheck programs:
- mintwelcome
- PulseAudio Sound System
- Update Manager
Start Menu → Power Icon → [Restart]
4. LAN configuration
These instructions apply to routers running Tomato firmware; tested on FreshTomato v2018.4
STATIC-IP is an IP address suitable for your LAN; ex: 192.168.0.55
HOSTNAME is a local hostname for your server; using an unassigned TLD such as .home or .lan is recommended (avoid .local as it is reserved for use with mDNS); ex: mint-vm.home
Log in to your router
4.1 Set a static IP address
[Status] → [Device List] → (your VM) → [static]
Set a STATIC-IP address, [Add], [Save]
[Status] → [Device List] → (your VM) → (click on lease time to delete current lease)
Deleting the lease will expire the existing IP allocation
Reboot the Mint VM, then verify the static IP address is in use
4.2 Set a local hostname for the server
[Advanced] → [DHCP/DNS] → [Dnsmasq Custom Configuration]
local-ttl=1
address=/.HOSTNAME/STATIC-IP
[Save]
This allows any computer on your LAN to access the Mint VM via the host name HOSTNAME
or any subdomain *.HOSTNAME
5. Install server software
Inside the Mint VM, open terminal and run these commands
5.1 Prepare to install AMP
sudo apt update && sudo apt -y upgrade
sudo reboot
5.2 Install MariaDB SQL server
Find out what Ubuntu version your Mint OS is based on; we need the DISTRIB_CODENAME:
cat /etc/upstream-release/lsb-release
In my case, Linux Mint 21.2 is based on Ubuntu 22.04 “jammy
”. The MariaDB respository only supports particular versions, so keep an eye on any error message generated from the CURL command below.
We want to install a long-term support (LTS) release of MariaDB. Check the releases list, note the newest “long-term MariaDB stable release” version number, MARIADB-VERSION. As of this writing, the latest LTS version is 10.11
.
curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup | sudo bash -s -- --os-type=ubuntu --os-version=DISTRIB_CODENAME --mariadb-server-version="mariadb-MARIADB-VERSION"
sudo apt-get install mariadb-server mariadb-client -y
mysql -V
sudo service mariadb status | grep "Active:"
sudo mysql_secure_installation
Enter current password for root (enter for none): [press enter]
Switch to unix_socket authentication [Y/n]: N
Change the root password? [Y/n]: Y → SQLPASS → SQLPASS
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
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
Edit the line containing bind-address
:
bind-address = 0.0.0.0
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo service mariadb restart
5.3 Install Apache web server
sudo apt-get install apache2 apache2-utils -y
apache2 -v
sudo service apache2 status | grep "Active:"
Test Apache: Open Firefox, view http://localhost
5.4 Install PHP and extensions
Add the ondrej
repository for access to newer PHP versions, check available versions, then install PHP.
sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
apt-cache policy php
sudo apt-get install php php-common php-cli libapache2-mod-php -y
php -v
Install PHP extensions:
sudo apt-get install php-mysql php-mbstring php-curl php-xml php-intl php-gd php-imagick -y
sudo service apache2 restart
Test PHP:
sudo nano /var/www/html/phpinfo.php
<?php phpinfo(); ?>
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
Open Firefox, view http://localhost/phpinfo.php
5.5 Install phpMyAdmin and configure SQL user
sudo apt-get install phpmyadmin -y
when prompted for a webserver, press space to tick the box selecting apache2
when prompted to configure database, select yes
when prompted for MySQL password, enter SQLPASS
sudo mysql -uroot -pSQLPASS
DROP USER 'phpmyadmin'@'localhost';
CREATE USER 'SQLUSER'@'%' IDENTIFIED BY '';
GRANT ALL PRIVILEGES ON *.* TO 'SQLUSER'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
SELECT User,Host FROM mysql.user;
Ctrl+Z (to exit)
mysqladmin --user=SQLUSER password "SQLPASS"
sudo nano -w /etc/dbconfig-common/phpmyadmin.conf
Edit the line containing dbc_dbuser
:
dbc_dbuser='SQLUSER'
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo nano -w /etc/phpmyadmin/config-db.php
Edit the line containing $dbuser
:
$dbuser='SQLUSER';
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo service mysql restart
sudo service apache2 restart
Open Firefox, view http://localhost/phpmyadmin
Username: SQLUSER
Password: SQLPASS
5.6 Enable “nologin” user accounts
sudo nano /etc/shells
Append this line to the end of the file:
/usr/sbin/nologin
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
5.7 Set permissions on web folder
sudo adduser $USER www-data
sudo chown $USER:www-data -R /var/www
sudo chmod u=rwX,g=srwX,o=rX -R /var/www
sudo chmod 0664 /var/www/html/*
5.8 Allow .htaccess configuration in web folder
sudo nano -w /etc/apache2/apache2.conf
Inside configuration block <Directory /var/www/>
, alter the AllowOverride
line:
AllowOverride All
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo service apache2 restart
5.9 Enable mod_rewrite Apache module
sudo a2enmod rewrite
sudo service apache2 restart
5.10 Increase PHP upload and POST size limits
PHP defaults to 8 megabytes max POST size and 2 megabytes max file upload size. Changing these limits so they match can make debugging easier. Select a limit MAXUPLOAD megabytes that is suitable for your projects.
Note: the path below may require updating to match the installed PHP version.
sudo nano -w /etc/php/8.2/apache2/php.ini
Alter the line containing post_max_size
:
post_max_size = MAXUPLOADM
Alter the line containing upload_max_filesize
:
upload_max_filesize = MAXUPLOADM
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo service apache2 restart
5.11 Enable PHP error reporting
If you're using this server for development purposes, you will want to allow PHP to display errors. The display_errors
setting should be On
for development, and Off
for production/live servers.
Note: the path below may require updating to match the installed PHP version.
sudo nano -w /etc/php/8.2/apache2/php.ini
Alter the line containing display_errors
:
display_errors = On
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo service apache2 restart
Alternately, you can control this setting on a script-by-script basis by calling the PHP ini_set()
function:
ini_set ('display_errors', 'On');
Error reporting can be further controlled by the error_reporting
setting in php.ini
or the corresponding error_reporting()
function in your PHP script. For production I use a value of 0
, or (E_ALL | E_STRICT)
for development.
5.12 Clear command-line history and reboot
history -cw
sudo reboot
6. Install and configure Samba
6.1 Install Samba
sudo apt-get update
sudo apt-get install samba -y
6.2 Create Samba user
sudo useradd -s /usr/sbin/nologin SMBUSER
sudo passwd SMBUSER
when prompted for password, enter SMBPASS
sudo adduser SMBUSER www-data
sudo smbpasswd -a SMBUSER
when prompted for password, enter SMBPASS
sudo smbpasswd -e SMBUSER
6.3 Add network share
sudo nano -w /etc/samba/smb.conf
Append these configuration lines to the end of the file:
[www]
comment = Web Data
path = /var/www
guest ok = no
read only = no
writeable = yes
browseable = yes
valid users = +www-data
create mask = 0664
directory mask = 0775
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo service smbd restart
Validate your Samba configuration:
testparm -s /etc/samba/smb.conf
normalized configuration file is printed; look for error messages
6.4 Test network share
On Windows you may need to flush all open network connections to use new credentials; run this from a command prompt:
net use * /delete
From a Windows PC, connect to the Samba share:
Start Menu → Run → "\\mint-vm\www"
Username: SMBUSER
Password: SMBPASS
7. Configure Apache virtual hosts
* Configuration tested on Apache v2.4
* For detailed reference, refer to the Apache documentation:
* Refer to section 4 in this guide to define a local hostname
Enable multi-project hosting using Apache virtual hosts; this example configures 4 hosts: delta, gamma, phpmyadmin, and a default host:
delta.HOSTNAME |
/var/www/delta |
gamma.HOSTNAME |
/var/www/gamma |
phpmyadmin.HOSTNAME |
/usr/share/phpmyadmin |
HOSTNAME |
/var/www/www |
Note that in this configuration the default host is served for any request by IP address and any request to an unknown hostname. This behaviour has security implications: if your server becomes publicly-accessible, your default host might be served. Therefore we remove all admin-related content (such as phpMyAdmin) from this area.
In this example we keep no content on the default host; all real content is served from specific subdomains.
7.1 Remove default host access to phpMyAdmin
Since phpMyAdmin will be accessed under its own subdomain, we should remove it from the default host; this allows us to explicitly control who can access it:
sudo nano -w /etc/phpmyadmin/apache.conf
Comment out (prepend a #
character) this Alias
line:
#Alias /phpmyadmin /usr/share/phpmyadmin
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo service apache2 restart
phpMyAdmin can no longer be accessed from http://localhost/phpmyadmin
7.2 Change the default host's server name and document root
By default Apache serves web files from /var/www/html
; we change this directory to better integrate with a multi-host setup:
sudo nano -w /etc/apache2/sites-enabled/000-default.conf
Insert the following line at the top of the file:
ServerName HOSTNAME
This comment may be worth adding inside the <VirtualHost>
configuration block:
# This first virtual host definition becomes the default.
# Default is served for all requests not matching hosts below,
# including requests by IP and requests for undefined hosts.
Add a ServerAlias
line inside the <VirtualHost>
configuration block:
ServerAlias www.HOSTNAME
Change the DocumentRoot
line:
DocumentRoot "/var/www/www"
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
Delete the previous html
directory and create a new www
directory
WARNING: all files in /var/www/html
will be deleted!
rm -r /var/www/html
mkdir /var/www/www
Validate your configuration and restart the server:
apache2ctl configtest
sudo service apache2 restart
You may implement a website on the default host, however in this example setup we prefer to respond “404 Not Found” to all requests that don't match an expected virtual host subdomain:
nano /var/www/www/index.php
<?php
http_response_code (404);
header ('Content-Type: text/plain');
echo '404 Not Found';
die();
?>
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
Visiting any address that resolves to this server should now yield a 404 error, generated from /var/www/www/index.php
; for example:
http://localhost
http://STATIC-IP
http://HOSTNAME
http://www.HOSTNAME
http://any-undefined-subdomain.HOSTNAME
7.3 Reenable phpMyAdmin under a virtual host
sudo nano -w /etc/apache2/sites-enabled/000-default.conf
Append the following configuration block to the end of the file:
<VirtualHost *:80>
DocumentRoot "/usr/share/phpmyadmin"
ServerName phpmyadmin.HOSTNAME
ServerAlias *.phpmyadmin.HOSTNAME
</VirtualHost>
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
Validate your configuration and restart the server:
apache2ctl configtest
sudo service apache2 restart
Visiting http://phpmyadmin.HOSTNAME
now accesses phpMyAdmin
7.4 Add additional virtual hosts, as desired
This example sets up two projects, delta and gamma, each with their own hostname and server directory. In your configuration, you would instead use these placeholders as examples to configure your own projects.
mkdir /var/www/delta
mkdir /var/www/gamma
sudo nano -w /etc/apache2/sites-enabled/000-default.conf
Append the following configuration blocks to the end of the file:
<VirtualHost *:80>
DocumentRoot "/var/www/delta"
ServerName delta.HOSTNAME
ServerAlias *.delta.HOSTNAME
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "/var/www/gamma"
ServerName gamma.HOSTNAME
ServerAlias *.gamma.HOSTNAME
</VirtualHost>
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
Validate your configuration and restart the server:
apache2ctl configtest
sudo service apache2 restart
Access these sites via http://delta.HOSTNAME
and http://gamma.HOSTNAME
8. Create a database and limited SQL user
Tip: Match the database name, username, and password of the database from your online hosting provider when configuring this local database. Migrating projects between the two then involves only changing the host name of the database server.
Execute this SQL code from the phpMyAdmin [SQL] tab to create a database:
CREATE DATABASE `DBNAME` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Create a limited user who can only control this database:
CREATE USER 'DBUSER'@'%' IDENTIFIED WITH mysql_native_password AS '';
GRANT USAGE ON *.* TO 'DBUSER'@'%' REQUIRE NONE;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER,
CREATE TEMPORARY TABLES, CREATE VIEW, EVENT, TRIGGER, SHOW VIEW,
CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON `DBNAME`.* TO 'DBUSER'@'%';
phpMyAdmin → [Home] → [User accounts] → (DBUSER) → [Edit privileges] → [Change password]
Assign a password DBPASS to the database user
From PHP, this database can now be accessed through mysqli
or equivalent:
$db = new mysqli ('localhost', 'DBUSER', 'DBPASS', 'DBNAME');
Appendix A: Changing passwords
If you need to change an account password after initial setup, use the following procedures.
If you specify a password directly on the command-line, you can later clear the command-line history, for security:
history -cw
A.1 Linux User
sudo passwd VMUSER
sudo
may ask for a password; use OLD-VMPASS
when prompted for new UNIX password, enter NEW-VMPASS
sudo reboot
A.2 SQL User
mysqladmin --user=SQLUSER --password=OLD-SQLPASS password "NEW-SQLPASS"
sudo nano -w /etc/dbconfig-common/phpmyadmin.conf
Edit the line containing dbc_dbpass
:
dbc_dbpass='NEW-SQLPASS'
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo nano -w /etc/phpmyadmin/config-db.php
Edit the line containing $dbpass
:
$dbpass='NEW-SQLPASS';
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo service mysql restart
sudo service apache2 restart
A.3 Samba User
sudo passwd SMBUSER
sudo
may ask for a password; use VMPASS
when prompted for new UNIX password, enter NEW-SMBPASS
sudo smbpasswd SMBUSER
when prompted for password, enter NEW-SMBPASS
sudo service smbd restart
On Windows you may need to flush all open network connections to use new credentials; run this from a command prompt:
net use * /delete
Appendix B: Mount a network share for read/write access
Mount a network share in Linux: This allows your VM to read from and write to shared folders on your network.
Appendix C: Project-specific features
Install the escpos-php receipt printer library
Install and test the escpos-php
library: used for communicating with thermal receipt printers via the ESC/POS
protocol.
Additionally, if your printer does not natively support printing QR codes, you can add image-based QR code support to the escpos-php
library by integrating the PhpQrCode
library.
Install the PHP Simple HTML DOM Parser
Install the SimpleHtmlDom
library: This PHP library allows for exceptionally-easy web scraping and parsing of arbitrary HTML pages.
[end of guide]