Skip to content

How to deploy Etherpad Lite as a service

SamTV12345 edited this page Jul 4, 2024 · 79 revisions

With systemd it is better not to use the run.sh but to let systemd run node directly.

Important! A manual run of bin/installDeps.sh is needed before the first start as service.

So you have to have your etherpad Installation in /opt/etherpad and to add the system user and group etherpad. Obviously you can change the names and paths as needed. The output of etherpad is logged directly into the systemd journal.

Debian 12 bookworm/Ubuntu Jammy (systemd)

Prerequisites

  1. Install certificates: sudo apt install -y ca-certificates curl git gnupg && sudo mkdir -p /etc/apt/keyrings
  2. Install signing key for latest node repository: curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
  3. Set node version to use: NODE_MAJOR=20
  4. Add deb repository: echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
  5. Update repository: sudo apt update
  6. Install desired node version: sudo apt install -y nodejs
  7. Add etherpad user: sudo adduser --system --group --home /opt/etherpad etherpad
  8. Download etherpad: cd /opt/etherpad && git clone --branch master https://github.com/ether/etherpad-lite.git && mv etherpad-lite/* .
  9. Execute sudo nano /etc/systemd/system/etherpad.service and paste the following content

etherpad.service:

[Unit]
Description=Etherpad-lite, the collaborative editor.
After=syslog.target network.target

[Service]
Type=simple
User=etherpad
Group=etherpad
WorkingDirectory=/opt/etherpad
Environment=NODE_ENV=production
ExecStart=pnpm run prod
# use mysql plus a complete settings.json to avoid Service hold-off time over, scheduling restart.
Restart=always

StandardOutput=append:/var/log/etherpad/etherpad.log
StandardError=append:/var/log/etherpad/etherpad-error.log

[Install]
WantedBy=multi-user.target
  1. Run sudo systemctl daemon-reload
  2. Run systemctl enable etherpad to enable the service on boot.
  3. Install dependencies: /opt/etherpad/bin/installDeps.sh
  4. Change owner to etherpad: chown -R etherpad /opt/etherpad/
  5. Run systemctl start etherpad to start the service. NB: might need to change "/srv/etherpad-lite/bin/run.sh" with "/bin/sh /srv/etherpad-lite/bin/run.sh" according to configuration

Ubuntu 10.04, Debian 6 (sysvinit)

  1. Create a user called etherpad-lite: adduser etherpad-lite --system --group --home /var/etherpad
  2. Setup a log folder for the service
  • Create: mkdir /var/log/etherpad-lite
  • Permiss: chown -R etherpad-lite /var/log/etherpad-lite
  1. Ensure app has full access to its source folder: chown -R etherpad-lite /path/to/install/dir
  2. Copy following script to /etc/init.d/ and configure the variables. You might want also configure the runSafe script in your git folder to ensure you get email notifications if there are problems with the applications
  3. Make sure the script is marked as executable: chmod +x /etc/init.d/etherpad-lite
  4. If etherpad-lite is not installed in /usr/share/etherpad-lite create a link with ln -s /your-path-to/etherpad-lite /usr/share/etherpad-lite
  5. Enable it with update-rc.d etherpad-lite defaults
  6. start with service etherpad-lite start
#!/bin/sh

### BEGIN INIT INFO
# Provides:          etherpad-lite
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts etherpad lite
# Description:       starts etherpad lite using start-stop-daemon
### END INIT INFO

PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/node/bin"
LOGFILE="/var/log/etherpad-lite/etherpad-lite.log"
EPLITE_DIR="/usr/share/etherpad-lite"
EPLITE_BIN="bin/safeRun.sh"
USER="etherpad-lite"
GROUP="etherpad-lite"
DESC="Etherpad Lite"
NAME="etherpad-lite"

set -e

. /lib/lsb/init-functions

start() {
  echo "Starting $DESC... "
  
	start-stop-daemon --start --chuid "$USER:$GROUP" --background --make-pidfile --pidfile /var/run/$NAME.pid --exec $EPLITE_DIR/$EPLITE_BIN -- $LOGFILE || true
  echo "done"
}

