HOWTO Ubuntu 18.04 LTS Base Server Setup

Introduction

All of our servers will start with this install. This base server is based on Ubuntu 18.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 18.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

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 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

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

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 setup 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.

TIP: Working with Disk Images Under Linux

Introduction

At times I need to work with disk images under linux.  Now I’m not talking about an image file that is a single partition. I’m talking about a disk image that represents a hard drive with an MBR and multiple partition in it.

Example 1:  Mounting A Disk Image

We need to start by mounting the image file to a loop back device.
> losetup /dev/loop0 yourimage.imgReplace yourimage.img with the path to your image file. Now lets use fdisk to

see the partions on the disk image.
> fdisk -ul /dev/loop0

Fdisk showed that my image file had 2 partitions. One was a linux partition and the other was a linux lvm partition. Let’s mount the linux partition.
> mkdir /mnt/diskimg_p1
> lomount -diskimage /dev/loop0 -partition 1 /mnt/diskimg_p1

This partition turned out to be /boot. You can unmount it just as easy.
> umount /mnt/diskimg_p1

Now unmount the disk image
> losetup -d /dev/loop0

Example 2:  Mount A Disk Image Partition Using Offsets

Here’s another way to mount the partitions. We will use losetup with offsets. So start with the following:
> losetup /dev/loop0 yourimage.img
> fdisk -ul /dev/loop0

Which gives:

Disk /dev/loop0: 4294 MB, 4294967296 bytes
 255 heads, 63 sectors/track, 522 cylinders, total 8388608 sectors
 Units = sectors of 1 * 512 = 512 bytes

Device Boot Start End Blocks Id System
 /dev/loop0p1 * 63 208844 104391 83 Linux
 /dev/loop0p2 208845 8385929 4088542+ 8e Linux

Now the important part is the start blocks. Your start blocks will look different. My starts are 63 and 208845. The sector size is 512. So do 63*512 and 208845*512. That will give you the offset numbers to use in loset. For my setup I do the following.
> losetup -o 32256 /dev/loop1 /dev/loop0
> losetup -o 106928640 /dev/loop2 /dev/loop0
> mkdir /mnt/p1
> mkdir /mnt/p2
> mount /dev/loop1 /mnt/p1
> mount /dev/loop2 /mnt/p2

Now you have the partitions mounted.

Now lets unmount the partitions and cleanup.
> umount /mnt/p1
> umount /mnt/p2
> rmdir /mnt/p1
> rmdir /mnt/p2
> losetup -d /dev/loop1
> losetup -d /dev/loop2
> losetup -d /dev/loop0

Conclusion

Hopefully this tip will help you master the disk image.

TIP: Disable Author Pages in WordPress

Introduction

In most WordPress websites the author pages functionality isn’t needed.   For search engines it can create unwanted duplicate links to your content.

There are a few solutions to the problem.  A couple are:  get a plugin or create an author template for your theme / child theme.  I will be showing you how to create an author template.

The Quick Tip

In your theme directory place the following into author.php

<?php

// Disable author pages
// PHP permanent URL redirection
header("Location: /", true, 301);

?>

This does a permanent redirect to your home page.

Conclusion

Its a quick and easy way to get the job done.

Move MySQL or MariaDB Databases To A New Location

Introduction

This quick TIP covers moving Mysql’s / MariaDB’s database storage to a different location.  This example was done on CentOS7.

Moving the Databases

First we need to stop mysql if it is running. Type the following:
> service mysqld stop

Next copy the data to the new location and fix the ownership.
> cp -R /var/lib/mysql /home/
> mv /home/mysql /home/databases
> chown -R mysql:mysql /home/databases

Save the old databases directory.
> mv /var/lib/mysql/ /var/lib/mysql_old

Now we need to take care of the needs of some scripts that may not know the data has been moved.
> ln -s /home/databases/ /var/lib/mysql
> chown mysql:mysql /var/lib/mysql

