Installation Guide
Docker Installation Guide
www.tine-groupware.de | docker-compose.yml | Dockerfile
Quickstart
This is an easy way to try out tine-groupware. You need Docker and Docker Compose (https://docs.docker.com/compose/).
First, create a folder. Docker Compose uses the folder names as an identifier.
mkdir tine
cd tine
wget https://tine-docu.s3web.rz1.metaways.net/de/operators/docker/docker-compose.yml
Note
Depending on your docker compose installation, you need to use this command: docker compose
or this docker-compose
.
docker compose up
Wait for the database to become available. If it is, the web container will log web_1 | DB available
. Now open another terminal and start the tine installer. There you need to accept the tine-license and Privacy policy and you will be able to set the initial admin password.
docker compose exec web tine20_install
Your tine-groupware is now reachable at http://127.0.0.1:4000.
setup.php UI
The setup.php browser interface can be accessed here: http://127.0.0.1:4000/setup.php. The site is protected by HTTP basic auth.
Username and password hash can be configured with the ENV Variable TINE20_SETUP_HTPASSWD (example: "setup:$apr1$JhCtViTh$k15DH.HvNR5hZ66Ew5aTH/" #setup:setuppw).
The hash can be generated with htpasswd:
1. htpasswd -c setup.htpasswd setup
.
2. Enter the password.
3. Copy username and password form the file setup.htpasswd
.
Note: When using docker-compose, $
needs to be escaped as follows: $$
.
Cleanup
Use the following to stop and delete all containers, networks and volumes created by this compose.
docker compose down --volumes
Image
This image contains the tine code, PHP-FPM, and Nginx. Additionally, a database e.g MariaDB is required. In production, this image should be utilized with a reverse proxy handling all the custom configuration and ssl termination.
Paths
Path | Description |
---|---|
/etc/tine20/config.inc.php |
tine main config file. |
/etc/tine20/conf.d/* |
tine auto include config files. |
/var/lib/tine20/files |
Stores user data. Files like in tine Filemanager |
/var/lib/tine20/tmp |
Temporary file storage |
/var/lib/tine20/caching |
Used for caching if TINE20_CACHING_BACKEND == 'File' |
/var/lib/tine20/sessions |
Used as session store if TINE20_SESSION_BACKEND == 'File' |
Update
Use 'docker compose up' to fetch the latest docker image.
Use this command to update tine:
docker exec --user tine20 tine-docker_web_1 sh -c "php /usr/share/tine20/setup.php --config=/etc/tine20 --update"
If you see this error during the update:
"Tinebase_Exception -> waited for Action Queue to become empty for more than 300 sec"
You should check why there are still jobs in the ActionQueue and/or run the update with skipQueueCheck=1
.
SSL / Reverse Proxy
NGINX
Example 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
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
To migrate from an old tine installation, you can try to just mount the database as a volume (you have to know the root password of the existing database and you should ideally use the same db version):
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"
#[...]
If this does not work or your existing tine database is on another server, it is recommended to use the tine CLI functions --backup
and --restore
for migration.
Please note that the tine container needs to access the backup/dump files, so it might be necessary to copy the files into the container.
Custom Configuration
web:
image: tinegroupware/tine:2021.11
volumes:
- "conf.d:/etc/tine20/conf.d"
#[...]
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 Role For Deployments
https://github.com/tine-groupware/tine/tree/main/scripts/ansible/roles/tinedockercompose