Skip to content

Commit

Permalink
systemd support
Browse files Browse the repository at this point in the history
This patch adds systemd support to SSVP.

Fixes: #27
Fixes: #34

Signed-off-by: Amy Parker <[email protected]>
  • Loading branch information
amyipdev committed Aug 9, 2023
1 parent 7e672b1 commit e459743
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 16 deletions.
12 changes: 10 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,27 @@ SASS_SRCS = $(shell find scss/ -name '*.scss')
INSTALLDIR :=
TSC := npx tsc
TSC_OPTIONS := --noEmitOnError --module es2015
OGUSER := $(USER)

.PHONY: docs

# TODO: automatically compile sass instead of manual

all:
mkdir -p assets/css assets/js
$(SASS) scss/custom.scss:assets/css/custom_bootstrap.css $(SASS_OPTIONS)
$(TSC) $(TSC_OPTIONS) --outDir assets/js js/*.ts
# $(MAKE) -C js

ssvplwc:
cd srv/ssvplwc; cargo run --release

install:
mkdir -p $(INSTALLDIR)
cp -a . $(INSTALLDIR)
chown -R $(USER):$(USER) $(INSTALLDIR)
chown -R $(OGUSER):$(OGUSER) $(INSTALLDIR)

clean:
rm -rf .sass-cache assets node_modules venv docs/_build

docs:
make -C docs html
51 changes: 49 additions & 2 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
Configuration
=============

Here's all of the configuration options:
SSVP is very versatile, and designed to run in a wide variety of environments.

Configuration file
------------------

The SSVP configuration file must be stored at :code:`srv/ssvp-config.json`. A new one can be created by:

- Manually entering the options seen below
- Running :code:`python3 installer/gen_config.py`
- Copying and editing :code:`srv/ssvp-config.json.example`

The file options are:

- :code:`enable_host_ipv6`: Determines whether to enable IPv6 support. On non-Linux OSes, having this option enabled may disable IPv4 support. (optional)
- Allowed values: :code:`true`, :code:`false`
Expand All @@ -26,6 +37,8 @@ Here's all of the configuration options:
"args": "list of module arguments"
}
- The :code:`module` can be one of :code:`ping`, :code:`http`, :code:`tcp`, :code:`ssvplwc`

- :code:`services`: List of services, set as an object
- Allowed values: must fit the servers schema
- :code:`database`: Database information
Expand All @@ -39,4 +52,38 @@ Here's all of the configuration options:
- :code:`username`: database username
- :code:`password`: database password
- :code:`database`: name of database in the DB system
- :code:`prefix`: prefix for tables
- :code:`prefix`: prefix for tables

Systemd
-------

If you're using systemd, there's four main options:

- **Enabling**: setting a unit to run at boot (:code:`systemctl enable unit_name`)
- **Disabling**: removing a unit from the at-boot list (:code:`systemctl disable unit_name`)
- **Starting**: launching a unit for the current boot (:code:`systemctl start unit_name`)
- **Stopping**: stopping a unit for the current boot (:code:`systemctl stop unit_name`)

It should be noted that, to start a unit at the same time as enabling it, you should pass the :code:`--now` flag, as in
:code:`systemctl enable --now unit_name`

SSVP uses three main units for operation:

- :code:`ssvp-gunicorn.service`: Production web server
- :code:`ssvp-werkzeug.service`: Development web server
- :code:`ssvp-interval.timer`: Server uptime checking timer

Some important notes:

1. :code:`ssvp-gunicorn.service` and :code:`ssvp-werkzeug.service` should not be run at the same time; you only need one web server.
If you try and run both at once, systemd will kill the first one.
2. For those with some experience in systemd, it is very important that :code:`ssvp-interval.timer` not have its suffix left off (running as :code:`systemctl start ssvp-interval`).
Doing so will just run the server uptime checker just once, and not periodically.
3. Do not remove :code:`ssvp-interval.service`; it gets called by :code:`ssvp-interval.timer`.

So, for instance, to set up a standard configuration:

.. code-block:: bash
systemctl enable --now ssvp-gunicorn.service
systemctl enable --now ssvp-interval.timer
4 changes: 2 additions & 2 deletions docs/installing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ If you use the defaults for databases, you should use the defaults in the config
fail to run without the entries.

The full installation is meant for server installs, when you want to segregate the installations and have automation set up for you automatically. If you're a developer,
this often is not necessary. Cron is currently the only supported mode for autoinstallation; please note your cron setup needs to be able to support `@reboot` (most do, but some old editions don't).
Systemd (and OpenRC) support will be added eventually.
this often is not necessary. Cron is one option for installation; systemd is another. Read the `configuration guide <configuration.html>`_ for more information on setting up systemd.
The "enable on boot" option for systemd will take care of everything. OpenRC is not currently supported, but may be added in the future; the same goes for other systems (sysvinit, upstart, runit, shepherd).

You're now done with the installation. You can run the server by running `srv/tmux.sh`. It should print :code:`no current client` when done. You can check on the server by running `tmux attach`,
and disconnect from it by pressing `CTRL-b d`.
Expand Down
59 changes: 50 additions & 9 deletions install.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/bash
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# ssvp: server statistics viewer project
Expand Down Expand Up @@ -27,8 +28,13 @@ cd "$(dirname "$0")"
if [ $(id -u) -ne 0 ]; then
which sudo > /dev/null
if [ $? -ne 0 ]; then
echo "Either run as root, or have sudo installed"
exit 1
which doas > /dev/null
if [ $? -ne 0 ]; then
echo "Either run as root, or have sudo installed"
exit 1
else
PREROOT="doas"
fi
else
PREROOT="sudo"
fi
Expand Down Expand Up @@ -113,25 +119,60 @@ fi
echo -n "Installation directory [current directory]: "
read INSDIR
if [ "$INSDIR" != "" ]; then
$PREROOT make install INSTALLDIR=$INSDIR
$PREROOT make install INSTALLDIR=$INSDIR OGUSER=$(whoami)
# handle SELinux
if [ -f "/usr/sbin/restorecon" ]; then
$PREROOT restorecon -rv $INSDIR
fi
else
INSDIR="$(pwd)"
fi

echo -n "Choose an autorunner method (cron/[none]): "
# TODO: switch to case
echo -n "Choose an autorunner method (systemd/cron/[none]): "
read ATRMTH
if [ "$ATRMTH" == "cron" ]; then
(crontab -l; echo "*/5 * * * * $INSDIR/venv/bin/python3 $INSDIR/srv/interval.py") | crontab -
echo "Cron runner installed"
elif [ "$ATRMTH" == "systemd" ]; then
for i in ssvp-gunicorn.service ssvp-werkzeug.service; do
sed -e "s/<INSTALLDIR>/$(echo $INSDIR | sed 's_/_\\/_g')/g" srv/systemd/$i | $PREROOT tee $INSDIR/srv/systemd/$i > /dev/null
$PREROOT ln -sf $INSDIR/srv/systemd/$i /usr/lib/systemd/system/$i
done
$PREROOT systemctl daemon-reload
echo -n "Enable on boot? prod/dev/[none] "
read ATRACN
case $ATRACN in
"prod")
$PREROOT systemctl enable --now ssvp-gunicorn.service
;;
"dev")
$PREROOT systemctl enable --now ssvp-werkzeug.service
;;
*)
echo "To load on boot or start SSVP later, read https://ssvp.docs.amyip.net/configuration.html#systemd"
;;
esac
fi

