Zum Inhalt

Installation Guide

www.tine-groupware.de | docker-compose.yml | Dockerfile

Schnellstart

Dies ist eine schnelle und leichte Möglichkeit, tine auszuprobieren. Hierfür benötigen Sie Docker und Docker Compose (https://docs.docker.com/compose/).

Erstellen Sie im ersten Schritt einen Ordner. Docker Compose verwendet die Ordnernamen zur Identifizierung.

mkdir tine
cd tine
Als zweiten Schritt laden Sie die aktuelle Datei docker-compose.yml herunter und speichern diese in dem soeben erstellten Ordner.

wget https://tine-docu.s3web.rz1.metaways.net/de/operators/docker/docker-compose.yml

Jetzt können Sie Docker-Compose starten.


Anmerkung

Je nach Docker-Installation erfolgt der Docker Compose Aufruf so: docker compose oder so docker-compose.


docker compose up

Warten Sie einen Moment, bis die Datenbank erreichbar ist. Im Webcontainer Log steht dann web_1 | DB available. Dann können Sie Tine installieren. Öffnen Sie dafür ein neues Terminal und führen Sie den Installer aus. Im Installer müssen Sie die Tine-Lizenz und Datenschutzerklärung bestätigen und können das Password für den initialen Admin festlegen.

docker compose exec web tine20_install

tine ist jetzt unter http://127.0.0.1:4000 erreichbar.

setup.php UI

Die tine-Setup-UI ist dann unter http://127.0.0.1:4000/setup.php erreichbar. Bitte dran denken, dass diese im Container mit HTTP Basic Auth geschützt ist. Benutzername und Passworthash sollten über die ENV Variable TINE20_SETUP_HTPASSWD gesetzt werden (Beispiel: "setup:$apr1$JhCtViTh$k15DH.HvNR5hZ66Ew5aTH/" #setup:setuppw). Der hash kann mit htpasswd generiert werden: 1. htpasswd -c setup.htpasswd setup. 2. Pasword eingeben wiederholen 3. Benutzername und Passworthash aus der Datei setup.htpasswd kopieren.

Hinweis: Bei der Verwendung von docker-compose muss $ wie folgt escaped werden: $$.

Aufräumen

Um alle von Docker Compose erstellten Container, Netzwerke und Volumes zu stoppen und löschen nutzen Sie:

docker compose down --volumes

Image

Dieses Image enthält den tine-Code, PHP-FPM und Nginx. Zusätzlich benötigen Sie eine Datenbank, beispielsweise MariaDB. In der Produktion sollte dieses Image mit einem Reverse-Proxy verwendet werden, der die gesamte benutzerdefinierte Konfiguration und SSL-Terminierung übernimmt.

Paths

Path Definition
/etc/tine20/config.inc.php tine Hauptkonfigurationsdatei.
/etc/tine20/conf.d/* tine Konfigurationsdateien werden automatisch eingeschlossen.
/var/lib/tine20/files Speichern der User-Daten. Dateien wie die im tine-Dateimanager
/var/lib/tine20/tmp Temporäre Dateispeicherung
/var/lib/tine20/caching Wird zum Zwischenspeichern verwendet, wenn TINE20_CACHING_BACKEND == 'File'
/var/lib/tine20/sessions Wird als Sitzungsspeicher verwendet, wenn TINE20_SESSION_BACKEND == 'File'

Update

Zum Updaten einmal 'docker compose down && docker composer up' machen. Falls man eine andere Major-Version haben möchte, kann vorher in der docker-compose.yml auch eine konkrete Version angegeben werden.

Zum Updaten von tine selbst verwendet man folgenden Befehl (ggf. muss der Name des Containers angepasst werden, herausfinden kann man ihn z.B. mit 'docker ps'):

docker exec --user tine20 tine-docker_web_1 sh -c "php /usr/share/tine20/setup.php --config=/etc/tine20 --update"

Falls dieser Fehler erscheint:

"Tinebase_Exception -> waited for Action Queue to become empty for more than 300 sec"

Sollte geprüft werden, ob noch Jobs in der Queue sind und/oder man startet das Update mit dem Schalter skipQueueCheck=1.

SSL / Reverse Proxy

Um den tine-Container "von aussen" verfügbar zu machen, kann man einen NGINX, Traefik oder HAProxy davorschalten.

NGINX

Beispiel einer NGINX VHOST conf:

server {
    listen 80;
    listen 443 ssl;

    ssl_certificate /etc/letsencrypt/live/MYDOMAIN.de/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/MYDOMAIN.de/privkey.pem;

    server_name tine.MYDOMAIN.de autodiscover.MYDOMAIN.de;

    if ($ssl_protocol = "" ) {
        rewrite        ^ https://$server_name$request_uri? permanent;
    }

    access_log /var/www/MYDOMAIN/logs/nginx-access.log;
    error_log /var/www/MYDOMAIN/logs/nginx-error.log;

    client_max_body_size 2G; # set maximum upload size

    location /.well-known { }

    location / {
        proxy_pass http://127.0.0.1:4000;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

TRAEFIK

Alternativ zu NGINX kann man auch traefik zur docker-composer.yml hinzufügen:

  traefik:
    image: "traefik:v2.6"
    restart: always
    container_name: "traefik"
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.http01.acme.httpchallenge=true"
      - "--certificatesresolvers.http01.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.http01.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  web:
    image: tinegroupware/tine:2021.11
    #[...]
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.tile-server.rule=Host(`MYDOMAIN.de`)"
      - "traefik.http.routers.tile-server.entrypoints=websecure"
      - "traefik.http.routers.tile-server.tls.certresolver=http01"
      - "traefik.http.services.tile-server.loadbalancer.server.port=80"

Migration

Um von einer alten Installation mit lokaler tine auf das Docker-Setup zu migrieren, müssen nur die Volumes entsprechend gemountet werden (das root-Passwort der Datenbank sollte bekannt sein und die DB sollte die gleiche Version haben):

  db:
    image: mariadb:10.6
    volumes:
      - "/var/lib/mysql:/var/lib/mysql"
    #[...]

  web:
    image: tinegroupware/tine:2021.11
    volumes:
      - "/var/lib/tine20/files:/var/lib/tine20/files"
    #[...]

Bitte achtet auf die korrekte Angabe des TINE20_DATABASE_TABLEPREFIX -> sonst werden ggf. die Tabellen nicht gefunden.

Falls das nicht klappt oder die alte tine DB auf einem anderen Server liegt, sollte man die tine CLI Funktionen --backup und --restore benutzen. Dabei muss beachtet werden, dass auf die Backup-Dateien von innerhalb des tine-Containers aus zugriffen werden kann.

Custom-Konfiguration

Wenn man möchte, kann man Custom-Configs (via conf.d) ebenfalls als eigenes Volume in den Container mounten:

  web:
    image: tinegroupware/tine:2021.11
    volumes:
      - "conf.d:/etc/tine20/conf.d"
    #[...]

docker-compose.yml

docker-compose.yml
version: '2'
services:
  db:
    image: mariadb:10.9.8
    command: --max-allowed-packet=209715210
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: &MYSQL_DATABASE tine
      MYSQL_USER: &MYSQL_USER tine
      MYSQL_PASSWORD: &MYSQL_PASSWORD tine
      MARIADB_AUTO_UPGRADE: 1
    ### use volume for persistent DB
    volumes:
      - "tine_db:/var/lib/mysql"
    ### OR
#      - "./data/tine_mysql:/var/lib/mysql"
    networks:
      - internal_network

  web:
    image: tinegroupware/tine:2023
    restart: always
    depends_on:
      - db
      - cache
    environment:
      TINE20_DATABASE_HOST: db
      TINE20_DATABASE_DBNAME: *MYSQL_DATABASE
      TINE20_DATABASE_USERNAME: *MYSQL_USER
      TINE20_DATABASE_PASSWORD: *MYSQL_PASSWORD
      TINE20_DATABASE_TABLEPREFIX: tine_
      TINE20_CACHING_BACKEND: Redis
      TINE20_CACHING_REDIS_HOST: cache
      TINE20_ACTIONQUEUE_HOST: cache
      TINE20_SESSION_BACKEND: Redis
      TINE20_SESSION_HOST: cache
      TINE20_CREDENTIALCACHESHAREDKEY: change_me
      TINE20_SETUPUSER_USERNAME: tinesetup
      TINE20_SETUPUSER_PASSWORD: tinesetup
      TINE20_SETUP_HTPASSWD: "setup:$$apr1$$JhCtViTh$$k15DH.HvNR5hZ66Ew5aTH/" #setup:setuppw
      TINE20_ACTIONQUEUE: "true"
      BROADCASTHUB_URL: http://broadcasthub
      # TINE20_LOGGER_PRIORITY: "7"
      ### the url of you tine installation (should be adjusted)
      # TINE20_URL: http://localhost:4000
      ### install+update tine automatically
      # TINE20_INSTALL: "true"
      ### needed for auto-install
      # TINE20_ACCEPTED_TERMS_VERSION: 10000
      # TINE20_LOGIN_USERNAME: admin
      # TINE20_LOGIN_PASSWORD: change_me
      ### apps to install - if omitted, all available apps are installed
      # TINE20_APPLICATION_TO_INSTALL: "Addressbook,Felamimail,Calendar,Filemanager"

    volumes:
      - "tine_files:/var/lib/tine20/files"
      # use this for custom configuration files (like logger.inc.php)
      - "./conf.d:/etc/tine20/conf.d"
    ### OR
      # NOTE: you need to make sure that the folder has the correct file permissions
#      - "./data/tine_files:/var/lib/tine20/files"
    networks:
      - external_network
      - internal_network
    ports:
      - "127.0.0.1:4000:80"
    ### for traefik support (see https://doc.traefik.io/traefik/providers/docker/)
#    labels:
#      - "traefik.enable=true"
#      - "traefik.http.routers.web.rule=Host(`MYDOMAIN.de`)"
#      - "traefik.http.routers.web.entrypoints=websecure"
#      - "traefik.http.routers.web.tls.certresolver=http01"
#      - "traefik.http.services.web.loadbalancer.server.port=80"

  cache:
    image: redis:6.0.16
    restart: always
    networks:
      - internal_network

  broadcasthub:
    image: tinegroupware/broadcasthub:0.7
    restart: always
    networks:
      - external_network
      - internal_network
    ports:
      - "5001:80"
    environment:
      REDIS_URL: redis://cache:6379
      REDIS_CHANNEL: broadcasthub
      TINE20_JSON_API_URL: http://localhost
      AUTH_TIMEOUT: 5000
      WS_PORT: 80
      DEBUG: '*'
      DEBUG_DEFAULT_LOGGING: "on"
      DEBUG_LOG_TO_FILE: "off"
      DEBUG_LOG_FILE: ../../stdout.log

### other optional services

############################################################################
# docservice
############
# to use this in tine, you need to add the following to your config:
#
# 'filesystem' => [
#   'createPreviews' => true,
#   'previewServiceUrl' => 'http://docservice/v2/documentPreviewService',
#   'previewServiceVersion' => 2,
#   [...]
# ],
############################################################################
#  docservice:
#    image: tinegroupware/document-preview-service:2.1
#    restart: always
#    networks:
#      - internal_network

############################################################################
#  documentserver
############################################################################
#
# to use this in tine, you need to add the following to your config:
#
# return [
#    'OnlyOfficeIntegrator' => [
#        'onlyOfficePublicUrl' => 'http://localhost:4020/',
#        'onlyOfficeServerUrl' => 'http://documentserver/',
#        'tine20ServerUrl' => 'http://web/',
#        'jwtEnabled' => true,
#        'jwtSecret' => 'change_me_also_define_in_tine_cfg',
#    ],
#
############################################################################
#  documentserver:
#    image: onlyoffice/documentserver:latest
#    restart: always
#    ports:
#      - "4020:80"
#    environment:
#      JWT_ENABLED: "true"
#      JWT_SECRET: "change_me_also_define_in_tine_cfg"
#    networks:
#      - external_network
#      - internal_network

#  clamav:
#    image: tiredofit/clamav
#    restart: always
#    container_name: clamav
#    environment:
#      - ZABBIX_HOSTNAME=clamav
#    # need to be created on the host
#    volumes:
#      - "clamav_files:/data"
#    networks:
#      - internal_network

#  traefik:
#    image: "traefik:v2.6"
#    restart: always
#    container_name: "traefik"
#    command:
#      - "--providers.docker=true"
#      - "--providers.docker.exposedbydefault=false"
#      - "--entrypoints.web.address=:80"
#      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
#      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
#      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
#      - "--entrypoints.websecure.address=:443"
#      - "--certificatesresolvers.http01.acme.httpchallenge=true"
#      - "--certificatesresolvers.http01.acme.httpchallenge.entrypoint=web"
#      - "--certificatesresolvers.http01.acme.storage=/letsencrypt/acme.json"
#    ports:
#      - "80:80"
#      - "443:443"
#      - "8080:8080"
#    volumes:
#      - "./letsencrypt:/letsencrypt"
#      - "/var/run/docker.sock:/var/run/docker.sock:ro"

### if you use directory mounts, you might no need that
volumes:
  tine_files:
  tine_db:
#  clamav_files:

networks:
  external_network:
  internal_network:
    internal: true

Ansible Rolle für Deployments

https://github.com/tine-groupware/tine/tree/main/scripts/ansible/roles/tinedockercompose