Installing dotCMS on Amazon AMI (CentOS) instance

Will Ezell

This is a procedure to get up and running with dotCMS on an Amazon EC2 instance, using the Amazon AMI (CentOS). This procedure should work fine on regular servers/VMs, too. DotCMS is very powerful and highly configurable with many moving parts, but basic
installation is really not that involved. Once you see how a basic server comes together, you'll quickly see how dotCMS can be grown to clusters, with separate database servers, etc. The big setups aren't that much different.

To get dotCMS up and running, we need the following:

1. An Amazon EC2 instance
2. Oracle Sun Java, JDK6
3. A database
4. Apache Ant
5. The dotCMS software itself

First, the Amazon EC2 instance. Lately, we've been setting up servers in CentOS, because that's the flavor Amazon has blessed for it's own
homebrew AMI, and they've optimized it for their system. So we'll be going with the Amazon AMI here. Nothing wrong with other Linux flavors, in
fact Debian/Ubuntu is well loved by a lot of us at dotCMS, and currently running many successful installations. As far as instance type, I like to use
the cc1 high-CPU instance, but lesser instances will get you of the ground. DotCMS often benefits more from extra CPU power than from extra

Now, this is not meant to be an EC2 tutorial, so I am going to assume you have downloaded and are ready with the .pem key that Amazon
provided you, and you and your command line are patiently waiting for me.

Next is Java. DotCMS is picky about this one, and wants the real deal, 100% Genuine OEM Oracle Sun Java. As of September 2012, the
download page is at . Click the JDK download button for version 6. On the next page
you'll need to click a radio button to agree before the download links will work. I find this part especially annoying, because it prevents use of
tools like wget, which would help greatly here. I have Googled for ways around this, and every time some braniac figures out a new way around
Oracle's hook and puts up a how-to, Oracle plugs the hole. Agh. Oracle wants you to go through a browser, period. Sure, I could install a graphical
environment with VPN and Firefox, but we're doing a headless install here, because I don't want to pay Amazon extra money for the precious
resources to run all that. So sitting on my Mac, I clicked on the link for jdk-6u34-linux-x64-rpm.bin, which downloads it into my Mac's Downloads
folder. From here we can use scp to get it up to the new server. I use the -i option to specify the location of my .pem login key:

scp -i /Users/matt/keys/dotcms.pem /Users/matt/Downloads/jdk-6u34-linux-x64-rpm.bin ec2-user@ec2-50-17-122-

In that command, I specified the location of my key on my Mac, the location of the java download file in the Downloads folder on my Mac, and the
place where I wanted to put it- the home folder of the ec2-user at

Now login to the server. We need to see if other Java installations are on this system, and erase them. It is possible to have multiple Java versions
on the system, and chose the one the system will pay attention to, but I'm one of those that likes to make double and triple-sure the wrong Java will
never be found. I check for the existence of other Javas by running the following commands:

rpm -qa | grep jre
rpm -qa | grep jdk
rpm -qa | grep openjdk

In this case it showed one installation of Java, java-1.6.0-openjdk- We need to get that out of there:

yum -y erase java-1.6.0-openjdk-

I like to create a folder for downloaded stuff called /usr/local/incoming:

mkdir /usr/local/incoming

Now we move the Java upload into place:

mv /home/ec2-user/jdk-6u34-linux-x64-rpm.bin /usr/local/incoming/jdk-6u34-linux-x64-rpm.bin

Set perms/ownership:

chown root:root /usr/local/incoming/jdk-6u34-linux-x64-rpm.bin
chmod 700 /usr/local/incoming/jdk-6u34-linux-x64-rpm.bin

Change directories and run the bin installer:

cd /usr/local/incoming

At the end we are prompted to hit the ENTER key before it lets us proceed.

