How To Configure a DNS Proxy on Ubuntu 22.04

Introduction

As you know it all begins with a story. My story is I didn’t want my DNS server directly connected to the internet. I wanted something basic and easy to use.

Say hello to dnsproxy. Its a basic and easy to use DNS proxy. Lets walk through the easy setup. I’ve even provided a script to help with setup. This setup relies on your server having a private IP address and a public IP address.

The Steps

Let’s start by updating Ubuntu. Hopefully you always update before installing new software.
> sudo apt update && sudo apt upgrade -y

Install dnsproxy.
> sudo apt install dnsproxy -y

Create /etc/dnsproxy.conf using the template below. There are place holders in ALL CAPS to highlight what you need to change.

# dnsproxy configuration file for Debian

# Authoritative server
# authoritative 192.168.1.2
authoritative YOUR_DNS_SERVER_IP
authoritative-port 53 # It's port. Defaults to 53.
authoritative-timeout 10 # Seconds to wait for answers.

# Recursive resolver
# recursive 192.168.1.2
recursive YOUR_DNS_SERVER_IP
recursive-port 53 # It's port. Defaults to 53.
recursive-timeout 90 # Seconds to wait for answers.

# Local addresses and ports of dnsproxy
# address and UDP port that dnsproxy use to communicate with users
# listen 8.9.1.2
listen YOUR_PUBLIC_IP
port 53

# address and UDP port that dnsproxy use to communicate with DNS servers.
# if your DNS servers are accessed by different network interfaces, you must
# use 0.0.0.0 as listen_answer. But if they are accessed by the same network
# interface, just set it to the IP address that you have on that interface.
listen_answer 0.0.0.0
port_answer 53003

# Security features
chroot /var/spool/dnsproxy
user dnsproxy

# Internal networks (allowed to do recursive queries)
internal 192.168.0.0/16 # Our internal network
internal 172.16.0.0/12 # Another internal network
internal 10.0.0.0/8 # Friendly neighbours
internal 127.0.0.1
internal YOUR_PRIVATE_IP # Private network
internal YOUR_PUBLIC_IP # Public IP considered as internal

Now start dnsproxy.
> sudo systemctl start dnsproxy

Test that everything is working.

Finally configure dnsproxy to start at boot.
> sudo systemctl enable dnsproxy

A Script To Make Things Easier

I’ve provided a script below that will help you set everything up.

#!/bin/bash
#
# This script sets up dnsproxy on a server.
# The server needs a private and a public network interface
#

#
# Variables
#
config_file="/etc/dnsproxy.conf"

#
# Functions
#

