Home

July 7, 2014

Guide to Installing Apache Solr 4.9, Tomcat 7 on RHEL 7

Goals

  • Serve up Apache Solr on port 80 via Tomcat
  • Leave Tomcat running on port 8080 and forward traffic to it from port 80.
  • Ensure Tomcat starts at server startup.

Background

Recently, I needed to install Apache Solr 4.9.0 and Apache Tomcat 7 on a RHEL7 server. I’m posting the details of how I set it up because someone may benefit from them, for two primary reasons: 1) RHEL does not have the latest and greatest packages (by design), unlike its Fedora and CentOS counterparts, so yum is not of much use here, and 2) RHEL7, released for general use in June 2014, replaced sysvinit with systemd, which requires that any custom initialization routines (in this case, starting Tomcat and persisting iptables rules) be written as systemd services.

I used an EC2 instance during this setup process, but nothing I did or made use of is specific to EC2, you can use any newly configured RHEL7 instance.

Initial Configuration of Amazon EC2 Instance

  • If you’re not using EC2 and can already SSH in to your machine, you can skip this section.
  • Added instance of ami-77d7a747 (RHEL-7.0GAHVM-x86_64-3-Hourly2) as m1.large
    • Assigned Elastic IP to instance.
    • Attached Security Group allowing inbound TCP traffic on port 22 and all ICMP traffic.
    • Booted instance.
  • Logged into instance as UNIX user ec2-user.
    • sudo -i to gain root
    • nano /etc/ssh/sshd_config
      • Changed PermitRootLogin from yes to no
    • systemctl restart sshd
    • mkdir /usr/local/tomcat -> this is the $CATALINA_HOME / $CATALINA_BASE for your Tomcat install
    • useradd -Mb /usr/local tomcat -> use $CATALINA_HOME for the tomcat user’s base directory, and don’t install a home directory
    • chown -R tomcat:tomcat /usr/local/tomcat
    • useradd mquinn
    • passwd mquinn
    • cp -R /home/ec2-user/.ssh /home/mquinn/.ssh -> copies the allowed public SSH key details from the default UNIX user set up by EC2 to the mquinn user, which I’ll be logging in as from now on.
    • chown -R mquinn:mquinn /home/mquinn/.ssh
    • visudo added line: mquinn ALL=(ALL) ALL
  • Logged out as UNIX user ec2-user; for the rest of the process, I use the mquinn UNIX user account I created above.

