Chapter 5. Deployment

Table of Contents

5.1. Deployment Options
5.1.1. Web Archive
5.1.2. Standalone
5.1.3. Embedded
5.2. Running as a Windows Service
5.3. Running as a Nix Service
5.4. Clustering
5.5. Encrypted Passwords
5.6. Secure Transport
5.6.1. Sym Launcher
5.6.2. Tomcat
5.6.3. Keystores
5.6.4. Generating Keys
5.7. Basic Authentication
5.8. IP Filtering
5.8.1. CIDR Filter
5.8.2. Literal Filter
5.8.3. Wildcarding
5.8.4. Range Filters
5.8.5. Inner workings
5.8.6. Configuration

This chapter focuses on the deployment options and configuration of SymmetricDS. Issues such as starting SymmetricDS as a service, clustering, and encryption are among the topics.

5.1. Deployment Options

An instance of SymmetricDS can be deployed in several ways:

  • Web application archive (WAR) deployed to an application server

    This option means packaging a WAR file and deploying to your favorite web server, like Apache Tomcat. It's a little more work, but you can configure the web server to do whatever you need. SymmetricDS can also be embedded in an existing web application, if desired.

  • Standalone service that embeds Jetty web server

    This option means running the sym command line, which launches the built-in Jetty web server. This is a simple option because it is already provided, but you lose the flexibility to configure the web server any further.

  • Embedded as a Java library in an application

    This option means you must write a wrapper Java program that runs SymmetricDS. You would probably use Jetty web server, which is also embeddable. You could bring up an embedded database like Derby or H2. You could configure the web server, database, or SymmetricDS to do whatever you needed, but it's also the most work of the three options discussed thus far.

  • Grails Application

    A Grails SymmetricDS plugin is provided at the default Grails plugin site. This option ends up being a WAR deployment, but allows for the use of the Grails SDK for configuring and building the deployment. The plugin also provides Gorm (Hibernate) access to many of the core database tables.

The deployment model you choose depends on how much flexibility you need versus how easy you want it to be. Both Jetty and Tomcat are excellent, scalable web servers that compete with each other and have great performance. Most people choose either the Standalone or Web Archive with Tomcat 5.5 or 6. Deploying to Tomcat is a good middle-of-the-road decision that requires a little more work for more flexibility.

Next, we will go into a little more detail on the first three deployment options listed above.

5.1.1. Web Archive

As a web application archive, a WAR or EAR file is deployed to an application server, such as Tomcat, Jetty, or JBoss. The structure of the archive should have a web.xml file in the WEB-INF folder, the symmetric.properties file in the WEB-INF/classes folder, and the required JAR files in the WEB-INF/lib folder.

The WEB-INF/web.xml file is configured with a SymmetricEngineContextLoaderListener, the required SymmetricFilter mapping, and the required SymmetricServlet mapping.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">

    <display-name>sync</display-name>
    
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!-- You can optionally specify other Spring files to 
                load into same context here -->
        <param-value>classpath:symmetric.xml</param-value>
    </context-param>
    
    <filter>
        <filter-name>SymmetricFilter</filter-name>
        <filter-class>
            org.jumpmind.symmetric.web.SymmetricFilter
        </filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>SymmetricFilter</filter-name>
        <servlet-name>/*</servlet-name>
    </filter-mapping>
    
    <listener>
        <listener-class>
            org.jumpmind.symmetric.SymmetricEngineContextLoaderListener
        </listener-class>
    </listener>
    
    <servlet>
        <servlet-name>SymmetricServlet</servlet-name>
        <servlet-class>
            org.jumpmind.symmetric.web.SymmetricServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>SymmetricServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

This example starts all the SymmetricDS Servlets with Filters to compress the stream, authenticate nodes, and reject nodes when the server is too busy.

The web.base.servlet.path property in symmetric.properties can be set if the SymmetricServlet needs to coexist with other Servlets.

5.1.2. Standalone

A standalone service can use the sym command line options to start a server. An embedded instance of Jetty is used to service web requests for all the servlets.

/symmetric/bin/sym --properties root.properties --port 8080 --server

This example starts the SymmetricDS server on port 8080 with the startup properties found in the root.properties file.

5.1.3. Embedded

A Java application with the SymmetricDS Java Archive (JAR) library on its classpath can use the SymmetricWebServer to start the server.

import org.jumpmind.symmetric.SymmetricWebServer;

public class StartSymmetricEngine {

    /**
     * Start an engine that is configured by two properties files. One is
     * packaged with the application and contains overridden properties that are
     * specific to the application. The other is found in the application's
     * working directory. It can be used to setup environment specific
     * properties.
     */
    public static void main(String[] args) throws Exception {
    
        SymmetricWebServer node = new SymmetricWebServer(
                                   "classpath://my-application.properties");

        // this will create the database, sync triggers, start jobs running
        node.start(8080);
        
        // this will stop the node
        node.stop();
    }   

}

