NextCloud and OnlyOffice via Docker: Difference between revisions

From WikiMLT
Line 159: Line 159:
It is possible to set-up OnlyOffice to use HTTPS and certain FQDN through its configuration. However in this section i described how to create Apache2 Reverse proxy that will handle this.
It is possible to set-up OnlyOffice to use HTTPS and certain FQDN through its configuration. However in this section i described how to create Apache2 Reverse proxy that will handle this.


First, test whether the necessary Apache2 modules are enabled. Below is show the list of the modules retired for this set-up.<syntaxhighlight lang="shell" line="1">
First, test whether the necessary Apache2 modules are enabled. Below is show the list of the modules retired for this set-up.
<syntaxhighlight lang="shell" line="1">
sudo apache2ctl -M | grep -E 'auth[nz]_core|unixd|proxy|headers|setenvif'
sudo apache2ctl -M | grep -E 'auth[nz]_core|unixd|proxy|headers|setenvif'
</syntaxhighlight><syntaxhighlight lang="bash">
</syntaxhighlight><syntaxhighlight lang="bash">
Line 174: Line 175:
</syntaxhighlight>Then setup a new virtual host as follow and restart Apache2. Note in this scenario you need a valid SSL/TLS certificate. In my case I'm using Let's encrypt wildcard certificate for the base domain where the instances of NextCloud and OnlyOffice are installed.<syntaxhighlight lang="shell" line="1">
</syntaxhighlight>Then setup a new virtual host as follow and restart Apache2. Note in this scenario you need a valid SSL/TLS certificate. In my case I'm using Let's encrypt wildcard certificate for the base domain where the instances of NextCloud and OnlyOffice are installed.<syntaxhighlight lang="shell" line="1">
sudo nano /etc/apache2/sites-enabled/docs.example.com.conf
sudo nano /etc/apache2/sites-enabled/docs.example.com.conf
</syntaxhighlight><syntaxhighlight lang="apacheconf" line="1">
</syntaxhighlight><syntaxhighlight lang="apacheconf" line="1" class="mlw-pre-max-height-320">
Define docs_base_fqdn example.com
Define docs_base_fqdn example.com
Define docs_fqdn docs.example.com
Define docs_fqdn docs.example.com

Revision as of 17:22, 25 September 2022

Here is a short step-by-step man­u­al: How to set­up On­ly­Of­fice Dock­er con­tain­er and proxy it by Apache2 for us­age via NextCloud.

In­stall Dock­er

Ac­cord­ing to the Dock­er and Dock­er-com­pose in­stal­la­tion, read the guide Dock­er Ba­sic Set­up. The rest part of this sec­tion is dep­re­cat­ed, but is leaved here as his­tor­i­cal note :)

#Re­move me: Dep­re­cat­ed Sec­tion
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu  $(lsb_release -cs)  stable"
sudo apt install docker-ce
docker --version
sudo systemctl start docker
sudo systemctl enable docker
Al­low Dock­er us­age by your $USER with­out us­ing su­do.
sudo groupadd docker
sudo usermod -aG docker $USER
su - $USER
id -nG
Prune un­used Dock­er con­tain­ers and im­ages pe­ri­od­i­cal­ly.
sudo crontab -l | grep -i 'docker'
0 2 * * 7 /usr/bin/docker container prune
In my case the fol­low­ing was the most im­por­taint step to get On­ly­Of­fice con­tain­er works cor­rect­ly.
sudo sed 's/^#DOCKER_OPTS/DOCKER_OPTS/' /etc/default/docker -i
sudo systemctl restart docker

Set­up the On­ly­Of­fice Dock­er Con­tain­er

Cre­ate a di­rec­to­ry where the con­fig­u­ra­tion file docker-compose.yaml and the per­sis­tent vol­umes will live.

mkdir /home/docker/onlyoffice
cd /home/docker/onlyoffice

Pull the Dock­er im­ages and run an On­ly­Of­fice con­tain­er for a first time

