Run Synchrony-standalone as a service on Linux for Confluence 6.4 and earlier
This guide applies to Confluence 6.1 to 6.4 only. If you're using Confluence 6.5 or later, we provide scripts to help you run Synchrony. See Run Synchrony-standalone as a service on Linux.
Purpose
To run Synchrony as a standalone node or cluster for use with Confluence Data Center.
Prerequisites
You should already have one Confluence Data Center node set up (see Installing Confluence Data Center), and are working through the Synchrony setup steps.
We also assume you already have the latest Oracle Java version installed.
How to run Synchrony as a service on a standalone node
On Linux, the best practice is to install, configure and run each service (including Synchrony) as a dedicated user with only the permissions they require.
To install, configure and run Confluence automatically on Linux (Ubuntu 16) use the following steps. These steps can also be adapted for RHEL, simply by adjusting the syntax of the commands.
Create a
synchrony
user for instance, using the following command running as root (not using sudo):addgroup --gid 1234 synchrony && useradd -m -s /bin/bash -u 1234 -g 1234 synchrony;
Set a password for the synchrony user:
sudo passwd synchrony
Create a directory to install Synchrony into and a log directory:
sudo mkdir -p /opt/atlassian/synchrony sudo mkdir -p /var/atlassian/synchrony-logs
Copy the following files and directories from your Confluence node to your Synchrony home directory:
<local-home>/synchrony-standalone.jar
- your database driver from
<install-directory>/confluence/WEB-INF/lib
(for examplepostgresql-9.4.1212.jar
) for convienience you may also want to copy over your
<local-home>/confluence-cfg.xml
file, as this contains some of the details you'll need to enter later.mv /path/to/synchrony-standalone.jar /opt/atlassian/synchrony mv /path/to/postgresql-9.4.1212.jar /opt/atlassian/synchrony mv /path/to/confluence.cfg.xml /opt/atlassian/synchrony
Give the
synchrony
user proper permissions on the directory and files:sudo chown -R synchrony:synchrony /opt/atlassian/synchrony sudo chown -R synchrony:synchrony /var/atlassian/synchrony-logs
Log in as the
root
user to install Synchrony:touch /lib/systemd/system/synchrony.service chmod 664 /lib/systemd/system/synchrony.service
Open the
synchrony
.service
file created in the previous step using your favorite text editor:vim /lib/systemd/system/synchrony.service
Paste in the following text to create the service (you will need to fill in the parameters, many can be copied from your confluence.cfg.xml file. See Configuring Synchrony for Data Center for your Confuence version for information on the parameters):
Skeleton[Unit] Description=Synchrony for Confluence After=network.target [Service] WorkingDirectory=/path/to/logs Type=simple User=user_to_run_service Environment="JAVA_HOME=/path/to/java" 'JAVA_OPTS=\ -Xss2048k -Xmx2g \ -classpath /path/to/synchrony-standalone.jar:/path/to/database-driver.jar \ -Dsynchrony.cluster.impl=hazelcast-btf \ -Dsynchrony.port=8091 \ -Dcluster.listen.port=5701 \ -Dsynchrony.cluster.base.port=25500 \ -Dcluster.join.type=tcpip \ -Dcluster.join.tcpip.members=X.X.X.X,Y.Y.Y.Y \ -Dsynchrony.context.path=/synchrony \ -Dsynchrony.cluster.bind=X.X.X.X \ -Dsynchrony.bind=X.X.X.X \ -Dcluster.interfaces=X.X.X.X \ -Dsynchrony.service.url=https://<confluence_base_url>/synchrony \ -Djwt.private.key=$JWT_PRIVATE \ -Djwt.public.key=$JWT_PUBLIC \ -Dsynchrony.database.url=jdbc:postgresql://IP.of.db.server:port/dbname \ -Dsynchrony.database.username=db_username \ -Dsynchrony.database.password=db_password \ -Dip.whitelist=127.0.0.1,localhost' ExecStart=/path/to/java/bin/java $JAVA_OPTS synchrony.core sql ExecStop=/bin/kill $MAINPID ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target
Example[Unit] Description=Synchrony for Confluence After=network.target [Service] WorkingDirectory=/var/atlassian/synchrony-logs Type=simple User=synchrony Environment="JAVA_HOME=/usr/bin/java" 'JAVA_OPTS=\ -Xss2048k -Xmx2g \ -classpath /opt/atlassian/synchrony/synchrony-standalone.jar:/opt/atlassian/synchrony/postgresql-9.4.1212.jar \ -Dsynchrony.cluster.impl=hazelcast-btf \ -Dsynchrony.port=8091 \ -Dcluster.listen.port=5701 \ -Dsynchrony.cluster.base.port=25500 \ -Dcluster.join.type=tcpip \ -Dcluster.join.tcpip.members=10.10.10.52,10.10.10.53 \ -Dsynchrony.context.path=/synchrony \ -Dsynchrony.cluster.bind=10.10.10.51 \ -Dsynchrony.bind=10.10.10.51 \ -Dcluster.interfaces=10.10.10.51 \ -Dsynchrony.service.url=https://confluence.example.com/synchrony \ -Djwt.private.key=$JWT_PRIVATE \ -Djwt.public.key=$JWT_PUBLIC \ -Dsynchrony.database.url=jdbc:postgresql://10.10.10.49:5432/conf6 \ -Dsynchrony.database.username=confluence \ -Dsynchrony.database.password=atlassian \ -Dip.whitelist=127.0.0.1,localhost' ExecStart=/usr/bin/java $JAVA_OPTS synchrony.core sql ExecStop=/bin/kill $MAINPID ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target
Change to the
synchrony
user and define the environment variables in the above scriptAssume the role of the service user:
sudo su - synchrony
Edit the appropriate profile, for example:
vi ~/.profile
- Bash as login shell will load
/etc/profile
,~/.bash_profile
,~/.bash_login
,~/.profile
in that order - Bash as non-login interactive shell will load
~/.bashrc
Your environment may vary.
- Bash as login shell will load
Add the environment variables by pasting in the following with your jwt-keys from
confluence.cfg.xml
:# synchrony service variables export JWT_PUBLIC=paste-your-key-here export JWT_PRIVATE=paste-your-key-here
For example:
# synchrony service variables export JWT_PUBLIC=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCTbrVr3XaIVehc6vlU7z4Fgk6fyyyyyyyyyyy6ExHHm5wugakp3l7l export JWT_PRIVATE=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgExxxxxxxxhV6FzqMIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI95zS4pKzOhCVNutWvddohV6Fzq
Save and exit the file.
You can confirm the variables are in place by exiting the bash session of the synchrony user, then reassuming the bash session and running the following command:
env
You should look for the JWT_PRIVATE and JWT_PUBLIC keys in the output, if they are there you are all set. If they are not, you may need to define them in a different profile config as noted above.
Notify systemd that a new name.service file exists by executing the following command as root:
systemctl daemon-reload
Enable the service and start it for the first time (enable runs the service at boot time)
systemctl enable synchrony.service systemctl start synchrony.service
Usage:
systemctl start synchrony.service systemctl stop synchrony.service systemctl restart synchrony.service systemctl status synchrony.service
Confirm the synchrony service is running using either of these commands:
systemctl status synchrony.service ps aux | grep synchrony.core
Here is an example output from the ps aux command:
$ ps aux | grep synchrony.core synchro+ 758 10.5 8.5 4856768 683408 ? Ssl 18:22 0:27 /opt/jdk1.8.0_141/bin/java -Xss2048k -Xmx2g -classpath /opt/atlassian/synchrony/synchrony-standalone.jar:/opt/atlassian/synchrony/mysql-connector-java-5.1.44-bin.jar -Dsynchrony.cluster.impl=hazelcast-btf -Dsynchrony.port=8091 -Dcluster.listen.port=5701 -Dsynchrony.cluster.base.port=25500 -Dcluster.join.type=tcpip -Dcluster.join.tcpip.members=10.125.88.1 -Dsynchrony.context.path=/synchrony -Dsynchrony.cluster.bind=10.125.88.233 -Dsynchrony.bind=10.125.88.233 -Dcluster.interfaces=10.125.88.233 -Dsynchrony.service.url=http://confluence.example.com/synchrony -Dsynchrony.database.url=jdbc:mysql://confdb.example.com/conf633 -Dsynchrony.database.username=charlie -Dsynchrony.database.password=atlassian -Dip.whitelist=127.0.0.1,localhost -Djwt.public.key=$JWT_PUBLIC -Djwt.private.key=$JWT_PRIVATE synchrony.core sql
You can then continue with the installation instructions in Step 3 of Installing Confluence Data Center
Running Synchrony using start and stop scripts
If you prefer to write your own service script, you may use these example start and stop scripts for Synchrony instead:
Start Synchrony script
#!/bin/bash
# Script to start a standalone Synchrony process on a separate node from Confluence (for use with data center).
# Define a timestamp function
timestamp() {
date +"[%Y-%m-%d %H:%M:%S]"
}
# Define the user with which to run Synchrony
# user must already be created before running this script
USER="synchrony"
# Enter your base url
CONFLUENCE_BASEURL="http://confluence.example.com"
# Enter the log location (create the directory & grant permissions to $USER first)
SYNCHRONY_LOG="/var/atlassian/synchrony-logs/atlassian-synchrony.log"
# This server's IP
SYNCHRONY_SERVER_IP="192.168.2.101"
# Copy these from your confluence server > /confluence-home/confluence.cfg.xml
JWT_PRIVATE_KEY="your jwt private key here in one line"
JWT_PUBLIC_KEY="your jwt public key here in one line"
DATABASE_URL="jdbc:postgresql://10.10.10.10:5432/conf6"
DATABASE_USER="dbusername"
DATABASE_PASSWORD="dbpassword"
# Location of the synchrony-standalone.jar and database driver jar
# You must copy these over from the confluence server to the directory of your choice
DATABASE_DRIVER_PATH="/opt/atlassian/synchrony/postgresql-9.4.1212.jar"
SYNCHRONY_CLASSPATH="/opt/atlassian/synchrony/synchrony-standalone.jar"
# Load balancer contect path, leave as "/synchrony"
SYNCHRONY_CONTEXT_PATH="/synchrony"
# This combines two variables above to create the synchrony service url
SYNCHRONY_SERVICE_URL=$CONFLUENCE_BASEURL$SYNCHRONY_CONTEXT_PATH
# path to store the PID - normally in /var/run/mydaemonname
# prerequisite: create this directory i.e. /var/run/synchrony and chown it to make the $USER the owner
SYNCHRONY_PID="/var/run/synchrony/synchrony.pid"
# this is where you can setup the jvm startup parameters
_RUNJAVA="java -Xss2048k -Xmx1024m"
# In this section, set the synchrony cluster member IP's using comma separated like so:
# -Dcluster.join.tcpip.members=192.168.2.1,192.168.2.2
# Don't change the other properties without consulting support first
SYNCHRONY_PROPERTIES="\
-classpath ${SYNCHRONY_CLASSPATH}:${DATABASE_DRIVER_PATH} \
-Dsynchrony.cluster.impl=hazelcast-btf \
-Dsynchrony.port=8091 \
-Dcluster.listen.port=5701 \
-Dsynchrony.cluster.base.port=25500 \
-Dcluster.join.type=tcpip \
-Dcluster.join.tcpip.members=192.168.2.1 \
-Dsynchrony.context.path=${SYNCHRONY_CONTEXT_PATH} \
-Dsynchrony.cluster.bind=${SYNCHRONY_SERVER_IP} \
-Dsynchrony.bind=${SYNCHRONY_SERVER_IP} \
-Dcluster.interfaces=${SYNCHRONY_SERVER_IP} \
-Dsynchrony.service.url=${SYNCHRONY_SERVICE_URL} \
-Dreza.service.url=${SYNCHRONY_SERVICE_URL} \
-Djwt.private.key=${JWT_PRIVATE_KEY} \
-Djwt.public.key=${JWT_PUBLIC_KEY} \
-Dsynchrony.database.url=${DATABASE_URL} \
-Dsynchrony.database.username=${DATABASE_USER} \
-Dsynchrony.database.password=${DATABASE_PASSWORD} \
-Djava.net.preferIPv4Stack=true \
-Dip.whitelist=127.0.0.1,localhost"
# Synchrony system properties:
# https://confluence.atlassian.com/doc/configuring-synchrony-for-data-center-858772125.html
/bin/su -m $USER -c "(${_RUNJAVA} ${SYNCHRONY_PROPERTIES} synchrony.core sql & ) >> ${SYNCHRONY_LOG} 2>&1"
# Getting the PID of the process
PID=`ps aux | grep -i synchrony.cluster | grep -i java | awk -F '[ ]*' '{print $2}'`
echo "$PID" > $SYNCHRONY_PID
echo "$(timestamp) Started Synchrony service with PID: $PID" >> $SYNCHRONY_LOG
echo "Starting Synchrony..."
echo "Binding: $SYNCHRONY_SERVER_IP:8091"
echo "Synchrony Logs: $SYNCHRONY_LOG"
echo "Please wait 30 seconds, then check this heartbeat URL in your browser for an 'OK': $SYNCHRONY_SERVICE_URL/heartbeat"
Stop Synchrony script
#!/bin/bash
# stop-synchrony.sh script
# Log location
LOG=/var/atlassian/synchrony-logs/atlassian-synchrony.log
# Getting the PID of the process
PID=`ps aux | grep -i synchrony.core | grep -i java | awk -F '[ ]*' '{print $2}'`
# Number of seconds to wait before using "kill -9"
WAIT_SECONDS=5
# Counter to keep count of how many seconds have passed
count=0
# Define a timestamp function for logging
timestamp() {
date +"[%Y-%m-%d %H:%M:%S]"
}
while kill $PID > /dev/null
do
# Wait for one second
sleep 1
# Increment the second counter
((count++))
# Has the process been killed? If so, exit the loop.
if ! ps -p $PID > /dev/null ; then
break
fi
# Have we exceeded $WAIT_SECONDS? If so, kill the process with "kill -9"
# and exit the loop
if [ $count -gt $WAIT_SECONDS ]; then
kill -9 $PID
break
fi
done
echo "$(timestamp) Synchrony process $PID has been stopped." >> $LOG