Install Apache Tomcat 7.0.54

  • Logged into instance as UNIX user mquinn
  • cd ~
  • sudo yum install java-1.7.0-openjdk java-1.7.0-opendjk-devel wget nano
  • sudo wget http://www.webhostingjams.com/mirror/apache/tomcat/tomcat-7/v7.0.54/bin/apache-tomcat-7.0.54-fulldocs.tar.gz
  • tar xvf apache-tomcat*.tar.gz
  • sudo cp -R apache-tomcat*/* /usr/local/tomcat
  • sudo chown -R tomcat:tomcat /usr/local/tomcat
  • Modified the EC2 Security Group associated with the instance to allow inbound HTTP traffic on port 8080.
  • sudo -u tomcat /usr/local/tomcat/bin/startup.sh
  • Opened http://<public_ip_of_instance>:8080 in web browser successfully (shows Tomcat welcome page).
  • sudo -u tomcat /usr/local/tomcat/bin/shutdown.sh

Install Apache Solr 4.9.0

  • Logged into instance as UNIX user mquinn
  • cd ~
  • sudo wget http://apache.mirrors.hoobly.com/lucene/solr/4.9.0/solr-4.9.0.tgz -> make sure you get the binary distribution, not the source
  • tar xvf solr*tgz
  • sudo -u tomcat mkdir /usr/local/tomcat/solr -> here I’m creating the so-called “Solr home,” a place for Solr configuration files, cores, etc.; you may or may not prefer that these be in a subdirectory of $CATALINA_HOME as I have done here.
  • sudo cp -R solr-4.9.0/example/solr/* /usr/local/tomcat/solr
  • sudo chown -R tomcat:tomcat /usr/local/tomcat/solr
  • sudo -u tomcat cp solr-4.9.0/dist/solr-4.9.0.war /usr/local/tomcat/webapps/solr.war
  • sudo chown tomcat:tomcat /usr/local/tomcat/webapps/solr.war
  • sudo cp solr-4.9.0/example/lib/ext/*.jar /usr/local/tomcat/lib -> these are the SLF4J and Log4j resources required by Solr and its plugins
  • sudo cp solr-4.9.0/dist/solrj-lib/* /usr/local/tomcat/lib/
  • sudo cp solr-4.9.0/dist/*.jar /usr/share/tomcat/lib
  • sudo cp solr-4.9.0/example/resources/log4j.properties /usr/local/tomcat/lib
    • I agree that $CATALINA_HOME/lib is a ridiculously illogical place for the Solr-specific log4j.properties file, but this file must be on the classpath and it is not packaged up inside the Solr WAR file as I would expect it to be; $CATALINA_HOME/lib is the suggested place for this file according to the documentation, but I don’t think it’s the best place.
  • nano /usr/local/tomcat/lib/log4j.properties; changed value of log4j.appender.file.File from ${solr.log}/solr.log to /usr/local/tomcat/logs/solr.log.
  • sudo chown tomcat:tomcat /usr/local/tomcat/lib/*
  • sudo -u tomcat nano /usr/local/tomcat/Catalina/localhost/solr.xml to create the file that tells the Solr webapp where the Solr home directory (created earlier) is via JNDI lookup:

/usr/local/tomcat/Catalina/localhost/solr.xml

<!-- MQUINN 07-07-2014 : Configure Solr Home for Solr webapp. -->
<Context crossContext="true">
  <Environment name="solr/home" type="java.lang.String"
      value="/usr/local/tomcat/solr" override="true"/>
</Context>
  • sudo -u tomcat /usr/local/tomcat/bin/startup.sh
  • Opened http://<public_ip_of_instance>:8080/solr in web browser successfully (shows Solr dashboard).
  • sudo -u tomcat /usr/local/tomcat/bin/shutdown.sh

Forward Port 80 Traffic to Tomcat on Port 8080

  • It is generally considered unwise to run Tomcat on port 80 directly; doing so would require running it as root, which is not the best idea considering that overlooked, poor, or malicious code could be executed by the container, thereby compromising your machine. Although there are ways to start Tomcat as root and downgrade its privileges after startup, I prefer to go with the simpler solution that just forwards traffic on port 80 to Tomcat on port 8080. The tricky part, documented herein, is getting the necessary forwarding rule to persist after reboots; this is accomplished via a custom systemd service.
  • Logged into instance as UNIX user mquinn
  • sudo -i to gain root
  • nano /lib/systemd/system/iptables.service; contents of file are as follows:

/lib/systemd/system/iptables.service

[Unit]
Description=Persists iptables rules
ConditionPathExists=/etc/sysconfig/iptables

[Service]
WorkingDirectory=/usr/local/sbin/
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh systemd-iptables start

[Install]
WantedBy=basic.target
  • ln -s /lib/systemd/system/iptables.service /etc/systemd/system/iptables.service
  • nano /usr/local/sbin/systemd-iptables; contents of file are as follows:

/usr/local/sbin/systemd-iptables

#!/bin/sh

case $1 in
  start)
    /sbin/iptables-restore < /etc/sysconfig/iptables
    ;;
  save)
    /sbin/iptables-save > /etc/sysconfig/iptables
    ;;
  *)
    echo "Unkown action '$1'"
    ;;
esac
  • chmod 755 /usr/local/sbin/systemd-iptables
  • iptables -A PREROUTING -t nat -p tcp --dport 80 -j REDIRECT --to-port 8080 -> this is the actual forwarding rule that will now be persisted by the custom service defined above.
  • /usr/local/sbin/systemd-iptables save -> saves the rule to file, which will be picked up on reboot.
  • systemctl daemon-reload -> ensure systemd is aware of our newly created service.
  • systemctl enable iptables.service -> enable our newly created service so that it starts on future boots.
  • On the EC2 Security Group attached to the instance, removed the rule allowing inbound TCP traffic on port 8080 and replaced it with a rule allowing TCP traffic on port 80 instead.
  • sudo -u tomcat /usr/local/tomcat/bin/startup.sh
  • Without rebooting yet, you should be able to open http://<public_ip_of_machine> in a browser and see the Tomcat welcome page from port 80.
  • reboot
  • sudo -u tomcat /usr/local/tomcat/bin/startup.sh
  • After rebooting and starting Tomcat, you should be able to open http://<public_ip_of_machine> again and see the Tomcat welcome page, now that the iptables.service service is being started at boot.
    • Note: systemctl status iptables.service will confirm whether or not you have registered and enabled the service correctly, in addition to indicating whether it executed successfully at start-up.

Running Tomcat at Startup

  • Just as was done above with iptables, we’ll create a systemd service for Tomcat to ensure that it starts up with the machine.
  • Logged in as UNIX user mquinn
  • sudo -i to gain root
  • nano /lib/systemd/system/tomcat.service; contents of file are as follows:

/lib/systemd/system/tomcat.service

[Unit]
Description=Tomcat 7 service
After=network.target

[Service]
WorkingDirectory=/usr/local/tomcat/bin
RemainAfterExit=yes
ExecStart=/bin/sh systemd-tomcat start
Type=forking
User=tomcat
Group=tomcat

[Install]
WantedBy=multi-user.target
# 10-12-2014 EDIT: Originally I had mistakenly written the line
# above as "WantedBy=multi.user.target"; thank you Profesesor Domingo
# Gallardo López for pointing this out.
  • NOTE: For this service, the User and Group directives are used to ensure that Tomcat starts as the tomcat UNIX user and group, and not as root.
  • ln -s /lib/systemd/system/tomcat.service /etc/systemd/system/tomcat.service
  • nano /usr/local/sbin/systemd-tomcat; file contents are as follows:

/usr/local/sbin/systemd-tomcat

#!/bin/sh

case $1 in
  start)
    /usr/local/tomcat/bin/startup.sh
    ;;
  stop)
    /usr/local/tomcat/bin/shutdown.sh
    ;;
  *)
    echo "Unkown action '$1'"
    ;;
 esac
  • chmod 755 /usr/local/sbin/systemd-tomcat
  • systemctl daemon-reload
  • systemctl enable tomcat.service
  • reboot
  • After waiting for a minute or two, you should be able to open http://<public_ip_of_machine> in your browser and see the Tomcat welcome page, without SSH'ing in to start anything manually. If that’s the case, you now have a clean Solr/Tomcat install running on RHEL7. If Tomcat doesn’t come back up after the reboot, check the output of systemctl status tomcat.service and ensure you stepped through the procedure above correctly.

Final Notes

  • At this point, I snapshotted the EBS volume underlying my EC2 instance for use in creating future Solr instances without needing to go through the steps above again.
  • Remember to keep up with updates to Tomcat and Solr, since this procedure installed them from binary distributions, rather than via yum.
  • The Tomcat 7 distribution comes with several webapps already deployed, such as a manager webapp to get container information; although no one can access it without you first modifying $CATALINA_HOME/conf/tomcat-users.xml, it’s best to remove this webapp for security reasons if you don’t plan on using it.
  • Don’t forget that your Solr dashboard, as configured in this procedure, is wide open to the Internet. Your next move should be to lock down access to this; see https://wiki.apache.org/solr/SolrSecurity.
  • The systemd services defined here are basic and may even have better alternative configurations than the ones I describe; aside from setting up these two services, I have little experience with systemd, which is something I’m working to change given that it’s seeing increasing adoption by various Linux distributions.

Useful References

I found the following to be good resources while setting things up and troubleshooting: