Zammad-Rolle

This commit is contained in:
phil 2021-07-28 18:28:22 +02:00
commit a6b16394ed
27 changed files with 552 additions and 0 deletions

22
defaults/main.yml Normal file
View file

@ -0,0 +1,22 @@
---
debian_version: buster
ruby_path: "{{ zammad_user_home }}/.rbenv"
ruby_bin_path: "{{ ruby_path }}/versions/{{ ruby_version }}/bin"
ruby_build_repo: https://github.com/rbenv/ruby-build.git
ruby_version: 2.6.6
zammad_database_name: zammad
zammad_database_password: "{{ lookup('password', '/tmp/zammad_database_pwd length=42 chars=ascii_letters,digits') }}"
zammad_database_user: zammad
zammad_database_configuration: "{{ zammad_home }}/config/database.yml"
zammad_home: /opt/zammad
zammad_host: support.sao
zammad_log_file: zammad.log
zammad_log_name: zammad
zammad_log_path: /var/log/zammad
zammad_repo: https://github.com/zammad/zammad.git
zammad_user: zammad
zammad_user_home: "/home/{{ zammad_user }}"
zammad_version: 4.1.0
zammad_webserver_configuration: "/etc/nginx/sites-available/{{ zammad_domain }}"

10
files/plain-text.patch Normal file
View file

@ -0,0 +1,10 @@
--- app/models/channel/email_build.rb.orig 2021-07-27 18:03:57.295467567 +0200
+++ app/models/channel/email_build.rb 2021-07-27 18:04:20.705471697 +0200
@@ -62,6 +62,7 @@
# generate plain part
attr[:body] = attr[:body].html2text
+ html_alternative = false
end
# add plain text part

6
files/zammad.env Normal file
View file

@ -0,0 +1,6 @@
BUNDLE_BINARY="rbenv exec bundle"
RAILS_ENV=production
RAILS_SERVE_STATIC_FILES=true
ZAMMAD_BIND_IP=127.0.0.1
ZAMMAD_RAILS_PORT=3000
ZAMMAD_WEBSOCKET_PORT=6042

18
files/zammad.service Normal file
View file

@ -0,0 +1,18 @@
[Unit]
Description=Zammad
After=syslog.target
After=network.target
StopWhenUnneeded=true
Wants=zammad-rails.service
Wants=zammad-scheduler.service
Wants=zammad-websocket.service
[Service]
EnvironmentFile=/etc/zammad/zammad.env
User=zammad
Group=zammad
Restart=always
ExecStart=/bin/sleep infinity
[Install]
WantedBy=multi-user.target

21
handlers/main.yml Normal file
View file

@ -0,0 +1,21 @@
---
- name: reload monit
service:
name: monit
state: reloaded
- name: reload nginx
service:
name: nginx
state: reloaded
- name: reload reverse_proxy
service:
name: nginx
state: reloaded
delegate_to: "{{ gateway_host }}"
- name: reload rsyslog
service:
name: rsyslog
state: reloaded

10
meta/main.yml Normal file
View file

@ -0,0 +1,10 @@
galaxy_info:
author: systemausfall.org
description: Install Zammad ticket system from source
company: Sense.Lab e.V.
license: GPLv3
min_ansible_version: 2.9
platforms:
- name: Debian
versions:
- Buster

52
tasks/database.yml Normal file
View file

@ -0,0 +1,52 @@
---
- name: "database: Datenbank anlegen"
postgresql_db:
name: "{{ zammad_database_name }}"
encoding: UTF8
template: template0
become: true
become_user: postgres
delegate_to: "{{ database_host }}"
- name: "database: Benutzer einrichten"
postgresql_user:
name: "{{ zammad_database_user }}"
password: "{{ zammad_database_password }}"
db: "{{ zammad_database_name }}"
become: true
become_user: postgres
delegate_to: "{{ database_host }}"
- name: "database: Konfiguration kopieren"
template:
src: database.yml.j2
dest: "{{ zammad_database_configuration }}"
- name: "database: Stoppe Service"
service:
name: zammad
state: stopped
register: unused_disable
failed_when: "unused_disable is failed and ('find' not in unused_disable.msg and 'found' not in unused_disable.msg)"
- name: "database: Führe Migrationen aus"
shell: "RAILS_ENV=production rbenv exec bundle exec rake db:migrate"
args:
chdir: "{{ zammad_home }}"
become: true
become_user: "{{ zammad_user }}"
- name: "database: Führe Seeds aus"
shell: "RAILS_ENV=production rbenv exec bundle exec rake db:seed"
args:
chdir: "{{ zammad_home }}"
become: true
become_user: "{{ zammad_user }}"
when: zammad_database_configured.stat.exists == False
- name: "database: Precompile Assets"
shell: "RAILS_ENV=production rbenv exec bundle exec rake assets:precompile"
args:
chdir: "{{ zammad_home }}"
become: true
become_user: "{{ zammad_user }}"