Next edit /etc/my.cnf.d/server.cnf to look like the folloeing

[mysqld]
 #datadir=/var/lib/mysql
 #socket=/var/lib/mysql/mysql.sock
 datadir=/home/databases
 socket=/home/databases/mysql.sock
 user=mysql
 # Disabling symbolic-links is recommended to prevent assorted security risks
 symbolic-links=0

[mysqld_safe]
 log-error=/var/log/mysqld.log
 pid-file=/var/run/mysqld/mysqld.pid

Finally we can restart Mysql. Type the follwoing:
> systemctl restart mariadb

Conclusion

Normally this isn’t done much.  However there are those times when the databases have to be in a different place.

Customizing a WordPress Theme By Creating a Child Theme

Introduction

Sooner or later you will want to customize a theme that you are using.  You have up to 4 possibilities.  They range from easy to complex.

First, many themes and the WordPress customizer provide many options for customizing a theme.  This is one of the easiest ways to customize a theme.

Second,  look for a plugin.  This is also an easy solution.  The challenge, find a plugin.  It may take several plugins to get what you want.

Third, create a child theme.  This is a big step compared to the first two choices.  You will need to be familiar with HTML, CSS and PHP.

Forth, create your own theme.  The most complex choice of the four.  If you don’t have the skills needed for web development then this isn’t the choice for you.

In this tutorial I’m going to focus on option three.  I’m using the Twenty Eleven theme.  Its an older theme but does what I want.  I started with the customizer.  I finally needed a change that a child theme could easily handle.

The example below will start with the Twenty Eleven theme.  So lets get started.

Creating a basic child theme

We are going to create a feature packed child them.  The theme won’t do a thing.  This will be the easiest child theme for you to create.

  1.  Create a directory named “MyChildTheme”.
  2. Create an empty text file named “functions.php”.
  3. Create a text file named “style.css” with the following text.
/*
Theme Name: MyChildTheme
Author: You
Description: 2011 child theme for WordPress
Author URI: yourdomain.tld/
Template: twentyeleven
*/
 
@import url(../twentyeleven/style.css);

That’s it.  You now have a fully functional child theme that does nothing.

Adding your custom CSS

I also over rode some of the CSS in the parent theme.  Since my CSS is simple, I added it to my theme’s style.css file.  Add the following CSS to the end of the file.

pre {
  border: solid 1px #111111;
  font-size: 1.3 em;
  color: #001100;
  margin: 10px;
  padding:10px;
  background: #D3D3FF;
}
#main {
  font-family: arial;
  font-size: 1.1em;
}
body {
  background-color: red;
}

The style.css file should look like the following.

/*
Theme Name: MyChildTheme
Author: You
Description: 2011 child theme for WordPress
Author URI: yourdomain.tld/
Template: twentyeleven
*/
 
@import url(../twentyeleven/style.css);

pre {
 border: solid 1px #111111;
 font-size: 1.3 em;
 color: #001100;
 margin: 10px;
 padding:10px;
 background: #D3D3FF;
}
#main {
 font-family: arial;
 font-size: 1.1em;
}
body {
 background-color: red;
}

Adding the side bar to single posts

When you are reading a post like this one the twenty eleven theme doesn’t have a sidebar.  In my child theme I put them back.

  1. Copy page.php and single.php from the twenty eleven theme to your child theme folder.
  2. Open the functions.php file and paste the following.
    <?php
    add_filter('body_class', 'fix_body_class_for_sidebar', 20, 2);
    function fix_body_class_for_sidebar($wp_classes, $extra_classes) {
     if( is_single() || is_page() ){ 
     if (in_array('singular',$wp_classes)){
     foreach($wp_classes as $key => $value) {
     if ($value == 'singular') 
     unset($wp_classes[$key]);
     }
     }
     }
     
     return array_merge($wp_classes, (array) $extra_classes);
    }
    ?>
  3. Open single.php and place the following
    <?php get_sidebar(); ?>

    on the line before

    <?php get_footer(); ?>
  4. Open page.php and place the following
    <?php get_sidebar(); ?>

    on the line before

    <?php get_footer(); ?>