This example starts the SymmetricDS server on port 8080 with startup properies found in two locations. The first file, my-application.properties, is packaged in the application to provide properties that override the SymmetricDS default values.

5.2. Running as a Windows Service

SymmetricDS uses the Java Service Wrapper product from Tanuki Software to run in the background as a Windows system service. The Java Service Wrapper executable is named sym_service.exe so it can be easily identified from a list of running processes. To install the service, use the provided script:

bin\install_service.bat

The service configuration is found in conf/sym_service.conf. Edit this file if you want to change the default port number (8080), initial memory size (256 MB), log file size (10 MB), or other settings. When started, the server will look in the conf directory for the symmetric.properties file and the log4j.xml file. Logging for standard out, error, and application are written to the logs directory.

Most configuration changes do not require the service to be re-installed. To un-install the service, use the provided script:

bin\uninstall_service.bat

Use the net command to start and stop the service:

net start symmetric
net stop symmetric

5.3. Running as a Nix Service

SymmetricDS uses the Java Service Wrapper product from Tanuki Software to run in the background as a Unix system service. The Java Service Wrapper executable is named sym_service so it can be easily identified from a list of running processes. The service configuration is found in conf/sym_service.conf. Edit this file if you want to change the default port number (8080), initial memory size (256 MB), log file size (10 MB), or other settings.

An init script is provided to work with standard Unix run configuration levels. The sym_service.initd file follows the Linux Standard Base specification, which should work on many systems, including Fedora and Debian-based distributions. To install the script, copy it into the system init directory:

cp bin/sym_service.initd /etc/init.d/sym_service

Edit the init script to set the SYM_HOME variable to the directory where SymmetricDS is located. The init script calls the sym_service executable.

To enable the service to run automatically when the system is started:

/sbin/chkconfig --add sym_service

To disable the service from running automatically:

/sbin/chkconfig --del sym_service

On Suse Linux install the service by calling:

/usr/lib/lsb/install_initd sym_service

Remove the service by calling:

/usr/lib/lsb/remove_initd sym_service

Use the service command to start, stop, and query the status of the service:

/sbin/service sym_service start
/sbin/service sym_service stop
/sbin/service sym_service status

Alternatively, call the init.d script directly:

/etc/init.d/sym_service start
/etc/init.d/sym_service stop
/etc/init.d/sym_service status
            

5.4. Clustering

A single SymmetricDS node may be clustered across a series of instances, creating a web farm. A node might be clustered to provide load balancing and failover, for example.

When clustered, a hardware load balancer is typically used to round robin client requests to the cluster. The load balancer should be configured for stateless connections. Also, the sync.url (discussed in Section 4.1, “Node Properties”) SymmetricDS property should be set to the URL of the load balancer.

If the cluster will be running any of the SymmetricDS jobs, then the cluster.lock.enabled property should be set to true. By setting this property to true, SymmetricDS will use a row in the LOCK table as a semaphore to make sure that only one instance at a time runs a job. When a lock is acquired, a row is updated in the lock table with the time of the lock and the server id of the locking job. The lock time is set back to null when the job is finished running. Another instance of SymmetricDS cannot aquire a lock until the locking instance (according to the server id) releases the lock. If an instance is terminated while the lock is still held, an instance with the same server id is allowed to reaquire the lock. If the locking instance remains down, the lock can be broken after a period of time, specified by the cluster.lock.timeout.ms property, has expired. Note that if the job is still running and the lock expires, two jobs could be running at the same time which could cause database deadlocks.

By default, the locking server id is the hostname of the server. If two clustered instances are running on the same server, then the cluster.server.id property may be set to indicate the name that the instance should use for its server id.

