HOWTO CentOS 6.x Virtual Web Hosting With Apache MYSQL and ProFTPD

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 also didn’t want to use system users for the virtual hosts. So I decided to use a mysql database to store the virtual user information.

Setting Up The Base Server

For a dedicated server start with the base server setup: HOWTO CentOS 6.x Base Server.
NOTE: If you don’t follow the base server setup then you may run into problems with this howto.

Install Softwre

We need to install is proftpd with mysql support. Type:
> yum -y install proftpd-mysql

Now lets download and install proftpd admin.
> wget http://downloads.sourceforge.net/proftpd-adm/proftpd_admin_v1.2.tar.gz
> tar -xzvf proftpd_admin_v1.2.tar.gz
> mv proftpd_admin_v1.2 /usr/share/proftpd_admin

Configuring Apache

First we need to create a user called virtwww. We will also make the directory world writable.
> useradd -r -d /home/virtwww -s /sbin/nologin -c “Virtual websites” virtwww
> mkdir /home/virtwww
> chmod a+rwx /home/virtwww

Create the virtual host config file. We will use the name the brouser passes to us to determin the website to load. We also turns on compression. Create /etc/httpd/conf.d/virutal.conf with the following:

# compress all text & html:
#AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE image/svg+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
AddOutputFilterByType DEFLATE text/html

UseCanonicalName Off
RewriteEngine On
RewriteOptions Inherit

VirtualDocumentRoot /home/virtwww/%0

Restart apache
> service httpd restart

Make a directory with your server’s ipaddress as its name. Example
> mkdir /home/virtwww/192.168.1.100

Create a test index.html page in your new directory.

Configuring ProFTPD

Create the following proftpd config file
> mv /etc/proftpd.conf /etc/proftpd.conf.old
> nano -w /etc/proftpd.conf

# This is the ProFTPD configuration file

ServerName			"ProFTPD server"
ServerIdent			on "FTP Server ready."
ServerAdmin			root@localhost
ServerType			standalone
DefaultServer			on
AccessGrantMsg			"User %u logged in."
DeferWelcome			off

DefaultRoot			~ !adm
IdentLookups			off
UseReverseDNS			off
Port				21
Umask				022
ListOptions			"-a"
MaxLoginAttempts		3
MaxInstances                    15
MaxClientsPerHost               3               "Only %m connections per host allowed"
MaxClients                      10              "Only %m total simultanious logins allowed"
MaxHostsPerUser                 1
AllowRetrieveRestart		on
AllowStoreRestart		on
User				nobody
Group				nobody
UseSendfile			no
ScoreboardFile			/var/run/proftpd.score

# Normally, we want users to do a few things.
<Global>
  AllowOverwrite		yes
  <Limit ALL SITE_CHMOD>
    AllowAll
  </Limit>
</Global>

# Define the log formats
LogFormat			default	"%h %l %u %t \"%r\" %s %b"
LogFormat			auth	"%v [%P] %h %t \"%r\" %s"

# TLS
# Explained at http://www.castaglia.org/proftpd/modules/mod_tls.html
#TLSEngine			on
#TLSRequired			on
#TLSRSACertificateFile		/etc/pki/tls/certs/proftpd.pem
#TLSRSACertificateKeyFile	/etc/pki/tls/certs/proftpd.pem
#TLSCipherSuite			ALL:!ADH:!DES
#TLSOptions			NoCertRequest
#TLSVerifyClient		off
##TLSRenegotiate		ctrl 3600 data 512000 required off timeout 300
#TLSLog				/var/log/proftpd/tls.log

# SQL authentication Dynamic Shared Object (DSO) loading
# See README.DSO and howto/DSO.html for more details.
<IfModule mod_dso.c>
   LoadModule mod_sql.c
   LoadModule mod_sql_mysql.c
</IfModule>

# Define log-files to use
TransferLog                     /var/log/proftpd/xferlog
ExtendedLog                     /var/log/proftpd/access_log    WRITE,READ write
ExtendedLog                     /var/log/proftpd/auth_log      AUTH auth
ExtendedLog                     /var/log/proftpd/paranoid_log  ALL default
SQLLogFile                      /var/log/proftpd/mysql

