Initial commit

This commit is contained in:
Luca 2023-09-25 18:42:20 +02:00
commit e9d217ac80
12 changed files with 318 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
facts/

40
README.md Normal file
View File

@ -0,0 +1,40 @@
# Deploy Zammad via Ansible and docker-compose
## Prerequisites
* Docker and docker-compose (v1, Ansible does not support v2)
* Traefik v2
* Externally defined Docker network `traefik`
* Entrypoint `websecure`
* Certificate resolver `lehttp`
* PostgreSQL on host
* Listening on socket in `/var/run/postgresql/`
* Database (`zammad_database_name`, default: `zammad`) and user (`zammad_database_user`, default: `zammad`) created
* (To use containerized Postgres, replace `postgres` service in `roles/zammad/templates/docker-compose.yml.j2` as follows:)
```yaml
postgres:
image: postgres:alpine
restart: unless-stopped
environment:
POSTGRES_DB: '{{ zammad_database_name }}'
POSTGRES_PASSWORD: '{{ zammad_database_password }}'
POSTGRES_USER: '{{ zammad_database_user }}'
networks:
- internal
```
* enough RAM (or set `zammad_enable_search` to `no`)
## Deploy
Add target host(s) to group `zammad` in `inventory/hosts` and copy `inventory/host_vars/example` to `inventory/host_vars/{hostname}` for each host.
Adjust values as needed and run:
```
ansible-playbook -D -t zammad site.yml
```
### Upgrade
```
ansible-playbook -D -t zammad -e 'zammad_upgrade=yes' site.yml
```

10
ansible.cfg Normal file
View File

@ -0,0 +1,10 @@
[defaults]
inventory = inventory
gathering = smart
fact_caching = jsonfile
fact_caching_connection = facts
fact_caching_timeout = 1200
nocows = True
[ssh_connection]
pipelining = True

View File

@ -0,0 +1,9 @@
---
zammad_memcached_version: '1'
zammad_opensearch_version: '1'
zammad_redis_version: '7'
zammad_version: 'stable'

View File

@ -0,0 +1,7 @@
---
zammad_database_password: ''
zammad_num_workers: 4
zammad_rule: Host(`zammad.example.com`)

1
inventory/hosts Normal file
View File

@ -0,0 +1 @@
[zammad]

View File

@ -0,0 +1,19 @@
---
zammad_database_name: zammad
zammad_database_user: zammad
zammad_enable_search: yes
zammad_memcached_memory: 256M
zammad_memcached_memory_limit: 512M
zammad_num_workers: 0
zammad_opensearch_memory_limit: 1G
zammad_opensearch_memory_max: 512M
zammad_opensearch_memory_min: 512M
zammad_redis_memory_limit: 512M
zammad_upgrade: no

View File

@ -0,0 +1,39 @@
---
- name: zammad_datadirs
file:
path: '{{ item.path }}'
state: directory
owner: '{{ item.owner | default(omit) }}'
group: '{{ item.group | default(omit) }}'
loop:
- path: /srv/zammad/search
owner: 1000
group: 1000
- path: /srv/zammad/zammad
owner: 1000
group: 1000
- name: zammad_composedir
file:
path: /etc/docker/compose/zammad
state: directory
mode: 0700
- name: zammad_composefile
template:
dest: /etc/docker/compose/zammad/docker-compose.yml
src: docker-compose.yml.j2
mode: 0600
- name: zammad_search
include_tasks: search.yml
when: zammad_enable_search
- name: zammad_compose
community.docker.docker_compose:
project_src: /etc/docker/compose/zammad
build: '{{ zammad_upgrade }}'
remove_orphans: yes
environment:
ELASTICSEARCH_REINDEX: "{{ 'true' if zammad_upgrade else 'false' }}"

View File

@ -0,0 +1,17 @@
---
- name: zammad_search_builddir
file:
path: /etc/docker/compose/zammad/opensearch
state: directory
- name: zammad_search_dockerfile
template:
dest: /etc/docker/compose/zammad/opensearch/Dockerfile
src: opensearch/Dockerfile.j2
- name: zammad_search_sysctl
sysctl:
name: vm.max_map_count
value: '262144'
sysctl_set: yes

View File

