From 604e6e621511762c4c611ef928724cef37c15cae Mon Sep 17 00:00:00 2001 From: Daniel Berteaud Date: Wed, 8 Nov 2023 22:40:57 +0100 Subject: [PATCH] Start working on docserver --- bundles.yml | 4 + .../service-defaults/onlyoffice-docserver.hcl | 3 + .../onlyoffice-docserver.hcl | 15 ++ images/onlyoffice-docserver/Dockerfile | 29 +++ .../root/entrypoint.d/10-mkdir.sh | 5 + .../root/entrypoint.d/20-sql.sh | 53 +++++ .../root/etc/nginx/nginx.conf | 48 +++++ .../documentserver/production-linux.json | 74 +++++++ .../root/etc/supervisord.conf | 8 + .../root/etc/supervisord.d/ds-converter.ini | 13 ++ .../root/etc/supervisord.d/ds-docserver.ini | 13 ++ .../root/etc/supervisord.d/ds-metrics.ini | 13 ++ .../root/etc/supervisord.d/ds-nginx.ini | 13 ++ .../root/etc/supervisord.d/ds.ini | 2 + .../root/etc/yum.repos.d/onlyoffice.repo | 5 + init/vault-onlyoffice-docserver | 8 + onlyoffice-docserver.nomad.hcl | 193 ++++++++++++++++++ prep.d/10-mv_conf.sh | 1 + prep.d/20-rand-keys.sh | 18 ++ templates/metrics.js.tpl | 8 + templates/nginx.conf.tpl | 72 +++++++ templates/production-linux.json.tpl | 107 ++++++++++ variables.yml | 49 +++++ vault/policies/onlyoffice-docserver.hcl | 8 + 24 files changed, 762 insertions(+) create mode 100644 bundles.yml create mode 100644 consul/config/service-defaults/onlyoffice-docserver.hcl create mode 100644 consul/config/service-intentions/onlyoffice-docserver.hcl create mode 100644 images/onlyoffice-docserver/Dockerfile create mode 100755 images/onlyoffice-docserver/root/entrypoint.d/10-mkdir.sh create mode 100755 images/onlyoffice-docserver/root/entrypoint.d/20-sql.sh create mode 100644 images/onlyoffice-docserver/root/etc/nginx/nginx.conf create mode 100644 images/onlyoffice-docserver/root/etc/onlyoffice/documentserver/production-linux.json create mode 100644 images/onlyoffice-docserver/root/etc/supervisord.conf create mode 100644 images/onlyoffice-docserver/root/etc/supervisord.d/ds-converter.ini create mode 100644 images/onlyoffice-docserver/root/etc/supervisord.d/ds-docserver.ini create mode 100644 images/onlyoffice-docserver/root/etc/supervisord.d/ds-metrics.ini create mode 100644 images/onlyoffice-docserver/root/etc/supervisord.d/ds-nginx.ini create mode 100644 images/onlyoffice-docserver/root/etc/supervisord.d/ds.ini create mode 100644 images/onlyoffice-docserver/root/etc/yum.repos.d/onlyoffice.repo create mode 100755 init/vault-onlyoffice-docserver create mode 100644 onlyoffice-docserver.nomad.hcl create mode 100755 prep.d/10-mv_conf.sh create mode 100755 prep.d/20-rand-keys.sh create mode 100644 templates/metrics.js.tpl create mode 100644 templates/nginx.conf.tpl create mode 100644 templates/production-linux.json.tpl create mode 100644 variables.yml create mode 100644 vault/policies/onlyoffice-docserver.hcl diff --git a/bundles.yml b/bundles.yml new file mode 100644 index 0000000..5b9120e --- /dev/null +++ b/bundles.yml @@ -0,0 +1,4 @@ +--- + +dependencies: + - url: ../common.git diff --git a/consul/config/service-defaults/onlyoffice-docserver.hcl b/consul/config/service-defaults/onlyoffice-docserver.hcl new file mode 100644 index 0000000..e977b34 --- /dev/null +++ b/consul/config/service-defaults/onlyoffice-docserver.hcl @@ -0,0 +1,3 @@ +Kind = "service-defaults" +Name = "[[ .oo.instance ]][[ .consul.suffix ]]" +Protocol = "http" diff --git a/consul/config/service-intentions/onlyoffice-docserver.hcl b/consul/config/service-intentions/onlyoffice-docserver.hcl new file mode 100644 index 0000000..c43f5b1 --- /dev/null +++ b/consul/config/service-intentions/onlyoffice-docserver.hcl @@ -0,0 +1,15 @@ +Kind = "service-intentions" +Name = "[[ .oo.instance ]][[ .consul.suffix ]]" +Sources = [ + { + Name = "[[ .traefik.instance ]]" + Permissions = [ + { + Action = "allow" + HTTP { + PathPrefix = "/" + } + } + ] + } +] diff --git a/images/onlyoffice-docserver/Dockerfile b/images/onlyoffice-docserver/Dockerfile new file mode 100644 index 0000000..08d1822 --- /dev/null +++ b/images/onlyoffice-docserver/Dockerfile @@ -0,0 +1,29 @@ +FROM [[ .docker.repo ]][[ .docker.base_images.alma9.image ]] +MAINTAINER [[ .docker.maintainer ]] + +ENV LANG=[[ .locale.lang ]] \ + TZ=[[ .locale.tz ]] + +USER root +COPY root/etc/yum.repos.d/ /etc/yum.repos.d/ +RUN set -euxo pipefail &&\ + dnf -y update &&\ + rpm -i https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm &&\ + dnf -y module disable postgresql &&\ + dnf -y install \ + postgresql16 \ + onlyoffice-documentserver \ + supervisor \ + nginx \ + jq \ + &&\ + chown :ds /etc/onlyoffice/documentserver/* &&\ + mkdir -p /data &&\ + chown ds:ds /data +COPY root/ / + +EXPOSE 8084 + +USER ds + +CMD ["supervisord", "-n", "-c", "/etc/supervisord.conf"] diff --git a/images/onlyoffice-docserver/root/entrypoint.d/10-mkdir.sh b/images/onlyoffice-docserver/root/entrypoint.d/10-mkdir.sh new file mode 100755 index 0000000..ba0bff1 --- /dev/null +++ b/images/onlyoffice-docserver/root/entrypoint.d/10-mkdir.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -euo pipefail + +mkdir -p /data/files /data/wopi /data/templates diff --git a/images/onlyoffice-docserver/root/entrypoint.d/20-sql.sh b/images/onlyoffice-docserver/root/entrypoint.d/20-sql.sh new file mode 100755 index 0000000..9b0bb52 --- /dev/null +++ b/images/onlyoffice-docserver/root/entrypoint.d/20-sql.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +set -euo pipefail + +function get_value(){ + local KEY=$1 + local VALUE=$(jq -r -s \ + " .[0].services.CoAuthoring.sql * .[1].services.CoAuthoring.sql | .${KEY}" \ + /etc/onlyoffice/documentserver/default.json \ + /etc/onlyoffice/documentserver/production-linux.json) + echo ${VALUE} +} + +export PGHOST=$(get_value "dbHost") +export DGPORT=$(get_value "dbport") +export PGDATABASE=$(get_value "dbName") +export PGUSER=$(get_value "dbUser") +export PGPASSWORD=$(get_value "dbPass") + +function init_db(){ + psql -f /var/www/onlyoffice/documentserver/server/schema/postgresql/createdb.sql +} + +function reset_db(){ + psql -f /var/www/onlyoffice/documentserver/server/schema/postgresql/removetbl.sql +} + +function write_version(){ + echo $(rpm -q onlyoffice-documentserver --qf "%{VERSION}-%{RELEASE}") > /data/onlyoffice.version +} + +export PGHOST=$(get_value "dbHost") +export DGPORT=$(get_value "dbport") +export PGDATABASE=$(get_value "dbName") +export PGUSER=$(get_value "dbUser") +export PGPASSWORD=$(get_value "dbPass") + +if [ ! -e "/data/onlyoffice.version" ]; then + echo "File /data/onlyoffice.version doesn't exist, initializing database" + init_db + write_version +else + PREVIOUS_VERSION=$(head -n 1 /data/onlyoffice.version) + CURRENT_VERSION=$(rpm -q onlyoffice-documentserver --qf "%{VERSION}-%{RELEASE}") + if [ "${CURRENT_VERSION}" != "${PREVIOUS_VERSION}" ]; then + echo "Running ${CURRENT_VERSION} while previous version was ${PREVIOUS_VERSION}. Reinitializing database" + reset_db + init_db + write_version + else + echo "Running ${CURRENT_VERSION}, same as previous version" + fi +fi diff --git a/images/onlyoffice-docserver/root/etc/nginx/nginx.conf b/images/onlyoffice-docserver/root/etc/nginx/nginx.conf new file mode 100644 index 0000000..b042753 --- /dev/null +++ b/images/onlyoffice-docserver/root/etc/nginx/nginx.conf @@ -0,0 +1,48 @@ +worker_processes auto; +error_log /dev/stderr warn; +pid /tmp/nginx.pid; +events { + worker_connections 1024; +} +http { + proxy_temp_path /tmp/proxy_temp; + client_body_temp_path /tmp/client_temp; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + include /etc/nginx/mime.types; + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /dev/stdout main; + sendfile on; + keepalive_timeout 65; + + include /etc/onlyoffice/documentserver/nginx/includes/http-common.conf; + + server { + listen 0.0.0.0:8084; + server_name _; + + client_max_body_size 100m; + + set_real_ip_from 127.0.0.1; + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + + # Override the fonts endpoint to add a Content-Type so reverse proxies can handle caching corectly + location ~ ^(\/[\d]+\.[\d]+\.[\d]+[\.|-][\d]+)?\/fonts(\/.*)$ { + add_header Content-Type font/opentype; + expires 365d; + alias /var/www/onlyoffice/documentserver/fonts$2; + } + set $secure_link_secret verysecretstring; + include /etc/onlyoffice/documentserver/nginx/includes/ds-docservice.conf; + } +} diff --git a/images/onlyoffice-docserver/root/etc/onlyoffice/documentserver/production-linux.json b/images/onlyoffice-docserver/root/etc/onlyoffice/documentserver/production-linux.json new file mode 100644 index 0000000..c6ee6b0 --- /dev/null +++ b/images/onlyoffice-docserver/root/etc/onlyoffice/documentserver/production-linux.json @@ -0,0 +1,74 @@ +{ + "log": { + "filePath": "/etc/onlyoffice/documentserver/log4js/production.json" + }, + "storage": { + "fs": { + "folderPath": "/data/files" + } + }, + "wopi": { + "htmlTemplate" : "/data/wopi" + }, + "services": { + "CoAuthoring": { + "server": { + "newFileTemplate" : "/data/templates", + "static_content": { + "/fonts": { + "path": "/var/www/onlyoffice/documentserver/fonts", + "options": {"maxAge": "7d"} + }, + "/sdkjs": { + "path": "/var/www/onlyoffice/documentserver/sdkjs", + "options": {"maxAge": "7d"} + }, + "/web-apps": { + "path": "/var/www/onlyoffice/documentserver/web-apps", + "options": {"maxAge": "7d"} + }, + "/welcome": { + "path": "/var/www/onlyoffice/documentserver/server/welcome", + "options": {"maxAge": "7d"} + }, + "/info": { + "path": "/var/www/onlyoffice/documentserver/server/info", + "options": {"maxAge": "7d"} + }, + "/sdkjs-plugins": { + "path": "/var/www/onlyoffice/documentserver/sdkjs-plugins", + "options": {"maxAge": "7d"} + }, + "/dictionaries": { + "path": "/var/www/onlyoffice/documentserver/dictionaries", + "options": {"maxAge": "7d"} + } + } + }, + "utils": { + "utils_common_fontdir": "/usr/share/fonts" + }, + "sockjs": { + "sockjs_url": "/web-apps/vendor/sockjs/sockjs.min.js" + } + } + }, + "license": { + "license_file": "/var/www/onlyoffice/documentserver/../Data/license.lic", + "warning_limit_percents": 70, + "packageType": 0 + }, + "FileConverter": { + "converter": { + "fontDir": "/usr/share/fonts", + "presentationThemesDir": "/var/www/onlyoffice/documentserver/sdkjs/slide/themes", + "x2tPath": "/var/www/onlyoffice/documentserver/server/FileConverter/bin/x2t", + "docbuilderPath": "/var/www/onlyoffice/documentserver/server/FileConverter/bin/docbuilder" + } + }, + "SpellChecker": { + "server": { + "dictDir": "/var/www/onlyoffice/documentserver/dictionaries" + } + } +} diff --git a/images/onlyoffice-docserver/root/etc/supervisord.conf b/images/onlyoffice-docserver/root/etc/supervisord.conf new file mode 100644 index 0000000..c94ef46 --- /dev/null +++ b/images/onlyoffice-docserver/root/etc/supervisord.conf @@ -0,0 +1,8 @@ +[supervisord] +pidfile=/tmp/supervisord.pi +nodaemon=true +logfile=/dev/stdout +logfile_maxbytes=0 + +[include] +files = supervisord.d/*.ini diff --git a/images/onlyoffice-docserver/root/etc/supervisord.d/ds-converter.ini b/images/onlyoffice-docserver/root/etc/supervisord.d/ds-converter.ini new file mode 100644 index 0000000..ffae110 --- /dev/null +++ b/images/onlyoffice-docserver/root/etc/supervisord.d/ds-converter.ini @@ -0,0 +1,13 @@ +[program:converter] +command=/var/www/onlyoffice/documentserver/server/FileConverter/converter +directory=/var/www/onlyoffice/documentserver/server/FileConverter +;user=ds +environment=NODE_ENV=production-linux,NODE_CONFIG_DIR=/etc/onlyoffice/documentserver,NODE_DISABLE_COLORS=1,APPLICATION_NAME=onlyoffice +stdout_logfile=/proc/self/fd/1 +stdout_logfile_backups=0 +stdout_logfile_maxbytes=0 +stderr_logfile=/proc/self/fd/2 +stderr_logfile_backups=0 +stderr_logfile_maxbytes=0 +autostart=true +autorestart=true diff --git a/images/onlyoffice-docserver/root/etc/supervisord.d/ds-docserver.ini b/images/onlyoffice-docserver/root/etc/supervisord.d/ds-docserver.ini new file mode 100644 index 0000000..03447f2 --- /dev/null +++ b/images/onlyoffice-docserver/root/etc/supervisord.d/ds-docserver.ini @@ -0,0 +1,13 @@ +[program:docservice] +command=/var/www/onlyoffice/documentserver/server/DocService/docservice +directory=/var/www/onlyoffice/documentserver/server/DocService +;user=ds +environment=NODE_ENV=production-linux,NODE_CONFIG_DIR=/etc/onlyoffice/documentserver,NODE_DISABLE_COLORS=1 +stdout_logfile=/proc/self/fd/1 +stdout_logfile_backups=0 +stdout_logfile_maxbytes=0 +stderr_logfile=/proc/self/fd/2 +stderr_logfile_backups=0 +stderr_logfile_maxbytes=0 +autostart=true +autorestart=true diff --git a/images/onlyoffice-docserver/root/etc/supervisord.d/ds-metrics.ini b/images/onlyoffice-docserver/root/etc/supervisord.d/ds-metrics.ini new file mode 100644 index 0000000..746a11e --- /dev/null +++ b/images/onlyoffice-docserver/root/etc/supervisord.d/ds-metrics.ini @@ -0,0 +1,13 @@ +[program:metrics] +command=/var/www/onlyoffice/documentserver/server/Metrics/metrics ./config/config.js +directory=/var/www/onlyoffice/documentserver/server/Metrics +;user=ds +environment=NODE_DISABLE_COLORS=1 +stdout_logfile=/proc/self/fd/1 +stdout_logfile_backups=0 +stdout_logfile_maxbytes=0 +stderr_logfile=/proc/self/fd/2 +stderr_logfile_backups=0 +stderr_logfile_maxbytes=0 +autostart=true +autorestart=true diff --git a/images/onlyoffice-docserver/root/etc/supervisord.d/ds-nginx.ini b/images/onlyoffice-docserver/root/etc/supervisord.d/ds-nginx.ini new file mode 100644 index 0000000..9ad24cd --- /dev/null +++ b/images/onlyoffice-docserver/root/etc/supervisord.d/ds-nginx.ini @@ -0,0 +1,13 @@ +[program:nginx] +command=/usr/sbin/nginx -g "daemon off;" +directory=/ +;user=nginx +stdout_logfile=/proc/self/fd/1 +stdout_logfile_backups=0 +stdout_logfile_maxbytes=0 +stderr_logfile=/proc/self/fd/2 +stderr_logfile_backups=0 +stderr_logfile_maxbytes=0 +autostart=true +autorestart=true + diff --git a/images/onlyoffice-docserver/root/etc/supervisord.d/ds.ini b/images/onlyoffice-docserver/root/etc/supervisord.d/ds.ini new file mode 100644 index 0000000..7c02b8b --- /dev/null +++ b/images/onlyoffice-docserver/root/etc/supervisord.d/ds.ini @@ -0,0 +1,2 @@ +[group:ds] +programs=docservice,converter,metrics,nginx diff --git a/images/onlyoffice-docserver/root/etc/yum.repos.d/onlyoffice.repo b/images/onlyoffice-docserver/root/etc/yum.repos.d/onlyoffice.repo new file mode 100644 index 0000000..b7fbab1 --- /dev/null +++ b/images/onlyoffice-docserver/root/etc/yum.repos.d/onlyoffice.repo @@ -0,0 +1,5 @@ +[onlyoffice] +baseurl = http://download.onlyoffice.com/repo/centos/main/noarch/ +gpgcheck = 1 +gpgkey = https://raw.githubusercontent.com/ONLYOFFICE/repo/master/centos/RPM-GPG-KEY-ONLYOFFICE +name = Only Office Repository diff --git a/init/vault-onlyoffice-docserver b/init/vault-onlyoffice-docserver new file mode 100755 index 0000000..7cc8ba7 --- /dev/null +++ b/init/vault-onlyoffice-docserver @@ -0,0 +1,8 @@ +#!/bin/sh + +set -euo pipefail + +[[- template "common/vault.mkpgrole.sh.tpl" + dict "ctx" . + "config" (dict "role" .oo.instance "database" "postgres") +]] diff --git a/onlyoffice-docserver.nomad.hcl b/onlyoffice-docserver.nomad.hcl new file mode 100644 index 0000000..6ad84d2 --- /dev/null +++ b/onlyoffice-docserver.nomad.hcl @@ -0,0 +1,193 @@ +[[ $c := merge .oo.ds . -]] + +job [[ .oo.instance | toJSON ]] { + +[[ template "common/job_start.tpl" $c ]] + + group "onlyoffice" { + network { + mode = "bridge" + # This can be used to ensure rabbitmq has a stable hostname + # Even if for now, we do not persist rabbitmq data + hostname = "[[ .oo.instance ]][[ $c.consul.suffix ]]" + } + + volume "ds" { + type = [[ .oo.volumes.ds.type | toJSON ]] + source = [[ .oo.volumes.ds.source | toJSON ]] + access_mode = "single-node-writer" + attachment_mode = "file-system" + } + + service { + name = "[[ .oo.instance ]][[ $c.consul.suffix ]]" + port = 8084 + +[[ template "common/connect.tpl" $c ]] + + check { + name = "health" + type = "http" + path = "/healthcheck" + expose = true + interval = "10s" + timeout = "5s" + + check_restart { + limit = 90 + grace = "2m" + } + } + + tags = [ +[[- if $c.traefik.enabled ]] + "[[ $c.traefik.instance ]].enable=true", + "[[ $c.traefik.instance ]].http.routers.[[ .oo.instance ]][[ $c.consul.suffix ]].rule=Host(`[[ (urlParse .oo.ds.public_url).Hostname ]]`) + [[- if not (regexp.Match "^/?$" (urlParse .oo.ds.public_url).Path) ]] && PathPrefix(`[[ (urlParse .oo.ds.public_url).Path ]]`)[[ end ]]", + "[[ $c.traefik.instance ]].http.routers.[[ .oo.instance ]][[ $c.consul.suffix ]].entrypoints=[[ join $c.traefik.entrypoints "," ]]", +[[- if not (regexp.Match "^/?$" (urlParse .oo.ds.public_url).Path) ]] + "[[ $c.traefik.instance ]].http.middlewares.[[ .oo.instance ]][[ $c.consul.suffix ]]-prefix.stripprefix.prefixes=[[ (urlParse .oo.ds.public_url).Path ]]", + "[[ $c.traefik.instance ]].http.routers.[[ .oo.instance ]][[ $c.consul.suffix ]].middlewares=[[ .oo.instance ]][[ $c.consul.suffix ]]-prefix,[[ template "common/traefik_middlewares.tpl" $c.traefik ]]", +[[- else ]] + "[[ $c.traefik.instance ]].http.routers.[[ .oo.instance ]][[ $c.consul.suffix ]].middlewares=[[ template "common/traefik_middlewares.tpl" $c.traefik ]]", +[[- end ]] +[[- end ]] + ] + + } + + task "documentserver" { + driver = [[ $c.nomad.driver | toJSON ]] + leader = true + + config { + image = [[ .oo.ds.image | toJSON ]] + pids_limit = 100 + readonly_rootfs = true + volumes = [ + "secrets/production-linux.json:/etc/onlyoffice/documentserver/production-linux.json:ro", + "local/metrics.js:/var/www/onlyoffice/documentserver/server/Metrics/config/config.js:ro", + "secrets/nginx.conf:/etc/nginx/nginx.conf:ro" + ] +[[ template "common/tmpfs.tpl" "/tmp" ]] + } + + vault { + policies = ["[[ .oo.instance ]][[ $c.consul.suffix ]]"] + disable_file = true + env = false + } + + env { +[[ template "common/proxy_env.tpl" $c ]] + } + +[[ template "common/file_env.tpl" $c.env ]] + + template { + data =<<_EOT +[[ template "onlyoffice-documentserver/production-linux.json.tpl" . ]] +_EOT + destination = "secrets/production-linux.json" + uid = 100000 + gid = 100990 + perms = 640 + } + + template { + data =<<_EOT +[[ template "onlyoffice-documentserver/metrics.js.tpl" . ]] +_EOT + destination = "local/metrics.js" + } + + template { + data =<<_EOT +[[ template "onlyoffice-documentserver/nginx.conf.tpl" . ]] +_EOT + destination = "secrets/nginx.conf" + uid = 100000 + gid = 100990 + perms = 640 + } + + volume_mount { + volume = "ds" + destination = "/data" + } + +[[ template "common/resources.tpl" $c.resources ]] + + } + +[[ template "common/task.wait_for.tpl" $c ]] + + task "redis" { + driver = [[ $c.nomad.driver | toJSON ]] + user = 2967 + + lifecycle { + hook = "prestart" + sidecar = true + } + + config { + image = "redis:alpine" + pids_limit = 20 + readonly_rootfs = true + args = ["/local/redis.conf"] + } + + template { + data =<<_EOT +bind 127.0.0.1 +maxmemory {{ env "NOMAD_MEMORY_LIMIT" | parseInt | subtract 5 }}mb +databases 1 +save "" +appendonly no +_EOT + destination = "local/redis.conf" + } + + resources { + cpu = 10 + memory = 20 + } + } + +[[ $c := merge .oo.rabbitmq . ]] + + task "rabbitmq" { + driver = [[ $c.nomad.driver | toJSON ]] + user = 100 + + lifecycle { + hook = "prestart" + sidecar = true + } + + config { + image = [[ $c.image | toJSON ]] + pids_limit = 100 + readonly_rootfs = true + volumes = [ + "local/rabbitmq.conf:/etc/rabbitmq/conf.d/30-oods.conf" + ] +[[ template "common/tmpfs.tpl" dict "target" "/var/lib/rabbitmq" "size" 20000000]] + } + + template { + data = <<_EOT +listeners.tcp.1 = 127.0.0.1:5672 +# Set watermark to 70% of the mem allocated to the container +vm_memory_high_watermark.absolute = [[ mul .oo.rabbitmq.resources.memory 734003 ]] +_EOT + destination = "local/rabbitmq.conf" + } + +[[ template "common/file_env.tpl" $c.env ]] + +[[ template "common/resources.tpl" $c.resources ]] + } + } +} diff --git a/prep.d/10-mv_conf.sh b/prep.d/10-mv_conf.sh new file mode 100755 index 0000000..b01df2b --- /dev/null +++ b/prep.d/10-mv_conf.sh @@ -0,0 +1 @@ +[[ template "common/mv_conf.sh.tpl" dict "ctx" . "services" (dict "onlyoffice-docserver" .oo.instance) ]] diff --git a/prep.d/20-rand-keys.sh b/prep.d/20-rand-keys.sh new file mode 100755 index 0000000..8150819 --- /dev/null +++ b/prep.d/20-rand-keys.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +set -euo pipefail + +# Initialize random passwords if needed + +if ! vault kv list [[ .vault.prefix ]]kv/service 2>/dev/null | grep -q -E '^[[ .oo.instance ]]$'; then + vault kv put [[ .vault.prefix ]]kv/service/[[ .oo.instance ]] \ + secret_key=$(pwgen -s -n 50 1) \ + link_secret=$(pwgen -s -n 50 1) +fi + +for PWD in secret_key link_secret; do + if ! vault kv get -field ${PWD} [[ .vault.prefix ]]kv/service/[[ .oo.instance ]] >/dev/null 2>&1; then + vault kv patch [[ .vault.prefix ]]kv/service/[[ .oo.instance ]] \ + ${PWD}=$(pwgen -s -n 50 1) + fi +done diff --git a/templates/metrics.js.tpl b/templates/metrics.js.tpl new file mode 100644 index 0000000..1f2e7a5 --- /dev/null +++ b/templates/metrics.js.tpl @@ -0,0 +1,8 @@ +{ + port: 8125, + address: "127.0.0.1", + mgmt_address: "127.0.0.1", + mgmt_port: 8126, + flushInterval: 600000, + backends: [ "./backends/console" ] +} diff --git a/templates/nginx.conf.tpl b/templates/nginx.conf.tpl new file mode 100644 index 0000000..d70d205 --- /dev/null +++ b/templates/nginx.conf.tpl @@ -0,0 +1,72 @@ +worker_processes auto; +error_log /dev/stderr info; +pid /tmp/nginx.pid; +events { + worker_connections 1024; +} +http { + proxy_temp_path /tmp/proxy_temp; + client_body_temp_path /tmp/client_temp; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + include /etc/nginx/mime.types; + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /dev/stdout main; + sendfile on; + keepalive_timeout 65; + + upstream docservice { + server unix:/tmp/oods.sock; + } + + map $http_host $this_host { + "" $host; + default $http_host; + } + + map $http_x_forwarded_proto $the_scheme { + default $http_x_forwarded_proto; + "" $scheme; + } + + map $http_x_forwarded_host $the_host { + default $http_x_forwarded_host; + "" $this_host; + } + + map $http_upgrade $proxy_connection { + default upgrade; + "" close; + } + + map $http_x_forwarded_prefix $the_prefix { + default $http_x_forwarded_prefix; + } + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $proxy_connection; + proxy_set_header X-Forwarded-Host $the_host; + proxy_set_header X-Forwarded-Proto $the_scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_socket_keepalive on; + + client_max_body_size 100m; + + set_real_ip_from 127.0.0.1; + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + server { + listen 127.0.0.1:8084 default_server; + server_tokens off; + + set $secure_link_secret [[ .oo.ds.link_secret ]]; + include /etc/nginx/includes/ds-docservice.conf; + include /etc/nginx/includes/ds-mime.types.conf; + } +} diff --git a/templates/production-linux.json.tpl b/templates/production-linux.json.tpl new file mode 100644 index 0000000..3290e3c --- /dev/null +++ b/templates/production-linux.json.tpl @@ -0,0 +1,107 @@ +{ + "log": { + "filePath": "/etc/onlyoffice/documentserver/log4js/development.json" + }, + "storage": { + "fs": { + "folderPath": "/data/files", + "secretString": "[[ .oo.ds.link_secret ]]" + } + }, + "wopi": { + "htmlTemplate" : "/data/wopi" + }, + "services": { + "CoAuthoring": { +[[- if and (has .oo.ds "secret_key") (ne .oo.ds.secret_key "") ]] + "secret": { + "inbox": { + "string": "[[ .oo.ds.secret_key ]]" + }, + "outbox": { + "string": "[[ .oo.ds.secret_key ]]" + } + }, + "token": { + "enable": { + "browser": true, + "request": { + "inbox": true, + "outbox": true + } + } + }, +[[- end ]] + "sql": { + "type": "[[ .oo.ds.database.type ]]", + "dbHost": "[[ .oo.ds.database.host ]]", + "dbPort": [[ .oo.ds.database.port ]], + "dbName": "[[ .oo.ds.database.name ]]", + "dbUser": "[[ .oo.ds.database.user ]]", + "dbPass": "[[ .oo.ds.database.password ]]" + }, + "autoAssembly": { + "enable": true, + "interval": "5m" + }, + "server": { + "port": "/tmp/oods.sock", + "newFileTemplate" : "/data/templates", + "static_content": { + "/fonts": { + "path": "/var/www/onlyoffice/documentserver/fonts", + "options": {"maxAge": "7d"} + }, + "/sdkjs": { + "path": "/var/www/onlyoffice/documentserver/sdkjs", + "options": {"maxAge": "7d"} + }, + "/web-apps": { + "path": "/var/www/onlyoffice/documentserver/web-apps", + "options": {"maxAge": "7d"} + }, + "/welcome": { + "path": "/var/www/onlyoffice/documentserver/server/welcome", + "options": {"maxAge": "7d"} + }, + "/info": { + "path": "/var/www/onlyoffice/documentserver/server/info", + "options": {"maxAge": "7d"} + }, + "/sdkjs-plugins": { + "path": "/var/www/onlyoffice/documentserver/sdkjs-plugins", + "options": {"maxAge": "7d"} + }, + "/dictionaries": { + "path": "/var/www/onlyoffice/documentserver/dictionaries", + "options": {"maxAge": "7d"} + } + } + }, + "utils": { + "utils_common_fontdir": "/usr/share/fonts" + }, + "sockjs": { + "sockjs_url": "/web-apps/vendor/sockjs/sockjs.min.js" + } + } + }, + "license": { + "license_file": "/var/www/onlyoffice/documentserver/../Data/license.lic", + "warning_limit_percents": 70, + "packageType": 0 + }, + "FileConverter": { + "converter": { + "fontDir": "/usr/share/fonts", + "presentationThemesDir": "/var/www/onlyoffice/documentserver/sdkjs/slide/themes", + "x2tPath": "/var/www/onlyoffice/documentserver/server/FileConverter/bin/x2t", + "docbuilderPath": "/var/www/onlyoffice/documentserver/server/FileConverter/bin/docbuilder" + } + }, + "SpellChecker": { + "server": { + "dictDir": "/var/www/onlyoffice/documentserver/dictionaries" + } + } +} diff --git a/variables.yml b/variables.yml new file mode 100644 index 0000000..7e9cb76 --- /dev/null +++ b/variables.yml @@ -0,0 +1,49 @@ +--- + +oo: + instance: onlyoffice-docserver + + ds: + image: danielberteaud/onlyoffice-docserver:latest + env: {} + resources: + cpu: 200 + memory: 512 + public_url: https://oods.example.org + secret_key: '{{ with secret "[[ .vault.prefix ]]kv/service/[[ .oo.instance ]]" }}{{ .Data.data.secret_key }}{{ end }}' + link_secret: '{{ with secret "[[ .vault.prefix ]]kv/service/[[ .oo.instance ]]" }}{{ .Data.data.link_secret }}{{ end }}' + database: + type: postgres + host: localhost + port: 5432 + name: '[[ .oo.instance ]]' + user: '{{- with secret "[[ .vault.prefix ]]database/creds/[[ .oo.instance ]]" }}{{ .Data.username }}{{ end }}' + password: '{{- with secret "[[ .vault.prefix ]]database/creds/[[ .oo.instance ]]" }}{{ .Data.password }}{{ end }}' + traefik: + enabled: true + base_middlewares: [] + #- rate-limit-std@file + #- inflight-std@file + #- security-headers@file + #- forward-headers@file + #- hsts@file + #- compression@file + wait_for: + - service: 'master.postgres[[ .consul.suffix ]]' + consul: + connect: + upstreams: + - destination_name: 'postgres[[ .consul.suffix ]]' + local_bind_port: 5432 + + rabbitmq: + image: rabbitmq:alpine + env: {} + resources: + cpu: 80 + memory: 128 + + volumes: + ds: + type: csi + source: '[[ .oo.instance ]]-data' diff --git a/vault/policies/onlyoffice-docserver.hcl b/vault/policies/onlyoffice-docserver.hcl new file mode 100644 index 0000000..f1f9108 --- /dev/null +++ b/vault/policies/onlyoffice-docserver.hcl @@ -0,0 +1,8 @@ +path "[[ .vault.prefix ]]kv/data/service/[[ .oo.instance ]]" { + capabilities = ["read"] +} + +path "[[ .vault.prefix ]]database/creds/[[ .oo.instance ]]" { + capabilities = ["read"] +} +