# Set up authentication via SQL
# ===========
AuthOrder                       mod_sql.c
SQLAuthTypes                    Backend
SQLConnectInfo                  proftpd_admin@localhost proftpd password
SQLUserInfo                     usertable userid passwd uid gid homedir shell
SQLGroupInfo                    grouptable groupname gid members
SQLUserWhereClause              "disabled=0 and (NOW()<=expiration or expiration=-1 or expiration=0)"
CreateHome on

# Log the user logging in
SQLLog PASS counter
SQLNamedQuery counter UPDATE "lastlogin=now(), count=count+1 WHERE userid='%u'" usertable

# logout log
SQLLog EXIT time_logout
SQLNamedQuery time_logout UPDATE "lastlogout=now() WHERE userid='%u'" usertable

# display last login time when PASS command is given
SQLNamedQuery login_time SELECT "lastlogin from usertable where userid='%u'"
SQLShowInfo PASS "230" "Last login was: %{login_time}"

# xfer Log in mysql
SQLLog RETR,STOR transfer1
SQLNamedQuery  transfer1 INSERT "'%u', '%f', '%b', '%h', '%a', '%m', '%T', now(), 'c', NULL" xfer_stat
SQLLOG ERR_RETR,ERR_STOR transfer2
SQLNamedQuery  transfer2 INSERT "'%u', '%f', '%b', '%h', '%a', '%m', '%T', now(), 'i', NULL" xfer_stat

AllowStoreRestart               on
AllowRetrieveRestart            on
RequireValidShell               off

Configuring ProFTPD Administrator

First lets create the apache config file and restart apache. The file has been set to only allow access from the local host. Change the access to meet your needs.

/etc/httpd/conf.d/proftpd_admin.conf

alias /ftpadmin /usr/share/proftpd_admin

<Location /ftpadmin>
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
    Allow from ::1
    Allow from 192.168.
    Allow from 10.
    # Allow from .example.com
</Location>

> service httpd restart

Edit the file /usr/share/proftpd_admin/misc/database_structure_mysql/db_structure.sql
Skip to the last three lines. Enter the desired password in these three lines.

Lets create the database and tables. Type the following.
> mysql -u root -p < /usr/share/proftpd_admin/misc/database_structure_mysql/db_structure.sql

Now type the following to do a little housekeeping for php5.
> chmod o+w /usr/share/proftpd_admin/configuration.xml

Now start proftpd. Be sure to also have it start at boot time.
> service proftpd start

Now go to the web interface configuration screen http://yourserver.tld/ftpadmin/configure.php
You will need to configure database access and some other settings.

Conclusion

That’s the complete setup. Proftpd Admin dose almost everything we need. You will need to create links for multiple host names pointing to the same directory. For example if your directory is ‘/home/virtwww/yourdomain.com’ and you want www.yourdomain.com to work then you’ll have to create a link called ‘/home/virtwww/www.yourdomain.com/’ which points to ‘/home/virtwww/yourdomain.com’.

HOWTO CentOS 6.x Base Server Setup

Introduction

All of our servers will start with this install. This base server is based on CentOS 6.x. There have been some changes since my 5.x howtos.

Downloading the ISO

Visit the CentOS website and download the minimum install ISO. The filename is CentOS-6.7-i386-minimal.iso as an example for this howto.

Initial Install

Boot the install DVD.

The graphical install loads and we’re ready to go.

  • Choose your language and keyboard.
  • Choose “Basic Storage Device”. Then click next.
  • The first complaint it will have is about your hard drive. When it asks you about data click “Yes, discard any data”.
  • Enter a host name for the computer.
  • Click the configure network button. Make any changes you may have.
  • When done click next.
  • Choose your time zone.
  • set the root password.
  • Next select “Use All Space”.
  • Click next. Sit back and watch the install go.

First boot

Reboot the machine when the install finishes. The OS will boot. Log in.

Get everything updated.
> yum -y upgrade

Now install the base system.
> yum -y groupinstall core base

Now we need to disable selinux.
Edit /etc/selinux/config and change SELINUX=enforcing to SELINUX=disabled

Edit /boot/grub/grub.conf and add selinux=0 to the kernel line. Here’s an example grub file with the change.

 
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/VolGroup00/LogVol00
#          initrd /initrd-version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Fedora (2.6.23.1-42.fc8)
        root (hd0,0)
        kernel /vmlinuz-2.6.23.1-42.fc8 ro root=/dev/VolGroup00/LogVol00 selinux=0
        initrd /initrd-2.6.23.1-42.fc8.img

Now reboot the server.

The Second Boot – Installing Additional Packages