Conclusion

A child theme can be basic or complex.  Best part is it provides a nice way to customize a theme.

Hacking The Aviosys IP Camera 9100 or 9100A

Introduction

In a nutshell I wanted access to the raw jpg files that the server should offer.

Watching the Raw Video Stream

The following URL allows you to watch the mjpeg video stream.

http://yourip/GetData.cgi
Example:  http://192.168.1.10/GetData.cgi

Here’s an example php script to extract the 4 video inputs into 4 image files. Be sure the device to set to round robin mode.

<?
// readstream.php
//
// by Richard Camp
// rcamp at campworld dot net
// Copyright 2006 - 2018
// All rights reserved
//
// There is no warranty. Use at your own risk.
// NOT FOR COMERCIAL USE. Personal use is fine.
//
// INTRODUCTION
// This script parses the stream form a IP Camera 9100 (A) for jpgs.
// Set the camera server for round robbin mode and all 4 inputs.
// Include the script in your script to generate the files.
//   ex.  include('readstream.php')
//
// User provided parameters
$camurl="http://192.168.151.253/GetData.cgi";
$imgpath="./";             // directory where to store images
$fname="img";              // image file name without extension
$log=1;                    // debugging / log flag
$maxcams=4;                // max cams 1-4

// global values
$maxloop=200;               // max images to read from the stream
$portoffset=14;            // ofset into jpg for cam port num
$imgfile=$imgpath.$fname;  // image file name
$camnum=0;                 // camera number

//
// start of script
//
if ($log) echo "readstream.php starting\n";

// open the stream to the video server
if ($log) echo "opening stream $camurl\n";
$fvid=fopen($camurl,"r");
if (!$fvid) {
  // cannot open mjpeg stream
  if ($log) echo "cannot open stream $camurl\n";
} else {
  // We are connected so start reading data
  if ($log) echo "connected to $camurl\n";
  $r='';

  // read a number of images from the stream and 
  // save them to files
  for ($loop=1; $loop<=$maxloop; $loop++) {

    // read the stream until 2 boundaries are found
    // 
    if ($log) echo "reading data\n";
    while (substr_count($r,"--WIN")<2) $r.=fread($fvid,256);

    // get the start and end offsets for the jpg
    // and extract the image
    if ($log) echo "extracting jpeg\n";
    $start = strpos($r,"Content-Type: image/jpeg")+28;
    $end   = strpos($r,"--WIN",$start);
    $frame = substr($r,$start,$end - $start);

    // get the camera port the image belongs to
    $cport=bin2hex($frame[$portoffset]);
    $cpnum=ord($frame[$portoffset]);
    if ($log) echo "image is for camera port $cport hex $cport\n";

    if (($camnum==$cpnum)&&($camnum<$maxcams)) {
      // save the image file
      if (file_exists("$imgfile-$cport.jpg")) {
        if ($log) echo "removing old file\n";
        unlink("$imgfile-$cport.jpg");
      }
      if ($log) echo "saving image file $imgfile-$cport.jpg\n";
      if ($fimg=fopen("$imgfile-$cport.jpg","wb")) {
        fwrite($fimg,$frame);
        fclose($fimg);
      }
      $camnum++;
      if ($camnum==$maxcams) $loop=$maxloop;
    }

    // we need the remainder of the buffer after the second
    // boundary. it contains the start of the next image.
    $r=substr($r,$end+1);    
    if ($log) echo "\n";
  }
}
fclose($fvid);
if ($log) echo "readstream.php complete\n";
?> 

Here’s another php script that reads the mjpeg stream and lets you select which cameras to extract images from, which cameras to flip the image horizonntally, and the creation of thumbnail images.