sudo docker run -i -t -d -p 8081:80 --restart=always \
-v $PWD/DocumentServer/logs:/var/log/onlyoffice  \
-v $PWD/DocumentServer/data:/var/www/onlyoffice/Data  \
-v $PWD/DocumentServer/lib:/var/lib/onlyoffice \
-v $PWD/DocumentServer/db:/var/lib/postgresql \
--hostname docs --name onlyoffice-docs \
onlyoffice/documentserver:latest

Test whether it works. At this point the On­ly­Of­fice doc­u­ment serv­er must be ac­ces­si­ble the brows­er, prob­a­bly you maybe need to wait about 10 sec­onds be­fore it be­come ac­ces­si­ble. Note the host port 8081 must be open (for you) with­in the host's fire­wall.

#De­tails
http://<host-ip>:8081/welcome/

En­able the in­te­grat­ed test ex­am­ples.

docker exec onlyoffice-docs supervisorctl start ds:example
docker exec onlyoffice-docs sed 's,autostart=false,autostart=true,' -i /etc/supervisor/conf.d/ds-example.conf

Now you can ac­cess the ex­am­ples at the fol­low­ing ad­dress.

http://<host-ip>:8081/example/

Ex­port the con­fig­u­ra­tion files. For some rea­son the con­fig­u­ra­tion files can­not be ex­port­ed via the vol­ume op­tion as this is done above for some oth­er di­rec­to­ries. So, if we need that, we need first to copy them man­u­al­ly.

#De­tails
sudo mkdir DocumentServer/etc
sudo docker cp onlyoffice-docs:/etc/onlyoffice DocumentServer/etc
sudo docker cp onlyoffice-docs:/etc/supervisor DocumentServer/etc

Now we can stop and prune the con­tain­er.

docker stop onlyoffice-docs
docker container prune
Now cre­ate new con­tain­er and at­tach the di­rec­to­ries with the con­fig­u­ra­tion files as vol­umes.
sudo docker run -i -t -d -p 8081:80 --restart=always \
-v "$PWD/DocumentServer/logs:/var/log/onlyoffice" \
-v "$PWD/DocumentServer/data:/var/www/onlyoffice/Data" \
-v "$PWD/DocumentServer/lib:/var/lib/onlyoffice" \
-v "$PWD/DocumentServer/db:/var/lib/postgresql" \
-v "$PWD/DocumentServer/etc/onlyoffice:/etc/onlyoffice" \
-v "$PWD/DocumentServer/etc/supervisor:/etc/supervisor" \
--hostname docs --name onlyoffice-docs \
onlyoffice/documentserver:latest

Start­ing from ver­sion 7.2, JWT (JSON Web To­ken) is en­abled by de­fault. A ran­dom se­cret is gen­er­at­ed au­to­mat­i­cal­ly if a cus­tom se­cret has not been added dur­ing in­stal­la­tion. To ob­tain the de­fault se­cret, run this com­mand:

docker exec onlyoffice-docs /var/www/onlyoffice/documentserver/npm/json \
-f /etc/onlyoffice/documentserver/local.json 'services.CoAuthoring.secret.session.string'
xd4f2PO5hdHJHjpV1NdD

You can re­place the de­fault se­cret with a cus­tom key us­ing Dock­er env. More in­for­ma­tion about JWT in the doc­u­men­ta­tion. Once again, in or­der to make the JWT per­sis­tent you need to pro­vide it via Dock­er as en­vi­ron­ment vari­able – this will be done with­in the next sec­tion. Fi­nal­ly. Stop and prune the con­tain­er, be­cause in the next sec­tion we will cre­ate a Dock­er-com­pose con­fig­u­ra­tion file.

docker stop onlyoffice-docs
docker container prune

Man­age an On­ly­Of­fice con­tain­er by Dock­er-com­pose

Cre­ate the docker-compose.yaml file. Tweak the val­ue of the host port 8081, and the time zone TZ if it is need­ed. The most im­por­tant thing is to set an unique val­ue for JWT_SECRET, thus the JWT will be­come per­sis­tent.

nano docker-compose.yaml
# https://hub.docker.com/r/onlyoffice/documentserver/
# https://github.com/ONLYOFFICE/onlyoffice-owncloud/issues/108

