Configure the EC2 server


Update OS image

The OS image from which the Ubuntu server was made will likely not be completely up to date.

  1. Using the terminal, SSH into the server if you haven't already: ssh -i /path/to/my-key-pair.pem ubuntu@{Elastic IP}
  2. sudo apt-get update
  3. sudo apt-get upgrade

Fix "sudo: unable to resolve host ip-xx-xx-xx-xx" error message

At the time of writing, each time you enter a sudo (superuser) command, this error message keeps appearing because the system doesn't know how to resolve that AWS-generated internal IP. So we will point it at a local IP.

  1. Within the terminal, copy the local IP within the error message, eg. "ip-123-45-6-78"
  2. sudo vi /etc/hosts
  3. The top line will say    localhost. Add a new line directly below that, and enter, add a tab or some spaces, then paste the internal IP. The 2nd line should now look like this:    ip-123-45-6-78


  1. sudo dpkg-reconfigure tzdata
  2. Select your timezone using the arrow keys
  3. Check it is correct with less /etc/timezone ("less" is just a quick way of reading a file)
  4. Enter "q" to exit the file when using less


  1. sudo locale-gen de_DE.UTF-8 en_US.UTF-8
  2. sudo vi /etc/environment
  3. Add this new line if you want everything in English: LC_ALL="en_US.UTF-8" or this if you want it in German: LC_ALL="de_DE.UTF-8"
  4. Leave the SSH session using exit, then SSH back into the server
  5. Confirm your new locale settings with: locale

Unattended upgrades

Set up the server to install essential security upgrades automatically.

  1. sudo apt-get install unattended-upgrades
  2. sudo dpkg-reconfigure unattended-upgrades
  3. Choose Yes
  4. sudo vi /etc/apt/apt.conf.d/50unattended-upgrades
  5. Comment in this line and change the email address as follows: Unattended-Upgrade::Mail "";

Open up AWS firewall for HTTP access

We will want to test that Apache and PHP are working on the server, so we firstly need to open up the HTTP inbound rule on the server using the AWS console. If we don't do this, the AWS firewall will block our browser's attempt to access the server, because we only allowed SSH access in the previous section.

  1. Log into the AWS console at
  2. Choose EC2
  3. From the menu on the left, choose "Security Groups"
  4. Click on "my-security-group" and from the Actions dropdown, select "Edit inbound rules"
  5. Click "Add Rule", choose "HTTP" as the new Type, and under Source choose "My IP", then click "Save"


  1. sudo apt-get install apache2
  2. In your browser, enter your Elastic IP in the address bar, ensure you see a page saying "It works!".

Turn off autoindex, so people can't use Apache to look at the server's directory structure.

  1. sudo a2dismod autoindex

Fix the "apache2: Could not reliably determine.." error message

  1. sudo vi /etc/apache2/apache2.conf
  2. Find Global configuration about 20% of the way down, and add a new line below it: ServerName localhost

Limit the amount of information Apache gives about itself in error messages etc

  1. sudo vi /etc/apache2/conf-enabled/security.conf
  2. Find ServerTokens and change its value to Prod
  3. Just below that, change the value of ServerSignature to Off

Restart Apache. There should not be any error messages.

  1. sudo apache2ctl restart

Test the changes

  1. In your browser, enter your Elastic IP in the address bar followed by "/xxx", you should see a plain "Not Found" page without any mention of the Apache version


Install PHP.

  1. sudo add-apt-repository ppa:ondrej/php5-oldstable
  2. sudo apt-get update
  3. sudo apt-get install php5

Use the default PHP production server settings for improved security.

  1. sudo cp /usr/share/php5/php.ini-production /etc/php5/apache2/php.ini
  2. sudo cp /usr/share/php5/php.ini-production.cli /etc/php5/cli/php.ini

Set the correct timezone for time functions.

  1. sudo vi /etc/php5/apache2/php.ini
  2. About 45% down, comment in the "date.timezone" line by removing the preceding semi-colon, then change the value to whichever timezone you are in according to this list. I change mine to Europe/Berlin
  3. sudo vi /etc/php5/cli/php.ini
  4. Same as point 2

Move session data storage to a new and secure directory.

  1. sudo mkdir /etc/php5/apache2/tmp. This creates the new directory
  2. sudo chmod go-rwx /etc/php5/apache2/tmp. This removes permissions for the current group and other users
  3. sudo chown www-data /etc/php5/apache2/tmp. This changes the owner to "www-data", which is the Apache user
  4. sudo vi /etc/php5/apache2/php.ini
  5. About 70% down, comment in the "session.save_path" line, and change the value to "/etc/php5/apache2/tmp". This tells PHP to use the new directory for session data.

Restart Apache, which also refreshes the PHP settings.

  1. sudo apache2ctl restart

