Guide v5.12 / Updated 2020-07-19 / First published 2020-01-21 / 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.
After a few unsatisfactory experiments with running a WAMP stack on my laptop, I decided to dive in and configure a proper LAMP server on a Linux virtual machine. This approach was ideal since I already had a home server running UnRAID, which has great VM support.
This guide was written primarily for myself as I set up the VM and configured Linux, and installed/configured all the various features and settings that are important for my needs. There was a lot of trial-and-error to get everything working, so I wanted to ensure the “correct” procedures were captured somewhere. The guide grew to the point where it seemed sensible to share publicly in the hopes that others might find it helpful. Here it is.
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
Platform:
- Linux Mint Xfce 19.3
Server:
- Apache 2.4
- MySQL 5
- PHP 7.2
Additional features:
- phpMyAdmin 4.6
- ImageMagick 6.9 PHP plugin
- 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 Mint Xfce 64-bit ISO from https://www.linuxmint.com/download.php
Place the ISO file in UnRAID /mnt/user/isos
UnRAID [VMs] tab → [Add VM] → [Linux]
Name: Linux Mint Xfce
Initial Memory: 1024 MB
Max Memory: 1024 MB
OS Install ISO: [select downloaded ISO file]
Primary vDisk Size: 16G
[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
Install all available updates
Open [System Reports] from the tray (warning icon with exclamation mark)
[Ignore this problem] 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]
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 Install LAMP
sudo apt-get update && sudo apt-get dist-upgrade -y
sudo reboot
sudo apt-get install lamp-server^ -y
Test Apache: Open Firefox, view http://localhost
5.2 Test PHP
sudo nano /var/www/html/phpinfo.php
<?php phpinfo(); ?>
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
sudo service apache2 restart
Open Firefox, view http://localhost/phpinfo.php
5.3 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 'root'@'localhost';
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.4 Enable “nologin” user accounts
sudo nano /etc/shells
Append this line to the end of the file (no trailing newline):
/usr/sbin/nologin
Ctrl+O, Enter (to save)
Ctrl+X (to exit nano)
5.5 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.6 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.7 Enable mod_rewrite Apache module
sudo a2enmod rewrite
sudo service apache2 restart
5.8 Install ImageMagick plugin for PHP
sudo apt-get install php-imagick
sudo service apache2 restart
5.9 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/7.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.10 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/7.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.11 Reboot
sudo reboot
6. Install and configure Samba
6.1 Install Samba
sudo apt-get update
sudo apt-get install samba
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
Validate your network share:
smbtree
look for \\MINT-VM\www
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:
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: Add a USB expansion card & connect a thermal printer
Connect a thermal receipt printer to a Linux VM in UnRAID: this guide provides troubleshooting suggestions and solutions for connecting a USB printer to the VM. It also outlines how to add a USB expansion card for exclusive use of the virtual machine.
Appendix C: 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.
Appendix D: 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.
Appendix E: 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.
[end of guide]