29
tasks/gateway.yml Normal file
View file

@ -0,0 +1,29 @@
---
- name: "gateway: Domain zur Zertifikatsliste hinzufügen"
lineinfile:
path: /etc/dehydrated/domains.txt
insertafter: "^### systemausfall"
line: "{{ zammad_domain }}"
when: "'dehydrated' in ansible_facts.packages"
register: add_certificate
delegate_to: "{{ gateway_host }}"
- name: "gateway: Zertifikat erstellen"
command: dehydrated --cron -g
when: add_certificate.changed
delegate_to: "{{ gateway_host }}"
- name: "gateway: Proxy einrichten"
template:
src: nginx-rp-site.j2
dest: "/etc/nginx/sites-available/{{ zammad_domain }}"
force: no
delegate_to: "{{ gateway_host }}"
- name: "gateway: Seite aktivieren"
file:
src: "/etc/nginx/sites-available/{{ zammad_domain }}"
dest: "/etc/nginx/sites-enabled/{{ zammad_domain }}"
state: link
notify: reload reverse_proxy
delegate_to: "{{ gateway_host }}"

4
tasks/locales.yml Normal file
View file

@ -0,0 +1,4 @@
- name: "locales: Richte locales ein"
locale_gen:
name: en_US.UTF-8
state: present

17
tasks/main.yml Normal file
View file

@ -0,0 +1,17 @@
- name: "Prüfe vorhandene Datenbank-Konfiguration"
stat:
path: "{{ zammad_database_configuration }}"
register: zammad_database_configured
- import_tasks: packages.yml
- import_tasks: locales.yml
- import_tasks: user.yml
- import_tasks: zammad.yml
- import_tasks: ruby.yml
- import_tasks: database.yml
- import_tasks: syslog.yml
- import_tasks: webserver.yml
- import_tasks: systemd.yml
- import_tasks: monit.yml
tags: monit
- import_tasks: gateway.yml

5
tasks/monit.yml Normal file
View file

@ -0,0 +1,5 @@
- name: "monit: Kopiere Konfiguration"
template:
src: monit.j2
dest: /etc/monit/conf-enabled/zammad
notify: reload monit

37
tasks/packages.yml Normal file
View file

@ -0,0 +1,37 @@
---
- name: "packages: Fakten sammeln"
package_facts:
manager: apt
- name: "packages: Abhängigkeiten installieren"
apt:
default_release: "{{ debian_version }}"
pkg:
- autoconf
- automake
- autotools-dev
- bison
- build-essential
- curl
- gawk
- git
- libffi-dev
- libgdbm-dev
- libgmp-dev
- libimlib2-dev
- libncurses5-dev
- libpq-dev
- libreadline-dev
- libssl-dev
- libtool
- libxml2-dev
- libxslt1-dev
- libyaml-0-2
- libyaml-dev
- locales
- nginx-light
- patch
- pkg-config
- rbenv
- sudo
- zlib1g-dev

50
tasks/ruby.yml Normal file
View file

@ -0,0 +1,50 @@
- name: "ruby: rbenv einrichten"
lineinfile:
path: "{{ zammad_user_home }}/.bashrc"
line: eval "$(rbenv init -)"
- name: "ruby: rbenv plugin-verzeichnis erstellen"
file:
path: "{{ ruby_path }}/plugins"
state: directory
owner: "{{ zammad_user }}"
group: "{{ zammad_user }}"
- name: "ruby: ruby-build installieren"
git:
repo: "{{ ruby_build_repo }}"
dest: "{{ ruby_path }}/plugins/ruby-build"
- name: "ruby: Version prüfen"
stat:
path: "{{ ruby_path }}/versions/{{ ruby_version }}"
register: ruby_installed
- name: "ruby installieren"
command:
cmd: "rbenv install {{ ruby_version }}"
chdir: "{{ zammad_user_home }}"
become: true
become_user: "{{ zammad_user }}"
when: ruby_installed.stat.exists == False
- name: "ruby aktivieren"
shell: "rbenv local {{ ruby_version }}"
args:
chdir: "{{ zammad_home }}"
become: true
become_user: "{{ zammad_user }}"
- name: "ruby: Bundler installieren"
command:
cmd: rbenv exec gem install bundler
chdir: "{{ zammad_home }}"
become: true
become_user: "{{ zammad_user }}"
- name: "ruby: Ruby-Abhängigkeiten installieren"
shell: "RAILS_ENV=production {{ ruby_bin_path }}/bundle install --without test development mysql"
args:
chdir: "{{ zammad_home }}"
become: true
become_user: "{{ zammad_user }}"

