Would you like to manage your own web server or maybe even offer web hosting services? This tutorial will show you how to turn the rock solid reliability of Debian 7 Wheezy into a web server which could host a dozen or even hundreds of websites all managed within an easy to use web control panel. The Open Source software which makes this all happen is called Virtualmin.
My installation is on a KVM virtual machine with 5 GB ram, 4 CPU. Debian amd64. From personal experience using commercial VPSes KVM or Xen worked the best for running a busy web server. I do notice though Virtualmin uses fewer resources when running on KVM. This article serves as my ongoing documentation while working with Virtualmin.
Installing Virtualmin GPL on Debian 7 Wheezy
Before doing all of the work preparing a VPS check the IP address issued to you by your VPS provider to make sure it is not listed as a threat from http://www.threatstop.com. If it is listed you may ran into issues which could prevent clients or applications from communicating with your VPS for the IP is being blocked.
Start by downloading the install script.
cd /usr/local/src wget http://software.virtualmin.com/gpl/scripts/install.sh chmod +x install.sh ./install.sh
(This could take a long time depending on how fast the server is)
Other software programs I like to install:
apt-get install fetchmail unzip zip zlib1g-dev \ ffmpeg flvtool2 pbzip2 lvm2 ntpdate curl rsync \ vim iftop smartmontools pvrg-jpeg iotop sysstat pflogsumm ncdu Use below when installing Virtualmin on Ubuntu 12.04 LTS server:
apt-get install fetchmail flex libarchive-zip-perl libc6-dev \ libpopt-dev lynx ncftp perl perl-modules unzip zip zlib1g-dev \ autoconf automake1.9 libtool bison autotools-dev g++ build-essential \ ffmpeg flvtool2 pbzip2 lvm2 ntpdate curl rsync libmagic-dev libio-compress-perl \ vim iftop smartmontools libjpeg-turbo-progs pvrg-jpeg atop
More software programs for web hosting I like installed:
apt-get install php5-curl php5-dev php5-gd php5-idn php5-imagick \ php5-imap php5-mcrypt php5-memcache php5-mhash php5-ming php5-mysql \ php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy \ php5-xmlrpc php5-xsl php5-odbc php5-dev apache2-prefork-dev unixodbc \ unixodbc-dev unixodbc-bin aspell-en imagemagick make memcached g++ \ graphicsmagick whowatch
Check for more updates and apply.
Reboot if there are newer kernel updates.
To complete installation go to URL of the newly installed Virtualmin GPL.
Login using root.
Pre-load Virtualmin Libraries: Y
Run email domain lookup server: Y
Run ClamAV server scanner: Y
Run SpamAssassin server filter: Y
Run MySQL database server: Y
Enter MySQL password.
MySQL configuration size: Leave default settings
Skip check for resolvability (If DNS is not yet setup for server’s fully qualified domain name)
Password storage mode: Only store hashed passwords.
Click next, next.
Click re-check and refresh configuration. I got this error after running check.
Easy enough to fix. I just have to add 127.0.0.1 into list of DNS servers as the error suggest. If you missed that part go to Webmin > Networking > Network Configuration > Host and DNS client. Click save. Then apply configuration.
At this point Virtualmin should be setup ready for use as indicated by two separate top menus on the left. Virtualmin and Webmin. Virtualmin is primarily used for managing virtual websites. Webmin is used to manage the Linux server using point and click instead of only using command line tools.
My personal preference is to set the Virtualmin menu to be under Webmin by going to Webmin > Webmin Configuration > Webmin Themes. Changing it to Blue Framed Theme. Click change. Then refreshing the page. This changes the layout to look this way. Virtualmin menu is now under Servers.
Before I start creating any virtual website accounts I like to tighten up security by doing the following.
Changing the administrator account and deleting the root account created by the install script. Going to Webmin > Webmin Users > click on root > clone. Fill out the account details. I prefer to use a difficult username for the Webmin account on top of a hard password to guess. Also limiting what IP addresses can connect to the admin port.
It now appears as one of the Webmin users. Clicking on it then switch to user, then refresh page. I am now login as user admin P3p0t. The next step is to delete the root account. Going to Webmin > Webmin Users > delete root.
Next is to stop brute force attempts directed at Webmin. Under Webmin configuration > Authentication. Limiting failed login attempts to 3 and blocking host and users for 3 hours. Click save.
Webmin’s default port uses 10000. I prefer to change this as well to something else. You can come up with your own unused port to use. In Webmin configuration > Ports and Addresses.
I will also change the default port SSH uses to something else other than 22. By going to Servers > SSH Server > Networking. Save and Apply changes.
Delete Virtualmin GPL install script when everything has been setup.
These are the following security software I like to have installed.
apt-get install libpam-shield libpam-chroot fail2ban logcheck chkrootkit rkhunter
Setup the following security tools and secure configuration for different software installed.
Change the following PHP settings to.
Search PHP function reference library here.
vi /home/example/etc/php5/php.ini expose_php = Off open_basedir = /home/ disable_functions = show_source, system, shell_exec, passthru, exec, popen, proc_open expose_php = Off max_execution_time = 30 memory_limit = 32M
Setting up fail2ban. Blocking brute force login attempts.
cd /etc/fail2ban cp jail.conf jail.local vi jail.local Values to change: # "ignoreip" can be an IP address, a CIDR mask or a DNS host ignoreip = 127.0.0.1/8 220.127.116.11/24 # add Google's IP range to ignoreip - 18.104.22.168/19 bantime = 259300 maxretry = 2 destemail = email@example.com # globally (section [DEFAULT]) or per specific section action = %(action_mw)s
Set to true for the following services to have fail2ban monitor.
ssh, proftpd, dovecot, sasl
Check to see if fail2ban is monitoring properly
/sbin/iptables -L -n
Output below indicates it is working.
To unblock an IP address blocked by Fail2ban
/sbin/iptables -D fail2ban-sasl -s 22.214.171.124/29 -d 0/0 -j DROP
cd /etc/logcheck vi logcheck.conf Change where to send email reports to. SENDMAILTO="firstname.lastname@example.org" Save edits. :wq
From the console I want to watch my server for any unusual activity. For this I have installed whowatch.
apt-get install whowatch
Running whowatch will launch a terminal with a process list. It will also show the owner and who is logged on via SSH, Telnet, etc. Anyone logged in remotely will have their IP address show up.
To view processes in tree view hit T.
Host based intrusion detection:
Blocking the ICMP timestamp request type using a single iptables rule.
/sbin/iptables -A INPUT -p icmp --icmp-type 13 -j DROP
vi /etc/apache2/conf.d/security ServerTokens Prod ServerSignature Off TraceEnable Off
Before going any further it would be wise to see if there are other software updates available. By clicking the package updates link this would be the safe way to do it especially when you already have client websites running on the server.
menu System Information. Whenever an update is available the package updates link will show how many are available. Clicking on the link will install the update through Webmin.
You can then setup the email alert when the page comes up.
Other settings I like to set up before creating a virtual website to host.
Sync time with a time server:
Go to Hardware > System Time > Time Server Sync. Enter values below. Then click sync and apply.
Restricting FTP access to user directory only:
Going to Servers > Virtualmin Virtual Servers > FTP Directory Restrictions. Activate it for all virtual servers.
After seeing a lot of break in attempt’s directed against FTP I would highly recommend doing this if your website owners don’t need to use FTP. Enable the deny FTP users file under the Proftpd global configuration > authentication > enable yes.
Then add their default username accounts into denied FTP users. Add usernames one line after another then click save. Then click apply changes.
Improve the speed of ClamAV when scanning emails if there is enough server resources. Under Spam and Virus Scanning > Virus scanning program set to clamdscan.
Enable Greylisting to cut down on spam. Click on Email Greylisting > Install Postgrey Now > Enable Greylisting.
Enable spamtrap and hamtrap addresses. This will allow a mailbox user to forward spam emails which don’t get caught by the filters to email@example.com or legit emails flagged incorrectly as spam to firstname.lastname@example.org. When enable these addresses are created automatically per domain. Go to Virtualmin Virtual Servers > Server Templates > Default settings or any other template created > Spam filtering > Create spamtrap and hamtrap aliases? – Yes.
Training Spamassassin for a user mailbox to learn what is spam and what is not spam. Add the following into cron.
In order to monitor how much bandwidth is being used by each virtual website hosted I am going to enable bandwidth monitoring by going to Bandwidth Monitoring > Click yes for Bandwidth monitoring active. Yes, to inform website owners when they reach 90% usage.
I like to change the default Virtualmin configuration on what compression program Virtualmin should use when backing up virtual websites by clicking module config.
Under Backup and restore. Change it to parallel (pbzip2). Click save. It may ask to re-check configuration again.
When re-starting apache2 an error comes up about not being able to reliably determine the server’s fully qualified domain name. To fix it I have to add the fully qualified domain name of my host by going to Servers > Apache Webserver > Existing virtual hosts > default server > Networking and Addresses. Add in fully qualified domain name of server. Click save. Then apply changes.
More settings to help cut down on spam.
Changing my Postfix configuration by going to Servers > Postfix Mail Server > General Options. Click save and apply.
This time I will edit configuration using vi.
Make a copy of the original main.cf file first.
cd /etc/postfix cp main.cf main.cf.orig vi main.cf Add the following: smtpd_helo_restrictions = reject_non_fqdn_helo_hostname,reject_invalid_helo_hostname,reject_rhsbl_helo zen.spamhaus.org Save the edits. :wq
Check the logs for any errors.
tail -f /var/mail.log
Some of my users like to pull email from external mailboxes therefore I have fetchmail enabled:
vi /etc/default/fetchmail START_DAEMON=yes
|I ran into an issue where after setting up a fetchmail schedule for a user each time it ran, all of the emails fetchmail pulled from another server was getting bounced by Postfix with an error “mail forwarding loop”. To resolve the issue I had to add the option dropdelivered in .fetchmailrc for each user.poll 126.96.36.199
user “sample user”
pass “sample pass”
Creating a virtual website to host:
Adding a virtual website to host by going to Servers > Virtualmin Virtual Servers. Click Add new virtual server owned by. Then add features required by the account holder. Click create server.
Note: I only have one WAN IP address assigned for this server. Which is why I picked the option shared IP.
After it is created clicking on the domain name brings up the control panel to manage example.us.
Virtualmin layout for home directory for each account holder is much easier to understand compared to other popular cpanel’s I have used.
Web document root location: /home/example/public_html
Mail account files for users of the domain: /home/example/homes
If this account had a subdomain it will be located at:
The free version of Virtualmin provides a few install scripts for one click software installs. Roundcube is one of them my favorite Open Source webmail. Clicking on install scripts > Roundcube > green play icon. Will automatically download and configure the software for this account! The pro version of Virtualmin has many more Open Source software install scripts. The developers even keep up the versions. This feature alone made a huge difference when I made my decision to buy a Pro version license.
Virtualmin Pro Install Scripts
If you expand your virtual server you will have an option to install like for example a WordPress website using a click of a mouse. This feature is only available for Virtualmin Pro. I am only showing available install scripts taken by my screen capture there are a lot more not shown.
When I setup Virtualmin I picked the option to keep hash passwords. This changes the location where to find the password for the database of the account holder this could be found at Servers > Virtualmin Virtual Servers > account holder website > Edit Databases > Passwords > show.
Running PHP as the site owner. The setting could be found at Servers > Virtualmin Virtual Servers > Website Options.
Sometimes PHP applications require more resources than what is provided by default. To change this login as website account holder by going to Webmin > Webmin Users > Name of Account holder > Click here link > Switch to user > refresh page > Others > PHP configuration > Resource Limits > Enter desired values. Then go to Servers > Apache Servers > Apply changes.
If you want to manually edit php.ini for the account holder this is where it is located.
Limiting Resource Limits Per Domain
It is also a good idea to apply some limits to a domain particularly if it is a very busy website. This prevents one particular website from consuming all resources. From the Virtualmin menu go to >
Clicking edit resource limits (Only available on the Pro version). If you’re using the free version of Virtualmin you can edit the file manually /etc/security/limits.conf.
Managing SSL Certificates to submit to GoDaddy.com. Go to Servers > Virtualmin Virtual Servers > account holder > Manage SSL Certificate > Create Signing Request > Generate CSR Now.
Copy to clip board the CSR from —begin to —end.
Login to GoDaddy account go purchase an SSL certificate then submit CSR certificate to GoDaddy.com. Check your email associated with your GoDaddy account to approve the pending certificate request. At this point you should be able to download the certificate from GoDaddy.com. Choose the type of server in this case it is Apache 2. Extract the downloaded file. Upload the file called example.net.crt. Click install now.
When I needed to move a website with SSL enabled to another server I had to re-download the signed certificate from my SSL provider which is Godaddy. This file ends with a .crt extension. I had to re-upload this into the website domain which got transferred using the built-in SSL manager. From Server Configuration > Manage SSL Certificate > Update Certificate Key. From the signed SSL certificate, upload the .crt file. Leaving the matching key to use the existing private key.
Backing up Virtual Websites.
Scheduling backups for all account holders. Go to Servers > Virtual Servers > Schedule Backups > Create Scheduled Backup > All virtual servers > Backup all features select all > Backup destinations, local file or directory browse to location where to store your backups. > Schedule and reporting, only send an email on failure > schedule it midnight. Click create schedule.
Let me share a personal experience when I had an account with a popular VPS provider from Canada. At that time I was only doing backups stored locally at the VPS server. Thinking they have redundancy in place. Well in turns out the server hosting my VPS suffered a serious hardware failure causing my VPS server to be down for three days! And there was no way for me to get to my files until it was fixed. From then on, on top of my daily backups stored locally I also have a scheduled backup which copies the backups to another server at a different data center using SSH.
If you noticed I use a colon after the IP address to separate the port number if I am not using the default SSH port when copying my Virtualmin backups to another location.
Whenever a website owner requires access to their directory I use Mysecureshell to limit their access within their folder only. First you will have to install mysecureshell. After it has been installed I have to do the following.
Change the default shell of the user to use mysecureshell
usermod -s /bin/MySecureShell sampleuser
Then add this line into /etc/ssh/sftp_config.
sampleuser> Home /home/sampleuser/public_html
Restart mysecureshell to apply changes.
Setting up WHMCS for Virtualmin. This could be done for Virtualmin GPL and Virtualmin Pro.
Login to WHMCS, go to Setup > Product / Services > Servers > Add new server.
Values to put in. Pay close attention how the port is added for Virtualmin. If you want server status available to customers you will have to upload the folder status from the WHMCS install file into a web root directory somewhere at the server.
Fill out the login account WHMCS will use to connect to your server running Virtualmin. Be sure to tick on SSL connect!
Clicking login to control panel should connect you to your Virtualmin server.
Newer versions of Virtualmin fixed security risks on symbolic links. Some of my Joomla and WordPress websites came up with errors, “an internal error has occured”. After moving it to a server running the newer version of Virtualmin. The fixed was to change in .htaccess the following.
Change the parameter “FollowSymlinks” to instead read “SymlinksIfOwnerMatch”.
Encountered a problem when the scheduled backup for virtual websites was backing up mysql databases. dump failed! mysqldump: Error: ‘Out of resources when opening file ‘/tmp/#sql_1340’. According to this link the fixed was to add the following parameters into /etc/init.d/mysql.conf before the pre-start block. This solved my backup issues!
# NB: Upstart scripts do not respect
# /etc/security/limits.conf, so the open-file limits
# settings need to be applied here.
limit nofile 32000 32000
limit nproc 32000 32000
Restart MySQL to apply new settings.
VPS provider I do use and like:
Starting Feb. 25, 2014, I am now using DigitalOcean.com as my VPS provider. They only offer KVM virtualization which is fine by me and SSD drives. From my research they have the best prices for VPS specs I require. Their VPS admin panel allows me to create snapshots of my VPS which allows me to restore prior image in case an update breaks the server. This option alone was a huge factor as to why I moved all of of my VPSes to Digital Ocean. Image snapshots are then backup remotely to Amazon Glacier. There is even an option to transfer your saved VPS image to another data center. Very easy to resize or add more resources and best of all their console does not rely on using Java. For security they provide two factor authentication to secure my login account.
After four months of VPS uninterrupted up-time I experienced my first 5 minute down time when the physical host hosting my VPS at Digital Ocean had to be rebooted by Digital Ocean’s support. I immediately received an email alert to inform me the host had to be rebooted after it became non-responsive. By the time I finished reading the email my VPS was already up and running. After contacting Digital Oceans support to inquire what caused the very brief outage I quickly got a response and not only an apology but was also given an immediate $20.00 credit! I have used many VPS providers in the past and experienced downtime ranging from hours or even a day only to get an apology or a miniscule credit. I would highly recommend using Digital Ocean for your production servers!
Have fun creating your own web hosting platform!
If you’re interested I can setup Virtualmin on your freshly installed Debian or Ubuntu server for $50.00 payable through paypal. Send me an email.