Test PHP and check timezone

  1. sudo vi /var/www/html/index.php
  2. Insert the text <?php echo date_default_timezone_get(); ?>
  3. In your browser, enter your Elastic IP in the address bar followed by "/index.php", ensure you see the timezone you entered previously


We will be sending mail programmatically via a Gmail account so we are not dependent on the mail functionality of any specific machine. You should have already created a Gmail account for this purpose if you completed Set up local development environment. The same account can be used here.

Install PEAR and PEAR Mail.

  1. sudo apt-get install php-pear php-net-smtp
  2. sudo pear install mail
  3. Verify installation using pear list-files Mail. The last entry should be "php /usr/share/php/Mail.php"

At the time of writing, using the Mail class generates numerous PHP warnings because the library is not up to date. PHP warnings are suppressed on the server, but we should make the following changes to update the library in any case, so we know the library is the same as on our development machine.

First Mail.php:

  1. sudo vi /usr/share/php/Mail.php
  2. On line 74, change function &factory($driver, $params = array())
    to static function &factory($driver, $params = array())
  3. On line 253 change function $addresses = Mail_RFC822::parseAddressList($recipients, 'localhost', false);
    to $Mail_RFC822 = new Mail_RFC822();
    $addresses = $Mail_RFC822->parseAddressList($recipients, 'localhost', false);

Now PEAR.php:

  1. sudo vi /usr/share/php/PEAR.php
  2. On line 250 change function isError($data, $code = null)
    to static function isError($data, $code = null)
  3. On line 472 change function &raiseError($message = null,
    to static function &raiseError($message = null,


Install Postgres and the PHP-Postgres connector.

  1. sudo apt-get install postgresql postgresql-contrib php5-pgsql

Change the default SQL password for the superuser "postgres".

  1. Open KeePass2 and add a new entry for "MyServer1 postgres". The username is "postgres". Make sure you don't mix up your local and remote passwords.
  2. sudo -u postgres psql. This takes you the Postgres psql prompt.
  3. \password postgres
  4. Copy the new password from KeePass2 and paste it, then again when prompted
  5. CTRL-d. The prompt should now return to normal. At the time of writing, I get a "could not save history to file" error message. Don't worry about it.

There is now also a Linux user called "postgres". Change the password of this user to match the SQL password.

  1. sudo passwd -d postgres
  2. sudo su postgres -c passwd
  3. Copy the same password as above from KeePass2 and paste it, then again when prompted

Improve log output and set timezone.

  1. sudo vi /etc/postgresql/9.3/main/postgresql.conf
  2. About 66% down, change the value of "log_line_prefix" to '%m | %u@%d | %p | %r | %e |'
  3. Just below that, change the value of "log_timezone" to whichever timezone you used for PHP above. So for me it is 'Europe/Berlin'
  4. About 87% down, change the value of "timezone" to the same value as point 2

NOTE: there are many other useful and important settings you can change in "postgresql.conf", but for our little website with its test data, the remaining default settings are fine.

Restart Postgres.

  1. sudo service postgresql restart

pgAdmin and Port Forwarding

pgAdmin is a great GUI for doing work on your Postgres database. It should be installed on your local computer if you were following the previous steps in Set up local development environment. Here is how you use your local pgAdmin to manage the Postgres installation on your server.

Firstly, we SSH into the server using Port Forwarding. You may have seen that Postgres uses port 5432 both locally and on the server. With port forwarding, we will assign one of our unused local ports to behave as if it were a port on the server. We will assign our local unused port 5433 to behave like port 5432, the Postgres port, on the server.

  1. Leave the current remote session with exit
  2. Re-enter with port forwarding, remember to change the path and the IP: ssh -i /path/to/my-key-pair.pem ubuntu@{Elastic IP} -L 5433:localhost:5432

Now as long as we remain SSH'd into the server, we can use our port 5433 to access Postgres on the server. Set up pgAdmin as follows.

  1. Open the pgAdmin GUI on your computer
  2. Click on "Add a connection to a server" in the top left
  3. Under Name, enter "MyServer1", since that is the name of the server we will be connecting to
  4. Under Host, enter "localhost"
  5. Under Port, enter "5433"
  6. Under Password, copy the postgres password from KeePass2
  7. Optional: assign a colour, as I have done in the picture above. This helps differentiate your local Postgres from your server's Postgres. It is critical to always remember where you are, especially when you start deleting things.
  8. Press "OK". There should be a new entry under Servers called "MyServer1 (localhost:5433)"
  9. Note: when you click on the Postgres database, you may get a message about Server Instrumentation. Click the button "Fix now!", if you see it

The server is now pretty much ready to go and we could start moving our application over and doing the final tweaks (Deploy the site) but there are some other optional AWS and server admin guides to look at too.

comments powered by Disqus