echo -n "Choose a server reboot launch method (cron/[none]): "
# TODO: switch to case
echo -n "Choose a server reboot launch method (systemd/cron/[none]): "
read RBTLNC
if [ "$RBTLNC" == "cron" ]; then
(crontab -l; echo "@reboot $INSDIR/srv/tmux.sh") | crontab -
elif [ "$RBTLNC" == "systemd" ]; then
for i in ssvp-interval.service ssvp-interval.timer; do
sed -e "s/<INSTALLDIR>/$(echo $INSDIR | sed 's_/_\\/_g')/g" srv/systemd/$i | $PREROOT tee $INSDIR/srv/systemd/$i > /dev/null
$PREROOT ln -sf $INSDIR/srv/systemd/$i /usr/lib/systemd/system/$i
done
$PREROOT systemctl daemon-reload
echo -n "Enable timer now? n/[y] "
read ENATIM
if [ "$ENATIM" != "n" ]; then
$PREROOT systemctl enable --now systemctl-interval.timer
else
echo "Timer loading information available at https://ssvp.docs.amyip.net/configuration.html#systemd"
fi
fi

echo "Installation finished."

# next todo: cron (also implement systemd timers)
# next todo: systemd service for web server?
echo "Installation finished."
12 changes: 12 additions & 0 deletions srv/systemd/ssvp-gunicorn.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Unit]
Description=ssvp (server statistics viewer project) production server
Documentation=https://ssvp.docs.amyip.net
Conflicts=ssvp-werkzeug