10
tasks/syslog.yml Normal file
View file

@ -0,0 +1,10 @@
- name: "syslog: Erstelle Verzeichnis"
file:
src: "{{ zammad_home }}/log"
dest: "{{ zammad_log_path }}"
state: link
- name: "syslog: Konfiguriere logrotate"
template:
src: logrotate.j2
dest: /etc/logrotate.d/zammad

32
tasks/systemd.yml Normal file
View file

@ -0,0 +1,32 @@
- name: "systemd: Kopiere Services"
template:
src: "systemd/{{ item }}.j2"
dest: "/etc/systemd/system/{{ item }}"
loop:
- zammad-rails.service
- zammad-scheduler.service
- zammad-websocket.service
- name: "systemd: Kopiere Zammad-Service"
copy:
src: zammad.service
dest: /etc/systemd/system/zammad.service
- name: "systemd: Erstelle Konfigurationsverzeichnis"
file:
path: /etc/zammad
state: directory
- name: "systemd: Kopiere Konfiguration"
copy:
src: zammad.env
dest: /etc/zammad/zammad.env
force: no
- name: "systemd: Aktiviere Service"
systemd:
enabled: yes
daemon_reload: yes
state: started
name: zammad

6
tasks/user.yml Normal file
View file

@ -0,0 +1,6 @@
---
- name: "user: Systemkonto anlegen"
user:
name: "{{ zammad_user }}"
shell: /bin/bash
password_lock: yes

12
tasks/webserver.yml Normal file
View file

@ -0,0 +1,12 @@
- name: "webserver: Konfiguration kopieren"
template:
src: nginx-site.j2
dest: "{{ zammad_webserver_configuration }}"
- name: "webserver: Kofiguration aktivieren"
file:
src: "{{ zammad_webserver_configuration }}"
dest: "/etc/nginx/sites-enabled/{{ zammad_domain }}"
state: link

20
tasks/zammad.yml Normal file
View file

@ -0,0 +1,20 @@
- name: "zammad: Hole Zammad Repo"
git:
repo: "{{ zammad_repo }}"
dest: "{{ zammad_home }}"
version: "{{ zammad_version }}"
force: yes
- name: "zammad: Ändere Besitzrechte"
file:
path: "{{ zammad_home }}"
state: directory
recurse: yes
owner: "{{ zammad_user }}"
group: "{{ zammad_user }}"
# https://github.com/zammad/zammad/issues/325
- name: "zammad: Wende plain-Text-Patch an"
patch:
src: plain-text.patch
dest: "{{ zammad_home }}/app/models/channel/email_build.rb"

44
templates/database.yml.j2 Normal file
View file

@ -0,0 +1,44 @@
# this is a database config sample for zammad ready to use with a postgresql db
# copy or symlink this file to config/database.yml to use it
default: &default
# For details on connection pooling, see Rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: 50
timeout: 5000
encoding: utf8
##### postgresql config #####
adapter: postgresql
username: {{ zammad_database_user }}
password: {{ zammad_database_password }}
# If the database server is not on localhost, you can set hostname and port:
host: {{ database_host }}
# port:
#### mysql config #####
# adapter: mysql2
# username: zammad
# password: <Password>
# If the database server is not on localhost, you can set hostname and port:
# host:
# port:
production:
<<: *default
database: {{ zammad_database_name }}
development:
<<: *default
database: zammad_development
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: zammad_test

9
templates/logrotate.j2 Normal file
View file