We need quite a few other packages. A change in this howto is that I’m installing RPMs reguardless if they were already installed by another dependency. This guards against RPM changes that could cause a package to not be installed.

We need to add and enable a few repositories first.

Type nano -w /etc/yum.repos.d/CentOS-Base.repo There are 2 lines in the file that say ‘enable=0’. Change the 0 to a 1

Lets add the rpmforge repo.
> cd /root
> wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.i686.rpm
> rpm -Uhv rpmforge*

We need to enable the rpmforge extras repo. The section of the file below should have the enabled=0 changed to enabled=1
> nano -w /etc/yum.repos.d/rpmforge.repo

[rpmforge-extras]
name = RHEL $releasever - RPMforge.net - extras
baseurl = http://apt.sw.be/redhat/el6/en/$basearch/extras
mirrorlist = http://apt.sw.be/redhat/el6/en/mirrors-rpmforge-extras
#mirrorlist = file:///etc/yum.repos.d/mirrors-rpmforge-extras
enabled = 1
protect = 0
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag
gpgcheck = 1

We need the webmin repo. Create webmin.repo with the text below.
> nano -w /etc/yum.repos.d/webmin.repo

[Webmin]
name=Webmin Distribution Neutral
#baseurl=http://download.webmin.com/download/yum
mirrorlist=http://download.webmin.com/download/yum/mirrorlist
enabled=1

And finally the EPEL repo.
> rpm -Uhv http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm

We need to exclude a couple of RPMs that have version problems with the rpmforge repo. So lets edit the CentOS base repo
> nano -w /etc/yum.repos.d/CentOS-Base.repo

Add the following below the ‘base’ and ‘updates’ sections.

exclude=spamassassin*,perl-Compress-Raw-Zlib*,perl-Compress-Raw-Bzip2*

Now bring everything up to date.
> yum -y update

Install the following RPMs.
> yum -y install gcc gcc-c++ wget bison nano make createrepo screen libmcrypt proftpd caching-nameserver

Install mysql.
> yum -y groupinstall ‘MySQL Database client’ ‘MySQL Database server’

Install Apache and PHP.
> yum -y groupinstall ‘Web Server’ ‘PHP Support’
> yum -y install php-gd php-ncurses php-snmp php-mbstring php-mysql php-devel php-imap
> yum -y install php-odbc php-pear php-xml
> yum -y install php-xmlrpc php-dba php-pear-DB php-process php-pear-DB php-mcrypt

Now lets install webmin. We need SSL support in perl. Setup is easier if you get this installed before webmin.
> yum -y install perl-Net-SSLeay
> rpm –import http://www.webmin.com/jcameron-key.asc
> yum -y install webmin
> service webmin start

Now run setup and disable the firewall. I’m assuming that you are setting up the server behind a firewall. When everything is working then the firewall can be configured and turned on.
> setup

Webmin Configuration

Connct to the webmin server. Use the ip assigned to your server. An example URL would be https://192.168.2.2:10000
Now configure your server.

Installing phpMyAdmin

I prefer to phpMyAdmin to manage my MySQL databases.

If you haven’t already done so, start MySQL.
Its time to set the root password.
> /usr/bin/mysqladmin -u root password ‘thepassword’
> /usr/bin/mysqladmin -p -u root -h localhost.localdomain password ‘thepassword’

Now install phpMyAdmin. NOTE: there is a package called phpmyadmin. Don’t install it.
> yum -y install phpMyAdmin

You will need to add access to phpMyAdmin. By default only the local server can access it. Edit /etc/httpd/conf.d/phpmyadmin.conf to look like the following.

#
#  Web application to manage MySQL
#

<Directory "/usr/share/phpmyadmin">
  Order Deny,Allow
  Deny from all
  Allow from 127.0.0.1
  Allow	from 192.168.
  Allow	from 10.
</Directory>

Alias /phpmyadmin /usr/share/phpmyadmin
Alias /phpMyAdmin /usr/share/phpmyadmin
Alias /mysqladmin /usr/share/phpmyadmin

Restart Apache.
> service httpd restart

Now test it out.

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.com
postmaster admin@yourdomain.com
abuse      admin@yourdomain.com

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

Just a couple commands to wrap everything up.
> postmap /etc/postfix/virtual
> /etc/init.d/postfix restart

Securing tmp and shm