<?
// readstream.php
//
// by Richard Camp
// rcamp at campworld dot net
// Copyright 2006 - 2018
// All rights reserved
//
// There is no warranty. Use at your own risk.
// NOT FOR COMERCIAL USE. Personal use is fine.
//
// INTRODUCTION
// This script parses the stream form a IP Camera 9100 (A) for jpgs.
// Set the camera server for round robbin mode and all 4 inputs.
// Include the script in your script to generate the files.
//   ex.  include('readstream.php')
//
// User provided parameters
$camurl="http://192.168.151.253/GetData.cgi";
$imgpath="./images/";      // directory where to store images
$fname="img";              // image file name without extension
$log=0;                    // debugging / log flag
$loadcam[0]=1;             // set to 1 to retreive image for cam 1
$loadcam[1]=1;             // set to 1 to retreive image for cam 2
$loadcam[2]=1;             // set to 1 to retreive image for cam 3
$loadcam[3]=1;             // set to 1 to retreive image for cam 4
$camflip[0]=1;             // set to 1 to flip image horizontally for cam 1
$camflip[1]=0;             // set to 1 to flip image horizontally for cam 2
$camflip[2]=1;             // set to 1 to flip image horizontally for cam 3
$camflip[3]=0;             // set to 1 to flip image horizontally for cam 4
$thumbs=1;                 // set to 1 to create image thumbnails
$thumbwidth=160;           // width of thumbnail
$thumbheight=120;          // height of thumbnail

// global values
$maxloop=200;                          // max images to read from the stream
$portoffset=14;                        // ofset into jpg for cam port num
$imgfile=$imgpath.$fname;              // image file name
$lockfile=$imgpath."readstream.lock";  // lock file name

//
// start of script
//
if ($log) echo "readstream.php starting\n";

// create the log file
$flock=fopen($lockfile,"w");
fwrite($flock,"Locked for update");
fclose($flock);
if ($log) echo "Lock file created.\n";

// open the stream to the video server
if ($log) echo "opening stream $camurl\n";
$fvid=fopen($camurl,"r");
if (!$fvid) {
  // cannot open mjpeg stream
  if ($log) echo "cannot open stream $camurl\n";
} else {
  // We are connected so start reading data
  if ($log) echo "connected to $camurl\n";
  $r='';

  // read a number of images from the stream and 
  // save them to files
  for ($loop=1; $loop<=$maxloop; $loop++) {

    // read the stream until 2 boundaries are found
    if ($log) echo "reading data\n";
    while (substr_count($r,"--WIN")<2) $r.=fread($fvid,256);

    // get the start and end offsets for the jpg
    // and extract the image
    if ($log) echo "extracting jpeg\n";
    $start = strpos($r,"Content-Type: image/jpeg")+28;
    $end   = strpos($r,"--WIN",$start);
    $frame = substr($r,$start,$end - $start);

    // get the camera port the image belongs to
    $cport=bin2hex($frame[$portoffset]);
    $cpnum=ord($frame[$portoffset]);
    if ($log) echo "image is for camera port $cport hex $cport\n";

    // if we have not saved the current cam image then process it
    if ($loadcam[$cpnum]==1) {
      $newfile=$imgfile."-$cport.jpg";
      $tmpfile=$newfile.".tmp";
      $thumbfile=$imgfile."-thumb-$cport.jpg";

      // save image into a temp file
      if ($log) echo "saving image file $tmpfile\n";
      if ($fimg=fopen("$tmpfile","wb")) {
        fwrite($fimg,$frame);
        fclose($fimg);
      }

      // flip the image horizontally if it is marked to be flipped
      if ($camflip[$cpnum]==1) {
        if ($log) echo "Flipping image horizontally.\n";
        exec("convert -flop $tmpfile $tmpfile");
      }

      // move temp file to final image file
      if ($log) echo "Renaming $tmpfile to $newfile\n";
      if (!rename($tmpfile,$newfile)) {
        unlink($newfile);
        rename($tmpfile,$newfile);
      } 

      // create thumbnails if the flag is true
      if ($thumbs==1) {
        if ($log) echo "Creating thumbnail image\n";
        $myimg=imagecreatefromjpeg($newfile);
        $iwidth=imagesx($myimg);
        $iheight=imagesy($myimg);
        $tmpimg=imagecreatetruecolor($thumbwidth,$thumbheight); 
        imagecopyresampled($tmpimg,$myimg,0,0,0,0,
                           $thumbwidth-1,$thumbheight-1,$iwidth,$iheight);
        imagedestroy($myimg);
        imagejpeg($tmpimg,$thumbfile.".tmp");
        if (!rename($thumbfile.".tmp",$thumbfile)) {
            unlink($thumbfile);
            rename($thumbfile.".tmp",$thumbfile);
        } 
      } 

      // mark the camera number as processed  and exit the loop when
      // we have all the images.
      $loadcam[$cpnum]=0;
      if (($loadcam[0]+$loadcam[1]+$loadcam[2]+$loadcam[3])==0) $loop=$maxloop;
    }

    // we need the remainder of the buffer after the second
    // boundary. it contains the start of the next image.
    $r=substr($r,$end+1);    
    if ($log) echo "\n";
  }
}
// close the image stream
fclose($fvid);

