Create A Local Network Web Server Virtual Machine Using Parallels And Ubuntu 20.04

Tutorial

A local network server is a server that cannot be accessed from the internet, only from the local network. A local network server is used for:

  • a development server

  • a test server

  • an internal production server

Preparation

  • Download the Ubuntu 20.04 Server image from the Ubuntu website.

  • You should have a MAC address and reserved IP address on your router for the virtual machine. In this case let's say the MAC address is BB:BB:DD:DD:02:04 and the reserved IP address is 10.0.5.204.

  • You should have a unique once in a lifetime domain name for your web server. This is the domain for the web server, not any website. In this process we will use this domain to display the default Apache website.

    ld5.mtfs.us

    There is domain should have a public DNS A record pointing to 10.0.5.204.

    Here's a page showing how Mattifesto sets up web server and website domains and IP addresses:

    https://devs.mattifesto.com/mattifesto-web-server-and-web-site-domain-name-strategy/

Create a new virtual machine in Parallels

  • In the Control Center window click the plus button on the right side of the title bar.

  • Select the "Install Windows or another OS from a DVD or image file" option in the Installation Assistant window.

  • Press the Continue button on the lower right of the window.  Select the Ubuntu 20.04 ISO file.

  • Check the "Install operating system manually" checkbox.

  • Press the Continue button.

  • Name and Location

    Name: enter the name of your server, which will be something like ld5.

    Check the "Customize settings before installation" checkbox.

    Press the Create button.

  • In the "<name>" Configuration window

    Select the "Options" tab.

    Select "Startup and Shutdown" in the left column

    Select "Custom"

    Start Automatically: When Mac starts

    Startup Delay: 15 sec

    Startup View: Headless

    Select "Sharing" in the left column

    Share folders: None

    For development servers:

    • Press the "Custom Folders..." button.

    • Press the "+" button.

    • Select the folder on your Mac that contains your Colby development website projects folders. For me it's "~/colby_websites".

    • Press the "OK" button.

    Un-check the "Share cloud folders with Linux" checkbox.

    Un-check the "Map Mac volumes to Linux"

    Select the "Hardware" tab.

    Select "CPU & Memory" in the left column.

    Processors: 1 (match DigitalOcean)

    Memory: 1024MB (match DigitalOcean)

    Select "Network" in the left column.

    Source: Default Adapter

    Press the "Advanced..." button.

    MAC: enter the MAC address you have reserved for this virtual machine.

    Press the "OK" button.

    Select "Hard Disk" in the left column.

    Press the "Advanced..." button.

    Press the "Properties..." button.

    Size: 25 GB (match DigitalOcean)

    When asked if you want to continue press the "Continue" button.

    Press the "Close" button.

    Press the "OK" button.

    Close the "<name>" Configuration window.

    Check the properties shown in the Virtual Machine Configuration panel and if correct, press the "Continue" button.

Install Ubuntu on the new virtual machine

  • Language Menu

    Select "English"

    Press return

  • Select "Install Ubuntu Server"

    Press return

    The Ubuntu install process will start.

  • Willkommen! panel

    Select "English"

    Press return

  • Installer update available panel

    If there are installer updates available select "Update to the new installer"

    Press return

  • Keyboard configuration panel

    Variant: If using a Mac change the Variant to "English (US) - English (Macintosh)"

    Press [ Done ]

  • Network connections

    Verify the a network connection with your MAC address and associated IP address shows up.

    Press [Done]

  • Configure proxy

    Select [ Done ]

  • Configure Ubuntu archive mirror

    Select [ Done ]

  • Guided storage configuration

    Select [ Done ]

  • Storage configuration

    Select [ Done ]

  • Confirm destructive action panel

    Select [ Continue ]

  • Profile setup panel

    Your name: enter your full name

    Your server's name: Use the ld5 name you used in the earlier step

    Pick a username: It's easiest to use the same username that you use on your workstation. You can the type "ssh ld5" from your workstation without specifying the username.

    Choose a password: It's easiest to use the same password that you use on your workstation if that is secure in your situation.

    Confirm your password: confirm password

    Select [ Done ]

  • SSH Setup panel

    Check the "Install OpenSSH server" option.

    Select [ Done ]

  • Featured Server Snaps panel

    Select [ Done ]

  • The Ubuntu install process will complete.

  • Let the "downloading and installing security updates" process finish.

  • Select / click the "Reboot Now" button.

  • It may complain about the Ubuntu disc being in the optical drive. It will most likely eject it. Verify that it has been ejected and press return.

  • Log in to the virtual machine for the first time.

  • Type: sudo shutdown now

Start the virtual machine and log in for the first time.

  • Click the power button for the virtual machine in Parallels Control Center.

  • Start the Terminal app in MacOS

  • $ ssh domain

    or

    $ ssh user@domain

    If you've recreated a server for the second time or greater you may get the message that the identification has changed. If you do you can fix it with this command and then trying again.

    $ ssh-keygen -R domain

    $ ssh-keygen -R ipaddress

Update and Setup Parallels Tools

Install Software

The following command disables IPv6 until reboot which is necessary to speed up the commands to add repositories:

$ sudo sysctl net.ipv6.conf.all.disable_ipv6=1

$ sudo apt install software-properties-common

$ sudo add-apt-repository ppa:ondrej/apache2

$ sudo add-apt-repository ppa:ondrej/php

$ sudo apt install ack apache2 libapache2-mod-php8.0 libapache2-mpm-itk mysql-server php8.0 php8.0-curl php8.0-imagick php8.0-mysql php8.0-gd php8.0-mbstring php8.0-xml

$ sudo apt update

$ sudo apt upgrade

$ sudo update-alternatives --config php

Select PHP version 8.0

Install Composer

The DigitalOcean website has good instructions for this task here.

Setup Firewall

From: https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-20-04

  • $ sudo ufw allow OpenSSH

  • $ sudo ufw enable

  • $ sudo ufw status

Setup Apache

From: https://www.digitalocean.com/community/tutorials/how-to-install-linux-apache-mysql-php-lamp-stack-on-ubuntu-20-04

  • $ sudo vi /etc/ufw/applications.d/apache2-server

    [Apache Full]
         title=<title>
         description=<description>
         ports=80/tcp|443/tcp
    
  • $ sudo ufw allow "Apache Full"

  • $ sudo a2enmod ssl

  • $ sudo a2enmod rewrite

  • DON'T DO THIS STEP UNLESS NOT USING ITK

    $ sudo vi /etc/apache2/envvars

    We are going to place the document roots for all the websites in your home directory and the only user with websites on this machine is you.

    Change:

    export APACHE_RUN_USER=www-data

    to:

    export APACHE_RUN_USER=mattcalkins

    :wq

  • $ sudo vi /etc/apache2/conf-available/servername.conf

    This file should have a single line:

    ServerName ld5.mtfs.us

    :wq

  • $ sudo a2enconf servername

  • Fix issue that makes Apache stop

    Note: Appears to be related to using SSL on Ubuntu. More information not available. Update if more is discovered.

    Reference: https://stackoverflow.com/questions/50652808/apache-shutdown-couldnt-grab-mutex

    • $ sudo vi /etc/apache2/conf-available/mutex-file.conf

    • This file should contain a single line:

      Mutex file:${APACHE_LOCK_DIR} default

    • $ sudo a2enconf mutex-file

  • $ sudo apache2ctl configtest

    If there are any unclear issues with the configtest, this command can help you find out exactly what is causing them:

    $ sudo apache2ctl -t -D DUMP_INCLUDES

  • $ sudo systemctl restart apache2

  • Go to http://ld5.mtfs.us to make sure apache is working.

Create SSL Certificate Using acme.sh

https://github.com/acmesh-official/acme.sh

https://github.com/acmesh-official/acme.sh/wiki/How-to-install

$ curl https://get.acme.sh | sh -s email=my@example.com

$ exit

$ ssh <virtual server domain>

Create or renew certificate.

Strategy

For private web servers, SSL certificates must be created manually. It is most convenient on private servers to create a wildcard certificate so that you don't have to create and renew multiple certificates for each website hosted on the web server.

We create a two domain certificate. The first domain is the domain of the server, ld5.mtfs.us, and the second domain is the wildcard domain, *.ld5.mtfs.us. Websites hosted on the server should add a single name to the domain such as, media.ld5.mtfs.us, and will not require any additional certificate to be created.