When deploying SymmetricDS to an application server like Tomcat or JBoss, no special session clustering needs to be configured for the application server.

5.5. Encrypted Passwords

The db.user and db.password properties will accept encrypted text, which protects against casual observation. The text is prefixed with enc: to indicate that it is encrypted. To encrypt text, use the following command:

sym -e secret

The text is encrypted by the cipher defined as alias "sym.secret" in the Java keystore. The keystore is specified by the "sym.keystore.file" system property, which defaults to security/keystore. If a cipher is not found, a default cipher using Triple DES with a random password is generated.

5.6. Secure Transport

By specifying the "https" protocol for a URL, SymmetricDS will communicate over Secure Sockets Layer (SSL) for an encrypted transport. The following properties need to be set with "https" in the URL:

sync.url

This is the URL of the current node, so if you want to force other nodes to communicate over SSL with this node, you specify "https" in the URL.

registration.url

This is the URL where the node will connect for registration when it first starts up. To protect the registration with SSL, you specify "https" in the URL.

For incoming HTTPS connections, SymmetricDS depends on the webserver where it is deployed, so the webserver must be configured for HTTPS. As a standalone deployment, the "sym" launcher command provides options for enabling HTTPS support.

5.6.1. Sym Launcher

The "sym" launch command uses Jetty as an embedded web server. Using command line options, the web server can be told to listen for HTTP, HTTPS, or both.

sym --port 8080 --server

sym --secure-port 8443 --secure-server

sym --port 8080 --secure-port 8443 --mixed-server

5.6.2. Tomcat

If you deploy SymmetricDS to Apache Tomcat, it can be secured by editing the TOMCAT_HOME/conf/server.xml configuration file. There is already a line that can be uncommented and changed to the following:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" 
  maxThreads="150" scheme="https" secure="true" 
  clientAuth="false" sslProtocol="TLS"
  keystoreFile="/symmetric-ds-1.x.x/security/keystore" />

5.6.3. Keystores

When SymmetricDS connects to a URL with HTTPS, Java checks the validity of the certificate using the built-in trusted keystore located at JRE_HOME/lib/security/cacerts. The "sym" launcher command overrides the trusted keystore to use its own trusted keystore instead, which is located at security/cacerts. This keystore contains the certificate aliased as "sym" for use in testing and easing deployments. The trusted keystore can be overridden by specifying the javax.net.ssl.trustStore system property.

When SymmetricDS is run as a secure server with the "sym" launcher, it accepts incoming requests using the key installed in the keystore located at security/keystore. The default key is provided for convenience of testing, but should be re-generated for security.

5.6.4. Generating Keys

To generate new keys and install a server certificate, use the following steps:

  1. Open a command prompt and navigate to the security subdirectory of your SymmetricDS installation.

  2. Delete the old key pair and certificate.

    keytool -keystore keystore -delete -alias sym

    keytool -keystore cacerts -delete -alias sym

    Enter keystore password:  changeit
  3. Generate a new key pair.

    keytool -keystore keystore -alias sym -genkey -keyalg RSA -validity 10950

    Enter keystore password:  changeit
    What is your first and last name?
      [Unknown]:  localhost
    What is the name of your organizational unit?
      [Unknown]:  SymmetricDS
    What is the name of your organization?
      [Unknown]:  JumpMind
    What is the name of your City or Locality?
      [Unknown]:
    What is the name of your State or Province?
      [Unknown]:
    What is the two-letter country code for this unit?
      [Unknown]:
    Is CN=localhost, OU=SymmetricDS, O=JumpMind, L=Unknown, ST=Unknown, C=Unknown
    correct?
      [no]:  yes
    
    Enter key password for <sym>
            (RETURN if same as keystore password):
  4. Export the certificate from the private keystore.

    keytool -keystore keystore -export -alias sym -rfc -file sym.cer

  5. Install the certificate in the trusted keystore.

    keytool -keystore cacerts -import -alias sym -file sym.cer

5.7. Basic Authentication

SymmetricDS supports basic authentication for client and server nodes. To configure a client node to use basic authentication when communicating with a server node, specify the following startup parameters:

http.basic.auth.username

username for client node basic authentication. [ Default: ]