# Function to validate IP address
validate_ip() {
  local ip=$1
  local stat=1

  if [[ $ip =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
    OIFS=$IFS
    IFS='.'
    ip=($ip)
    IFS=$OIFS
    if [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]; then
      stat=0
    fi
  fi
  return $stat
}

#
# Main Script Start
#

# Check if the script is running as root
if [ "$EUID" -ne 0 ]; then
  echo "This script must be run as root. Please run it with sudo or as root."
  exit 1
fi

# Introduction message
echo "This script will create a dnsproxy.conf file for configuring DNS Proxy."
echo "It will also check if dnsproxy is installed, back up any existing config file, and manage the dnsproxy service."
echo ""
read -p "Do you want to continue? (y/n): " continue_script
if [[ $continue_script != "y" && $continue_script != "Y" ]]; then
  echo "Exiting script."
  exit 0
fi

# Check if dnsproxy is installed
if ! command -v dnsproxy &> /dev/null; then
  echo "dnsproxy is not installed."
  read -p "Do you want to install dnsproxy? (y/n): " install_dnsproxy
  if [[ $install_dnsproxy == "y" || $install_dnsproxy == "Y" ]]; then
    echo "Installing dnsproxy..."
    if ! sudo apt-get update && sudo apt-get install -y dnsproxy; then
      echo "Failed to install dnsproxy. Continuing without it..."
    fi
  else
    echo "Continuing without installing dnsproxy..."
  fi
fi

# Prompt for public interface IP
default_public_ip="8.9.1.2"
while true; do
  read -p "Enter the public interface IP address [default: $default_public_ip]: " public_ip
  public_ip=${public_ip:-$default_public_ip}
  validate_ip $public_ip
  if [[ $? -eq 0 ]]; then
    break
  else
    echo "Invalid IP address. Please enter a valid IP address."
  fi
done

# Prompt for private interface IP
default_private_ip="192.168.1.2"
while true; do
  read -p "Enter the private interface IP address [default: $default_private_ip]: " private_ip
  private_ip=${private_ip:-$default_private_ip}
  validate_ip $private_ip
  if [[ $? -eq 0 ]]; then
    break
  else
    echo "Invalid IP address. Please enter a valid IP address."
  fi
done

# Prompt for authoritative DNS server IP
while true; do
  read -p "Enter the IP address of the authoritative DNS server: " auth_dns_ip
  validate_ip $auth_dns_ip
  if [[ $? -eq 0 ]]; then
    break
  else
    echo "Invalid IP address. Please enter a valid IP address."
  fi
done

# Prompt for recursive DNS server IP
while true; do
  read -p "Enter the IP address of the recursive DNS server: " rec_dns_ip
  validate_ip $rec_dns_ip
  if [[ $? -eq 0 ]]; then
    break
  else
    echo "Invalid IP address. Please enter a valid IP address."
  fi
done

# Backup existing config file if it exists
if [ -f "$config_file" ]; then
  timestamp=$(date +%Y%m%d%H%M%S)
  backup_file="${config_file}.${timestamp}.bak"
  cp "$config_file" "$backup_file"
  echo "Existing config file backed up as $backup_file"
fi

# Create dnsproxy.conf file
cat < $config_file
# dnsproxy configuration file example for Debian

# Authoritative server
authoritative        $auth_dns_ip
authoritative-port   53              # It's port. Defaults to 53.
authoritative-timeout 10             # Seconds to wait for answers.

# Recursive resolver
recursive            $rec_dns_ip
recursive-port       53              # It's port. Defaults to 53.
recursive-timeout    90              # Seconds to wait for answers.

# Local addresses and ports of dnsproxy
# address and UDP port that dnsproxy use to communicate with users
listen $public_ip
port 53

# address and UDP port that dnsproxy use to communicate with DNS servers.
# if your DNS servers are accessed by different network interfaces, you must
# use 0.0.0.0 as listen_answer. But if they are accessed by the same network
# interface, just set it to the IP address that you have on that interface.
listen_answer 0.0.0.0
port_answer 53003

# Security features
chroot /var/spool/dnsproxy
user dnsproxy

# Internal networks (allowed to do recursive queries)
internal 192.168.0.0/16          # Our internal network
internal 172.16.0.0/12           # Another internal network
internal 10.0.0.0/8              # Friendly neighbours
internal 127.0.0.1
internal $private_ip             # Private network
internal $public_ip              # Public IP considered as internal
EOF

echo "dnsproxy.conf file created successfully."

# Check if dnsproxy is running
if pgrep dnsproxy > /dev/null; then
  echo "dnsproxy is currently running. Restarting it..."
  sudo systemctl restart dnsproxy
  echo "dnsproxy has been restarted."
else
  read -p "dnsproxy is not running. Do you want to start it? (y/n): " start_dnsproxy
  if [[ $start_dnsproxy == "y" || $start_dnsproxy == "Y" ]]; then
    echo "Starting dnsproxy..."
    sudo systemctl start dnsproxy
    sudo systemctl enable dnsproxy
    echo "dnsproxy has been started and set to start on boot."
  else
    echo "dnsproxy was not started."
  fi
fi

# Script end
echo "dnsproxy setup complete."
exit 0

You can create an empty file for pasting the script into.
> nano -w setup_dnsproxy.sh

Copy the script from the website and paste it into nano. When done exit namo and save changes.

Use the following command to run the script.
> sudo bash setup_dnsproxy.sh

Conclusion

That’s it! A quick and easy DNS proxy setup.

Ubuntu 22.04 – Extending the root partition

Introduction

I run several virtual machines based on Ubuntu. I create a base image that is cloned when I need a new virtual machine. Since most of my VMs don’t need a large disk image I keep the base image on the small side. So I extend the size of the disk image when needed. After the disk image size is increased you need to allocate that space to use it. The steps below will show you how to extend the root partition to the new size.

The Steps

I’m assuming that the disk image or physical hard drive of the machine has been increased.

Do a df -h to get the logical volume name of the partition you want to extend.
> df -h

Filesystem                        Size Used Avail Use% Mounted on
tmpfs                             393M 1.1M  392M   1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv  24G 9.0G   14G  41% /
tmpfs                             2.0G    0  2.0G   0% /dev/shm
tmpfs                             5.0M    0  5.0M   0% /run/lock
/dev/sda2                         2.0G 367M  1.5G  21% /boot
tmpfs                             393M 4.0K  393M   1% /run/user/1000

Now check to be sure the volume group has free space. The free space is the possible max amount you can extend the partition.
> vgdisplay

With the information above I can expand the partition 23G. Here’s the command I would use.
> sudo lvextend -L +23G /dev/mapper/ubuntu–vg-ubuntu–lv

Finally we extend the filesystem to the new logical volume size.
> sudo resize2fs /dev/mapper/ubuntu–vg-ubuntu–lv                     

Now that we’re done, lets reboot the system.
> sudo reboot

Log back into the ubuntu system. Check that your partition has been extended.
> df -h

Conclusion

Thanks to LVM the process of extending the root partition is simple and straight forward.

HOWTO Ubuntu 22.04 Virtual Web Hosting With Apache, PHP, vsFTPD and Let’s Encrypt

Introduction

The focus of this howto is for those users who need to host their own domains and maybe a few customer domains. This is not aimed at being used for mass web hosting.

There are many ways to do virtual websites under linux. The technique I am going to use is multiple domains on one ip address. I’m using standard linux users to log into the virtual domains.

Setting Up The Base Server

For a dedicated server start with the base server setup:

Howto Ubuntu 22.04 Base Server Setup

Introduction All of our servers will start with this install. This base server is based on Ubuntu 22.04 LTS Server.  I don’t explain much in the howto so if you have a question leave a comment or use Google. Downloading … Continue reading

NOTE: If you don’t follow the base server setup then you may run into problems with this howto.

Install Software

We need to install an FTP server and Let’s Encrypt. So type the following:
> sudo add-apt-repository ppa:certbot/certbot
> sudo apt update
> sudo apt install vsftpd python3-certbot-apache

Setup Default User Directory

A new user’s directory needs to have some files and folders created for them.  We will modify the user skel directory so when a new user is created the required folder structure will be there.

Type the following.
> sudo mkdir -p /etc/skel/{website,logs,cgi-bin,backup}
> sudo echo “HELLO WORLD” > index.html
> sudo mv index.html /etc/skel/website/

Configuring vsftpd

Lets create the configuration file.  Replace the contents of /etc/vsftpd.conf with the text below.

listen=NO
listen_ipv6=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
#local_umask=022
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
chroot_local_user=YES
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
ssl_enable=NO
allow_writeable_chroot=YES
pasv_enable=Yes
pasv_min_port=40000
pasv_max_port=40100

Start vsftpd.
> sudo systemctl enable vsftpd
> sudo systemctl start vsftpd.service

Configuring Apache

Most of the apache configuration is already done.  We are going to do some changes to make managing websites easier.

Create the virtual host config file. I defined macros to make virtual host creation easier.  I also turn on compression. Create /etc/apache2/conf-available/virtual.conf with the following:

# Go ahead and accept connections for these vhosts
# from non-SNI clients
SSLStrictSNIVHostCheck off

# define a macro for the virtual hosts
# the user's directory should be setup as follows:
# |- cgi-bin
# |- logs
# |- website
# |- ssl
#
LoadModule macro_module modules/mod_macro.so

<Macro virtHost $type $user $host>
    use $type $host

    ServerName $host
    ServerAlias www.$host 
    DocumentRoot /home/$user/website
    ScriptAlias "/cgi-bin/" "/home/$user/cgi-bin"
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    CustomLog /home/$user/logs/access_log common
    ErrorLog /home/$user/logs/error_log
    <Directory /home/$user/website>
      DirectoryIndex index.html index.php
      Options Indexes FollowSymLinks
      AllowOverride All
      Require all granted

      # setup file compression
      use CompressFiles

      # setup browser caching
      use BrowserCache

      # disable hotlinking for some files
      use DisableHotLink $host
    </Directory>
  </VirtualHost>
</Macro>

<Macro BrowserCache>
  # Enable expires cache
  <IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "access 1 month"
    ExpiresByType text/html "access 1 month"
    ExpiresByType image/gif "access 1 year"
    ExpiresByType image/png "access 1 year"
    ExpiresByType image/jpg "access 1 year"
    ExpiresByType image/jpeg "access 1 year"
    ExpiresByType image/x-icon "access 1 year"
    ExpiresByType application/pdf "access 1 month"
    ExpiresByType application/javascript "access 1 month"
    ExpiresByType text/x-javascript "access 1 month"
    ExpiresDefault "access 1 month"
  </IfModule>

  # Cache-Control Headers
  <ifModule mod_headers.c>
    <filesMatch "\.(ico|jpe?g|png|gif|swf)$">
      Header set Cache-Control "public"
    </filesMatch>
    <filesMatch "\.(css)$">
      Header set Cache-Control "public"
    </filesMatch>
    <filesMatch "\.(js)$">
      Header set Cache-Control "private"
    </filesMatch>
    <filesMatch "\.(x?html?|php)$">
      Header set Cache-Control "private, must-revalidate"
    </filesMatch>
  </ifModule>
</Macro>

<Macro CompressFiles>
  # enable compression
  <IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE "application/atom+xml"
    AddOutputFilterByType DEFLATE "application/javascript"
    AddOutputFilterByType DEFLATE "application/json"
    AddOutputFilterByType DEFLATE "application/ld+json"
    AddOutputFilterByType DEFLATE "application/manifest+json"
    AddOutputFilterByType DEFLATE "application/rdf+xml"
    AddOutputFilterByType DEFLATE "application/rss+xml"
    AddOutputFilterByType DEFLATE "application/schema+json"
    AddOutputFilterByType DEFLATE "application/vnd.geo+json"
    AddOutputFilterByType DEFLATE "application/vnd.ms-fontobject"
    AddOutputFilterByType DEFLATE "application/x-font"
    AddOutputFilterByType DEFLATE "application/x-font-opentype"
    AddOutputFilterByType DEFLATE "application/x-font-otf"
    AddOutputFilterByType DEFLATE "application/x-font-truetype"
    AddOutputFilterByType DEFLATE "application/x-font-ttf"
    AddOutputFilterByType DEFLATE "application/x-javascript"
    AddOutputFilterByType DEFLATE "application/x-web-app-manifest+json"
    AddOutputFilterByType DEFLATE "application/xhtml+xml"
    AddOutputFilterByType DEFLATE "application/xml"
    AddOutputFilterByType DEFLATE "font/eot"
    AddOutputFilterByType DEFLATE "font/otf"
    AddOutputFilterByType DEFLATE "font/ttf"
    AddOutputFilterByType DEFLATE "font/opentype"
    AddOutputFilterByType DEFLATE "image/bmp"
    AddOutputFilterByType DEFLATE "image/svg+xml"
    AddOutputFilterByType DEFLATE "image/vnd.microsoft.icon"
    AddOutputFilterByType DEFLATE "image/x-icon"
    AddOutputFilterByType DEFLATE "text/cache-manifest"
    AddOutputFilterByType DEFLATE "text/css"
    AddOutputFilterByType DEFLATE "text/html"
    AddOutputFilterByType DEFLATE "text/javascript"
    AddOutputFilterByType DEFLATE "text/plain"
    AddOutputFilterByType DEFLATE "text/vcard"
    AddOutputFilterByType DEFLATE "text/vnd.rim.location.xloc"
    AddOutputFilterByType DEFLATE "text/vtt"
    AddOutputFilterByType DEFLATE "text/x-component"
    AddOutputFilterByType DEFLATE "text/x-cross-domain-policy"
    AddOutputFilterByType DEFLATE "text/xml"
  </IfModule>
</Macro>

<Macro DisableHotLink $host >
  # Disable file hotlinking - jpg jpeg png gif pdf
  <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{HTTP_REFERER} !^$
    RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?$host [NC]
    RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?google.com [NC]
    RewriteRule \.(jpg|jpeg|png|gif|pdf)$ – [NC,F,L]
  </IfModule>
</macro>

<Macro VHost443 $host >
  <VirtualHost *:443>
    SSLEngine on
    SSLProtocol all -SSLv2
    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
    SSLCertificateFile /etc/letsencrypt/live/$host/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/$host/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/$host/fullchain.pem
</Macro>

<Macro VHost80 $host >
  <VirtualHost *:80>
</Macro>

Enable the configuration.
> sudo a2enconf virtual

Enable macros and ssl.
> sudo a2enmod macro
> sudo a2enmod ssl

Restart apache
> sudo service apache2 restart

Configuring Let’s Encrypt

Let’s Encrypt needs to be configured to auto renew certs. Lets create a daily cron job
> sudo nano -w /etc/cron.daily/letsencrypt

#!/usr/bin/bash
# letsencrypt auto renew
/usr/bin/certbot renew --no-self-upgrade >> /var/log/le-renew.log

Adding a Default Website

Now we will create a default website.  This site will be used when no other website can be found.

Setup a DNS record for the new domain. I won’t cover this here.

Add a user. This user will be associated with the new domain name. Type the following.
> sudo useradd -m -U -s /bin/bash -c “default website” defaultweb
> sudo passwd defaultweb

Add the apache user to the new user’s group.
> sudo usermod -a -G defaultweb www-data

Update directory permissions.
> sudo chmod g+rwx /home/defaultweb
> sudo chown -R defaultweb:defaultweb /home/defaultweb

Create the virtual host file.  For the default server we will use port 80. Past the text below into the file.  Type:
> sudo nano -w /etc/apache2/sites-available/00-default.conf

# Virtual host config file
#
# MACRO FORMAT
# virtHost [type] [user] [host]
#  type = VHost80 or VHost443
#  user = the username of the website
#  host = domain name or virtual host name
#
# Use the line below to configure a site on port 80
use virtHost VHost80 defaultweb myserver.mydomain.tld

# Uncomment the line below once lets encrypt is setup
# use virtHost VHost443 defaultweb myserver.mydomain.tld

Disable the old default site and enable our default site.
> sudo a2dissite 000-default
> sudo a2ensite 00-default

Reload apache config
> sudo service apache2 reload

Test out the new website.  You should get a page that says ‘Hello World’.

Now we will setup lets encrypt for the default website.  The website must be reachable from the internet.  So lets get the cert:
> sudo certbot certonly –webroot -w /home/defaultweb/website/ -d <YOUR_DOMAIN> –email <YOUR_EMAIL_ADDRESS> –agree-tos

Edit /etc/httpd/virtualHosts.d/00-default.conf
Uncomment the last line to enable ssl connections for the virtual host.

Reload apache.
> sudo service apache2 reload

Test it out.  Connect to your default host via https.

Setup Additional Virtual Hosts

Adding a new virtual host is like adding the default virtual host.  Lets go through the steps.

Be sure DNS is configured for the new virtual host.

Setup a new user. This user will be associated with the new domain name. Type the following. Change ‘NEWUSER’ to the username you want.
> sudo useradd -m -U -s /bin/bash -c “Virtual Website User” NEWUSER
> sudo passwd NEWUSER
> sudo usermod -a -G NEWUSER www-data
> sudo chmod g+rwx /home/NEWUSER
> sudo chown -R NEWUSER:NEWUSER /home/NEWUSER

Create the virtual host file.  For the virtual server we will use port 80. Past the text below into the file.  Replace ‘NEWUSER’ with your user name.  Replace NEWVHOST with your hostname.
> sudo nano -w /etc/apache2/sites-available/NEWUSER.conf

# Virtual host config file
#
# MACRO FORMAT
# virtHost [type] [user] [host]
#  type = VHost80 or VHost443
#  user = the username of the website
#  host = domain name or virtual host name
#
# Use the line below to configure a site on port 80
use virtHost VHost80 NEWUSER NEWVHOST

# Uncomment the line below once lets encrypt is setup
# use virtHost VHost443 NEWUSER NEWVHOST

Enable the new site and reload apache config
> sudo a2ensite NEWUSER
> sudo service apache2 reload

Now we will setup lets encrypt for the new website.  The website must be reachable from the internet.  Replace NEWUSER and NEWVHOST with the info you have.  So lets get the cert.
> sudo certbot certonly –webroot -w /home/NEWUSER/website/ -d NEWHOST -d www.NEWHOST –email YOUR_EMAIL_ADDRESS –agree-tos

Edit /etc/httpd/virtualHosts.d/NEWUSER.conf
Uncomment the last line to enable ssl connections for the virtual host.

Reload apache.
> sudo service apache2 reload

Test it out.  Connect to your new host via https.

Conclusion

That’s the complete setup.

Howto Ubuntu 22.04 Base Server Setup

Introduction

All of our servers will start with this install. This base server is based on Ubuntu 22.04 LTS Server.  I don’t explain much in the howto so if you have a question leave a comment or use Google.

Downloading the ISO

Visit the Ubuntu website and download the ubuntu 22.04 server ISO.

Initial Install

The install screens are straight forward.  I’m not going to cover them in much detail.  Unless you need to customize a setting, just choose the default settings.  Boot the install DVD.

Click ‘Reboot’ when it appears.

First boot

Reboot the machine when the install finishes.
The OS will boot. Log in. All the commands need to be run as root so lets start a shell with root privilleges.
> sudo bash

Get everything updated and install a couple of items.
> sudo apt update
> sudo apt dist-upgrade
> sudo apt install software-properties-common

Install and enable ssh.
> sudo apt install ssh
> sudo systemctl enable –now ssh

WARNING: My server isn’t directly connected to the internet. The firewall is disabled to help with installation, configuration and testing easier. Once everything is working, turn on the firewall and configure it. I wil remind you to secure your server at the end of this howto.

now reboot the server.

The Second Boot – Installing Additional Packages

We need quite a few other packages. In this howto I’m installing packages regardless if they were already installed by another dependency. This guards against package changes that could cause a package to not be installed. Once again log in to your server.

Let’s add a 3rd party repo for Apache.
> add-apt-repository ppa:ondrej/apache2

Add a 3rd party repo for PHP.
> sudo add-apt-repository ppa:ondrej/php

Now bring everything up to date.
> sudo apt update && sudo apt upgrade

Install the following packages. Multiple lines to make cut and paste easier.
> sudo apt install make screen snmp composer libcurl4 unzip net-tools
> sudo apt install apache2 libapache2-mod-php mysql-server mysql-client
> sudo apt install libapache2-mod-fcgid php8.2-opcache php-apcu

Install some extra PHP libraries.
> sudo apt install php-gd php-snmp php-mbstring php-mysql
> sudo apt install php-odbc php-imap
> sudo apt install php-xmlrpc php8.2-dba
> sudo apt install php-soap php-zip php-intl php-curl

Configure Apache and PHP

Enable the rewrite module.
> sudo a2enmod rewrite actions fcgid alias proxy_fcgi expires headers

Enable Apache.
> sudo systemctl enable apache2.service

Reload apache.
> sudo systemctl restart apache2.service

Configuring MySQL

We need to set the root password in mysql. so type:
> sudo mysql

Set the root password for mysql.
mysql> ALTER USER ‘root’@’localhost’ IDENTIFIED WITH mysql_native_password by ‘my-secret-password’;
mysql> exit

Configure mysql.
> sudo mysql_secure_installation

Installing and Configuring phpMyAdmin

I prefer to phpMyAdmin to manage my MySQL databases.

Now install phpMyAdmin.
> sudo apt install phpmyadmin

Restart Apache.
> sudo systemctl restart apache2.service

NOTE: You should think about limiting access to phpMyAdmin. This will help secure your server.

Installing Postfix

Lets install postfix.
> sudo apt install postfix

When prompted select internet site. Next set the mail server name.

Installing cockpit

I’m using cockpit as my server admin tool.  Do the following to set it up.
> sudo apt install cockpit
> sudo systemctl start cockpit
> sudo systemctl enable cockpit.socket

You can now login to https://yourserver.tld:9090 to administer your server.

NOTE: You should limit access to this service.

Getting root’s and other’s mail

You need to get some local system user’s mail. We’ll use postfix’s virtual file to get the emails to the right place.

Add the following to /etc/postfix/virtual

root admin@yourdomain.tld
postmaster admin@yourdomain.tld
abuse admin@yourdomain.tld

Now add the configuration option to main.cf
> sudo postconf -e “virtual_alias_maps = hash:/etc/postfix/virtual”

Just a couple commands to wrap everything up.
> sudo postmap /etc/postfix/virtual
> sudo systemctl restart postfix
> sudo systemctl enable postfix

Remove Cloud Init

Our server won’t be using cloud-init.  To keep from causing you trouble in the future we will remove it now.

Type:
> sudo apt remove cloud-init cloud-initramfs-copymods cloud-initramfs-dyn-netconf

Final Settings

You may want to enable the linux firewall.
Set your timezone in /etc/php.ini

Conclusion

That’s it for the basic server setup. This is an example of a standard linux server setup. Be sure to use cockpit to set which services you want to start at boot time. See the other pages for info on configuring servers for virtual webhosting or virtual email hosting. Remember to configure the firewall on the server.

HOWTO: Change Thin LVM to Directory Storage in Proxmox 7.x

Introduction

In Proxmox 7.x LVM thin is the default local storage for VMs.  However I prefer the old method of directory based storage for local storage.  You can find this information in the proxmox wiki.  These are my terse notes to get the job done.

The Conversion

This should only be done on a new installation of proxmox.  We will be mounting the storage to /var/lib/vz. If you have data in that directory you will lose it.

Start by logging into the Proxmox gui. Click on cluster then select storage. Remove the lvm-thin storage.

Next you will need to ssh into your Proxmox node. Type the following to set everything up.
> sudo lvremove pve/data
> sudo lvcreate –name data -l +100%FREE pve
> sudo mkfs.ext4 /dev/pve/data

Add the following to /etc/fstab
> nano -w /etc/fstab

/dev/pve/data /var/lib/vz ext4 defaults 0 1

Restart proxmox.
> sudo reboot

Conclusion

Once rebooted you can log into the gui and see your new local directory storage.  Maybe someday I’ll switch to lvm-thin or zfs.

Configure Proxmox 7.x for a Low Power Home Server

Introduction

I’ve been using low power CPUs for some time. This has caused some issues when I’ve needed more CPU processing power. My goal is to move to more power hungry CPUs but still try and save power. To this end I decided to change the CPU governor Proxmox uses. I also switched to using a small form factor case with its lower power power supply.

Configure CPU for Low Power

To make these changes you’ll need to ssh into your proxmox host.

Lat’s start by looking at your current CPU freequency.
> cat /proc/cpuinfo | grep MHz

The above command returns the following for my server.

cpu MHz : 3800.000
cpu MHz : 1760.822
cpu MHz : 3800.000
cpu MHz : 3800.000

First update repos.
> sudo apt update

Install acpi utilities.
> sudo apt install acpi-support acpid acpi

Its time to edit grub.
> nano -w /etd/default/grub

Look for the line that starts with “GRUB_CMDLINE_LINUX_DEFAULT” and add “intel_pstate=disable”..

Mine looks like this.

GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_pstate=disable"

Save and now rebuild grub.
> update-grub

Reboot the system and ssh back in. Change the governor being used.
> echo “conservative” | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

Check your new CPU frequency.
> cat /proc/cpuinfo | grep MHz

Mine shows then following when idle.

cpu MHz : 1605.058
cpu MHz : 1600.000
cpu MHz : 1600.000
cpu MHz : 1600.000

Edit crontab to make the changes permanent.
> crontab -e

add the following to the bottom and save.

@reboot  echo "conservative" | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

 

Conclusion

This is a quick tutorial that I hope helps someone out.

Ubuntu 18.04 Upgrade Apache to Latest Version

Introduction

The apache2 version that is installed on Ubuntu is a couple updates behind.  This unfortunately exposes your server to unpatched vulnerabilities. This can be fixed easily.  So lets get started.

A few quick steps

We will start things off by adding a third party repo.
> sudo add-apt-repository ppa:ondrej/apache2

Now bring everything up to date.
> sudo apt update
> sudo apt dist-upgrade

Conclusion

Not much to it. Enjoy.

HOWTO Ubuntu 20.04 Virtual Web Hosting With Apache, PHP, vsFTPD and Let’s Encrypt

Introduction

The focus of this howto is for those users who need to host their own domains and maybe a few customer domains. This is not aimed at being used for mass web hosting.

There are many ways to do virtual websites under linux. The technique I am going to use is multiple domains on one ip address. I’m using standard linux users to log into the virtual domains.

Setting Up The Base Server

For a dedicated server start with the base server setup:

HOWTO Ubuntu 20.04 LTS Base Server Setup

Introduction All of our servers will start with this install. This base server is based on Ubuntu 20.04 LTS Server.  I don’t explain much in the howto so if you have a question leave a comment or use Google. Downloading … Continue reading

NOTE: If you don’t follow the base server setup then you may run into problems with this howto.

Install Software

We need to install an FTP server and Let’s Encrypt. So type the following:
> sudo add-apt-repository ppa:certbot/certbot
> sudo apt update
> sudo apt install vsftpd python3-certbot-apache

Setup Default User Directory

A new user’s directory needs to have some files and folders created for them.  We will modify the user skel directory so when a new user is created the required folder structure will be there.

Type the following.
> sudo mkdir -p /etc/skel/{website,logs,cgi-bin,backup}
> sudo echo “HELLO WORLD” > index.html
> sudo mv index.html /etc/skel/website/

Configuring vsftpd

Lets create the configuration file.  Replace the contents of /etc/vsftpd.conf with the text below.

listen=NO
listen_ipv6=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
#local_umask=022
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
chroot_local_user=YES
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
ssl_enable=NO
allow_writeable_chroot=YES
pasv_enable=Yes
pasv_min_port=40000
pasv_max_port=40100

Start vsftpd.
> sudo systemctl enable vsftpd
> sudo systemctl start vsftpd.service

Configuring Apache

Most of the apache configuration is already done.  We are going to do some changes to make managing websites easier.

Create the virtual host config file. I defined macros to make virtual host creation easier.  I also turn on compression. Create /etc/apache2/conf-available/virtual.conf with the following:

# Go ahead and accept connections for these vhosts
# from non-SNI clients
SSLStrictSNIVHostCheck off

# define a macro for the virtual hosts
# the user's directory should be setup as follows:
# |- cgi-bin
# |- logs
# |- website
# |- ssl
#
LoadModule macro_module modules/mod_macro.so

<Macro virtHost $type $user $host>
    use $type $host

    ServerName $host
    ServerAlias www.$host 
    DocumentRoot /home/$user/website
    ScriptAlias "/cgi-bin/" "/home/$user/cgi-bin"
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    CustomLog /home/$user/logs/access_log common
    ErrorLog /home/$user/logs/error_log
    <Directory /home/$user/website>
      DirectoryIndex index.html index.php
      Options Indexes FollowSymLinks
      AllowOverride All
      Require all granted

      # setup file compression
      use CompressFiles

      # setup browser caching
      use BrowserCache

      # disable hotlinking for some files
      use DisableHotLink $host
    </Directory>
  </VirtualHost>
</Macro>

<Macro BrowserCache>
  # Enable expires cache
  <IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "access 1 month"
    ExpiresByType text/html "access 1 month"
    ExpiresByType image/gif "access 1 year"
    ExpiresByType image/png "access 1 year"
    ExpiresByType image/jpg "access 1 year"
    ExpiresByType image/jpeg "access 1 year"
    ExpiresByType image/x-icon "access 1 year"
    ExpiresByType application/pdf "access 1 month"
    ExpiresByType application/javascript "access 1 month"
    ExpiresByType text/x-javascript "access 1 month"
    ExpiresDefault "access 1 month"
  </IfModule>

  # Cache-Control Headers
  <ifModule mod_headers.c>
    <filesMatch "\.(ico|jpe?g|png|gif|swf)$">
      Header set Cache-Control "public"
    </filesMatch>
    <filesMatch "\.(css)$">
      Header set Cache-Control "public"
    </filesMatch>
    <filesMatch "\.(js)$">
      Header set Cache-Control "private"
    </filesMatch>
    <filesMatch "\.(x?html?|php)$">
      Header set Cache-Control "private, must-revalidate"
    </filesMatch>
  </ifModule>
</Macro>

<Macro CompressFiles>
  # enable compression
  <IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE "application/atom+xml"
    AddOutputFilterByType DEFLATE "application/javascript"
    AddOutputFilterByType DEFLATE "application/json"
    AddOutputFilterByType DEFLATE "application/ld+json"
    AddOutputFilterByType DEFLATE "application/manifest+json"
    AddOutputFilterByType DEFLATE "application/rdf+xml"
    AddOutputFilterByType DEFLATE "application/rss+xml"
    AddOutputFilterByType DEFLATE "application/schema+json"
    AddOutputFilterByType DEFLATE "application/vnd.geo+json"
    AddOutputFilterByType DEFLATE "application/vnd.ms-fontobject"
    AddOutputFilterByType DEFLATE "application/x-font"
    AddOutputFilterByType DEFLATE "application/x-font-opentype"
    AddOutputFilterByType DEFLATE "application/x-font-otf"
    AddOutputFilterByType DEFLATE "application/x-font-truetype"
    AddOutputFilterByType DEFLATE "application/x-font-ttf"
    AddOutputFilterByType DEFLATE "application/x-javascript"
    AddOutputFilterByType DEFLATE "application/x-web-app-manifest+json"
    AddOutputFilterByType DEFLATE "application/xhtml+xml"
    AddOutputFilterByType DEFLATE "application/xml"
    AddOutputFilterByType DEFLATE "font/eot"
    AddOutputFilterByType DEFLATE "font/otf"
    AddOutputFilterByType DEFLATE "font/ttf"
    AddOutputFilterByType DEFLATE "font/opentype"
    AddOutputFilterByType DEFLATE "image/bmp"
    AddOutputFilterByType DEFLATE "image/svg+xml"
    AddOutputFilterByType DEFLATE "image/vnd.microsoft.icon"
    AddOutputFilterByType DEFLATE "image/x-icon"
    AddOutputFilterByType DEFLATE "text/cache-manifest"
    AddOutputFilterByType DEFLATE "text/css"
    AddOutputFilterByType DEFLATE "text/html"
    AddOutputFilterByType DEFLATE "text/javascript"
    AddOutputFilterByType DEFLATE "text/plain"
    AddOutputFilterByType DEFLATE "text/vcard"
    AddOutputFilterByType DEFLATE "text/vnd.rim.location.xloc"
    AddOutputFilterByType DEFLATE "text/vtt"
    AddOutputFilterByType DEFLATE "text/x-component"
    AddOutputFilterByType DEFLATE "text/x-cross-domain-policy"
    AddOutputFilterByType DEFLATE "text/xml"
  </IfModule>
</Macro>

<Macro DisableHotLink $host >
  # Disable file hotlinking - jpg jpeg png gif pdf
  <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{HTTP_REFERER} !^$
    RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?$host [NC]
    RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?google.com [NC]
    RewriteRule \.(jpg|jpeg|png|gif|pdf)$ – [NC,F,L]
  </IfModule>
</macro>

<Macro VHost443 $host >
  <VirtualHost *:443>
    SSLEngine on
    SSLProtocol all -SSLv2
    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
    SSLCertificateFile /etc/letsencrypt/live/$host/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/$host/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/$host/fullchain.pem
</Macro>

<Macro VHost80 $host >
  <VirtualHost *:80>
</Macro>

Enable the configuration.
> sudo a2enconf virtual

Enable macros and ssl.
> sudo a2enmod macro
> sudo a2enmod ssl

Restart apache
> sudo service apache2 restart

Configuring Let’s Encrypt

Let’s Encrypt needs to be configured to auto renew certs. Lets create a daily cron job
> sudo nano -w /etc/cron.daily/letsencrypt

#!/usr/bin/bash
# letsencrypt auto renew
/usr/bin/certbot renew --no-self-upgrade >> /var/log/le-renew.log

Adding a Default Website

Now we will create a default website.  This site will be used when no other website can be found.

Setup a DNS record for the new domain. I won’t cover this here.

Add a user. This user will be associated with the new domain name. Type the following.
> sudo useradd -m -U -s /bin/bash -c “default website” defaultweb
> sudo passwd defaultweb

Add the apache user to the new user’s group.
> sudo usermod -a -G defaultweb www-data

Update directory permissions.
> sudo chmod g+rwx /home/defaultweb
> sudo chown -R defaultweb:defaultweb /home/defaultweb

Create the virtual host file.  For the default server we will use port 80. Past the text below into the file.  Type:
> sudo nano -w /etc/apache2/sites-available/00-default.conf

# Virtual host config file
#
# MACRO FORMAT
# virtHost [type] [user] [host]
#  type = VHost80 or VHost443
#  user = the username of the website
#  host = domain name or virtual host name
#
# Use the line below to configure a site on port 80
use virtHost VHost80 defaultweb myserver.mydomain.tld

# Uncomment the line below once lets encrypt is setup
# use virtHost VHost443 defaultweb myserver.mydomain.tld

Disable the old default site and enable our default site.
> sudo a2dissite 000-default
> sudo a2ensite 00-default

Reload apache config
> sudo service apache2 reload

Test out the new website.  You should get a page that says ‘Hello World’.

Now we will setup lets encrypt for the default website.  The website must be reachable from the internet.  So lets get the cert:
> sudo certbot certonly –webroot -w /home/defaultweb/website/ -d <YOUR_DOMAIN> –email <YOUR_EMAIL_ADDRESS> –agree-tos

Edit /etc/httpd/virtualHosts.d/00-default.conf
Uncomment the last line to enable ssl connections for the virtual host.

Reload apache.
> sudo service apache2 reload

Test it out.  Connect to your default host via https.

Setup Additional Virtual Hosts

Adding a new virtual host is like adding the default virtual host.  Lets go through the steps.

Be sure DNS is configured for the new virtual host.

Setup a new user. This user will be associated with the new domain name. Type the following. Change ‘NEWUSER’ to the username you want.
> sudo useradd -m -U -s /bin/bash -c “Virtual Website User” NEWUSER
> sudo passwd NEWUSER
> sudo usermod -a -G NEWUSER www-data
> sudo chmod g+rwx /home/NEWUSER
> sudo chown -R NEWUSER:NEWUSER /home/NEWUSER

Create the virtual host file.  For the virtual server we will use port 80. Past the text below into the file.  Replace ‘NEWUSER’ with your user name.  Replace NEWVHOST with your hostname.
> sudo nano -w /etc/apache2/sites-available/NEWUSER.conf

# Virtual host config file
#
# MACRO FORMAT
# virtHost [type] [user] [host]
#  type = VHost80 or VHost443
#  user = the username of the website
#  host = domain name or virtual host name
#
# Use the line below to configure a site on port 80
use virtHost VHost80 NEWUSER NEWVHOST

# Uncomment the line below once lets encrypt is setup
# use virtHost VHost443 NEWUSER NEWVHOST

Enable the new site and reload apache config
> sudo a2ensite NEWUSER
> sudo service apache2 reload

Now we will setup lets encrypt for the new website.  The website must be reachable from the internet.  Replace NEWUSER and NEWVHOST with the info you have.  So lets get the cert.
> sudo certbot certonly –webroot -w /home/NEWUSER/website/ -d NEWHOST -d www.NEWHOST –email YOUR_EMAIL_ADDRESS –agree-tos

Edit /etc/httpd/virtualHosts.d/NEWUSER.conf
Uncomment the last line to enable ssl connections for the virtual host.

Reload apache.
> sudo service apache2 reload

Test it out.  Connect to your new host via https.

Conclusion

That’s the complete setup.

Ubuntu: Disable Floppy Drive

Introduction

I was creating a new virtual machine in my development environment and was getting a kernel error complaining about the floppy drive.  Well I use VMWare Fusion and I don’t configure the virtual machine to have a floppy.  This time I configured the VM to use UEFI.  Wouldn’t you know it, UEFI creates a floppy controller.  And guess what? You can’t disable it. Follow the steps below to take care of the problem.

Steps

    1. First we need to blacklist the floppy kernel module. So type the following
      sudo echo "blacklist floppy" > /etc/modprobe.d/blacklist-floppy.conf
    2. Next we need to update the initial ramdisk. Type the follosing:
      sudo update-initramfs -u
    3. Now update grub. Type:
      sudo update-grub
    4. Time to reboot the system. Type:
      sudo reboot

Conclusion

Just a few commands and your console won’t be plastered with floppy drive errors.

Opnsense Stuck at Booting on J1900 Motherboaard

Introduction

I have an Asrock motherboard with a J1900 CPU.  I was setting up a new Opnsense firewall.  Well FreeBSD hence Opnsense has a video bug.  The firewall boots and runs.  You just don’t get the console screen. Below is a quick guide on getting the video working.

Steps

  1. Power on the firewall.
  2. Hit the spacebar at the boot screen.
  3. Choose number 3 to set boot options.
  4. Type the following:
    set kern.vty=sc
  5. Then type:
    boot
  6. Once the firewall boots login as root.
  7. Select the option to exit to a shell.
  8. Type the following:
    echo 'kern.vty="sc"' > /boot/loader.conf.local
  9. Type:
    reboot

Conclusion

Sometimes those little bugs can be a pain.

HOWTO Ubuntu 20.04 Setup An APT Caching server

Introduction

When you are running a few Ubuntu servers you may want to think about setting up an APT caching server.  Installs and upgrades will go quicker.  You might save some bandwidth on your internet connection

Setting Up The Base Server (Optional

For a dedicated server start with the base server setup:

HOWTO Ubuntu 20.04 LTS Base Server Setup

Introduction All of our servers will start with this install. This base server is based on Ubuntu 20.04 LTS Server.  I don’t explain much in the howto so if you have a question leave a comment or use Google. Downloading … Continue reading

NOTE: You can choose an existing server to use.  I chose to have a dedicated server.

Install Software

Install apt-cacher-ng
> sudo apt install apt-cacher-ng

Configure and Test the server

Apt-cacher-ng has a web interface.  To test it visit http://<your-ip-address>:3142/acng-report.html

Create /etc/apt/apt.conf.d/00aptproxy with the following
> sudo nano -w /etc/apt/apt.conf.d/00aptproxy

Acquire::http::Proxy "http://<your-ip-address>:3142";

Do a software update to test it out.
> sudo apt update
> sudo apt dist-upgrade

Now reload the server web page.  It should now show that some items have been downloaded.

Configuring Clients

On each client create /etc/apt/apt.conf.d/00aptproxy with the following
> sudo nano -w /etc/apt/apt.conf.d/00aptproxy

Acquire::http::Proxy "http://<your-ip-address>:3142";

Do a software update to test it out.
> sudo apt update
> sudo apt dist-upgrade

Conclusion

Its a nice and easy setup.  The cache will work for several distros.

Howto Ubuntu 20.04 Setting up a DNS Server

Introduction

DNS is a big player on the internet.  It gives us a way to assign names to all those IP addresses out there.  This howto is going to cover installing DNS and 3 configuration examples.  Keep in mind that one server can encompass all three configurations at the same time.

Setup New Server (Optional)

I like to have dedicated DNS servers.  So you can start with a fresh server install.  Follow the HOWTO below to setup a new server.  Otherwise move on to install software.

HOWTO Ubuntu 20.04 LTS Base Server Setup

Introduction All of our servers will start with this install. This base server is based on Ubuntu 20.04 LTS Server.  I don’t explain much in the howto so if you have a question leave a comment or use Google. Downloading … Continue reading

Install Software

We will be using BIND for our DNS server.  Software is a quick install.  Type the following.
> sudo apt-get install bind9 bind9utils bind9-doc

Three DNS Configurations

I’m going to cover 3 common DNS configurations.  They are:

Caching DNS Server:
Usually a local server.  It helps speed up the DNS lookup process by storing a local cache of frequently looked up host names by clients.

Primary DNS Server:
This type of server provides authoritative answers for domains and sub domains.  Zone files contain information about the domain.

Secondary DNS Server:
This type of server is known as a slave server.  It provides redundancy to the primary DNS server.

Caching only DNS Server

Out of the box the Bind package for Ubuntu has been configured as a caching DNS server.  We can speed up lookups by forwarding them to your ISP’s DNS servers, Googles DNS server and / or other fast DNS server.  In this example I’m going to use Google’s DNS server.  We are also going to limit the clients that can use the server.

Make a backup of /etc/bind/named.conf.options
> sudo cp /etc/bind/named.conf.options /etc/bind/named.conf.options.save

Change /etc/bind/named.conf.options to look like the text below.
> sudo nano -w /etc/bind/named.conf.options

// caching only DNS server config
//
acl localclients {
  192.168.0.0/16;
  10.0.0.0/8;
  localhost;
  localnets;
};
options {
  directory "/var/cache/bind";
  recursion yes;
  allow-query { any; };
  allow-query-cache { any; };
  allow-recursion { localclients; };
  forwarders { 
    0.0.0.0;
    8.8.4.4;
  }; 
  dnssec-validation auto;
  auth-nxdomain no; # conform to RFC1035
  listen-on-v6 { any; };
};

Restart bind
> sudo service bind9 restart

Primary DNS Server

This configuration is for providing DNS for your domain name(s).  I’m only going to cover a basic domain setup.  There are a lot of configuration options for zone files.

Make a backup of /etc/bind/named.conf.options
> sudo cp /etc/bind/named.conf.options /etc/bind/named.conf.options.save

Change /etc/bind/named.conf.options to look like the text below.
> sudo nano -w /etc/bind/named.conf.options

// caching only DNS server config
//
acl localclients {
  192.168.0.0/16;
  10.0.0.0/8;
  localhost;
  localnets;
};
options {
  directory "/var/cache/bind";
  recursion yes;
  allow-query { any; };
  allow-query-cache { any; };
  allow-recursion { localclients; };
  forwarders { 
    0.0.0.0;
    8.8.4.4;
  }; 
  dnssec-validation auto;
  auth-nxdomain no; # conform to RFC1035
  listen-on-v6 { any; };
  allow-transfer { none; };
};

Edit /etc/bind/named.conf.local and add the text below.
> sudo nano -w /etc/bind/named.conf.local

zone "example.com" {
  type master;
  file "/etc/bind/db.example.com";
};

Now create /etc/bind/db.example.com and use the text below.
> sudo nano -w /etc/bind/db.example.com

$TTL 604800
@ IN SOA dns1.example.com. admin.example.com. (
          10   ; Serial
      604800   ; Refresh
       86400   ; Retry
     2419200   ; Expire
      604800 ) ; Negative Cache TTL
;

; Name servers
example.com.    IN   NS   dns1.example.com.

; A records for name servers
dns1            IN   A    192.168.1.1

; Other A records
@               IN   A    192.168.1.2
www             IN   A    192.168.1.2

Restart bind
> sudo service bind9 restart

Secondary DNS Server

This configuration is for providing DNS for your domain name(s).  I’m only going to cover a basic domain setup.  There are a lot of configuration options for zone files.

Make a backup of /etc/bind/named.conf.options
> sudo cp /etc/bind/named.conf.options /etc/bind/named.conf.options.save

Change /etc/bind/named.conf.options to look like the text below.
> sudo nano -w /etc/bind/named.conf.options

// caching only DNS server config
//
acl localclients {
  192.168.0.0/16;
  10.0.0.0/8;
  localhost;
  localnets;
};
options {
  directory "/var/cache/bind";
  recursion yes;
  allow-query { any; };
  allow-query-cache { any; };
  allow-recursion { localclients; };
  forwarders { 
    0.0.0.0;
    8.8.4.4;
  }; 
  dnssec-validation auto;
  auth-nxdomain no; # conform to RFC1035
  listen-on-v6 { any; };
  allow-transfer { none; };
};

Edit /etc/bind/named.conf.local and add the text below.
> sudo nano -w /etc/bind/named.conf.local

zone "example.com" {
  type slave;
  file "db.example.com";
  masters { 192.168.1.1; }
};

Restart bind
> sudo service bind9 restart

Conclusion

This howto was focused on configuring Bind on Ubuntu.  You will need to do research on all the options that Bind offers.

HOWTO Ubuntu 20.04 LTS Base Server Setup

Introduction

All of our servers will start with this install. This base server is based on Ubuntu 20.04 LTS Server.  I don’t explain much in the howto so if you have a question leave a comment or use Google.

Downloading the ISO

Visit the Ubuntu website and download the ubuntu 20.04 server ISO.

Initial Install

The install screens are straight forward.  I’m not going to cover them in much detail.  Unless you need to customize a setting, just choose the default settings.  Boot the install DVD.

Click ‘Reboot’ when it appears.

First boot

Reboot the machine when the install finishes.
The OS will boot. Log in. All the commands need to be run as root so lets start a shell with root privilleges.
> sudo bash

Get everything updated and install a couple of items.
> sudo apt update
> sudo apt dist-upgrade

Install and enable ssh.
> sudo apt install ssh
> sudo systemctl enable –now ssh

WARNING: My server isn’t directly connected to the internet. The firewall is disabled to help with installation, configuration and testing easier. Once everything is working, turn on the firewall and configure it. I wil remind you to secure your server at the end of this howto.

now reboot the server.

The Second Boot – Installing Additional Packages

We need quite a few other packages. In this howto I’m installing packages regardless if they were already installed by another dependency. This guards against package changes that could cause a package to not be installed. Once again log in to your server.

We need the webmin repo. Create webmin.repo with the text below.
> sudo nano -w /etc/apt/sources.list.d/webmin.list

deb http://download.webmin.com/download/repository sarge contrib

Install the webmin key.
> wget http://www.webmin.com/jcameron-key.asc
> sudo apt-key add jcameron-key.asc

Let’s add a 3rd party repo for Apache.
> add-apt-repository ppa:ondrej/apache2

Now bring everything up to date.
> sudo apt update

Install the following packages. Multiple lines to make cut and paste easier.
> sudo apt install make screen snmp composer libcurl4 unzip net-tools
> sudo apt install apache2 libapache2-mod-php7.4 mysql-server mysql-client
> sudo apt install libapache2-mod-fcgid php-opcache php-apcu

Install some extra PHP libraries.
> sudo apt install php7.4-gd php7.4-snmp php7.4-mbstring php7.4-mysql
> sudo apt install php7.4-odbc php7.4-imap
> sudo apt install php7.4-xmlrpc php7.4-dba
> sudo apt install php7.4-soap php7.4-zip php7.4-intl php7.4-curl

Now lets install webmin.
> sudo apt install webmin
> sudo systemctl enable webmin
> sudo service webmin start

Configure Apache and PHP

Enable the rewrite module.
> sudo a2enmod rewrite actions fcgid alias proxy_fcgi expires headers

Enable Apache.
> sudo systemctl enable apache2.service

Reload apache.
> sudo systemctl restart apache2.service

Configuring MySQL

Configure mysql.
> sudo mysql_secure_installation

Installing and Configuring phpMyAdmin

I prefer to phpMyAdmin to manage my MySQL databases.

Now install phpMyAdmin.
> sudo apt install phpmyadmin

Restart Apache.
> sudo systemctl restart apache2.service

Installing Postfix

Lets install postfix.
> sudo apt install postfix

When prompted select internet site. Next set the mail server name.

Installing cockpit

I’m trying cockpit as my server admin tool.  Do the following to set it up.
> sudo apt install cockpit
> sudo systemctl start cockpit
> sudo systemctl enable cockpit.socket

You can now login to https://yourserver.tld:9090 to administer your server.

Getting root’s and other’s mail

You need to get some local system user’s mail. We’ll use postfix’s virtual file to get the emails to the right place.

Add the following to /etc/postfix/virtual

root admin@yourdomain.tld
postmaster admin@yourdomain.tld
abuse admin@yourdomain.tld

Now add the configuration option to main.cf
> sudo postconf -e “virtual_alias_maps = hash:/etc/postfix/virtual”
Just a couple commands to wrap everything up.
> sudo postmap /etc/postfix/virtual
> sudo systemctl restart postfix
> sudo systemctl enable postfix

Remove Cloud Init

Our server won’t be using cloud-init.  To keep from causing you trouble in the future we will remove it now.

Type:
> sudo apt remove cloud-init cloud-initramfs-copymods cloud-initramfs-dyn-netconf

Final Settings

You may want to enable the linux firewall.
Set your timezone in /etc/php.ini

Conclusion

That’s it for the basic server setup. This is an example of a standard linux server setup. Be sure to use cockpit or webmin to set which services you want to start at boot time. See the other pages for info on configuring servers for virtual webhosting or virtual email hosting. Remember to configure the firewall on the server.

An Easy Way To Delete All Tables From A MySQL Database

Introduction

Sometimes you need to remove all the tables in a database.  For example, when you are installing or testing a web application.  There are GUI tools that can help but we are going to use the command line.

Solution

This is a two step process.

First we use mysqldump and grep to generate an sql file containing the tables to drop.  Change ‘MYDB’ to the name of the database to drop tables from.

mysqldump --add-drop-table --no-data -u root -p MYDB | grep 'DROP TABLE' > drop_tables.sql

Next use mysql CLI to execute the sql file.  Change ‘MYDB’ to the name of the database to drop tables from.

mysql -u root -p MYDB < drop_tables.sql

Conclusion

Thats it.  Straight forward and simple.

My Favorite WordPress Plugins

Introduction

This is a quick rundown of the plugins I like to use on my WordPress sites.  I do try my best not to install tons of plugins on my sites.  For the most part I use small lightweight plugins that do a specific task.

Plugins

They aren’t in any particular order.  So here’s the list.

Plugin:  404Page

You need a custom page not found.  This plugin helps take care of those 404 errors.

Plugin:  Amazon Associates Link Builder

Sorry to say my sites have ads.  This is the official plugin from Amazon.

Plugin:  Contact Form 7

I needed a few forms.  Its the plugin to use.  Seems like everyone uses it.

Plugin:  Display Posts Shortcode

I like to do easy custom posts pages.  This plugin gives me a shortcode I can use on any page.

Plugin:  Duplicator

My goto plugin for backing up and migrating my sites.

Plugin:  Easy WP Meta Description

An easy way to create meta descriptions for search engines.

Plugin:  Enhanced Media Library

Allows you to easily categorize and filter your media.

Plugin:  Flamingo

Adds storage capabilities to contact form 7.

Plugin:  Google Analytics Dashboard For WP

I don’t want to go to Google to see how my sites are doing.  This plugin puts the data I want to see in my wordpress dashboard.

Plugin:  Google XML Sitemaps

Creates sitemap for the search engines.

Plugin:  Insert Pages

This plugin provides shortcodes so I can insert posts into posts on my site.

Plugin:  Lazy Load XT

Got to load your web page fast.  This plugin loads images, youtube and iframes on your pages as they are needed.

Plugin:  Simple Cache

Well the name says it all.  A simple caching plugin for wordpress.

Plugin:  Smush

Its popular.  Optimize your images.

Plugin:  TinyMCE Advanced

Just adds some extra functionality to TinyMCE.

Plugin:  Wordfence Security

The most important plugin of them all.  Protect your site with this plugin.  There are a lot of settings to go through but protecting your site is very important.

Plugin:  wpDiscuz

Just a better comment plugin.

Plugin:  YouTube

Adds shortcodes with more options for embedding your youtube videos.

Conclusion

The above plugins have helped out my sites.  Give one a try.

HOWTO: Configure A UPS on Proxmox 5.x

Introduction

Each of my proxmox servers has its own dedicated UPS.  My servers are low power and the UPS will keep them up for at least 2 hours.  I’m using a Cyberpower UPS connected via USB.

This howto will use a Cyberpower UPS as the example.  Its very easy to make a couple changes to use another UPS.

We will be using NUT to do the heavy lifting.  When done the server will run and shutdown when the battery reaches 20%.  As a bonus notification emails will be sent as well.

Installation and configuration

SSH into your proxmox server with an account that has root privileges.

The only package to install is nut.
>sudo apt install nut

Plug in your UPS to a USB port.  We need to find the USB device information for your UPS.  So lets list our USB devices.
> lsusb

Here’s my list of USB devices.  In this example I’m interested in the Cyberpower.  Copy down the ID of your UPS.

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 001 Device 002: ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Create the following config file:  /etc/nut/ups.conf

maxretry = 3
[theUPS]
  driver = usbhid-ups
  port = auto
  desc = "the server UPS"

We need to create a udev rule to allow nut user access to the driver.  The ID you copied down earlier is used here so udev knows which device the rule applies to.  So create:  /etc/udev/rules.d/90-nut-ups.rules

# Rule for a Cyberpower UPS
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0764", ATTR{idProduct}=="0501", MODE="0660", GROUP="nut"

Now restart udev.
> sudo service udev restart

Next unplug the usb cable to the UPS and plug it back in for the rule to work.

Ok.  Its time to configure NUT to run in stand alone mode.  Replace /etc/nut/nut.conf with the following:

MODE=standalone

The ups daemon has 2 configuration files to deal with.  It needs to be configured for the ip and port to listen on.  We also create a user that can monitor the UPS.

Replace /etc/nut/upsd.conf with the following.

# LISTEN <address> [<port>]
LISTEN 127.0.0.1 3493
LISTEN ::1 3493

Replace /etc/nut/upsd.users with the following.

[upsmonitor]
password = YOUR_PASSWORD
upsmon master

The last file to configure is the UPS monitoring daemon. Replace /etc/nut/upsmon.conf with the following.

# Commands for shutdown on power loss
MONITOR theUPS@localhost 1 upsmonitor YOUR_PASSWORD master
POWERDOWNFLAG /etc/killpower
SHUTDOWNCMD "/sbin/shutdown -h now"

Enable the nut server and client services.
> sudo systemctl enable nut-server.service
> sudo systemctl enable nut-client.service

For the final step lets start the server and client services.
> service nut-server start
> service nut-client start

Conclusion

Nut is a pain to configure, but well worth it.

 

 

Creating a MySQL or MariaDB Database and User for WordPress

Introduction

These are just some quick notes on creating a mysql database and user.  This example shows how to set it up for WordPress.

The Steps

Just type the following lines.  Replace ‘dbname’, ‘username’ and ‘password’ with your values.

mysql -u root -p
CREATE DATABASE dbname;
CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON dbname.* TO 'username'@'localhost';
FLUSH PRIVILEGES;
exit

 

Enable Opcache for PHP 7 and Up

Introduction

If you are running PHP 7+ on a production server then you want to enable PHP’s opcache.  Your PHP applications will receive a well deserved speed boost.

Configure PHP

This configuration example is being done on Ubuntu 18.04.  Only mod_php for Apache will have the opcache enabled.

The php.ini file has all the settings commented out.  So for Ubuntu copy the following and paste it at the end of /etc/php/7.2/apache2/php.ini

[opcache]
opcache.enable=1
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.memory_consumption=192
opcache.max_accelerated_files=20000
opcache.interned_strings_buffer=16
opcache.use_cwd=1
opcache.fast_shutdown=1

Now restart apache.
> systemctl restart apache2.service

Install an Opcache Status PHP Script (Optional)

If you want to see how your opcache is doing then this script will help you out.

Download the php file:
> wget https://raw.github.com/rlerdorf/opcache-status/master/opcache.php

Now copy the file into your web directory.  You can create an htaccess file limiting access to the script.

Conclusion

PHP 7’s opcache is a wonderful improvement.  Enable it.  You won’t be disappointed.

Ubuntu LTS 18.04 Base Server Setup Using Proxmox LXC Container

Introduction

All of our servers will start with this install. This base server is based on Ubuntu 18.04 LTS Server.  This setup starts with a Proxmox LXC container instead of installing from an ISO.  I don’t explain much in the howto so if you have a question leave a comment or use Google.

Downloading the Template

Login to your Proxmox server.  Navigate to the storage where you store container templates.  Click the ‘add template’ button and select and download the Ubuntu 18.04 standard template.

Create the Container

Creating an LXC container is easy.  Click the ‘Create CT’ button.  Follow the wizard entering the requested info.

First boot

Boot the container.
The container will boot. Log in. At this point there is only the root user.  So lets create a user with root privileges.  Replace MYUSER with the user name you wish to use.
> sudo useradd -m -U -s /bin/bash -c “Admin User” MYUSER
> sudo passwd MYUSER
> sudo usermod -a -G sudo MYUSER

Logout of the root account and log back in using the new user account you created.

Get everything updated and install a couple of items.
> sudo apt update
> sudo apt dist-upgrade

WARNING: My server isn’t directly connected to the internet. The firewall is disabled to help with installation, configuration and testing easier. My servers sit behind a firewall.  Once everything is working, turn on the firewall and configure it. I wil remind you to secure your server at the end of this howto.

now reboot the server.

The Second Boot – Installing Additional Packages

We need quite a few other packages. In this howto I’m installing packages regardless if they were already installed by another dependency. This guards against package changes that could cause a package to not be installed. Once again log in to your server.

Install the following packages. Multiple lines to make cut and paste easier.
> sudo apt install make screen snmp composer libcurl3 unzip
> sudo apt install apache2 php7.2-fpm libapache2-mod-php7.2 mysql-server mysql-client
> sudo apt install libapache2-mod-fcgid php7.2-opcache php-apcu

Install some extra PHP libraries.
> sudo apt install php7.2-gd php7.2-snmp php7.2-mbstring php7.2-mysql
> sudo apt install php7.2-odbc php7.2-imap
> sudo apt install php7.2-xmlrpc php7.2-dba
> sudo apt install php7.2-soap php7.2-zip php7.2-intl php7.2-curl

Configure Apache and PHP

Enable some needed modules.
> sudo a2enmod rewrite actions fcgid alias proxy_fcgi expires headers

Enable Apache.
> sudo systemctl enable apache2.service

Reload apache.
> sudo systemctl restart apache2.service

Configuring MySQL

Configure mysql.
> sudo mysql_secure_installation

Installing and Configuring phpMyAdmin

I prefer to phpMyAdmin to manage my MySQL databases.

Now install phpMyAdmin.
> sudo apt install phpmyadmin

Restart Apache.
> sudo systemctl restart apache2.service

Getting root’s and other’s mail

You need to get some local system user’s mail. We’ll use postfix’s virtual file to get the emails to the right place.

Add the following to /etc/postfix/virtual

root admin@yourdomain.tld
postmaster admin@yourdomain.tld
abuse admin@yourdomain.tld

Now add the configuration option to main.cf
> sudo postconf -e “virtual_alias_maps = hash:/etc/postfix/virtual”
Just a couple commands to wrap everything up.
> sudo postmap /etc/postfix/virtual
> sudo systemctl enable postfix
> sudo systemctl restart postfix

Final Settings

You may want to enable the linux firewall.  You can also use the Proxmox firewall.
Set your timezone in /etc/php.ini

Conclusion

That’s it for the basic server setup. This is an example of a standard linux server setup. See my other pages for info on configuring servers for virtual webhosting or virtual email hosting.

Fix phpMyAdmin and PHP 7.2 Issues on Ubuntu 18.04

Introduction

The version of phpmyadmin for ubuntu doesn’t play nice with php 7.2.  The problems were fixed in newer versions of phpmyadmin.

The Fix

Just a few steps and things will be fixed.

First visit www.phpmyadmin.net and download the latest version. My example is version 4.8.1.
> cd /tmp
> wget https://files.phpmyadmin.net/phpMyAdmin/4.8.1/phpMyAdmin-4.8.1-all-languages.zip

Unzip and rename the folder.
> unzip phpMyAdmin-4.8.1-all-languages.zip
> mv phpMyAdmin-4.8.1-all-languages phpmyadmin

Backup the old version of phpmyadmin and move over the new version.
> mv /usr/share/phpmyadmin /usr/share/phpmyadmin.save
> mv phpmyadmin /usr/share/

Edit /usr/share/phpmyadmin/libraries/vendor_config.php and make the following change.

Change

define('CONFIG_DIR', '');

to

define('CONFIG_DIR', '/etc/phpmyadmin/');

That’s it.

Conclusion

This is a bug that will eventually get fixed.