A research organization’s experiment records are the foundation of its intellectual property, and, as such, must be stored in a way that allows the research organization to maintain control over these records. Enterprise electronic notebooks, such as our iExperiment, store their experiment records on a server. Many organizations, including Colabrativ, Inc., are using cloud computing to lower the cost of a server and IT costs in general. Amazon’s Elastic Compute Cloud (EC2) is one of the lower cost cloud service providers. Amazon is Statement on Auditing Standards No. 70 (SAS70) compliant. They completed the Type II audit in 2009 (see AWS Completes SAS70 Type II Audit announcement). Thus, one can be comfortable that they are doing everything they can to keep one’s data secure. Amazon Web Services places the responsibility of the enterprise application setup and maintenance on the client’s administrator. Other full-service SAS70-compliant cloud service providers will happily take on these responsibilities for you, for a fee.
In my previous post, I described the Setup of Amazon’s Elastic Compute Cloud (EC2) Server for iExperiment, our enterprise electronic notebook application. That post covered the following topics:
- iExperiment Server Requirements
- Setup of Amazon Web Services EC2 Instance
- Creating and Attaching an Elastic Block Storage Volume (optional)
- Assigning URL of the iExperiment EC2 Server on the DNS Server
You may want to take a quick look at iExperiment Server Requirements.
In this post we will go over the setup and configuration of the EC2 server and the installation and setup of iExperiment on it. Topics in this post include:
- Updating the EC2 Server
- Mounting Elastic Block Storage Volume (optional)
- Installing MySQL
- iExperiment Database Setup
- SSL Certificate Creation
- Set Up of Apache and Tomcat
- Adding index.html
- iExperiment Applications Installation
- Removing Port 8443 from HTTPS Requests
The majority of these tasks are preformed on the iExperiment EC2. Tests of the server’s operation were made using Firefox 5. We use PuTTY to log onto our EC2 server (Instructions can be found in an Amazon appendix on PuTTY.
Updating the EC2 Server using Amazon’s Yum repository
The update of the EC2 server from Amazon’s Yum repository takes only a single command “sudo yum update”. It produces a large output. During the update you will be asked two yes-no question. You should answer “yes” to both of these questions. Below I have edited the session to only include the yum command and text around the two questions.
> sudo yum update ... =============================================================================== Install 1 Package(s) Upgrade 47 Package(s) Total download size: 113 M Is this ok [y/N]: Y ... Importing GPG key 0x21C0F39F "Amazon Linux AMI (Beta)" from /etc/pki/rpm-gpg/RPM-GPG-KEY-amazon-beta Is this ok [y/N]: Y
Mounting Elastic Block Storage Volume (optional)
In order to format the elastic block storage (EBS) volume, we need to install XFS filesystem utilities (xfsprogs) from the Amazon Yum repository.
The /proc/partitions file contains a list of the volumes associated with the EC2 instance. The /dev/xvda1 device is the system volume. The other volume is the unformatted EBS volume we associated with the EC2 instance. The EBS volume has two related device names; the system refers to the device as dev/xvd[f-p], but mkds.xfs takes /dev/sd[f-p]. In the case below, the device names are /dev/xsdf and /dev/sdf, respectively.
- Format the EBS volume using mkfs.xfs and the device name (/dev/sdf)
- Create a mount point for the volume (/ebs1).
- Add the mount point to the /etc/fstab file.
- Mount the volume.
> sudo yum install xfsprogs Is this ok [y/N]: y > more /proc/partitions major minor #blocks name 202 1 8388608 xvda1 202 80 10485760 xvdf > sudo mkfs.xfs /dev/sdf meta-data=/dev/sdf isize=256 agcount=4, agsize=65536 blks = sectsz=512 attr=2 data = bsize=4096 blocks=2621440, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 log =internal log bsize=4096 blocks=2560, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0sudo vi /etc/fstab > sudo mkdir /ebs1 > sudo cp -p /etc/fstab /etc/fstab.orig > sudo vi /etc/fstab > more /etc/fstab # LABEL=/ / ext4 defaults,noatime 1 1 tmpfs /dev/shm tmpfs defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 sysfs /sys sysfs defaults 0 0 proc /proc proc defaults 0 0 /dev/xvdf /ebs1 xfs noatime 0 0 > sudo mount /ebs1
After mounting the EBS volume on /ebs1, we create and link both the iExperiment and MySQL directories. We add the mounts to the /etc/fstab file, then mount the directories.
> sudo mkdir /ebs1/etc > sudo mkdir /ebs1/etc/mysql > sudo mkdir /ebs1/lib > sudo mkdir /ebs1/lib/mysql > sudo mkdir /ebs1/log > sudo mkdir /ebs1/log/mysql > sudo mkdir /ebs1/log/iexperiment > sudo mkdir /ebs1/local/iexperiment > sudo mkdir /etc/mysql > sudo mkdir /var/lib/mysql > sudo mkdir /var/log/mysql > sudo mkdir /var/log/iexperiment > sudo mkdir /var/local/iexperiment > sudo vi /etc/fstab > more /etc/fstab # LABEL=/ / ext4 defaults,noatime 1 1 tmpfs /dev/shm tmpfs defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 sysfs /sys sysfs defaults 0 0 proc /proc proc defaults 0 0 /dev/xvdf /ebs1 xfs noatime 0 0 /ebs1/etc/mysql /etc/mysql none bind /ebs1/lib/mysql /var/lib/mysql none bind /ebs1/log/mysql /var/log/mysql none bind /ebs1/log/iexperiment /var/log/iexperiment none bind /ebs1/local/iexperiment /var/local/iexperiment none bind > sudo mount /etc/mysql > sudo mount /var/lib/mysql > sudo mount /var/log/mysql > sudo mount /var/log/iexperiment > sudo mount /var/local/iexperiment
If MySQL has already been installed and setup, then instead of making the /mysql directories, we would move (mv) the existing MySQL directories to the EBS volume. We continue from the snippet above remaking mysql directories that are used as mount bind points.
> sudo mkdir /ebs1/etc > sudo mkdir /ebs1/lib > sudo mkdir /ebs1/log > sudo mv /etc/mysql /vol/etc/ > sudo mv /var/lib/mysql /vol/lib/ > sudo mv /var/log/mysql /vol/log/ > sudo mkdir /etc/mysql ...
Installing MySQL
MySQL and MySQL Server (mysqld) are available from the Amazon Yum repository. Like update snippets above, the snippet below has been edited to show only what is necessary.
> sudo yum install mysql Is this ok [y/N]: y > sudo yum install mysql-server Is this ok [y/N]: y
After installing MySQL and MySQL Server, we start the MySQL service.
> sudo service mysqld start Initializing MySQL database: Installing MySQL system tables... OK Filling help tables... OK To start mysqld at boot time you have to copy support-files/mysql.server to the right place for your system PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER ! To do so, start the server, then issue the following commands: /usr/bin/mysqladmin -u root password 'new-password' /usr/bin/mysqladmin -u root -h ip-10-176-31-62 password 'new-password' Alternatively you can run: /usr/bin/mysql_secure_installation which will also give you the option of removing the test databases and anonymous user created by default. This is strongly recommended for production servers. See the manual for more instructions. You can start the MySQL daemon with: cd /usr ; /usr/bin/mysqld_safe & You can test the MySQL daemon with mysql-test-run.pl cd /usr/mysql-test ; perl mysql-test-run.pl Please report any problems with the /usr/bin/mysqlbug script! [ OK ] Starting mysqld: [ OK ]
Finally the mysql_secure_installation script is run.
> /usr/bin/mysql_secure_installation NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY! In order to log into MySQL to secure it, we'll need the current password for the root user. If you've just installed MySQL, and you haven't set the root password yet, the password will be blank, so you should just press enter here. Enter current password for root (enter for none): OK, successfully used password, moving on... Setting the root password ensures that nobody can log into the MySQL root user without the proper authorisation. Set root password? [Y/n] Y New password: Re-enter new password: Password updated successfully! Reloading privilege tables.. ... Success! By default, a MySQL installation has an anonymous user, allowing anyone to log into MySQL without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. Remove anonymous users? [Y/n] Y ... Success! Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network. Disallow root login remotely? [Y/n] Y ... Success! By default, MySQL comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment. Remove test database and access to it? [Y/n] Y - Dropping test database... ... Success! - Removing privileges on test database... ... Success! Reloading the privilege tables will ensure that all changes made so far will take effect immediately. Reload privilege tables now? [Y/n] Y ... Success! Cleaning up... All done! If you've completed all of the above steps, your MySQL installation should now be secure. Thanks for using MySQL!
Set Up the iExperiment Database
- Log in as root to the MySQl database. We recommend that you not put the root password in the mysql command, so that it does not end up in .bash_history.
- Create a user ‘iexperiment‘@‘localhost‘.
- Grant the iexperiment user appropriate privileges.
> mysql -h localhost -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 9 Server version: 5.1.52 Source distribution Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. This software comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to modify and redistribute it under the GPL v2 license Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> create user 'iexperiment'@'localhost' identified by 'iexperimentpassword'; Query OK, 0 rows affected (0.00 sec) mysql> grant usage on *.* to 'iexperiment'@'localhost'; Query OK, 0 rows affected (0.00 sec) mysql> grant all privileges on *.* to 'iexperiment'@'localhost'; Query OK, 0 rows affected (0.00 sec) mysql> exit Bye
- Create the /var/log/iexperiment, /var/local/iexperiment and /var/local/iexperiment/ddl directories.
- Upload the iExperiment SQL files to the /var/local/iexperiment/ddl directory using an FTP application that supports SSL, such at FileZilla.
> sudo mkdir /var/log/iexperiment > sudo mkdir /var/local/iexperiment > sudo mkdir /var/local/iexperiment/ddl
- Log in to MySQL as iexperiment.
- Create a database named iexperiment.
- Load the database by sourcing the initial_setup.sql file.
> pushd /var/local/iexperiment/ddl /var/local/iexperiment/ddl ~ > ls -lt total 136 -rw-rw-r-- 1 root root 917 Jul 17 21:22 initial_setup.sql -rw-rw-r-- 1 root root 3465 Jul 17 21:08 insert_permissions_START-UP.sql -rw-rw-r-- 1 root root 944 Jul 17 21:08 insert_admin_START-UP.sql -rw-rw-r-- 1 root root 22612 Jul 14 17:33 create_tables.sql -rw-rw-r-- 1 root root 73893 Jul 14 17:09 insert_record_categories.sql -rw-rw-r-- 1 root root 18355 Jul 14 17:09 create_constraints.sql -rw-rw-r-- 1 root root 932 Jul 14 17:08 insert_admin.sql > mysql -h localhost -u iexperiment -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 12 Server version: 5.1.52 Source distribution Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. This software comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to modify and redistribute it under the GPL v2 license Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show grants; +-----------------------------------------------------------------------------------------------------------------------------+ | Grants for iexperiment@localhost | +-----------------------------------------------------------------------------------------------------------------------------+ | GRANT ALL PRIVILEGES ON *.* TO 'iexperiment'@'localhost' IDENTIFIED BY PASSWORD '*BAA33824FACE624B5B0AAC8A604733A5648A7A6B' | +-----------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> create database iexperiment; Query OK, 1 row affected (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | iexperiment | | mysql | +--------------------+ 3 rows in set (0.00 sec) mysql> use iexperiment; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> source initial_setup.sql; Query OK, 1 row affected (0.00 sec) . . . Query OK, 1 row affected (0.00 sec) mysql> show tables; +------------------------+ | Tables_in_iexperiment | +------------------------+ | admin_group_member | | ... | version | +------------------------+ 55 rows in set (0.00 sec) mysql> select * from version; +-------------+----------------------------------+ | version_num | comment | +-------------+----------------------------------+ | 6 | May 25, 2010 - Switch to Records | +-------------+----------------------------------+ 1 row in set (0.00 sec) mysql> exit Bye
Create SSL Certificate
iExperiment runs under the secure HTTPS protocol; thus, we need a Secure Sockets Layer (SSL) certificate. If you already have a wildcard certificate for your domain, then you can skip this step.
Note, that if you use a self-signing certificate, then your iExperiment users will be notified of this. In FireFox they will see a “This Connection is Untrusted” page, in which they will need to open the “I understand the Risks” link and click on the “Add Exception…” button.
- Make a directory for the SSL certificate.
- Generate the self-signing SSL certificate. In the snippet below, the certificate’s file name, temp.iexperiment.bin, reflects the URL we are using.
> sudo mkdir /usr/etc/cert > cd /usr/etc/cert > sudo keytool -genkey -alias tomcat -keypass sslcert1 -keystore temp.iexperiment.bin -storepass sslcert1 What is your first and last name? [Unknown]: Marc Whitlow What is the name of your organizational unit? [Unknown]: What is the name of your organization? [Unknown]: Colabrativ, Inc. What is the name of your City or Locality? [Unknown]: El Sobrante What is the name of your State or Province? [Unknown]: California What is the two-letter country code for this unit? [Unknown]: US Is CN=Marc Whitlow, OU=Unknown, O="Colabrativ, Inc.", L=El Sobrante, ST=California, C=US correct? [no]: y > ls -l total 4 -rw-r--r-- 1 root root 1292 Jul 18 02:30 temp.iexperiment.bin
Write down the certificate “keypass” as you will need it to set up Tomcat.
Setup Apache & Tomcat
- Install Apache Hypertext Transfer Protocol Server (httpd), Apache Tomcat 6 (tomcat6), Tomcat’s web application service (tomcat6-webapps) and Apache Interface to OpenSSL (mod_ssl) from Amazon’s Yum repository.
- Start the Apache (httpd) and Tomcat (tomcat6) services.
> sudo yum install httpd Is this ok [y/N]: y > sudo yum install tomcat6 Is this ok [y/N]: y > sudo yum install tomcat6-webapps Is this ok [y/N]: y > sudo yum install mod_ssl Is this ok [y/N]: y > sudo service httpd start Starting httpd: [ OK ] > sudo service tomcat6 start Starting tomcat6: [ OK ]
Now we can check to see if the “Amazon Linux AMI Test Page” loads in a Browser using:
- EC2 Instance’s public URL that is found in the EC2 Instance information on the AWS Management Console, e.g. http://ec2-204-236-137-138.us-west-1.compute.amazonaws.com
- The URL that was assigned to the Elastic IP address associated with the EC2 Instance in the Domain Name Server (DNS), e.g. http://temp.iexperiment.net/
Next, we will configure Tomcat to support applications and services under the secure https protocol on port 8443. We do this by editing the server.xml file in /etc/tomcat.
> cd /etc/tomcat6 > sudo cp -p server.xml server.xml.orig > sudo vi server.xml > diff server.xml.orig server.xml 83,88c83,92 < < --- > >protocol="HTTP/1.1" > SSLEnabled="true" > maxThreads="150" > scheme="https" secure="true" > clientAuth="false" sslProtocol="TLS" > keystoreFile="/usr/etc/cert/temp.iexperiment.bin" > keystorePass="sslcert1" /> > sudo service tomcat6 restart Stopping tomcat6: [ OK ] Starting tomcat6: [ OK ]
We should now beable to see the sample web applications supplied with the tomcat6-webapps Yum distribution found in /var/lib/tomcat6/webapps/sample, using the following URLs:
- “EC2 Public URL”:8080/sample e.g. http://ec2-204-236-137-138.us-west-1.compute.amazonaws.com:8080/sample
- http://”iExperiment Domain”:8080/sample, e.g. http://temp.iexperiment.net:8080/sample
- https://”iExperiment Domain”:8443/sample, e.g. https://temp.iexperiment.net:8443/sample
Adding index.html
Upload the iExperiment index.html page and any images associated with the page to the /var/www/html directory. You can either overwrite the existing index.html page or rename it.
iExperiment Applications Installation
iExperiment has three applications: Admin, Record and ResetPassword.
- Upload the iExperiment applications .war files (admin.war, record.war and resetPassword.war) to the /var/lib/tomcat6/webapps/ directory in the EC2 server.
- Stop the Tomcat service.
- Create directories for the attachments and the Lucene search engine index.
- For each of the iExperiment applications.
- Create a directory for the application in /var/lib/tomcat6/webapps/
- Change the group to tomcat.
li>Unzip the contents of the war file into the newly created directory.
- Upload and replace the “application”.html file with deployment specific version.
- Add deployment specific images to the images directory.
- Upload and replace existing iexperiment.properties, dbpool.properties and log4j.properties with files specific for this deployment.
> sudo service tomcat6 stop Stopping tomcat6: [ OK ] > sudo mkdir /var/local/iexperiment/attachments > sudo mkdir /var/local/iexperiment/lucene > sudo chown -R tomcat:tomcat /var/local/iexperiment/* > cd /var/lib/tomcat6/webapps/ > ls -lt total 12 drwxrwxr-x 5 root tomcat 4096 Jul 14 14:53 sample drwxrwxr-x 5 root tomcat 4096 Jul 14 14:53 examples drwxrwxr-x 3 root tomcat 4096 Jul 14 14:53 ROOT > sudo mkdir record > sudo mkdir admin > sudo mkdir resetPassword > sudo chgrp tomcat * # Begein of admin application configuration. > pushd admin > sudo unzip ../admin.war # After uploading Admin.html > sudo chown -R root:root *.html # After uploading deployment specific images to the images diectory. > pushd images > sudo chown -R root:root * > popd # After uploading the deployment specific properties files # to the WEB-INF/classes directory > pushd WEB-INF/classes/ > sudo chown -R root:root *.properties > ls -lt total 28 -rw-rw-r-- 1 root root 1287 Jul 14 18:33 log4j.properties -rw-rw-r-- 1 root root 2020 Jul 14 18:33 iexperiment.properties -rw-rw-r-- 1 root root 1514 Jul 14 18:33 dbpool.properties drwxr-xr-x 3 root root 4096 Jul 14 17:49 net drwxr-xr-x 3 root root 4096 Jul 14 17:49 org drwxr-xr-x 4 root root 4096 Jul 14 17:49 com -rw-r--r-- 1 root root 1370 May 3 19:05 mail.properties # End of admin application configuration. # Repeat for the record and resetPassword applications. > sudo service tomcat6 start Starting tomcat6: [ OK ]
Removing Port 8443 from HTTPS Requests
The final task in setting up the iExperiment Server is to remove the port number from the secure https requests. We do this by relay the port 443 TCP connections to port 8443 using iptables in the Netfilter package that already installed on the EC2 instance.
- Using iptables redirect the incoming port 443 request to port 8443.
- Using iptables redirect the output from the incoming port 443 request to port 8443.
- We can see these rules in the “nat” table using the command “sudo iptables -t nat -L”.
- Save the iptable in /etc/iptables.conf, and change ownership to root.
- Finally, add “/sbin/iptables-restore < /etc/iptables.conf” to the bottom to /etc/rc.local file.
> sudo iptables -t nat -I PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8443 > sudo iptables -t nat -I OUTPUT -p tcp --dport 443 -j REDIRECT --to-ports 8443 > sudo iptables -t nat -L Chain PREROUTING (policy ACCEPT) target prot opt source destination REDIRECT tcp -- anywhere anywhere tcp dpt:https redir ports 8443 Chain OUTPUT (policy ACCEPT) target prot opt source destination REDIRECT tcp -- anywhere anywhere tcp dpt:https redir ports 8443 Chain POSTROUTING (policy ACCEPT) target prot opt source destination > sudo iptables-save > iptables.conf > more iptables.conf # Generated by iptables-save v1.4.7 on Thu Sep 8 03:32:23 2011 *nat :PREROUTING ACCEPT [5:300] :OUTPUT ACCEPT [50:3801] :POSTROUTING ACCEPT [50:3801] -A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8443 -A OUTPUT -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8443 COMMIT # Completed on Thu Sep 8 03:32:23 2011 > sudo cp -p iptables.conf /etc/. > sudo chown -R root:root /etc/iptables.conf > sudo ls -l /etc/iptables.conf -rw-rw-r-- 1 root root 332 Sep 8 03:32 /etc/iptables.conf > sudo vi /etc/rc.local > more /etc/rc.local #!/bin/sh # # This script will be executed *after* all the other init scripts. # You can put your own initialization stuff in here if you don't # want to do the full Sys V style init stuff. touch /var/lock/subsys/local /sbin/iptables-restore < /etc/iptables.conf
Closing Remarks
iExperiment run on a typical AWS Apache Tomcat deployment.
Resources
- “Configuring MySQL to use the EBS volume” section of Eric Hammond’s article on Running MySQL on Amazon EC2 with EBS (Elastic Block Store).
- Installing Apache Tomcat on Linux by Werner Puschitz.
- How Do I Save Iptables Rules or Settings? by Vivek Gite.