@ -0,0 +1,9 @@
{{ zammad_log_path }}/*.log {
daily
missingok
rotate 2
compress
delaycompress
notifempty
copytruncate
}

23
templates/monit.j2 Normal file
View file

@ -0,0 +1,23 @@
check process zammad-rails with pidfile {{ zammad_home }}/tmp/pids/server.pid
start program = "/usr/sbin/service zammad-rails start"
stop program = "/usr/sbin/service zammad-rails stop"
if 2 restarts within 3 cycles then timeout
if cpu usage > 95% for 3 cycles then restart
if failed host 127.0.0.1 port 3000 for 3 cycles then restart
if 5 restarts within 5 cycles then timeout
check process zammad-websocket
matching "script/websocket-server.rb -b 127.0.0.1 -p 6042 start"
start program = "/usr/sbin/service zammad-websocket start"
stop program = "/usr/sbin/service zammad-websocket stop"
if 2 restarts within 3 cycles then timeout
if cpu usage > 95% for 3 cycles then restart
if failed host 127.0.0.1 port 6042 for 3 cycles then restart
if 5 restarts within 5 cycles then timeout
check process zammad-scheduler with pidfile {{ zammad_home }}/tmp/pids/scheduler.pid
start program = "/usr/sbin/service zammad-scheduler start"
stop program = "/usr/sbin/service zammad-scheduler stop"
if 2 restarts within 3 cycles then timeout
if cpu usage > 95% for 3 cycles then restart
if 5 restarts within 5 cycles then timeout

View file

@ -0,0 +1,21 @@
server {
listen 80;
server_name {{ zammad_domain }};
include snippets/letsencrypt.conf;
location / { return 301 https://$http_host$request_uri; }
}
server {
listen 443 ssl http2;
server_name {{ zammad_domain }};
ssl_certificate /var/lib/dehydrated/certs/{{ zammad_domain }}/fullchain.pem;
ssl_certificate_key /var/lib/dehydrated/certs/{{ zammad_domain }}/privkey.pem;
include /etc/nginx/snippets/add_headers.conf;
location /ws {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_pass http://{{ zammad_host }}:80;
}
location / { proxy_pass http://{{ zammad_host }}:80; }
}

35
templates/nginx-site.j2 Normal file
View file

@ -0,0 +1,35 @@
server {
listen 80;
server_name {{ zammad_domain }};
root {{ zammad_home }}/public;
error_log /var/log/nginx/{{ zammad_domain }}.error.log;
client_max_body_size 50M;
location ~ ^/(assets/|robots.txt|humans.txt|favicon.ico|apple-touch-icon.png) {
expires max;
}
location /ws {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header CLIENT_IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
proxy_pass http://127.0.0.1:6042;
}
location / {
proxy_set_header Host $http_host;
proxy_set_header CLIENT_IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
# Change this line in an SSO setup
proxy_set_header X-Forwarded-User "";
proxy_read_timeout 300;
proxy_pass http://127.0.0.1:3000;
}
}

1
templates/syslog.j2 Normal file
View file

@ -0,0 +1 @@
if $programname == '{{ zammad_log_name }}' then { action(type="omfile" file="{{ zammad_log_path }}/{{ zammad_log_file }}") stop }

View file

@ -0,0 +1,19 @@
[Unit]
Description=Zammad rails server
After=syslog.target
After=network.target
After=zammad.service
Requires=zammad.service
[Service]
EnvironmentFile=/etc/zammad/zammad.env
User=zammad
Group=zammad
Restart=always
WorkingDirectory={{ zammad_home }}
ExecStart=/bin/bash -l -c "${BUNDLE_BINARY} exec script/rails server -b ${ZAMMAD_BIND_IP} -p ${ZAMMAD_RAILS_PORT}"
[Install]
WantedBy=zammad.service

View file

@ -0,0 +1,20 @@
[Unit]
Description=Zammad scheduler
After=syslog.target
After=network.target
After=zammad.service
Requires=zammad.service
[Service]
Type=forking
EnvironmentFile=/etc/zammad/zammad.env
User=zammad
Group=zammad
Restart=always
WorkingDirectory={{ zammad_home }}
ExecStart=/bin/bash -l -c "${BUNDLE_BINARY} exec script/scheduler.rb start"
[Install]
WantedBy=zammad.service

View file

@ -0,0 +1,19 @@
[Unit]
Description=Zammad websocket
After=syslog.target
After=network.target
After=zammad.service
Requires=zammad.service
[Service]
EnvironmentFile=/etc/zammad/zammad.env
User=zammad
Group=zammad
Restart=always
WorkingDirectory={{ zammad_home }}
ExecStart=/bin/bash -l -c "${BUNDLE_BINARY} exec script/websocket-server.rb -b ${ZAMMAD_BIND_IP} -p ${ZAMMAD_WEBSOCKET_PORT} start"
[Install]
WantedBy=zammad.service