Here is a guide to Setting up a Linux Webserver with SSH. This is for Debian 8 (Jessie) although other versions of Debian will be similar, and Debian-based versions of Linux, like Ubuntu will also use similar commands. I’ll just call it the webserver because it can be a dedicated server, a VPS, or a cloud instance.

A lot of this comes from these excellent guides… Getting Started with Linode and Securing your Server… but I’d say that searching around and getting different information from different sources is definitely a good way to go. I wanted to install PHP 7.0 so some of this guide is different to other guides, which tend to use PHP 5.6. This guide is also primarily for people using a Windows PC to talk to a remote Linux webserver, but other operating systems will be the same for most of the stages. Most of the contents of this guide uses a terminal and an SSH connection, which windows needs software for (e.g. Putty), but other operating systems may have it built-in. This guide doesn’t talk about FTPing (or SFTPing) much, but a good SFTP client for Windows is WinSCP.

There is often more than one way to get the same results. For example, you can reboot the system in a number of different ways. I tend to use the methods that appear simplest to me.

Requirements

  • A linux server (Debian 8, in this case).
  • The IP address of the server.
  • The root password of the server.
  • A computer to access your remote linux webserver, in this case a Windows PC with Putty installed.

Contents

1) Login to the server with SSH
2) Update/upgrade
3) Install Apache2
4) Find your webserver’s IP address
5) Set a Hostname
6) Configure the Apache virtual hosts
7) Create the web directory
8) Install PHP7
9) Your webserver’s Timezone
10) Unattended upgrades
11) Install Sudo
12) Add a user
13) Public/private key pair
14) Turn off root login
15) Sending email
16) Fail2ban
17) Firewall: UFW
18) Install MySQL and PHPmyAdmin
19) Monitor
20) Apache Config file
Conclusion

1) Login to the server with SSH

With Windows you can download and install some software, such as Putty, then connecting to your instance should be pretty straight-forward with the login information from your hosting company. To begin with you’ll probably be logging in as “root” so you will not need to type sudo as root is the master login (this is handy because sudo is not installed, yet). The commands on this guide may need sudo adding at the beginning if you are not logging in as “root”.

2) Update/upgrade

Once you are logged in the first thing to do is to make sure everything is updated so that you are installing the latest versions of everything when you get to that stage.

apt-get update && apt-get upgrade

or, later if you login as another user, you’ll need sudo…

sudo apt-get update && sudo apt-get upgrade

3) Install Apache2

First, you can check if Apache is already installed by typing…

which apache2

If it is not already installed, i.e. the above does not give you any results. To install Apache type…

apt-get install apache2

4) Find your webserver’s IP address

If your hosting company has not told you what the IP address is, this shows all IP’s installed on your instance…

hostname -I

5) Set a Hostname

The hostname can be anything. If you have more than one instance you might name your instances so that they are all plant species, stars, geographical locations, chemical elements, Roman Emperors or Greek philosophers.

Add the hostname by opening up the hosts file in nano…

nano /etc/hosts

Then, the hosts file might look like using the IP address that you already know, above…


127.0.0.1 localhost
127.0.1.1 myhostnamegoeshere
123.123.456.789 example.com

6) Configure the Apache Virtual Hosts

Make sure 000-default.conf is off, copy it to mywebsite.com.conf and enable. link

cd /etc/apache2/sites-available
cp 000-default.conf example.com.conf
nano example.com.conf

Then, edit the example.com.conf so that it looks like this…

ServerAdmin webmaster@localhost
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com

Then, enable the site by typing…

a2ensite example.com

7) Create the web directory

We specified the DocumentRoot should be /var/www/example.com, above. So, now we need to make it!

Move to the place for all your web directories…

cd /var/www/

Then, create the web directory…

mkdir example.com

Once you have the directory you can add an index.html inside it.

If you have not restarted apache2 since typing the a2ensite command you need to do that before the domain name will work in your browser. Restart then test it by typingthe domain name into a browser.

8) Install PHP7

You can install any version of PHP. PHP5.6 is popular. I wanted to go with PHP7 so following this guide… Installing PHP7

Add these two lines to your /etc/apt/sources.list file:

deb http://packages.dotdeb.org jessie all
deb-src http://packages.dotdeb.org jessie all

Add the GPG key:

wget https://www.dotdeb.org/dotdeb.gpg
apt-key add dotdeb.gpg

Install PHP 7:

apt-get update
apt-get install php7.0

Then, straight away before you do too much else you’ll want to add the other modules you need. There is information abput some common ones from here..

apt-get install php7.0-cli php7.0-common libapache2-mod-php7.0 php7.0 php7.0-mysql php7.0-fpm php7.0-curl php7.0-gd php7.0-bz2