@ -0,0 +1,167 @@
---
services:
init:
image: 'zammad/zammad-docker-compose:{{ zammad_version | mandatory }}'
restart: on-failure
command:
- zammad-init
depends_on:
- postgres
environment:
<<: &cache
MEMCACHE_SERVERS: 'memcached:11211'
REDIS_URL: 'redis://redis:6379'
{% if zammad_enable_search %}
ELASTICSEARCH_HOST: search
ELASTICSEARCH_REINDEX: '${ELASTICSEARCH_REINDEX:-false}'
{% else %}
ELASTICSEARCH_ENABLED: 'false'
{% endif %}
POSTGRESQL_DB: '{{ zammad_database_name }}'
POSTGRESQL_DB_CREATE: 'false'
POSTGRESQL_HOST: postgres
POSTGRESQL_PASS: '{{ zammad_database_password | mandatory }}'
POSTGRESQL_USER: '{{ zammad_database_user }}'
networks:
- internal
volumes:
- /srv/zammad/zammad:/opt/zammad
memcached:
image: 'memcached:{{ zammad_memcached_version }}-alpine'
restart: unless-stopped
command:
- memcached
- -m
- '{{ zammad_memcached_memory }}'
deploy:
resources:
limits:
memory: '{{ zammad_memcached_memory_limit }}'
networks:
- internal
nginx:
image: 'zammad/zammad-docker-compose:{{ zammad_version | mandatory }}'
restart: unless-stopped
command:
- zammad-nginx
depends_on:
- railsserver
environment:
NGINX_SERVER_SCHEME: 'https'
ZAMMAD_RAILSSERVER_HOST: 'railsserver'
ZAMMAD_WEBSOCKET_HOST: 'websocket'
expose:
- 8080
networks:
- internal
- traefik
volumes:
- /srv/zammad/zammad:/opt/zammad
labels:
traefik.enable: 'true'
traefik.docker.network: traefik
traefik.http.routers.zammad.entrypoints: websecure
traefik.http.routers.zammad.rule: '({{ zammad_rule | mandatory }}) && !Path(`/auth/sso`)'
traefik.http.routers.zammad.tls.certresolver: lehttp
postgres:
image: git.luj0ga.de/luca/postgres-tcpify:1
restart: unless-stopped
networks:
- internal
volumes:
- /var/run/postgresql:/var/run/postgresql
railsserver:
image: 'zammad/zammad-docker-compose:{{ zammad_version | mandatory }}'
restart: unless-stopped
command:
- zammad-railsserver
depends_on:
- memcached
- postgres
- redis
environment:
<<: *cache
ZAMMAD_WEB_CONCURRENCY: '{{ zammad_num_workers }}'
networks:
- internal
volumes:
- /srv/zammad/zammad:/opt/zammad
redis:
image: 'redis:{{ zammad_redis_version }}-alpine'
restart: unless-stopped
deploy:
resources:
limits:
memory: '{{ zammad_redis_memory_limit }}'
networks:
- internal
scheduler:
image: 'zammad/zammad-docker-compose:{{ zammad_version | mandatory }}'
restart: unless-stopped
command:
- zammad-scheduler
depends_on:
- memcached
- railsserver
- redis
environment: *cache
networks:
- internal
volumes:
- /srv/zammad/zammad:/opt/zammad
{% if zammad_enable_search %}
search:
build: opensearch
image: 'opensearch-ingest-attachment:{{ zammad_opensearch_version | mandatory }}'
restart: unless-stopped
deploy:
resources:
limits:
memory: '{{ zammad_opensearch_memory_limit }}'
environment:
DISABLE_INSTALL_DEMO_CONFIG: 'true'
DISABLE_SECURITY_PLUGIN: 'true'
OPENSEARCH_JAVA_OPTS: '-Xms{{ zammad_opensearch_memory_min }} -Xmx{{ zammad_opensearch_memory_max }}'
bootstrap.memory_lock: 'true'
compatibility.override_main_response_version: 'true'
discovery.type: single-node
networks:
- internal
ulimits:
memlock:
hard: -1
soft: -1
nofile:
hard: 65536
soft: 65536
volumes:
- /srv/zammad/search:/usr/share/opensearch/data
{% endif %}
websocket:
image: 'zammad/zammad-docker-compose:{{ zammad_version | mandatory }}'
restart: unless-stopped
command:
- zammad-websocket
depends_on:
- memcached
- railsserver
- redis
environment: *cache
networks:
- internal
volumes:
- /srv/zammad/zammad:/opt/zammad
networks:
internal:
traefik:
external: yes

View File

@ -0,0 +1,3 @@
FROM public.ecr.aws/opensearchproject/opensearch:{{ zammad_opensearch_version | mandatory }}
RUN /usr/share/opensearch/bin/opensearch-plugin install --batch ingest-attachment

5
site.yml Normal file
View File

@ -0,0 +1,5 @@
---
- hosts: zammad
roles:
- { role: zammad, tags: zammad }