http.basic.auth.password

password for client node basic authentication. [ Default: ]

The SymmetricDS Standalone and Embedded Server also support basic authentication. This feature is enabled by specifying the basic authentication username and password using the following startup parameters:

embedded.webserver.basic.auth.username

username for basic authentication for an embedded server or standalone server node. [ Default: ]

embedded.webserver.basic.auth.password

password for basic authentication for an embedded server or standalone server node. [ Default: ]

If the server node is deployed to Tomcat or another application server as a WAR or EAR file, then basic authentication is setup with the standard configuration in the WEB.xml file.

5.8. IP Filtering

SymmetricDS supports restricting IP addresses of clients that are allowed to connect to servers. The following filtering functionality is supported for IPv4 addresses (IPv6 is currently not supported).

  • CIDR (Classless Inter-Domain Routing) notation

  • Wildcarding

  • Range

  • Literal

5.8.1. CIDR Filter

Classless Inter-Domain Routing, CIDR, notation is the preferred notation for restricting client connections to a server node in a SymmetricDS tree. It is a commonly utilized format for IP address filtering. Many established frameworks, such as Apache, utilize this notation for filtering IP addresses.

The basis for implementing CIDR notation is defining the IP address block and significant bits of that address that are to be checked. The filter must be a well formatted IP address with a ending with a “/” followed by a numeric value between 0 and 32. The use of “0” denotes that all IP addresses are allowed (in which case it's fairly pointless to enable the filtering framework), and “32” signifies only the precesding IP address would be authorized. In the latter case, a Literal Filter string would be recommended as it is significantly more obvious that only that address is allowed.

                #
                # Filter string definition to restrict connecting client
                # IP addresses
                #
                ip.filters=10.10.4.32/27, 10.5.0.0/16
            

Example 5.1. CIDR Filter String Definition in symmetric.properties


5.8.2. Literal Filter

Literal filter definitions are just that: they define a single IP address that is authorized to connect to the server. The only requirement is that the filter string is a complete, well formatted IP address.

5.8.3. Wildcarding

The wildcard notation allows all values for a specific piece of an IP address to be valid (0 to 255 for IPv4 addresses). This is denoted with a “*” within the specific piece (octet for IPv4) of an IP address. The wildcard character is the only allowable character within that piece of the address (no other characters included whitespace).

Wildcard filters may be combined with Range Filters. They may NOT be combined with CIDR Filter.

                #
                # Filter string definition to restrict connecting client
                # IP addresses
                #
                ip.filters=10.10.*.40
            

Example 5.2. Wildcard Filter String Definition in symmetric.properties


5.8.4. Range Filters

Range filter definitions allow for a numeric range to be specified within an address filter. A range must be a valid numeric range for an piece of an IP address (i.e. an octet in IPv4). The range definition must be in the form:

                #
                # Filter string definition to restrict connecting client
                # IP addresses
                #
                ip.filters=10.10.40-20.200-1
            

Example 5.3. Filter String Definition in symmetric.properties


5.8.5. Inner workings

Filter strings are compiled on startup, so the hit (although very small) of compiling the authorizers is incurred only once. Once compiled each request is passed through the chain of authorizers until either a authorization is passed or the chain is exhausted. In the latter case the request is denied and a protocol specific response is sent to the client. In the case of HTTP this would be a response code of 401 (FORBIDDEN).

5.8.6. Configuration

Configuring IP filter strings is done through defining the following property in the SymmetricDS configuration (one of the symmetric .properties files). One need only to define the ip.filter property and assign a comma “,” delimited string of filter tokens to provide to the filter framework.

                #
                # Filter string definition to restrict connecting client
                # IP addresses
                #
                ip.filters=10.10.4.32/27, 100.50-40.10-5.*, 35.58.124.89
            

Example 5.4. Filter String Definition in symmetric.properties


Important

Note, that there is obvious overlap between the some of the filtering notation, and hence, functionality. The Wildcarding and Range Filters functionality exists to provide workarounds for scenarios where CIDR Filter notation and Literal Filter will not suffice.

Warning

Take care in defining your filter string as it is possible to overlap filters. Also, as with the definition of any other property in the SymmetricDS configuration, if the property is defined in multiple properties files the property file that is read in last will override any previous filter string definitions.