version: "3.9"
services:
  onlyoffice-docs:
    container_name: onlyoffice-docs
    image: onlyoffice/documentserver:latest
    hostname: docs
    #network_mode: host
    ports:
      - "8081:80/tcp"
    environment:
      TZ: 'Europe/Sofia'
      JWT_SECRET: "xd4f2PO5hdHJHjpV1NdD"
    # Volumes store your data between container upgrades
    volumes:
      - "./DocumentServer/logs:/var/log/onlyoffice"
      - "./DocumentServer/data:/var/www/onlyoffice/Data"
      - "./DocumentServer/lib:/var/lib/onlyoffice"
      - "./DocumentServer/db:/var/lib/postgresql"
      - "./DocumentServer/etc/onlyoffice:/etc/onlyoffice"
      - "./DocumentServer/etc/supervisor:/etc/supervisor"
    restart: unless-stopped

volumes:
    DocumentServer:

Down­load the Dock­er im­ages and run the con­tain­er in de­tached (per­sis­tent) mode.

docker-compose up -d

Open the On­ly­Of­fice doc­u­ment serv­er via the brows­er. Note the host port 8081 must be open (for you) with­in the host's fire­wall.

http://<host-ip>:8081/welcome/

The rest part of this sec­tion is dep­re­cat­ed, but is leaved here as his­tor­i­cal note :)

#Re­move me: Dep­re­cat­ed Sec­tion
Get a list of all avail­able ver­sions of On­ly­Of­fice im­ages (ref­er­ence).
wget -q https://registry.hub.docker.com/v1/repositories/onlyoffice/documentserver/tags -O - | jq -r '.[].name'
Down­lad the lat­est On­ly­Of­fice im­age and run it at port 81 of 127.0.0.1 lo­cal­host.
# docker pull onlyoffice/documentserver
docker run -i -t -d -p 81:80 --restart=always onlyoffice/documentserver:latest
  • Note the op­tion –restart=always means the con­tain­er will run au­to­mat­i­cal­ly when Dock­er is started/​​​restarted.
  • Dock­er will pull the im­age au­to­mat­i­cal­ly when it is not avail­able lo­cal­ly.

Apache2 HTTPS Re­verse Proxy

It is pos­si­ble to set-up On­ly­Of­fice to use HTTPS and cer­tain FQDN through its con­fig­u­ra­tion. How­ev­er in this sec­tion i de­scribed how to cre­ate Apache2 Re­verse proxy that will han­dle this.

First, test whether the nec­es­sary Apache2 mod­ules are en­abled. Be­low is show the list of the mod­ules re­tired for this set-up.

sudo apache2ctl -M | grep -E 'auth[nz]_core|unixd|proxy|headers|setenvif'
 unixd_module (static)          # Required
 authn_core_module (shared)     # Required
 authz_core_module (shared)     # Required
 headers_module (shared)        # Required
 proxy_module (shared)          # Required
 proxy_fcgi_module (shared)
 proxy_http_module (shared)     # Required
 proxy_http2_module (shared)
 proxy_wstunnel_module (shared) # Required
 setenvif_module (shared)       # Required

Then set­up a new vir­tu­al host as fol­low and restart Apache2. Note in this sce­nario you need a valid SSL/TLS cer­tifi­cate. In my case I'm us­ing Let's en­crypt wild­card cer­tifi­cate for the base do­main where the in­stances of NextCloud and On­ly­Of­fice are in­stalled.

sudo nano /etc/apache2/sites-enabled/docs.example.com.conf
Define docs_base_fqdn example.com
Define docs_fqdn docs.example.com
Define docs_srvr 127.0.0.1
Define docs_port 8081
Define docs_doc_root "/var/www/${docs_fqdn}"
 
<VirtualHost *:80>
    ServerName ${docs_fqdn}
    ServerAdmin admin@${docs_base_fqdn}

    ErrorLog ${APACHE_LOG_DIR}/${docs_fqdn}.error.log
    CustomLog ${APACHE_LOG_DIR}/${docs_fqdn}.access.log combined

    # Redirect Requests to HTTPS
    Redirect permanent "/" "https://${docs_fqdn}/"