You can then test out the PHP by making a page that has phpinfo(); on it to show you 1) that it’s working and 2) the modules that are installed and enabled. Assuming everything works fine it’s time to do more setting up…

9) Your webserver’s Timezone

Set your server timezone by typing the following command…

dpkg-reconfigure tzdata

Then, this command shows you the current time on your server…

date

10) Unattended upgrades

You will want to keep everything as up-to-date as possible on your instance. You can do this by configuring the Unattended upgrades… Automatic updates. Then if you don’t want to have to login to your instance and reboot/restart it after every upgrade, you can automatically reboot, if needed, after upgrading. First install the package…

apt install unattended-upgrades

Then configure the settings you want in nano…

nano /etc/apt/apt.conf.d/50unattended-upgrades

11) Install sudo

From Installing sudo on Debian

apt-get install sudo

12) Add a user

adduser myname

Then, add the user to sudo…

usermod -aG sudo myname

Then logout of root, login as myname and test sudo out by doing something that requires sudo privileges, e.g. reload apache2.

13) Public/private key pair

This is the main thing that is different on Windows PCs than it is with either Linux or Macs. For Windows PCs you have to use downloadable software, such as putty. This guide: Use Public Key Authentication with SSH talks you through the process.

Then, logout of root and login with your user to check that the new user works correctly with the public key authentication. You should be asked for the keyphrase, as opposed to the password.

14) Turn off root login

If you can login with the username you set up with the public/private key pair you can “turn off” root logins.

Turn off root logins and turn off password authentication in the sshd_config file using nano…

nano /etc/ssh/sshd_config

15) Sending email

https://www.debian.org/releases/jessie/amd64/ch08s05.html.en allows server to send email, e.g. for unattended upgrades reboot.

16) Fail2ban

Fail2ban

apt-get install fail2ban

Then, you can endit the config file, and/or make a local file…

nano /etc/fail2ban/fail2ban.conf

17) Firewall

For a firewall, UFW (Uncomplicated Firewall) is there for Debian systems. This is a good guide: Configure firewall with UFW

apt-get install ufw

As the guide says, you’ll have to be very careful when switching on the firewall that you do not lock yourself out of SSH.

18) Install MySQL and PHPmyAdmin

Here are two useful guides: MySQL and MySQL on PHP7.

apt-get install mysql-server

mysql_secure_installation

apt-get install libapache2-mod-php7.0 php7.0-mysql php7.0-curl php7.0-json

A good place to begin before installing PHPmyAdmin is by checking the phpmyadmin prerequisites and installing everything needed (e.g. mbstring). If 500 server errors, check the prerequisites again, installing anything that isn’t already installed, then re-install phpmyadmin to get rid of the error.

Install PHPmyAdmin on Debian 8

For each virtual host that you would like to give access to your PHPMyAdmin installation, create a symbolic link from the document root to the phpMyAdmin installation location (/usr/share/phpmyadmin). You do this by moving into the public directory of each virtual host, then creating a symlink…

cd /var/www/example.com/public_html
sudo ln -s /usr/share/phpmyadmin

19) Monitor

You can monitor the performance and usage of the web server by using top… Just type top into the terminal and you’ll get a summary of the usage every few seconds.

Linux TOP command explained

You can also set up a script that will email you if certain conditions are met (RAM usage, for example).

20) Apache Config file

It’s a good thing to take a look at the apache2 config file to make sure it is configured correctly. One of the things you’ll want to check is that KeepAlive is set to off. From Setting up LAMP on Debian 8.

sudo nano /etc/apache2/apache2.conf
KeepAlive Off

TL;DR / Conclusion

Different setups are all slightly different. If you are getting errors the best thing to do is to either examine the error itself or find the relevant error logs and do some problem solving. Unix & Linux Stack Exchange and Server Fault tend to have a lot of problems already answered.

This is just a general guide to setting up a Linux Webserver with SSH with a Windows PC talking to a Debian 8 remote webserver. You may want to change the order I have followed here and there may well be steps I’ve missed out here, errors I get that you do not get, or vice versa. But, I hope it can be useful to someone.

After getting this far there will probably still be thing you need to do to your webserver. There will be other PHP and Apache modules that your web applications and/or frameworks require, such as mod_rewrite. As before, figure out what you need for your application and add it as required. Have fun!

There are 1,000s of WordPress Plugins and each one is individual, but for anyone wanting to make a plugin for themselves here are a few basics to help you get stated. I made my first plugin recently for WordPress and I was amazed at how little information was out there. So, I decided to make this simple tutorial on “How to write a WordPress Plugin” for anyone else with an interest in web programming or web design who would like to see if they can make a plugin. Obviously, the plugin itself will be whatever you want it to be and will be as complex as you want to make it. This tutorial will be an easy introduction that you can add to if you wish.

Prerequisites