Unless you customized your partion layout we’ve got some work to do. The /tmp and /var/tmp directories need to be secured. We will do this by mounting a file as a loop device.

First lets start with shm. change the following line in /etc/fstab

tmpfs /dev/shm tmpfs defaults 0 0

to:

tmpfs /dev/shm tmpfs defaults,nosuid,noexec,rw 0 0

Remount shm.
> mount -o remount /dev/shm

Now for the tmp directories. We’ll be creating a 2gig sparse disk image.
> dd if=/dev/null of=/var/tmpfs.img bs=1 count=1 seek=2G
> /sbin/mkfs.ext3 /var/tmpfs.img

Now mount the /tmp and set permissions.
> mount -o loop,noexec,nosuid,rw /var/tmpfs.img /tmp
> chmod 1777 /tmp

Edit /etc/fstab and add the following:

/var/tmpfs.img /tmp ext3 loop,nosuid,noexec,rw 0 0

Now test the change.
> mount -o remount /tmp

Lets secure /var/tmp
> mv /var/tmp /var/vartmp
> ln -s /tmp /var/tmp

Reboot the system.

Moving Mysql’s Databases (Optional)

This covers moving Mysql’s database storage to a different location.

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 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:
> service mysqld start

Notes On Cloning The Server in a Virtual Machine Enviroment

Some misc notes on using the base server.

No more network after cloning

Edit the following files:
/etc/udev/rules.d/70-persistant-net.rules
/etc/sysconfig/network-scripts/ifcfg-eth0

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.

Howto Ubuntu 18.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 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

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.

TIP: Disable Unattended Upgrades on Ubuntu 18.04 Server

Introduction

When running a server automatic updates can be a dangerous affair.  When I setup my servers I disable this feature in Ubuntu.

The Fix

Edit /etc/apt/apt.conf.d/20auto-upgrades
> sudo nano -w /etc/apt/apt.conf.d/20auto-upgrades

Change the file to the follosing

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "0";

Now reboot the system.
> sudo reboot

Conclution

A quick change to a file.  A reboot and its all done.

HOWTO Ubuntu 18.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 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 … 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 18.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 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 … 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 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 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:

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

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 install ISO.

Initial Install

Boot the install DVD/CD/USB. Select the ‘Installation’ option from the menu.

The graphical install loads and we’re ready to go.
*Select your language and keyboard. Click next.
*Change the partitioning if you want. Click next.
*Select your timezone. Click next.
*For user interface select server. Click next.
*Enter local user information. Uncheck ‘Automatic Login’. Click next.
*At the bottom of installations settings enable the ssh service. Click install.

First boot

Reboot the machine when the install finishes.
The OS will boot. Log in.

Get everything updated and install a couple of items.
> zypper in nano
> zypper update

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. A change in this howto is that I’m installing RPMs reguardless if they were already installed by another dependency. This guards against RPM changes that could cause a package to not be installed.

We need to add and enable a few repositories.
Add the following Repo for Webmin. Create /etc/zypp/repos.d/webmin.repo

 [Webmin]
 name=Webmin Distribution Neutral
 baseurl=http://download.webmin.com/download/yum
 enabled=1

Install the following RPMs. Multiple lines to make cut and paste easier.
> zypper in make screen bind
> zypper in libmcrypt perl perl-Net-SSLeay perl-Crypt-SSLeay
> zypper in openssl libopenssl-devel man

Run the following to install Webmin:
> rpm –import http://www.webmin.com/jcameron-key.asc
> zypper in webmin
> systemctl enable webmin
> service webmin start

Install MariaDB.
> zypper in mariadb mariadb-tools
> systemctl enable mysql
> systemctl start mysql

Run the following script to setup mariadb.
> mysql_secure_installation

Install Apache web server
> zypper in apache2
> systemctl enable apache2
> systemctl start apache2

Install PHP.
> zypper in php7 php7-fpm apache2-mod_php7
> zypper in php7-gd php7-snmp php7-mbstring php7-mysql php7-devel
> zypper in php7-odbc php7-imap php7-xmlrpc php7-dba php7-mcrypt
> cp /etc/php7/fpm/php-fpm.conf.default /etc/php7/fpm/php-fpm.conf
> cp /etc/php7/fpm/php-fpm.d/www.conf.default /etc/php7/fpm/php-fpm.d/www.conf
> chkconfig php-fpm on
> systemctl start php-fpm.service

Installing and Configuring phpMyAdmin