</VirtualHost>

<IfModule mod_ssl.c>
<VirtualHost _default_:443>
    ServerName ${docs_fqdn}
    ServerAdmin admin@${docs_base_fqdn}

    ErrorLog ${APACHE_LOG_DIR}/${docs_fqdn}.error.log
    CustomLog ${APACHE_LOG_DIR}/${docs_fqdn}.access.log combined

    <IfModule http2_module>
        # https://httpd.apache.org/docs/2.4/mod/mod_http2.html
        # https://httpd.apache.org/docs/2.4/howto/http2.html

        Protocols h2 h2c http/1.1
        #ProtocolsHonorOrder Off
        #H2Direct on
        H2Upgrade on

        H2Push on
        # Default Priority Rule:
        # H2PushPriority *                      After 16 
        # More complex ruleset:
        H2PushPriority *                        after
        H2PushPriority text/css                 before
        H2PushPriority image/jpg                after 32
        H2PushPriority image/jpeg               after 32
        H2PushPriority image/png                after 32
        H2PushPriority application/javascript   interleaved
        <LocationMatch "^.*$">
            # Header add Link "</example.png>; rel=preload; as=image"
            # Header add Link "</style.css>; rel=preload; as=style"
            # Header add Link "</script.js>; rel=preload; as=script"
        </LocationMatch>

        # From apache2/mods-available/http2.conf
        # Since mod_http2 doesn't support the mod_logio module (which provide the %O format),
        # you may want to change your LogFormat directive as follow:
		LogFormat "%v:%p %h %l %u %t \"%r\" %>s %B \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
        LogFormat "%h %l %u %t \"%r\" %>s %B \"%{Referer}i\" \"%{User-Agent}i\"" combined
        LogFormat "%h %l %u %t \"%r\" %>s %B" common
    </IfModule>

    SSLEngine on
    #SSLCertificateFile /etc/letsencrypt/live/${docs_base_fqdn}/cert.pem
    #SSLCertificateKeyFile /etc/letsencrypt/live/${docs_base_fqdn}/privkey.pem
    #SSLCertificateChainFile /etc/letsencrypt/live/${docs_base_fqdn}/chain.pem
    SSLCertificateFile /etc/letsencrypt/live/${docs_base_fqdn}/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/${docs_base_fqdn}/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

    SetEnvIf Host "^(.*)$" THE_HOST=$1

    Header edit Set-Cookie ^(.*)$ "$1; HttpOnly; Secure"
    RequestHeader setifempty X-Forwarded-Proto https
    RequestHeader setifempty X-Forwarded-Host %{THE_HOST}e

    # Reference about OnlyOffice Proxy settings
    # https://github.com/ONLYOFFICE/onlyoffice-owncloud/issues/108
    ProxyAddHeaders Off
    <Location "/">
        ProxyPass "http://${docs_srvr}:${docs_port}/"
        ProxyPassReverse "http://${docs_srvr}:${docs_port}/"
    </Location>

    ProxyPassMatch (.*)(\/websocket)$ "ws://${docs_srvr}:${docs_port}/$1$2"
    
    # DocumentRoot "${docs_doc_root}"
    # <Directory "${docs_doc_root}">
    #     DirectoryIndex index.php index.html hello.html
    #     Require all granted
    #     #Options None FollowSymLinks MultiViews
    #     Options None FollowSymLinks
    #     # AllowOverride None
    #     AllowOverride All
    #     <IfModule security2_module>
    #         #SecRuleEngine Off
    #     </IfModule>
    # </Directory>

    # Limit the acces to the URIs  /, /welcome, /example, /healthcheck
    <ifModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond "%{REMOTE_ADDR}" "!^(172\.16\.[0-9]{1,3}\.[0-9]{1,3}|0\.0\.0\.0|127\.0\.0\.[0-9]{1,3})$"
        RewriteCond "%{REQUEST_URI}" "^/(welcome.*$|example.*$|healthcheck.*$|$)"
        RewriteRule "^(.*)$" https://cloud.example.com/? [L,R=307]
    </ifModule>
</VirtualHost>
</IfModule>

Ref­er­ences