While it can be very straight-forward there are two things you’ll definitely need to begin working on a WordPress plugin.

  • A working version of WordPress wether on a website or on a localhost.
  • Knowledge of PHP.

You are going to need a working version of WordPress. I won’t go into the details here of how to setup and install a WordPress blog but if you are interested in making a WordPress plugin I’m assuming that you’ve had some experience with using WordPress.

WordPress has many existing functions that will assist you in making your plugin but the programming language that you’ll need to use to make a WordPress plugin is PHP. There’s no getting around the fact that you should probably have some PHP knowledge to make a plugin that behaves exactly the way you’d like it to behave and has all the functionality you want it to have. I’d say that you may not have to be a PHP whizz and you can learn-as-you-go, but you’d need to have an understanding of programming languages, and an idea of how to write PHP.

A good source of information about PHP is PHP.net, often searching for a PHP function will take you there. Another good place for PHP examples and troubleshooting is Stack Overflow, again searching for a problem you are having will often take you here where someone has generally already asked the question and it has already been answered.

Why WordPress? Why a plugin?

WordPress rocks. There are many many people using WordPress all over the world, and WordPress.com is in the world’s top 50 websites. The basic blogging software is amazing and constantly evolving, but the power of WordPress is in it’s open source. Because the source code can be viewed by anyone and there is extensive online documentation many people have made plugins and themes which aid and enhance WordPress blogs. Through plugins you can modify almost any aspect of the blog, adding things, removing things and changing it until it is almost unrecognisable from the original blog you added to your hosting.

You’ll want to use plugins that other people have made, but maybe the plugin that would be perfect for you has not been made yet. If this is the case or you just want to give it a try, read on…

Making a WordPress Plugin: First Things First

Ok then, let’s begin! We’ll start off with a one page plugin. The first thing you have to do is open up a text editor and create a file called whatever you’d like your plugin to be called. There are 1000’s of plugins already so my advice would be to call it something with at least 2 or 3 words in the name if you wish to submit to the WordPress Repository. WordPress needs each plugin to have a unique filename so that there are no conflicts between different plugins. This concept extends to the naming of functions which should all begin with a unique prefix so as not to cause any conflicts with WordPress functions or functions of other plugins. If you are not interested in submitting your plugin you can call it pretty much whatever you like as it’ll only be on your website.

So, let’s call our plugin “My First Ever Plugin” and give it the filename “my-first-ever-plugin.php” and let’s start off with this code in our PHP file, I’ll call this the “header” code…

<?php
/**
 * @package my-first-ever-plugin
 * @version 0.0.01
 * Plugin Name: My First Ever Plugin
 * Plugin URI: http://www.shortdark.net/my-first-ever-plugin/
 * Description: My plugin does...
 * Author: My Name
 * Text Domain: my-first-ever-plugin
 * Version: 0.0.01
 * Author URI: http://www.shortdark.net/
 */

It should be fairly self-explanatory. This plugin will have the file "my-first-ever-plugin.php" in a directory called "my-first-ever-plugin". If your plugin was called "Whatever" it would have a file called "whatever.php" inside a directory called "whatever". The description is a short description of what the plugin does.

Prevent Direct Access

Next, still on the "my-first-ever-plugin.php" file, it's good practice to prevent direct access to your plugin. I.e. we want the plugin to be used by someone within their WordPress blog, we do not want the plugin to be accessed from elsewhere. To prevent direct access we insert this code after the header...

/**************************
 ** PREVENT DIRECT ACCESS
 **************************/

defined('ABSPATH') or die('No script kiddies please!');

So, if "ABSPATH" is not defined the PHP script will die().

Believe it or not, we're almost done if you're just making a WordPress plugin for your own use. I'll cover the steps you need to take if you want to add your plugin to the WordPress repository later. All that has to be done now is to hook some code to WordPress.

Hook It Up

WordPress uses "hooks" to connect functions you have written to a WordPress blog. A hook can be either an "action" or a "filter". An action adds something and a filter changes something that already exists. We will use a filter for this tutorial but an example of an action would be to make a page in the admin area we would use the "add_action" like this... "add_action('admin_menu', 'function_name');". For more information check out the WordPress Plugin API reference.

Here we are filtering the content of all the posts and pages. We are going to add some "Hello World!" text in <p> tags at the end of the post and page content. We make a function that has the parameter "$content" then we hook the function using the filter "the_content" whoch means that whatever we return from the function will replace the post or page content. As we do not want to remove the content we just want to add to it I have just added the string we want onto the end of the "$content" variable.

This goes next in the "my-first-ever-plugin.php" file...

/**********************
 ** DO SOMETHING
 **********************/
// Add "<p>Hello World!</p>" to the end of each post and page
function mfep_hello_world($content) {
	$content .= "<p>Hello World!</p>";
	return $content;
}