I prefer to phpMyAdmin to manage my MySQL databases. The nginx config above has the configuration for phpMyAdmin.

Now install phpMyAdmin.
> zypper in phpMyAdmin

Restart apache2.
> systemctl restart apache2

Now test it out.

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
> postconf -e “virtual_alias_maps = hash:/etc/postfix/virtual”
Just a couple commands to wrap everything up.
> postmap /etc/postfix/virtual
> systemctl restart postfix

Final Settings

You may want to enable the linux firewall.

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.

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 loads and we’re ready to go.
*Choose your language and click next.
The next screen has a menu with groups of settings that need to be configured.
*Click on ‘DATE & TIME’ and set your timezone.
*Click on ‘INSTALLATION DESTINATION’ and click done to let it auto partition the drive.
*Click on ‘NETWORK & HOSTNAME’ and set the hostname. Click the ‘Configure’ button and set the adaptor to auto connect. Then click done.
*Click on ‘SOFTWARE SELECTION’. Select ‘Minimal Install’. Check the option for ‘Compatibility Libraries’. Then click done.
*When done click ‘Begin Installation’.
The installation progress screen has a couple of menu items for setting the root password and creating users.
*set the root password.
*You should create a user to admin the system.
*Click ‘Finish Configuration’ when it appears.
*Click ‘Reboot’ when it appears.

First boot

Reboot the machine when the install finishes.
The OS will boot. Log in.

Get everything updated and install a couple of items.
> yum -y install nano net-tools deltarpm
> yum -y group install ‘Infrastructure Server’
> yum -y upgrade

Disable selinux

Now we need to disable selinux. There is some software that doesn’t play well with selinux.
Edit /etc/selinux/config and change SELINUX=enforcing to SELINUX=disabled

Disable the firewall

> systemctl stop firewalld
> systemctl disable firewalld

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. A change in this howto is that I’m installing RPMs reguardless if they were already installed by another dependency. This guards against RPM changes that could cause a package to not be installed.

We need to add and enable a few repositories.
Type nano -w /etc/yum.repos.d/CentOS-Base.repo
For the centosplus section change ‘enable=0’. Change the 0 to a 1.

We need the webmin repo. Create webmin.repo with the text below.
> nano -w /etc/yum.repos.d/webmin.repo

[Webmin]
 name=Webmin Distribution Neutral
 #baseurl=http://download.webmin.com/download/yum
 mirrorlist=http://download.webmin.com/download/yum/mirrorlist
 enabled=1

And the EPEL repo.
> yum install epel-release

Finish up by installing hte remi repo.
> wget http://rpms.remirepo.net/enterprise/remi-release-7.rpm
> rpm -Uvh remi-release-7.rpm

Edit /etc/yum.repos.d/remi.repo. Change enable=0 to enable=1 in the sections “remi” and “remi-php56”.

Now bring everything up to date.
> yum -y update

Install the following RPMs. Multiple lines to make cut and paste easier.
> yum -y install gcc gcc-c++ wget bison nano make createrepo screen
> yum -y install libmcrypt caching-nameserver

Now lets install webmin. We need SSL support in perl. Setup is easier if you get this installed before webmin.
> yum -y install perl-Net-SSLeay
> rpm –import http://www.webmin.com/jcameron-key.asc
> yum -y install webmin
> systemctl enable webmin
> service webmin start

Install MariaDB.
> yum -y install mariadb-server mariadb
> systemctl enable mariadb
> systemctl start mariadb

Run the following script to setup mariadb.
> mysql_secure_installation

Install PHP.
> yum -y install php php-cli php-fpm
> yum -y install php-gd php-ncurses php-snmp php-mbstring php-mysql php-devel
> yum -y install php-odbc php-imap php-pecl-apc
> yum -y install php-xmlrpc php-dba php-pear-DB php-mcrypt
> systemctl enable php-fpm
> systemctl start php-fpm

Install Apache web server
> yum -y install @web-server
> systemctl enable httpd
> systemctl start httpd

Installing and Configuring phpMyAdmin

I prefer to phpMyAdmin to manage my MySQL databases.

Now install phpMyAdmin.
> yum -y install phpMyAdmin

You will need to add access to phpMyAdmin. By default only the local server can access it. Edit /etc/httpd/conf.d/phpMyAdmin.conf to look like the following.

