Spinning up a new Virtual Machine
Most of my websites are low volume and so I host them on the same VPS at Linode. For a new project, I decided to put the websites on a separate VPS. I spent a day researching the current choices and you probably won’t go wrong with any of them. For me, it came down to either Linode (which I’ve been happy with) or Digital Ocean (which I’ve used for backups and helping my nephew learn programming). Since I don’t need a lot of space right now and I had a referral code, I decided to go with the $5/mo Digital Ocean plan.
Since I’m familiar with it, I installed Ubuntu 14.04.2 LTS with Apache, MySQL, and PHP. I have some customizations that I made to make it consistent with my current server.
Users, Permissions, and Groups
The first thing I did was log in as root and create a new user—me and add myself to the sudoer’s table.
adduser myusername
There are a couple of ways to do this but for now I just added my user name directly instead of creating a sudoers group like I normally do.
myusername ALL=(ALL:ALL) ALL
Without logging out of the root account, I logged in with my username and edited the /etc/ssh/sshd_config. This was a test to see whether I could log in as myself and that I could edit files owned by root using sudo. I then changed PermitRootLogin to no
# Authentication:
PermitRootLogin no
To get the changes to take effect, I restarted the SSH daemon with sudo service ssh restart.
I like to have a group that is able to edit all of the files in www. I call this different things on different machines, e.g. ‘staff’, ‘web-admin’, ‘www’. On this machine I’m using ‘www’.
If you type the command groups, you can see which groups you belong to. To add a new group you can edit the groups file or use these commands to add a group and add a member to a group.
sudo groupadd www
sudo usermod -a -G www myusername
Fail2ban
I don’t know how they find random IP addresses to attach, but 7 minutes after installing Fail2ban it banned the first site. Installation is straightforward. I didn’t make any customizations except to add my IP address and change the email address for notifications.
sudo apt-get install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo vi /etc/fail2ban/jail.local
sudo service fail2ban restart
sudo iptables -L
Updating Apache
First, I updated my .profile as I described in an earlier post. Then I changed the default location for my web pages from /var/www/html to /srv/www. First I created a www directory in srv. Then made a symlink to it in root.
I want everyone in the web admin group to be able to edit the files so I ran sudo chown myusername:www www
I edited the /etc/apache2/apache2.conf file to change the default location to /www and prevent directory listing—I removed Indexes from Options.
<Directory /www/*>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
I don’t want people to see the contents of my .inc files. Some people add the suffix .php to them to hide them, but I prefer to make them all invisible to browsers.
# We don't want people to see .inc files
<Files ~ "\.inc$">
Order allow,deny
Deny from all
</Files>
I also don’t want people to see the Subversion files from my WordPress installs and backups from old projects that used Subversion (nowadays I use git).
Order deny,allow
Deny from all
And I don’t want anyone to see .git files, although best practice says don’t put them in document root.
Order deny,allow
Deny from all
Since I don’t have a domain name attached to this IP address, I added these lines to the bottom of the conf file.
# Suppress the warning message when restarting Apache until we get a FQDN
ServerName localhost
I have a couple of templates for websites so I put one in the www directory for testing. Then I changed the DocumentRoot in 000-default.conf to that directory and restarted Apache.
Miscellaneous
I don’t plan to use a database for these websites, but I decided to set up MySQL and PhpMyAdmin. I followed the instructions at Digital Ocean to change the root password and add myself as a user.
phpMyAdmin install is straightforward, except that you need to add this line:
Include /etc/phpmyadmin/apache.conf
to the end of your /etc/apache2/apache2.conf and restart Apache—even if you are running the latest version of Ubuntu LTS.
Then I installed git using the command sudo apt-get install git-core.
Finally, I often convert MySQL databases to SQLite databases for use in Apple Apps so I installed SQLite.
apt-get install php5-sqlite
sudo apt-get install sqlite3
When $30 Billion is a small number
Tim Cook announced that Apple has paid out $30 Billion dollars to app developers. And over 100 Billion apps have been downloaded. For those of you who are not math challenged, I’ll do the division for you. $30,000,000,000/100,000,000,000 = $.3. So the average app generates 30 cents for each app download.
Don’t quit your day job.
In-page style tag
I’ll often use an in-page style tag when I am developing a page, then move the style to a .css file when I have everything just like I want it. There are some cases though, when you must use an in-page style. Changing the background image is one.
For my responsive web page, I want to change the background image depending on the page that is being viewed. I could use an in-line style tag—style=”background: url(images/Hawk.jpg);” but I need more properties to make the background center and scroll. For readability, it is easier to put it in an in-page style tag and modify an existing style. At the same time I use some php to decide which image to display. Putting it right before the element that uses it also makes it easy to debug and change. (When you’re done, you need to move it to the
tag if you want your page to validate.)
<style>
.intro {
background: url(./images/<?php echo $page ?>.jpg) no-repeat bottom center scroll;
-webkit-background-size: cover;
-moz-background-size: cover;
background-size: cover;
-o-background-size: cover;
}
</style>
<header class="intro">
Find all the files in a directory.
When I find a comic amusing, I grab a screenshot of it. I thought it would be nice to display one comic on my home page each day, so I wrote a little code to look in the comics directory and find all the files, then randomly choose one to display.
There are a few interesting things about the code. First up is scope. Notice that I initialized the two arrays outside of the while loop. That way when I add elements to the arrays, they are not local to the loop. Second, notice that I don’t use an index to add to the arrays. In PHP the preferred way to add an element to an array is with the $arrayName[] notation. Third, I define $location to be the directory handle of the directory. Since I assign it in an if statement, if it fails to find the directory, none of the rest of the code runs. Fourth, I use a similar pattern to read the files in the directory. I read files until there aren’t any more. Finally, I use a flag in my URL so I can proof all of the comics— $all = $_GET[‘all’];.
<?php
$title = array();
$comicsLst = array();
$title = array();
$comicsLst = array();
if ($location = opendir('./Comics')) {
while (false !== ($entry = readdir($location))) {
if ($entry != "." && $entry != "..") {
$titleArray = explode(".", $entry);
$title[] = $titleArray[0];
$comicsLst[] = $entry;
}
}
closedir($location);
$numComics = count($comicsLst);
$randomComic = rand(0,$numComics);
$all = $_GET['all'];
if (is_null($all)) {
echo "<p>";
echo "<img class='align-left' src='/Comics/$comicsLst[$randomComic]' ";
echo "alt='$title[$randomComic]' title='$title[$randomComic]' /> ";
echo "</p>";
/*
echo "<p class='attribution'>";
echo "<a href='index.php?p=Comics&all=y'>Display all comics.</a>";
echo "</p>";
*/
} else {
for($i=0; $i<$numComics; $i++) {
echo "<p>";
echo "$title[$i]<br />";
echo "<img class='align-left' src='/Comics/$comicsLst[$i]' alt='$title[$i]' /> ";
echo "</p>";
}
}
}
I frequently find new comics and add them to my local folder. To keep them synchronized with the server, I wrote a little rsync script.
#!/bin/bash
rsync -a -H -vv -z -l --update --delete --exclude \ Comics --exclude .DS_Store ~wellgolly/Documents/Comics/ \
wellgolly@ wellgolly:/www/WellGolly/Comics/ > \
~ wellgolly/Sites/rsync-backup-comics-`date +%F`.log