Add a rendered example

This commit is contained in:
Daniel Berteaud 2024-01-05 16:05:38 +01:00
parent 8b578689bd
commit 7c2c6bfd2f
17 changed files with 608 additions and 0 deletions

9
example/LICENSE Normal file
View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2023 nomad
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

2
example/README.md Normal file
View File

@ -0,0 +1,2 @@
# onlyoffice-documentserver

View File

@ -0,0 +1,3 @@
Kind = "service-defaults"
Name = "onlyoffice"
Protocol = "http"

View File

@ -0,0 +1,21 @@
Kind = "service-intentions"
Name = "onlyoffice"
Sources = [
{
Name = "traefik"
Permissions = [
{
Action = "deny"
HTTP {
PathRegex = "^(\\/[\\d]+\\.[\\d]+\\.[\\d]+[\\.|-][\\d]+)?\\/(internal|info)(\\/.*)$"
}
},
{
Action = "allow"
HTTP {
PathPrefix = "/"
}
}
]
}
]

View File

@ -0,0 +1,53 @@
FROM danielberteaud/alma:9.24.1-3
MAINTAINER Daniel Berteaud <dbd@ehtrace.com>
ARG OO_VERSION=7.5.1 \
CARETAKERD_VERSION=1.0.8
ENV LANG=fr_FR.utf8 \
TZ=Europe/Paris \
NGINX_LISTEN_IP=0.0.0.0 \
NODE_ENV=production-linux \
NODE_CONFIG_DIR=/etc/onlyoffice/documentserver \
NODE_DISABLE_COLORS=1 \
APPLICATION_NAME=onlyoffice \
OO_STORAGE_SECRET=changeme \
OO_JWT_TOKEN=changeme \
OO_USE_TOKEN=true \
OO_AUTOSAVE=true \
OO_AUTOSAVE_INTERVAL=5m \
OO_VERIFY_CERT=true \
OO_LOG4JS_CONFIG=/etc/onlyoffice/documentserver/log4js/production.json \
OO_DB_HOST=localhost \
OO_DB_PORT=5432 \
OO_DB_NAME=onlyoffice \
OO_DB_USER=onlyoffice \
OO_DB_PASS=onlyoffice
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 &&\
addgroup -g 819 ds &&\
adduser --system --ingroup ds --disabled-password --uid 819 --home /var/www/onlyoffice/documentserver/ --shell /sbin/nologin ds &&\
dnf -y install \
dnf \
postgresql16 \
onlyoffice-documentserver \
nginx \
&&\
curl -sSL https://github.com/echocat/caretakerd/releases/download/v${CARETAKERD_VERSION}/caretakerd-linux-amd64.tar.gz | \
tar xvz --exclude caretakerd.html -C /usr/local/bin &&\
chmod +x /usr/local/bin/caretakerd &&\
dnf clean all &&\
rm -rf /var/cache/dnf/* /var/cache/yum/* /var/log/dnf* /var/log/yum/* /var/lib/dnf/history*
COPY root/ /
EXPOSE 8819
USER ds
CMD ["caretakerd", "run"]

View File

@ -0,0 +1,6 @@
#!/bin/sh
set -euo pipefail
echo "Replacing env variable in nginx config"
/usr/local/bin/envsubst < /etc/nginx/nginx.conf > /tmp/nginx.conf

View File

@ -0,0 +1,38 @@
#!/bin/sh
set -euo pipefail
export PGHOST=${OO_DB_HOST}
export DGPORT=${OO_DB_PORT}
export PGDATABASE=${OO_DB_NAME}
export PGUSER=${OO_DB_USER}
export PGPASSWORD=${OO_DB_PASS}
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}") > /var/lib/onlyoffice/documentserver/App_Data/onlyoffice.version
}
if [ ! -e "/var/lib/onlyoffice/documentserver/App_Data/onlyoffice.version" ]; then
echo "File /var/lib/onlyoffice/documentserver/App_Data/onlyoffice.version doesn't exist, initializing database"
init_db
write_version
else
PREVIOUS_VERSION=$(head -n 1 /var/lib/onlyoffice/documentserver/App_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

View File

@ -0,0 +1,15 @@
services:
docserver:
type: master
command: ["/var/www/onlyoffice/documentserver/server/DocService/docservice"]
preCommands:
- ["rm", "-f", "/tmp/oods.sock"]
directory: /var/www/onlyoffice/documentserver/server/DocService
metrics:
command: ["/var/www/onlyoffice/documentserver/server/Metrics/metrics", "./config/config.js"]
directory: /var/www/onlyoffice/documentserver/server/Metrics
converter:
command: ["/var/www/onlyoffice/documentserver/server/FileConverter/converter"]
directory: /var/www/onlyoffice/documentserver/server/FileConverter
nginx:
command: ["/usr/sbin/nginx", "-c", "/tmp/nginx.conf"]

View File

@ -0,0 +1,71 @@
worker_processes auto;
error_log /dev/stderr warn;
pid /tmp/nginx.pid;
daemon off;
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 max_fails=0 fail_timeout=0s;
}
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;
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 ${NGINX_LISTEN_IP}:8819 default_server;
server_tokens off;
set $secure_link_secret ${OO_STORAGE_SECRET};
include /etc/nginx/includes/ds-docservice.conf;
include /etc/nginx/includes/ds-mime.types.conf;
}
}

View File

@ -0,0 +1,48 @@
{
"log": {
"filePath": "OO_LOG4JS_CONFIG"
},
"storage": {
"fs": {
"secretString": "OO_STORAGE_SECRET"
}
},
"services": {
"CoAuthoring": {
"secret": {
"inbox": {
"string": "OO_JWT_TOKEN"
},
"outbox": {
"string": "OO_JWT_TOKEN"
},
"session": {
"string": "OO_JWT_TOKEN"
}
},
"token": {
"browser": "OO_USE_TOKEN",
"request": {
"inbox": "OO_USE_TOKEN",
"outbox": "OO_USE_TOKEN"
}
},
"requestDefaults": {
"rejectUnauthorized": "OO_VERIFY_CERT"
},
"sql": {
"type": "OO_DB_TYPE",
"dbHost": "OO_DB_HOST",
"dbPort": "OO_DB_PORT",
"dbName": "OO_DB_NAME",
"dbUser": "OO_DB_USER",
"dbPass": "OO_DB_PASS"
},
"autoAssembly": {
"enable": "OO_AUTOSAVE",
"interval": "OO_AUTOSAVE_INTERVAL"
}
}
}
}

View File

@ -0,0 +1,9 @@
{
"services": {
"CoAuthoring": {
"server": {
"port": "/tmp/oods.sock"
}
}
}
}

View File

@ -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

View File

@ -0,0 +1,12 @@
#!/bin/sh
set -euo pipefail
vault write database/roles/onlyoffice \
db_name="postgres" \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
GRANT \"onlyoffice\" TO \"{{name}}\"; \
ALTER ROLE \"{{name}}\" SET role = \"onlyoffice\"" \
default_ttl="12h" \
max_ttl="720h"

View File

@ -0,0 +1,271 @@
job "onlyoffice" {
datacenters = ["dc1"]
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 = "onlyoffice"
}
volume "data" {
source = "onlyoffice-data"
type = "csi"
access_mode = "single-node-writer"
attachment_mode = "file-system"
}
volume "rabbitmq" {
source = "onlyoffice-rabbitmq"
type = "csi"
access_mode = "single-node-writer"
attachment_mode = "file-system"
}
service {
name = "onlyoffice"
port = 8819
connect {
sidecar_service {
proxy {
upstreams {
destination_name = "postgres"
local_bind_port = 5432
}
}
}
sidecar_task {
resources {
cpu = 50
memory = 64
}
}
}
check {
name = "health"
type = "http"
path = "/healthcheck"
expose = true
interval = "10s"
timeout = "8s"
check_restart {
limit = 30
grace = "2m"
}
}
tags = [
"traefik.enable=true",
"traefik.http.routers.onlyoffice.rule=Host(`oods.example.org`)",
"traefik.http.routers.onlyoffice.entrypoints=https",
"traefik.http.middlewares.onlyoffice-headers.headers.contentsecuritypolicy=connect-src 'self' https://www.zotero.org https://cdn.jsdelivr.net https://cdn.rawgit.com https://translate.googleapis.com https://code.responsivevoice.org https://onlyoffice.github.io;default-src 'self';font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com;frame-src 'self' https://www.youtube.com https://onlyoffice.github.io;img-src 'self' data: https://*;media-src 'self' https://code.responsivevoice.org;script-src 'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' blob: https://ajax.googleapis.com https://www.youtube.com/ https://*.cloudfront.net https://cdn.rawgit.com https://code.jquery.com https://translate.googleapis.com https://code.responsivevoice.org https://cdn.jsdelivr.net https://onlyoffice.github.io;style-src 'self' 'unsafe-inline' data: https://fonts.googleapis.com https://translate.googleapis.com https://onlyoffice.github.io;",
"traefik.http.middlewares.onlyoffice-headers.headers.customrequestheaders.X-Forwarded-Proto=https",
"traefik.http.routers.onlyoffice.middlewares=onlyoffice-headers,rate-limit-high@file,inflight-high@file,security-headers@file,hsts@file,compression@file",
]
}
task "docserver" {
driver = "docker"
leader = true
config {
image = "danielberteaud/onlyoffice-docserver:7.5.1-8"
pids_limit = 200
readonly_rootfs = true
volumes = [
"local/:/tmp",
"local/metrics.js:/var/www/onlyoffice/documentserver/server/Metrics/config/config.js:ro"
]
}
vault {
policies = ["onlyoffice"]
disable_file = true
env = false
}
env {
NGINX_LISTEN_IP = "127.0.0.1"
APPLICATION_NAME = "onlyoffice"
WAIT_FOR_TARGETS = "127.0.0.1:5672"
}
# Use a template block instead of env {} so we can fetch values from vault
template {
data = <<_EOT
LANG=fr_FR.utf8
OO_DB_HOST=127.0.0.1
OO_DB_NAME=onlyoffice
OO_DB_PASS={{ with secret "database/creds/onlyoffice" }}{{ .Data.password }}{{ end }}
OO_DB_PORT=5432
OO_DB_USER={{ with secret "database/creds/onlyoffice" }}{{ .Data.username }}{{ end }}
OO_JWT_TOKEN={{ with secret "kv/service/onlyoffice" }}{{ .Data.data.jwt_token }}{{ end }}
OO_STORAGE_SECRET={{ with secret "kv/service/onlyoffice" }}{{ .Data.data.storage_secret }}{{ end }}
TZ=Europe/Paris
_EOT
destination = "secrets/.env"
perms = 400
env = true
}
template {
data = <<_EOT
{
port: 8125,
address: "127.0.0.1",
mgmt_address: "127.0.0.1",
mgmt_port: 8126,
flushInterval: 600000,
backends: [ "./backends/console" ]
}
_EOT
destination = "local/metrics.js"
}
volume_mount {
volume = "data"
destination = "/var/lib/onlyoffice/documentserver/App_Data/"
}
resources {
cpu = 300
memory = 512
}
}
# wait for required services tp be ready before starting the main task
task "wait-for" {
driver = "docker"
user = 1053
config {
image = "danielberteaud/wait-for:24.1-1"
readonly_rootfs = true
pids_limit = 20
}
lifecycle {
hook = "prestart"
}
env {
SERVICE_0 = "master.postgres.service.consul"
}
resources {
cpu = 10
memory = 10
memory_max = 30
}
}
task "redis" {
driver = "docker"
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
}
}
task "rabbitmq" {
driver = "docker"
#user = 100
lifecycle {
hook = "prestart"
sidecar = true
}
config {
image = "rabbitmq:alpine"
pids_limit = 100
readonly_rootfs = true
volumes = [
"local/rabbitmq.conf:/etc/rabbitmq/conf.d/30-oods.conf"
]
}
# Use a template block instead of env {} so we can fetch values from vault
template {
data = <<_EOT
LANG=fr_FR.utf8
TZ=Europe/Paris
_EOT
destination = "secrets/.env"
perms = 400
env = true
}
template {
data = <<_EOT
listeners.tcp.1 = 127.0.0.1:5672
# Set watermark to 95% of the mem allocated to the container
#vm_memory_high_watermark.absolute = 155398932
vm_memory_high_watermark.relative = 0.999
_EOT
destination = "local/rabbitmq.conf"
}
volume_mount {
volume = "rabbitmq"
destination = "/var/lib/rabbitmq"
}
resources {
cpu = 200
memory = 156
}
}
}
}

19
example/prep.d/10-mv_conf.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
set -eu
if [ "onlyoffice" != "onlyoffice" ]; then
for DIR in vault consul nomad; do
if [ -d output/${DIR} ]; then
for FILE in $(find output/${DIR} -name "*onlyoffice*.hcl" -type f); do
NEW_FILE=$(echo "${FILE}" | sed -E "s/onlyoffice/onlyoffice/g")
mv "${FILE}" "${NEW_FILE}"
done
fi
done
fi

18
example/prep.d/20-rand-keys.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/sh
set -euo pipefail
# Initialize random passwords if needed
if ! vault kv list kv/service 2>/dev/null | grep -q -E '^onlyoffice$'; then
vault kv put kv/service/onlyoffice \
jwt_token=$(pwgen -s -n 50 1) \
storage_secret=$(pwgen -s -n 50 1)
fi
for PWD in jwt_token storage_secret; do
if ! vault kv get -field ${PWD} kv/service/onlyoffice >/dev/null 2>&1; then
vault kv patch kv/service/onlyoffice \
${PWD}=$(pwgen -s -n 50 1)
fi
done

View File

@ -0,0 +1,8 @@
path "kv/data/service/onlyoffice" {
capabilities = ["read"]
}
path "database/creds/onlyoffice" {
capabilities = ["read"]
}