# phpMyAdmin - Web based MySQL browser written in php
# 
# Allows only localhost by default
#
# But allowing phpMyAdmin to anyone other than localhost should be considered
# dangerous unless properly secured by SSL

Alias /phpMyAdmin /usr/share/phpMyAdmin
Alias /phpmyadmin /usr/share/phpMyAdmin

<Directory /usr/share/phpMyAdmin/>
 AddDefaultCharset UTF-8

<IfModule mod_authz_core.c>
 # Apache 2.4
 Require local
 Require ip 192.168.0.0/16
 Require ip 10.0.0.0/8
 </IfModule>
 <IfModule !mod_authz_core.c>
 # Apache 2.2
 Order Deny,Allow
 Deny from All
 Allow from 127.0.0.1
 Allow from ::1
 </IfModule>
</Directory>

<Directory /usr/share/phpMyAdmin/setup/>
 <IfModule mod_authz_core.c>
 # Apache 2.4
 Require local
 Require ip 192.168.0.0/16
 Require ip 10.0.0.0/8
 </IfModule>
 <IfModule !mod_authz_core.c>
 # Apache 2.2
 Order Deny,Allow
 Deny from All
 Allow from 127.0.0.1
 Allow from 192.168. 
 Allow from 10.
 Allow from ::1
 </IfModule>
</Directory>

# These directories do not require access over HTTP - taken from the original
# phpMyAdmin upstream tarball
#
<Directory /usr/share/phpMyAdmin/libraries/>
 Order Deny,Allow
 Deny from All
 Allow from None
</Directory>

<Directory /usr/share/phpMyAdmin/setup/lib/>
 Order Deny,Allow
 Deny from All
 Allow from None
</Directory>

<Directory /usr/share/phpMyAdmin/setup/frames/>
 Order Deny,Allow
 Deny from All
 Allow from None
</Directory>

# This configuration prevents mod_security at phpMyAdmin directories from
# filtering SQL etc. This may break your mod_security implementation.
#
#<IfModule mod_security.c>
# <Directory /usr/share/phpMyAdmin/>
# SecRuleInheritance Off
# </Directory>
#</IfModule>

Restart Apache.
> systemctl restart httpd

Now test it out.

Installing cockpit

I’m trying cockpit as my server admin tool.  Do the following to set it up.
> yum -y install cockpit cockpit-dashboard cockpit-networkmanager cockpit-packagekit
> yum -y install cockpit-selinux cockpit-sosreport cockpit-storaged
> systemctl start cockpit
> 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
> postconf -e “virtual_alias_maps = hash:/etc/postfix/virtual”
Just a couple commands to wrap everything up.
> postmap /etc/postfix/virtual
> systemctl restart postfix

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.

Fix Proxmox Crashing on J1900 and J3455 CPUs

Sometimes kvm has trouble running on some cpus.  Unfortunately you end up finding this out the hard way when proxmox crashes and / or shuts down.  As it turns out its our friend cpu c states.

The solution to the problem is limiting the c states to C1. We will do this by telling the linux kernel the maximum c state to use.

Edit /etc/default/grub and add the following line.

GRUB_CMDLINE_LINUX_DEFAULT="intel_idle.max_cstate=1 processor.max_cstate=1"

Next update grub.
> update-grub

Now reboot the system.
> reboot

Your system should now be crash free.

 

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

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

Initial Install

The install screens are straight forward.  I’m not going to cover them in much detail.  I will cover areas that have settings that are important.  Boot the install DVD.

When you get to the software selection screen select the following software packages.
– DNS Server
– LAMP Server
– standard system utilities
– OpenSSH Server

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-get update
> sudo apt-get install nano net-tools
> sudo apt-get 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

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

Install the following packages. Multiple lines to make cut and paste easier.
> sudo apt-get install make screen snmp composer libcurl3 unzip
> sudo apt-get install libapache2-mod-fastcgi php7.0-fpm

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

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

Configure Apache and PHP

Enable the rewrite module.
> sudo a2enmod rewrite

Enable mcrypt in php.
> sudo phpenmod mcrypt

Reload apache.
> sudo systemctl restart apache2.service

Installing and Configuring phpMyAdmin

I prefer to phpMyAdmin to manage my MySQL databases.

Now install phpMyAdmin.
> sudo apt-get install phpmyadmin

Restart Apache.
> sudo systemctl restart apache2.service

Installing Postfix

Lets install postfix.
> sudo apt-get 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-get 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

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.