Required

Your domain must publicly point to an IP address or a CNAME that directs to a domain that points to an IP address. It's fine if the IP address is only locally available.

Create SSL Certificate

  • Go to https://github.com/acmesh-official/acme.sh/wiki/dnsapi which will provide you with instructions on how to export the appropriate variable for your DNS provider such as :

    $ export DH_API_KEY="<api key>"

    or

    $ export DO_API_KEY="<api key>"

  • The web page link above will also provide you with the correct <provider> name to use in the command below:

    $ acme.sh --issue --dns dns_dgon|dns_dreamhost -d 'ld5.mtfs.us' -d '*.ld5.mtfs.us'

    2021_04_22 When I'm using DigitalOcean as my DNS provider I don't need to specify "---dnssleep 120". When I use DreamHost as my DNS provider I do. For multiple reasons I am moving most services from DreamHost to DigitalOcean.

    I have at times used this command without the dnssleep option, and at times it has worked, but even when the TXT record can be seen by running dig on this virtual machine, the acme process will still not see it.

    So the dnssleep option usually is a workaround to this issue but not always. This process should be easy, but it's not currently, but if you just keep trying it will work.

    Also, make sure you don't have typos in your domain names. (Made that mistake before.)

  • We are going to update the default virtual host to support SSL to verify our certificate.

    $ sudo vi /etc/apache2/sites-available/000-default.conf

  • Copy the <VirtualHost *:80> section and paste it below itself.

  • Alter the copy to use port 443 instead of port 80.

  • Copy the following lines into the end of the virtual host block:

    SSLEngine               on
    SSLCertificateFile      /home/mattcalkins/.acme.sh/ld5.mtfs.us/ld5.mtfs.us.cer
    SSLCertificateKeyFile   /home/mattcalkins/.acme.sh/ld5.mtfs.us/ld5.mtfs.us.key
    
  • $ sudo apache2ctl configtest

  • $ sudo systemctl restart apache2

  • Go to https://ld5.mtfs.us to make sure the SSL certificate is working.

Setup MySQL

  • $ sudo mysql_secure_installation

    Basically answer yes to everything.

Configure PHP

  • webserver$ sudo cp /etc/php/8.0/apache2/php.ini /etc/php/8.0/apache2/php.ini.<today's date>

  • webserver$ sudo vi /etc/php/8.0/apache2/php.ini

  • Find and alter the following properties.

    post_max_size = 65M
    upload_max_filesize = 64M
    date.timezone = 'UTC'
    

    If this is a development server, also find and alter the following property.

    zend.assertions = 1
    
  • :wq

  • webserver$ sudo systemctl restart apache2

Fix Gmail IPv6 Issue

$ sudo reboot

Reboot and login again to re-enable IPv6.

$ ping smtp.gmail.com

If this works fine, you don't have issues and can move on from this section.

If this ping command doesn't work it means there is an issue with gmail and IPv6 on your server which will prevent your website from sending email. I do not currently know what causes this issue, but I do know how to fix it:

$ nslookup smtp.gmail.com

Copy the IPv4 address from the result.

$ sudo vi /etc/hosts

Add the following line to this file using the IPv4 address you copied:

xxx.xxx.xxx.xxx smtp.gmail.com

After saving the ping command should work.

$ ping smtp.gmail.com

Setup GitHub SSH

NOTE 2022_01_03

  • This is not needed for development virtual machines.

  • This is only needed for private repositories.

  • We generally make a machine account and give it access.

  • The instructions below are wonky and unclear. Adjust as you can.

NOTE: this should be done per user account in the new user method of apache. Create one machine account on github but add the ssh keys for any user that has private access OR SOMETHING I'M NOT SURE

This step is only required for private GitHub repositories.

If you have private GitHub repositories you will need to authenticate with GitHub using SSH keys.

This link tells you more about this process.

https://docs.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent

If you have your keys on your dev machine but just created a new virtual machine these instructions help you copy them to the new VM.

In MacOS terminal signed in to Mac:

  • $ scp -r <key directory> webserver1:~

In MacOS terminal sign in to server VM:

  • move keys to .ssh directory

  • $ eval "$(ssh-agent -s)"

  • $ ssh-add <key name>