#We need this function to ensure the whole process tree will be killed
killtree() {
    local _pid=$1
    local _sig=${2-TERM}
    for _child in $(ps -o pid --no-headers --ppid ${_pid}); do
        killtree ${_child} ${_sig}
    done
    kill -${_sig} ${_pid}
}

stop() {
  echo "Stopping $DESC... "
  if test -f /var/run/$NAME.pid; then
    while test -d /proc/$(cat /var/run/$NAME.pid); do
      killtree $(cat /var/run/$NAME.pid) 15
      sleep 0.5
    done
    rm /var/run/$NAME.pid
  fi
  echo "done"
}

status() {
  status_of_proc -p /var/run/$NAME.pid "" "etherpad-lite" && exit 0 || exit $?
}

case "$1" in
  start)
	  start
	  ;;
  stop)
    stop
	  ;;
  restart)
	  stop
	  start
	  ;;
  status)
	  status
	  ;;
  *)
	  echo "Usage: $NAME {start|stop|restart|status}" >&2
	  exit 1
	  ;;
esac

exit 0

Ubuntu 10.04 (upstart)

  1. Create a user called etherpad-lite
  2. Create a log folder for the service /var/log/etherpad-lite
  3. Ensure the etherpad-lite user have full access to the log and the git folder
  4. Save the following script to /etc/init/etherpad-lite.conf
  5. Set EPHOME and EPUSER to the proper values
  6. Run sudo start etherpad-lite
description "etherpad-lite"

start on started networking
stop on runlevel [!2345]

env EPHOME=/usr/local/etherpad-lite
env EPLOGS=/var/log/etherpad-lite
env EPUSER=etherpad-lite

respawn

pre-start script
    cd $EPHOME
    mkdir $EPLOGS                              ||true
    chown $EPUSER:admin $EPLOGS                ||true
    chmod 0755 $EPLOGS                         ||true
    chown -R $EPUSER:admin $EPHOME/var         ||true
    $EPHOME/bin/installDeps.sh >> $EPLOGS/error.log || { stop; exit 1; }
end script

script
  cd $EPHOME/
  exec su -s /bin/sh -c 'exec "$0" "$@"' $EPUSER -- node --experimental-worker node_modules/ep_etherpad-lite/node/server.js \
                        >> $EPLOGS/access.log \
                        2>> $EPLOGS/error.log
end script

Mac OS-X (launchd)

  1. Create a user called etherpad-lite Either use Preferences > Users and Accounts > + (then select User or Group) or use the following commands: dscl / -create /Users/etherpad (Creates a user, note that you need further commands to create passwords, etc, see here ) sudo dscl . -create /groups/etherpad (Creates a group, , note that you need further commands to create passwords, bind users with group etc. See here. )
  2. Create a log folder for the service at /var/log/etherpad-lite (requires sudo) mkdir /var/log/etherpad-lite
  3. Ensure the etherpad user has full access to the log and the git folder
  4. Copy following property list file as org.etherpad.etherpad-lite.plist to /Library/LaunchDaemons/. You might want to edit the paths and also configure the runSafe script in your git folder to ensure you get email notifications if there are problems with the applications
  5. Load into launchd: sudo launchctl load /Library/LaunchDaemons/org.etherpad.etherpad-lite.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>KeepAlive</key>
	<true/>
	<key>Label</key>
	<string>org.etherpad.etherpad-lite</string>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/local/etherpad-lite/bin/safeRun.sh</string>
		<string>/var/log/etherpad-lite/etherpad.log</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>StandardOutPath</key>
	<string>/var/log/etherpad-lite/etherpad.log</string>
	<key>StandardErrorPath</key>
	<string>/var/log/etherpad-lite/etherpad-error.log</string>
	<key>UserName</key>
	<string>etherpad</string>
	<key>GroupName</key>
	<string>etherpad</string>
</dict>
</plist>

Windows (nssm)

  1. Download and extract nssm, the non-sucking service manager. This application allows you to host an executable as a Windows service. Put the nssm binary into a folder that is set in your PATH IE \windows\system32
  2. Install the service: nssm.exe install etherpad C:\etherpad-location\start.bat. Nssm creates the service under the Local System account, so you might want to consider changing this afterwards. You will need to be running command prompt as the administrator to do this.
  3. Launch it: Run net start etherpad.