Now we set the JAVA_HOME environment variable. This frst command sets it temporarily (for as long as we're logged in), and the second one will ensure the variable is set for subsequent logins:

export JAVA_HOME=/usr/java/jdk1.6.0_34
echo "export JAVA_HOME=/usr/java/jdk1.6.0_34" >> /root/.bashrc

Now we are going to have a quick look at the alternatives command output. Alternatives would let us choose which of many installed Java versions we wanted the system to recognize, but we made sure to wipe out all existing versions before installing, so it's probably unnecessary, but we're
going to do it anyway. Nothing wrong with doting the i:

First we type the command that makes our new Java install the system's preferred Java:

alternatives --install /usr/bin/java java /usr/java/jdk1.6.0_34/jre/bin/java 1

Now we verify that our installation of Java is the one in use by the system (and of course the only one in the list):

alternatives --config java

There is 1 program that provides 'java'.

Selection        Command
*+ 1              /usr/java/jdk1.6.0_34/jre/bin/java

Allright! We have a server and we have the right Java on it. Now on to the database. At dotCMS, we are very fond of PostgreSQL, although MySQL, Oracle and MS SQL are also supported. We don't need much too fancy here, just a database and create rights.

Get Postgres installed:

yum -y install postgresql9-server.x86_64

Initialize postgresql:

service postgresql initdb -D /var/share/pgsql

We need to make edits to Postgres' pg_hba.conf file. It defines a bunch of things, but we are interested in the stuff near the bottom of the file. I use vi as my editor:

vi /var/lib/pgsql9/data/pg_hba.conf

Now, there are different settings that can be used here, and you really ought to refer to the excellent PostgreSQL documentation for in-depth info on these settings. The settings below are to trust "localhost", and ask for a password on "". You might prefer to use "ident", or you might have no problem with the "trust" setting for all... it's up to you, but the below will work:

# "local" is for Unix domain socket connections only
# IPv4 local connections:

Fire up PostgreSQL:

service postgresql start

As part of the above steps, a new "postgres" user was created on the system. We need to login as that postgres user, to issue some commands. I
am going to su from root to the user:

su - postgres

One particular gotcha with Postgres and dotCMS: Postgres did not until recently support procedural languages "out-of-the-box".  To enable procedural languages, run the following command in postgres before running any CREATE DATABASE commands:

createlang plpgsql template1

This may only be an issue if you're working with an older version of PostgreSQL. If you are installing the latest PostgreSQL, you're probably going to get a message back that says this is already set. Cool, and no harm done.

Now we are going to use PostgreSQL's psql command to enter a couple commands. The psql command drops you into a new prompt- you're talking directly to PostgreSQL here, and when done, we are going to get back to our regular UNIX shell prompt. We are going to create our
database with the CREATE DATABASE command, then give create privileges on our database to the postgres user. Not all of the settings in my CREATE DATABASE command are necessary. I specified no limits on connections, for example (CONNECTION LIMIT = -1). That might not
always be a good idea for your setup, but no big deal for now. Read the PostgreSQL documentation for details.

psql -d template1 -U postgres

Create the database:


Assign create rights on our database to the postgres user:

GRANT CREATE on database "dotcms" to postgres;

We need to have a quick peek to see what we did. In psql, listing databases is done by entering a backslash followed by a lower-case letter l:


You should see output similar to the following:

                                                    List of databases
Name  | Owner  | Encoding |  Collate  | Ctype  |  Access privileges
dotcms | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres+ postgres=CTc/postgres
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |=c/postgres +postgres=CTc/postgres 
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |=c/postgres +postgres=CTc/postgres

Now we are going to set the postgres user's password:

ALTER ROLE postgres WITH PASSWORD 'abc123';

Now quit psql, with a backslash followed by a letter q:

We are still in the postgres user's UNIX shell. We need to do a quick test of our database access:

psql -h "dotCMS" -W

You should now be back on the psql command line again. Log out:


Now just for yucks, try it with a bad password:

psql -h "dotCMS" -W

A bad password should have rejected you, and you should not be on the psql command line.

Remember we are still in the postgres user's UNIX shell, so let's get out of the postgres user's shell now, back to root:


On to Apache Ant. Ant is going to build the dotCMS Java source code for us. There exists a zip file dotCMS installation method which does not require the use of Apache Ant, but here we are working with source code. Don't let that scare you though, what we need to do with Ant is pretty
minimal, and you need not be an Ant expert. First let's go to that /usr/local/incoming folder we created earlier:

cd /usr/local/incoming

Now, I like to be on the latest versions of things when I can. Turns out that yum is a bit outdated with Ant. Yum wants to install Ant version 1.8.2.
The Apache Ant page has 1.8.4 available, so I am going to go there to get that binary install:


Extract it:

tar -zxvf apache-ant-1.8.4-bin.tar.gz

Issue some environment commands so the system finds Ant when we need it:

export ANT_HOME=/usr/local/incoming/apache-ant-1.8.4
echo "export ANT_HOME=/usr/local/incoming/apache-ant-1.8.4" >> /root/.bashrc
export PATH=$PATH:${ANT_HOME}/bin
echo "export PATH=$PATH:${ANT_HOME}/bin" >> /root/.bashrc

Now we need the optional stuff for Ant. The casual UNIX admin might think Ant is fully installed after running the installer, but nope, there's an extra step. Pretty simple though, just run these commands:

ant -f fetch.xml -Ddest=optional

Now a quick version test tells us Ant is found on our UNIX path and is talking back to us:

ant -version

You should see something like this:

Apache Ant(TM) version 1.8.4 compiled on May 22 2012

Okay! Finally we can get our copy of dotCMS downloaded and installed. There are several procedures that could be written for the various methods of downloading and installing dotCMS. This can seem a bit confusing at first, but stick with me here.

First we need to create a place for dotCMS to live. At dotCMS, we like to create a wwwroot folder in the root of the machine/instance:

mkdir /wwwrooot

Get into that directory:

cd /wwwroot/

Now grab a copy of the tarball install & unarchive:

tar xvf ./2.1.1

Set the startup scripts to execute. We should cd to the root of the installation first, /wwwroot/dotCMS-dotCMS-f469648, before running the other

cd /wwwroot/dotCMS-dotCMS-f469648
chmod 755 ./bin/*.sh
chmod 755 ./tomcat/bin/*.sh

Out of the box, dotCMS will run on port 80, but if you need it to run on a different port, say 8080, you'd want to make that change in Tomcat's server.xml file. If you are happy with port 80 (at least for now), then we don't need to mess with this file now.

vi tomcat/conf/server.xml

Now we need to set up the database connector. This is the authentication/login info that dotCMS needs to talk to the database.

vi tomcat/conf/Catalina/localhost/ROOT.xml

Notice we have four different database connectors listed here for different database vendors, PostgreSQL, MySQL, Oracle and MS SQL. Now, XML is using "<!--" to begin a comment, and " -->" to denote the end of a comment. Everything inside those tags is ignored when parsing. Notice
that all the connectors (except the several lines that make up the PostgreSQL connector) are commented out.

We want to make our PostgreSQL connector reflect the database name and password we set up earlier. In this case our connector info should look like below. The lines that begin with "url" and "username" are where the edits happen. Check the url (ends with the name of the database),
and the user and password:

<Resource name="jdbc/dotCMSPool" auth="Container"
username="postgres" password="abc123" maxActive="60" maxIdle="10" maxWait="60000"
removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"
validationQuery="SELECT 1" testOnBorrow="true" />

Here's where Apache Ant comes in. Make sure we are still sitting in the root of the installation:

cd /wwwroot/dotCMS-dotCMS-f469648/

Build the installation:

ant deploy

Now we are ready to fire it up! Make sure we are still in the root of the installation:

cd /wwwroot/dotCMS-dotCMS-f469648/

As part of the command to startup dotCMS, good practice is to tail the dotcms log, so we can catch any errors. The problem with a brand new installation is, there is no logfile yet because dotCMS has not started yet to create a logfile, and it will barf the first time around if we don't do
something first. So we are going to use the touch command to create an empty file:

touch tomcat/logs/dotcms.log

Now, at last, for the grand startup command, including tailing the log. I know I have been a pain about this, but I cannot stress enough how important it is to be in the installation root, especially now that we are starting up. Run these startup scripts sitting here in the root of the installation,
and not from anywhere else:

./bin/; tail -f tomcat/logs/dotcms.log

A lot of info is going to be produced here. Startup may take a minute or two, expecially the first time out where dotCMS wants to set a lot of things up with PostgreSQL.

Now we can check our favorite browser to see if dotCMS has itself together yet. Just http to that Amazon address we were assigned:

If all is well, we will see the starter website that comes with the default installation of dotCMS.

So that's really it. We can get more complicated by spreading acrosss a cluster, load balancing, putting PostgreSQL on a different server and configuring the settings in pg_hba.conf... lots of options, but not too tough once you see the different pieces.

Will Ezell
Chief Technology Officer
September 05, 2012

Filed Under:

amazon ami amazon ec2

Recommended Reading

Beware of CMS Fads

This blog warns against adopting new technologies without sufficient consideration, using examples to illustrate how jumping on trends can lead to wasted resources.

24.04.24 LTS: Upgrade to the Universe

Now available: dotCMS 24.04.24 LTS, the first long-term supported release of 2024

Getting started with the dotCMS Universal Visual Editor with Next.js

In this blog post, I’ll demonstrate how you can get started with the Universal Visual Editor and Next.js in just fifteen minutes.