// remove the lock file
unlink($lockfile);
if ($log) echo "readstream.php complete\n";
?>

 Getting Access to JPGs

I wanted to get the raw JPGs from the video server. This would allow me to put the images up on my website. It took some digging but here it is. Below are the URLs for the image file.

http://yourip/Jpeg/CamImg.jpg

Changing the Video Channel

To get the different video images you’ll need to use round robin mode or change the video channel. The following url changes the channel.

http://yourip/SetChannel.cgi?Channel=M

M=the channel number 0-3

Getting the Video Channel you are on

What channel am I on? The following url shows you how to get the channel number.

http://yourip/GetChannel.cgi

Configuring The Device For Round Robin Mode

Here is the information on setting the camera into round robin mode. Use the following url.

http://yourip/SetChannel.cgi?Channel=M

M=256+C1+C2+C3+C4

Here’s a table with the values for C1-C4

Video Input Off Selected
C1 0 1
C2 0 2
C3 0 4
C4 0 8

For example I want to use cameras 1 and 3 in round robin mode.

So M=256+1+0+4+0=261

Changing the Camera Resolution

This is the quick easy way to change the camera resolution. Use the following url.

http://yourip/ChangeResolution.cgi?ResType=N

N=the following
0 – 176*144
1 – 352*288
2 – 320*240
3 – 640*480

Change the Image Compression

Below is the url for changing the image compression level.

http://yourip/ChangeCompressRatio.cgi?Ratio=x

x = the following ratio
0 = low (image size 18.2kB)
1 = high (image size 25.2kB)
2 = medium (image size 27.2kB)
3 = clarity (image size 30.2kB)
4 = motion (image size 34.7kB)

Get the capabilities

I’m still working on this one. Here is the url for getting the camera capabilities.

http://yourip/GetCapability.cgi

Conclusion

I hope these notes help you out.

HOWTO Ubuntu 16.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 16.04 LTS Base Server Setup

Introduction All of our servers will start with this install. This base server is based on Ubuntu 16.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-get update
> sudo apt-get install vsftpd python-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 bash
> sudo echo “HELLO WORLD” > /etc/skel/website/index.html

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:

# compress all text & html:
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-httpd-fastphp
AddOutputFilterByType DEFLATE application/x-httpd-eruby

# 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
  </Directory>
 </VirtualHost>
</Macro>

<Macro VHost80 $host >
 <VirtualHost *:80>