CentOS 6 (SysV Init)

  1. Create a user called etherpad-lite
  2. Install etherpad-lite under /srv/etherpad-lite (or where ever you want)
  3. Ensure the etherpad-lite user have full access to the git folder
  4. Copy following script to /etc/init.d/ and configure the variables.
  5. Make sure the script is marked as executable: chmod +x /etc/init.d/etherpad-lite
  6. Enable it with chkconfig etherpad-lite on
  7. After a update the script "bin/run.sh" must be run once manual as root.
#!/bin/bash
# chkconfig: 2345 90 90
# description: program_name
### BEGIN INIT INFO# Provides: program_name
# Required-Start: network
# Required-Stop: network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6# Description: Start the program
### END INIT INFO

START_CMD="/home/etherpad-lite-dev/bin/safeRun.sh > /var/log/etherpad.log 2>&1 &"
NAME="etherpad"
PGREP_STRING="/home/etherpad-lite-dev/bin/safeRun.sh"
PGREP_NODE_STRING="node --experimental-worker /home/etherpad-lite-dev/node_modules/ep_etherpad-lite/node/server.js"
PID_FILE="/var/run/etherpad/etherpad-dev.pid"
USER="etherpad-lite"

### No further muckin' about needed!

CUR_USER=`whoami`

killproc() {
  pkill -u $USER -f $PGREP_STRING
  pkill -u $USER -f "$PGREP_NODE_STRING"
}

killproc_node(){
  pkill -u $USER -f "$PGREP_NODE_STRING"
}

start_daemon() {
  eval "$*"
}

log_success_msg() {
  echo "$*"
  logger "$_"
}

log_failure_msg() {
  echo "$*"
  logger "$_"
}

check_proc() {
  pgrep -u $USER -f $PGREP_STRING >/dev/null
}

check_proc_node(){
  pgrep -u $USER -f "$PGREP_NODE_STRING" >/dev/null
}

start_script() {
  if [ "${CUR_USER}" != "root" ] ; then
    log_failure_msg "$NAME can only be started as 'root'."
    exit -1
  fi

  check_proc
  if [ $? -eq 0 ]; then
    log_success_msg "$NAME is already running."
    exit 0
  fi

  [ -d /var/run/$NAME ] || (mkdir /var/run/$NAME )

   # make go now
    start_daemon /bin/su - $USER -c $START_CMD

  # Sleep for a while to see if anything cries
  echo "Checking status..."
  sleep 5
  check_proc

  if [ $? -eq 0 ]; then
    log_success_msg "Started $NAME."
  else
    log_failure_msg "Error starting $NAME."
    exit -1
  fi
}

stop_script() {
  if [ "${CUR_USER}" != "root" ] ; then
    log_failure_msg "You do not have permission to stop $NAME."
    exit -1
  fi

  check_proc
  if [ $? -eq 0 ]; then
    killproc -p $PID_FILE >/dev/null

    # Make sure it's dead before we return
    until [ $? -ne 0 ]; do
      sleep 1
      check_proc
    done

    check_proc
    if [ $? -eq 0 ]; then
      log_failure_msg "Error stopping $NAME."
      exit -1
    else
      log_success_msg "Stopped $NAME."
    fi
  else
    log_failure_msg "$NAME is not running or you don't have permission to stop it"
  fi

  check_proc_node
  if [ $? -eq 0 ]; then
    killproc_node -p $PID_FILE >/dev/null

    # Make sure it's dead before we return
    # until [ $? -ne 0 ]; do
    #  sleep 1
    #  check_proc_node
    # done

    #check_proc_node
    #if [ $? -eq 0 ]; then
    #  log_failure_msg "Error stopping $NAME."
    #  exit -1
    #else
    #  log_success_msg "Stopped $NAME."
    #fi
  else
    log_failure_msg "$NAME is not running or you don't have permission to stop it"
  fi

}

check_status() {
  check_proc
  if [ $? -eq 0 ]; then
    log_success_msg "$NAME is running."
  else
    log_failure_msg "$NAME is stopped."
    exit -1
  fi
}