[Service]
Type=simple
ExecStart=<INSTALLDIR>/venv-wrapper.sh srv/gunicorn.sh
Restart=always

[Install]
WantedBy=multi-user.target
10 changes: 10 additions & 0 deletions srv/systemd/ssvp-interval.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Unit]
Description=ssvp (server statistics viewer project) server uptime checker
Documentation=https://ssvp.docs.amyip.net

[Service]
Type=oneshot
ExecStart=<INSTALLDIR>/venv-wrapper.sh python3 srv/interval.py

[Install]
WantedBy=multi-user.target
11 changes: 11 additions & 0 deletions srv/systemd/ssvp-interval.timer
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[Unit]
Description=ssvp (server statistics viewer project) server uptime checker
Documentation=https://ssvp.docs.amyip.net
Requires=ssvp-interval.service

[Timer]
Unit=ssvp-interval.service
OnUnitActiveSec=5min

[Install]
WantedBy=timers.target
12 changes: 12 additions & 0 deletions srv/systemd/ssvp-werkzeug.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Unit]
Description=ssvp (server statistics viewer project) development server
Documentation=https://ssvp.docs.amyip.net
Conflicts=ssvp-gunicorn

[Service]
Type=simple
ExecStart=<INSTALLDIR>/venv-wrapper.sh python3 srv/app.py
Restart=always

[Install]
WantedBy=multi-user.target
2 changes: 1 addition & 1 deletion srv/tmux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
# License version 3 is available at, for your convenience,
# https://www.gnu.org/licenses/agpl-3.0.en.html.

# Should be run with venv-wrapper or the venv natively
cd "$(dirname "$0")"
source ../venv/bin/activate
tmux new-session -d -s ENTER
tmux detach -s ENTER
tmux send-keys -t 0 "./gunicorn.sh" ENTER
67 changes: 67 additions & 0 deletions uninstall.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/bash
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# ssvp: server statistics viewer project
# Copyright (C) 2023 Amy Parker <[email protected]>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA or visit the
# GNU Project at https://gnu.org/licenses. The GNU Affero General Public
# License version 3 is available at, for your convenience,
# https://www.gnu.org/licenses/agpl-3.0.en.html.

set -e

cd "$(dirname "$0")"

echo "SSVP Uninstaller - cleanly uninstalls SSVP"

if [ $(id -u) -ne 0 ]; then
which sudo > /dev/null
if [ $? -ne 0 ]; then
which doas > /dev/null
if [ $? -ne 0 ]; then
echo "Either run as root, or have sudo installed"
exit 1
else
PREROOT="doas"
fi
else
PREROOT="sudo"
fi
fi

echo -n "Installation directory: [none] "
read INSDIR
if [ "$INSDIR" != "" ]; then
$PREROOT rm -rf $INSDIR
fi

which systemctl > /dev/null
if [ $? -eq 0 ]; then
echo -n "Clear systemd? n/[y] "
read CLRSMD
if [ "$CLRSMD" != "n" ]; then
set +e
for i in ssvp-gunicorn.service ssvp-interval.service ssvp-interval.timer ssvp-werkzeug.service; do
# --now was causing systemctl to hang, so do it manually
$PREROOT systemctl disable $i
$PREROOT systemctl stop $i
$PREROOT rm -f /usr/lib/systemd/system/$i
done
set -e
fi
fi

echo "Uninstall complete."
30 changes: 30 additions & 0 deletions venv-wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/bash
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# ssvp: server statistics viewer project
# Copyright (C) 2023 Amy Parker <[email protected]>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA or visit the
# GNU Project at https://gnu.org/licenses. The GNU Affero General Public
# License version 3 is available at, for your convenience,
# https://www.gnu.org/licenses/agpl-3.0.en.html.

set -e

cd "$(dirname "$0")"

source venv/bin/activate

${@: 1}

0 comments on commit e459743

Please sign in to comment.