</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> 

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 /sbin/nologin -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 /sbin/nologin -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 Open Suse 42 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 SUSE 42 Base Server Setup

Introduction All of our servers will start with this install. This base server is based on OpenSUSE 42. Downloading the ISO Visit the OpenSUSE website and download the Leap version. Download the install DVD. You could also use the Network … 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:
> zypper in vsftpd python-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.
> mkdir -p /etc/skel/{website,logs,cgi-bin,backup}
> echo “HELLO WORLD” > /etc/skel/website/index.html

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.d/virtual.conf with the following:

# compress all text & html:
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-httpd-fastphp
AddOutputFilterByType DEFLATE application/x-httpd-eruby

# 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
  </Directory>
 </VirtualHost>
</Macro>

<Macro VHost80 $host >
 <VirtualHost *:80>
</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>

Enable mod_macro, mod_filter and mod_deflate.
> a2enmod mod_macro
> a2enmod mod_filter
> a2enmod mod_deflate

Restart apache
> systemctl restart httpd

Configuring Let’s Encrypt

Let’s Encrypt needs to be configured to auto renew certs. Lets create a daily cron job
> 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. \\
> useradd -m -U -s /sbin/nologin -c “default website” defaultweb
> passwd defaultweb

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

Update directory permissions.
> chmod g+rwx /home/defaultweb
> 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:
> nano -w /etc/apache2/vhosts.d/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

Reload apache config
systemctl reload httpd

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:
> 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.
> systemctl reload apache

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.\\
> useradd -m -U -s /sbin/nologin -c “Virtual Website User” NEWUSER
> passwd NEWUSER
> usermod -a -G NEWUSER wwwrun
> chmod g+rwx /home/NEWUSER
> 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.
> nano -w /etc/httpd/virtualhosts.d/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

Reload apache config
systemctl reload httpd

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.
> 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.
> systemctl reload apache

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

Conclusion

That’s the complete setup.

HOWTO CentOS 7 Virtual Web Hosting With Apache, 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 CentOS 7.x Base Server Setup

Introduction All of our servers will start with this install. This base server is based on CentOS 7. Downloading the ISO Visit the CentOS website and download the Minimal install ISO. Initial Install Boot the install DVD. The graphical install … 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:
> yum -y install vsftpd ftp python-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.
> mkdir -p /etc/skel/{website,logs,cgi-bin,backup}
> echo “HELLO WORLD” > /etc/skel/website/index.html

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.  Lets start out by creating a directory for virtual host file storage.
> mkdir /etc/httpd/virtualhosts.d

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

# compress all text & html:
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-httpd-fastphp
AddOutputFilterByType DEFLATE application/x-httpd-eruby

# 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
  </Directory>
 </VirtualHost>
</Macro>

<Macro VHost80 $host >
 <VirtualHost *:80>
</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> 

# include the virtual host files
IncludeOptional /etc/httpd/virtualhosts.d/*.conf

#undefine the macros
UndefMacro virtHost
UndefMacro VHost80
UndefMacro VHost443

Restart apache
> systemctl restart httpd

Configuring Let’s Encrypt

Let’s Encrypt needs to be configured to auto renew certs. Lets create a daily cron job
> 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. \\
> useradd -s /sbin/nologin -c “default website” defaultweb
> passwd defaultweb

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

Update directory permissions.
> chmod g+rwx /home/defaultweb
> 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:
> nano -w /etc/httpd/virtualhosts.d/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

Reload apache config
systemctl reload httpd

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:
> 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.
> systemctl reload apache

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.\\
> useradd -s /sbin/nologin -c “Virtual Website User” NEWUSER
> passwd NEWUSER
> usermod -a -G NEWUSER apache
> chmod g+rwx /home/NEWUSER
> 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.
> nano -w /etc/httpd/virtualhosts.d/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

Reload apache config
systemctl reload httpd

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.
> 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.
> systemctl reload apache

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

Conclusion

That’s the complete setup.