case "$1" in
  start)
    start_script
    ;;
  stop)
    stop_script
    ;;
  restart)
    stop_script
    start_script
    ;;
  status)
    check_status
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
    exit 1
esac

exit 0

Gentoo

  1. Create a user 'etherpad-lite'
  2. Copy this initscript into directory /etc/init.d
#!/sbin/runscript
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

depend() {
        need net mysql
        after apache2
}

start() {
        ebegin "Starting ${RC_SVCNAME}"
                start-stop-daemon -S -m --pidfile ${PIDFILE} -x ${NODE} -u ${USER} -d "${ETHERPATH}" -b -- ${ARGS}
        eend $?
}

stop() {
        ebegin "Stopping ${RC_SVCNAME}"
                start-stop-daemon -K -x ${NODE} -u ${USER} -d "${ETHERPATH}" 
        eend $?
}
  1. chmod 0755 /etc/init.d/etherpad-lite

  2. Copy this File into Directory /etc/conf.d/ (Change as necessary)

ETHERPATH="/local/etherpad-lite/"
ARGS="--experimental-worker node_modules/ep_etherpad-lite/node/server.js"
ETHERLOG="${ETHERPATH}/log/error.log"
USER="etherpad-lite"
PIDFILE="/var/run/etherpad-lite.pid"
NODE="/usr/bin/node"
  1. rc-update add etherpad-lite default
  2. rc-service etherpad-lite start

Slackware Linux/Porteus Linux/Byzantium Linux/You like to do things manually.

  1. Create a user 'etherpad-lite'
  2. Copy this initscript into the directory /etc/rc.d: https://github.com/Byzantium/Byzantium/blob/master/porteus/etherpad-lite/rc.etherpad-lite
  3. Edit the script, change the username the 'pad instance will run as. Also change the value of the $HOMEDIR variable to be wherever Etherpad-Lite was installed to.
  4. chmod 0755 /etc/rc.d/rc.etherpad-lite
  5. Add the command /etc/rc.d/rc.etherpad-lite start to the /etc/rc.d/rc.local script if you prefer.

openSUSE and/or SLES (sysvinit)

  1. Create a user and a group called etherpad-lite (using the yast2 users module as example) with /srv/etherpad-lite as home directory
  2. Install etherpad-lite under /srv/etherpad-lite (or where ever you want - if etherpad-lite is not installed in /srv/etherpad-lite either create a link with ln -s /your-path-to/etherpad-lite /srv/etherpad-lite or adapt the path in the init script)
  3. Ensure the etherpad-lite user has full access to the git folder (/srv/etherpad-lite) and logfile (/var/log/etherpad-lite)
  4. Copy the following script to /etc/init.d/ and configure the variables. You might want also configure the runSafe script in your git folder to ensure you get email notifications if there are problems with the applications
  5. Make sure the script is marked as executable: chmod +x /etc/init.d/etherpad-lite
  6. Create a rc-Symlink if you like: ln -s /etc/init.d/etherpad-lite /usr/sbin/rcetherpad-lite
  7. Enable it with chkconfig etherpad-lite on
  8. start with /etc/init.d/etherpad-lite start or rcetherpad-lite start
#!/bin/bash
#
#     Template LSB system startup script for example service etherpad-lite
#     Copyright (C) 1995--2005  Kurt Garloff, SUSE / Novell Inc.
#          
#     This library is free software; you can redistribute it and/or modify it
#     under the terms of the GNU Lesser General Public License as published by
#     the Free Software Foundation; either version 2.1 of the License, or (at
#     your option) any later version.
#                             
#     This library is distributed in the hope that it will be useful, but
#     WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#     Lesser General Public License for more details.
#      
#     You should have received a copy of the GNU Lesser General Public
#     License along with this library; if not, write to the Free Software
#     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
#     USA.
#
# /etc/init.d/etherpad
# LSB compatible service control script; see http://www.linuxbase.org/spec/
# Please send feedback to http://www.suse.de/feedback/
# 
# Note: This template uses functions rc_XXX defined in /etc/rc.status on
# UnitedLinux/SUSE/Novell based Linux distributions. However, it will work
# on other distributions as well, by using the LSB (Linux Standard Base) 
# or RH functions or by open coding the needed functions.
# Read http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/ if you prefer not 
# to use this template.
#
# chkconfig: 345 99 00
# description: Start etherpad lite
# 
### BEGIN INIT INFO
# Provides:          etherpad
# Required-Start:    $syslog $remote_fs $time
# Should-Start:      $time smtp
# Required-Stop:     $syslog $remote_fs
# Should-Stop:       smtp
# Default-Start:     3 4 5
# Default-Stop:      0 1 2 6
# Short-Description: Starts etherpad lite
# Description:       Start etherpad lite using startproc
### END INIT INFO

PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/node/bin"
LOGFILE="/var/log/etherpad-lite/etherpad-lite.log"
EPLITE_DIR="/srv/etherpad-lite"
EPLITE_BIN="bin/safeRun.sh"
USER="etherpad-lite"
GROUP="etherpad-lite"
DESC="Etherpad Lite"
NAME="etherpad-lite"

test -x "$EPLITE_DIR/$EPLITE_BIN" || { echo "$EPLITE_DIR/$EPLITE_BIN not installed";
        if [ "$1" = "stop" ]; then exit 0;
        else exit 5; fi; } 

test -d $(dirname "$LOGFILE") || mkdir -p $(dirname "$LOGFILE")
chown -R $USER:$GROUP $(dirname "$LOGFILE")

# Shell functions sourced from /etc/rc.status
. /etc/rc.status

# Reset status of this service
rc_reset

case "$1" in
    start)
        echo -n "Starting $DESC "
        ## Start daemon with startproc(8). If this fails
        ## the return value is set appropriately by startproc.
        /sbin/startproc -p "/var/run/$NAME.pid" -u $USER -g $GROUP -l "$LOGFILE"  "$EPLITE_DIR/$EPLITE_BIN" "$LOGFILE"
        # Remember status and be verbose
        rc_status -v
        ;;
    stop)
        echo -n "Shutting down $DESC "
        ## Stop daemon with killproc(8) and if this fails
        ## killproc sets the return value according to LSB.
        /sbin/killproc -TERM -p "/var/run/$NAME.pid" "$EPLITE_DIR/$EPLITE_BIN"
        # Remember status and be verbose
        rc_status -v
        ;;
    try-restart|condrestart)
        ## Do a restart only if the service was active before.
        ## Note: try-restart is now part of LSB (as of 1.9).
        ## RH has a similar command named condrestart.
        if test "$1" = "condrestart"; then
                echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
        fi
        $0 status
        if test $? = 0; then
                $0 restart
        else
                rc_reset        # Not running is not a failure.
        fi
        # Remember status and be quiet
        rc_status
        ;;
    restart)
        ## Stop the service and regardless of whether it was
        ## running or not, start it again.
        $0 stop
        $0 start
        # Remember status and be quiet
        rc_status
        ;;
    force-reload)
        ## Signal the daemon to reload its config.
        $0 try-restart
        rc_status
        ;;
    reload)
        ## Like force-reload, but if daemon does not support
        ## signaling, do nothing (!)
        rc_failed 3
        rc_status -v
        ;;
    status)
        echo -n "Checking for service $DESC "
        ## Check status with checkproc(8), if process is running
        ## checkproc will return with exit status 0.
        # NOTE: checkproc returns LSB compliant status values.
        /sbin/checkproc -p "/var/run/$NAME.pid" "$EPLITE_DIR/$EPLITE_BIN"
        # NOTE: rc_status knows that we called this init script with
        # "status" option and adapts its messages accordingly.
        rc_status -v
        ;;
    *)
        echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload}"
        exit 1
        ;;
esac
rc_exit

Fedora 15 or later (systemd)

Create codepad.service in /usr/lib/systemd/system

[Unit]
Description=Run Etherpad-lite, the collaborative editor.
After=syslog.target network.target

[Service]
Type=simple
ExecStart=/home/etherpad-user/etherpad-lite/bin/run.sh 2>&1 < /dev/null &

[Install]
WantedBy=multi-user.target

General

Resources

For Developers

How to's

Set up

Advanced steps

Integrating Etherpad in your web app

for Developers

Clone this wiki locally