// Hook the function to "the_content"...
add_filter('the_content', 'mfep_hello_world');

Notice, I have named my function beginning with an acronym of my plugin. My plugin is called "My First Ever Plugin" so I put "mfep_" at the start of all my function names.

And, that's it. You've made a plugin!

Make your WordPress Plugin Translatable

To make your plugin translatable you'll need to load your text domain. In the "header" we had a line like this...

 * Text Domain: my-first-ever-plugin

So, now we need to use another hook, which this time is an "add_action" to tell WordPress where you'll be storing the translation files. Here, I'm storing the translation files in a directory within my plugin called "languages".

/****************************
 ** LOAD PLUGIN TEXT DOMAIN
 ****************************/

function mfep_load_textdomain() {
	load_plugin_textdomain('my-first-ever-plugin', false, dirname(plugin_basename(__FILE__)) . '/languages');
}

add_action('init', 'mfep_load_textdomain');

Again, you'll notice that my function has the acronym of my plugin name, "mfep_", at the beginning.

That's all we have to do in the "my-first-ever-plugin.php" file.

readme.txt

If you want to submit your plugin to the WordPress repository you'll also need a "readme.txt" file in your plugin directory.

Similar to the header of the PHP file, the readme.txt also has a header...

=== My First Ever Plugin ===
Contributors: shortdark
Donate link: http://www.shortdark.net/my-first-ever-plugin/
Tags: posts, pages
Requires at least: 3.5
Tested up to: 4.6.1
Stable tag: trunk
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html

Adds a Hello World! to the end of the post and page content.

The plugin title is on the top line in between two sets of "===".
Contributors is hwo has helped to make the plugin.
Tags should be exactly the same as the ones that WordPress has already. You can see the existing tags here.
Requires at least is the minimum WordPress version number your plugin should work for. Our plugin here is very simple but if you used a WordPress function that was created fairly recently you should investigate which version of WordPress it was introduced in. This will allow you to calculate the minimum version without installing every single version of WordPress ever.
Tested up to should be the version of WordPress you have tested your plugin on. This should always be the latest version of WordPress because you should always update to the latest version every time an update comes out.
Stable tag is telling WordPress which is the stable version of your plugin. To begin with this will be the "trunk".
Then, your plugin must be open source and it must have a public licence,
Lastly, before the next section of the "readme.txt" you can add one sentence to describe your plugin. This will be what will show up on the plugin page of the user's blog after they download your plugin.

The rest of readme.txt

After the one sentence short description you can add a much longer description that can be as long as you like with several paragraphs. Links can be added as shown with the link text in square brackets before the URL in brackets. Then comes the necessary "Installation" and "Changelog" sections. You'll notice that all the sub headings are in the middle of a set of "==" and the subheadings have "=" around them.

== Description ==

Much longer description goes here.

Please let me know if you like this plugin by leaving a review or [contacting me](http://www.shortdark.net/contact-me/).

Go to the [Shortdark WordPress plugin page](http://www.shortdark.net/wordpress-plugin/) for more information.

== Installation ==

This section describes how to install the plugin and get it working.

1. Upload the plugin folder to the `/wp-content/plugins/` directory, or install the plugin through the WordPress 
plugins screen directly.
2. Activate the plugin through the 'Plugins' screen in WordPress.

== Changelog ==

= 0.0.01 =

* New plugin.

And that's it!

Once you've finished your readme.txt you can check your readme.txt at the readme.txt validator.

Now your're ready to review the Plugin Directory information zip your plugin up and submit it to the WordPress Repository.

Once your Plugin has been Approved

WordPress uses SVN, so you'll probably need something like TortoiseSVN to upload your plugin to the WordPress repository. More info on how to do that at this youtube video.

Here are some extra things that I didn't find out immediately that might be helpful to you.

Add images to your WordPress Plugin Page

You should have two images: "banner-772x250.jpg" and "icon-128x128.jpg". They can be in your plugin folder (the "trunk" of your WordPress repository), or it may be better to put them in your "assets" folder out of the way. These will be the banner image at the top of your plugin page and the square icon that people will see when they search for a plugin.

Add Screenshots

To add a screenshots section you simply add "== Screenshots ==" to your readme.txt.

== Screenshots ==

Here are some screenshots...

1. Nice screenshot of my plugin.
2. Another screenshot of my plugin.

Each number in this section will be a different screenshot. Screenshot 1 will look for the file "screenshot-1.jpg", and screenshot 2 will look for "screenshot-2.jpg". Similar to the banner and icon, you'll either put these images in your trunk or in your assets folder. The text by each number on the readme.txt is the caption that will go under the image on the screenshot page.

Everything All Together

The complete files from this "How to write a WordPress Plugin" tutorial can be cloned or downloaded from GitHub page.