Installation
Server requirements
DockerorJava 17or higher- PostgreSQL 9.4 or higher
- (Optionally) Sentry account for error tracking
NB! Lower versions may work too, but never tested.
Environment variables
The app relies on the following environment variables (envs) to operate:
APP__VERSION- app version, used in Sentry reportingAPP__ENV[defaultproduction] - app environment (e.g.test,stage,production), used in Sentry reportingSLACK__TOKEN[defaultToken] - Slack Bot User OAuth Token (see details in theSlack settingssection)SLACK__SIGN[defaultSecret] - Slack Signing Secret key (see details in theSlack settingssection)ALERTS__SENTRY_DSN- Sentry data source name [defaulthttps://public:private@localhost/1]SERVER__PORT[default8080] - Jetty application server portSERVER__LOGLEVEL[defaultINFO] - App log level (dienstplanlogger only)SERVER__ROOTLEVEL[defaultINFO] - Root log level (all loggers, including DB, Jetty server, etc.)SERVER__ACCESS_LOG[defaulttrue] - Enable access logging? Access logs haveINFOlevel.DAEMON__DELAY[default60] - Delay in seconds for checks in the schedule daemonDB__SERVER_NAME[defaultlocalhost] - PostgreSQL server host nameDB__PORT_NUMBER[default5432] - PostgreSQL server port numberDB__DATABASE_NAME[defaultdienstplan] - PostgreSQL server database nameDB__USERNAME[defaultdienstplan] - PostgreSQL server user nameDB__PASSWORD[defaultdienstplan] - PostgreSQL server passwordDB__POOL_MIN_IDLE[default20] - PostgreSQL connection pool's min number of idle connectionsDB__POOL_MAX_SIZE[default20] - PostgreSQL connection pool's max number of connectionsDB__TIMEOUT_MS_CONNECTION[default10000] - PostgreSQL connection timeout in millisecondsDB__LIFETIME_MAX_MS_CONNECTION[default1800000] - Maximum lifetime of a connection in the pool in millisecondsDB__LIFETIME_KEEPALIVE_MS_CONNECTION[default0] - Keep alive in milliseconds for idle connections in the pool
Deployment to production
dienstplan is a Clojure program that can be deployed as:
- a
Dockercontainer jaroruberjarfile
Docker
The easiest option to run an app is by using a Docker image:
$ docker pull pilosus/dienstplan:X.Y.Z
$ docker run \
-e APP__VERSION="X.Y.Z" \
-e APP__ENV="production" \
-e APP__DEBUG=false \
-e SLACK__TOKEN="xoxb-Your-Bot-User-OAuth-Token" \
-e SLACK__SIGN="Your-Signing-Secret" \
-e ALERTS__SENTRY_DSN="https://public:private@localhost/1" \
-e SERVER__PORT=8080 \
-e SERVER__LOGLEVEL=INFO \
-e DB__SERVER_NAME=your-postgresql.example.com \
-e DB__PORT_NUMBER=5432 \
-e DB__DATABASE_NAME="your-postgresql-db-name" \
-e DB__USERNAME="your-postgresql-db-username" \
-e DB__PASSWORD="your-postgresql-db-passwords" \
-it --rm pilosus/dienstplan:X.Y.Z \
java -jar app.jar --mode server
For database migrations and rollbacks instead of java -jar app.jar
--mode server entypoint use:
java -jar app.jar --mode migratejava -jar app.jar --mode rollback
For schedules processing as one-time job use:
java -jar app.jar --mode schedule
For schedules processing as a background running worker (daemon) use:
java -jar app.jar --mode schedule-daemon
It's recommended to use a SemVer tag matching the latest
release for a Docker
image (e.g. pilosus/dienstplan:X.Y.Z). Do not rely on the
pilosus/dienstplan:latest unless you know what you are doing!
Jar file
- Get Clojure to compile a standalone
jarfile - Clone the GitHub repository with
git clone git@github.com:pilosus/dienstplan.git - In the repo directory complile a standalone
jarfile withmake uberjar - Run the app:
$ APP__DEBUG=false \
SLACK__TOKEN="xoxb-Your-Bot-User-OAuth-Token" \
SLACK__SIGN="Your-Signing-Secret" \
ALERTS__SENTRY_DSN="https://public:private@localhost/1" \
SERVER__PORT=8080 \
SERVER__LOGLEVEL=INFO \
DB__SERVER_NAME=your-postgresql.example.com \
DB__PORT_NUMBER=5432 \
DB__DATABASE_NAME="your-postgresql-db-name" \
DB__USERNAME="your-postgresql-db-username" \
DB__PASSWORD="your-postgresql-db-passwords" \
java -jar /path/to/repo/target/uberjar/dienstplan-X.Y.Z-standalone.jar
For database migrations and rollbacks instead of java -jar dienstplan-X.Y.Z-standalone.jar entypoint use:
java -jar dienstplan-X.Y.Z-standalone.jar --mode migratejava -jar dienstplan-X.Y.Z-standalone.jar --mode rollback
For schedules processing as one-time job use:
java -jar dienstplan-X.Y.Z-standalone.jar --mode schedule
For schedules processing as a daemon use:
java -jar dienstplan-X.Y.Z-standalone.jar --mode schedule-daemon
Ansible Playbook
You can get a full set of installation scripts needed to:
- Provision a GNU/Linux server from scratch
- Set up the
dienstplanbot app as asystemdservice - Apply database migrations automatically as a
systemdservice - Run the app
in the dienstplan-deploy repository.
Running locally
The app can be run locally with Docker Compose with:
make build
make up
make migrate
These will build a Docker container, start the app and the database locally, and apply database migrations.
Another way to run the app is with Clojure CLI:
clojure M:run
Schedules processing as a one-time job can be done:
make schedule
or
clojure -X:schedule
Scheduling processing as a daemon (background worker) can be done:
make daemon
or
clojure -X:schedule-daemon
Don't forget to use envs to configure the app properly.
Extra configs
Java system properties allow to configure some extra behaviours of the
app. System properties can be passed as an option
-Dproperty.name=property.value in java invocation:
java -Dproperty.name=property.value -jar app.jar
including in Docker entrypoints:
docker run -it --rm pilosus/dienstplan:X.Y.Z java -Dproperty.name=property.value -jar app.jar
Logging
By default, logs are printed to the standard output in plain text format. It may be optimal for local development or staging environment, but structured logging with JSON stream of events suits best production grade installations. To enable logging in JSON format use the following system props:
java -Dlogback.configurationFile=resources/logback.json.xml ...
Custom logging configs can be written and passed in to the app using the same system property. See the logback manual for more details.
Socket Server
Clojure allows to start a socket server at initialization using system properties:
java -Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl} ..."
See the guide for more details.
Slack settings
In order to install the app in your Slack workspace, do the following:
- Sign in to your Slack Apps Dashboard
Create New App->From an app manifest->Workspace: your workspace- Copy and paste the app manifest in YAML format:
_metadata:
major_version: 1
minor_version: 1
display_information:
name: dienstplan
description: Slack bot for duty rotations
background_color: "#002087"
features:
bot_user:
display_name: dienstplan
always_online: false
oauth_config:
scopes:
bot:
- app_mentions:read
- channels:read
- chat:write
- chat:write.customize
settings:
event_subscriptions:
request_url: https://YOUR-DOMAIN/api/events
bot_events:
- app_mention
org_deploy_enabled: false
socket_mode_enabled: false
token_rotation_enabled: false
- Fix
settings -> event_subscriptions -> request_urlto match your server's public url (/api/eventsurl path is hardcoded in the app) Basic Information->Install your app->Install to WorkspaceOAuth & Permissions-> copyOAuth Tokens for Your Workspaceto be used forSLACK__TOKENenvironment variableBasic Information->App Credentials-> copySigning Secretto be used forSLACK__SIGNenvironment variable- Make it looking nice:
Basic Information->Display Information-> upload an app icon with a public domain license - Deploy the app