Kontakt

Carsten Rieger IT Services
Am Danglfeld 8 | 83132 Pittenhart
Telefon: 08624.9009794
E-Mail: info@c-rieger.de

Zammad Ticketsystem v. 6.x

Quelle: zammad.org

Mit Hilfe dieser Schnell-Installationsanleitung installieren Sie Zammad 6.3.x auf einem Debian 12- oder Ubuntu 24 – Serversystem. Partizipieren Sie dabei von der Performance des nginx-Webservers, der Elasticsearch-Volltextsuche u.v.m..

sudo -s
apt install curl apt-transport-https gnupg

Prüfen Sie, ob die Spracheinstellungen UTF8 enthalten:

locale |grep "LANG="

Wenn keine Rückgabe wie <sprache>.utf8 erscheint, dann korrigieren Sie es wie folgt:

apt install locales
locale-gen en_US.UTF-8
echo "LANG=en_US.UTF-8" > sudo /etc/default/locale
curl -fsSL https://dl.packager.io/srv/zammad/zammad/key | \
gpg --dearmor | tee /etc/apt/trusted.gpg.d/pkgr-zammad.gpg> /dev/null
echo "deb [signed-by=/etc/apt/trusted.gpg.d/pkgr-zammad.gpg] https://dl.packager.io/srv/deb/zammad/zammad/stable/debian 12 main"| \
tee /etc/apt/sources.list.d/zammad.list > /dev/null
curl -fsSL https://dl.packager.io/srv/zammad/zammad/key | \
gpg --dearmor | tee /etc/apt/trusted.gpg.d/pkgr-zammad.gpg> /dev/null
echo "deb [signed-by=/etc/apt/trusted.gpg.d/pkgr-zammad.gpg] https://dl.packager.io/srv/deb/zammad/zammad/stable/ubuntu 24.04 main"| \
tee /etc/apt/sources.list.d/zammad.list > /dev/null
apt install apt-transport-https sudo wget curl gnupg socat
echo "deb [signed-by=/etc/apt/trusted.gpg.d/elasticsearch.gpg] https://artifacts.elastic.co/packages/7.x/apt stable main"| \
tee -a /etc/apt/sources.list.d/elastic-7.x.list > /dev/null
curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | \
gpg --dearmor | tee /etc/apt/trusted.gpg.d/elasticsearch.gpg> /dev/null
apt update && apt install zammad

/usr/share/elasticsearch/bin/elasticsearch-plugin install ingest-attachment

Bestätigen Sie den Dialog mit ‚y‘

systemctl start elasticsearch && systemctl enable elasticsearch && systemctl status elasticsearch

Optimieren wir Elasticsearch, fügen SIe die nachfolgenden Zeilen am Ende der Datei hinzu:

nano /etc/elasticsearch/elasticsearch.yml
[…]
# Tickets above this size (articles + attachments + metadata)
# may fail to be properly indexed (Default: 100mb).
#
# When Zammad sends tickets to Elasticsearch for indexing,
# it bundles together all the data on each individual ticket
# and issues a single HTTP request for it.
# Payloads exceeding this threshold will be truncated.
#
# Performance may suffer if it is set too high.
http.max_content_length: 400mb

# Allows the engine to generate larger (more complex) search queries.
# Elasticsearch will raise an error or deprecation notice if this value is too low,
# but setting it too high can overload system resources (Default: 1024).
#
# Available in version 6.6+ only.
indices.query.bool.max_clause_count: 2000

Passen Sie den Map_Count an:

sed -i '$avm.max_map_count=262144' /etc/sysctl.conf
sysctl -p

Verbinden Sie nun Zammad mit Elasticsearch

zammad run rails r "Setting.set('es_url', 'http://localhost:9200')"
zammad run rake zammad:searchindex:rebuild

Optional: Passen Sie ggf. die Anzahl Cores bspw. [4] an Ihr System an

zammad run rake zammad:searchindex:rebuild[4]

Weitere optionale Settings werden hier beschrieben.

Richten Sie nun den Webserver ein:

openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak && touch /etc/nginx/nginx.conf && nano /etc/nginx/nginx.conf

Kopieren Sie den gesamten nachfolgenden Inhalt in die Datei:

user www-data;
worker_processes auto;
pid /var/run/nginx.pid;
events {
  worker_connections 2048;
  multi_accept on; use epoll;
  }
http {
  log_format criegerde escape=json
  '{'
    '"time_local":"$time_local",'
    '"remote_addr":"$remote_addr",'
    '"remote_user":"$remote_user",'
    '"request":"$request",'
    '"status": "$status",'
    '"body_bytes_sent":"$body_bytes_sent",'
    '"request_time":"$request_time",'
    '"http_referrer":"$http_referer",'
    '"http_user_agent":"$http_user_agent"'
  '}';
  server_names_hash_bucket_size 64;
  access_log /var/log/nginx/access.log criegerde;
  error_log /var/log/nginx/error.log warn;
  set_real_ip_from 127.0.0.1;
  real_ip_header X-Forwarded-For;
  real_ip_recursive on;
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  sendfile on;
  send_timeout 3600;
  tcp_nopush on;
  tcp_nodelay on;
  open_file_cache max=500 inactive=10m;
  open_file_cache_errors on;
  keepalive_timeout 65;
  reset_timedout_connection on;
  server_tokens off;
  resolver 127.0.0.53 valid=30s;
  resolver_timeout 5s;
  include /etc/nginx/conf.d/*.conf;
  }

und legen weitere notwendige Verzeichnisse an:

mkdir -p /var/www/letsencrypt/.well-known/acme-challenge /etc/letsencrypt/rsa-certs /etc/letsencrypt/ecc-certs

Bereinigen Sie den Webserver

rm -f /etc/nginx/sites-enabled/*.conf

und erstellen dann die notwendigen vHost-Dateien:

[ -f /etc/nginx/conf.d/default.conf ] && mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
touch /etc/nginx/conf.d/default.conf
touch /etc/nginx/conf.d/http.conf
touch /etc/nginx/conf.d/ihre.domain.de.conf
nano /etc/nginx/conf.d/http.conf
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name ihre.domain.de;
root /var/www;
location ^~ /.well-known/acme-challenge {
default_type text/plain;
root /var/www/letsencrypt;
}
location / {
return 301 https://$host$request_uri;
}
}

Wechseln Sie in die zammad-vHost-Datei:

nano /etc/nginx/conf.d/ihre.domain.de.conf

und kopieren den nachfolgenden Text in diese Datei. Passen Sie die roten Werte an.

upstream zammad-railsserver {
  server 127.0.0.1:3000;
}
upstream zammad-websocket {
  server 127.0.0.1:6042;
}
server {
  listen 80;
  listen [::]:80;
  server_name ihre.domain.de;
  server_tokens off;
  access_log /var/log/nginx/zammad.access.log;
  error_log /var/log/nginx/zammad.error.log;
  location /.well-known/ {
    root /var/www/html;
  }
  return 301 https://$server_name$request_uri;
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name ihre.domain.de;
  server_tokens off;
  ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
  ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
  ssl_trusted_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
  #ssl_certificate /etc/letsencrypt/rsa-certs/fullchain.pem;
  #ssl_certificate_key /etc/letsencrypt/rsa-certs/privkey.pem;
  #ssl_certificate /etc/letsencrypt/ecc-certs/fullchain.pem;
  #ssl_certificate_key /etc/letsencrypt/ecc-certs/privkey.pem;
  #ssl_trusted_certificate /etc/letsencrypt/ecc-certs/chain.pem;
  ssl_dhparam /etc/ssl/certs/dhparam.pem;
  ssl_session_timeout 1d;
  ssl_session_cache shared:SSL:50m;
  ssl_session_tickets off;
  ssl_protocols TLSv1.3 TLSv1.2;
  ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384';
  ssl_ecdh_curve X448:secp521r1:secp384r1;
  ssl_prefer_server_ciphers on;
  ssl_stapling on;
  ssl_stapling_verify on;
  resolver 176.9.93.198 176.9.1.117 valid=30s;
  add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload;" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-XSS-Protection "1; mode=block" always;
  add_header X-Robots-Tag none always;
  add_header X-Download-Options noopen always;
  add_header X-Permitted-Cross-Domain-Policies none always;
  add_header Referrer-Policy no-referrer always;
  add_header X-Frame-Options "SAMEORIGIN" always;
  add_header Permissions-Policy "interest-cohort=()";
  location = /robots.txt  {
    access_log off; log_not_found off;
  }
  location = /favicon.ico {
    access_log off; log_not_found off;
  }
  root /opt/zammad/public;
  access_log /var/log/nginx/zammad.access.log;
  error_log  /var/log/nginx/zammad.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://zammad-websocket;
  }
  location /cable {
    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://zammad-railsserver;
  }
  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	$scheme;
    proxy_set_header X-Forwarded-User "";
    proxy_read_timeout 180;
    proxy_pass http://zammad-railsserver;
    gzip on;
    gzip_types text/plain text/xml text/css image/svg+xml application/javascript application/x-javascript application/json application/xml;
    gzip_proxied any;
  }
}

Testen Sie den Webserver und starten diesen neu.

nginx -t
systemctl restart nginx.service

Stellen Sie sicher, dass die Firewall entsprechend konfiguriert ist:

apt install -y ufw
ufw logging medium
ufw default deny incoming
ufw allow 22/tcp comment "SSH"
ufw allow 80 comment "LE und http-redirect"
ufw allow 443 comment "TLS"
ufw enable

Bestätigen Sie die Abfrage mit ‚y‘

systemctl restart ufw.service
ufw status verbose

Für das Zertifikatshandling erstellen wir nun einen dedizierten Benutzer und fügen diesen der www-data Gruppe hinzu:

adduser acmeuser --gecos "" --disabled-password
usermod -aG www-data acmeuser

Diesem technischen Benutzer erteilen wir noch die notwendigen Berechtigungen, um bei einer Zertifikatserneuerung den notwendigen Webserverstart initiieren zu können.

touch /etc/sudoers.d/acmeuser
cat <<EOF >/etc/sudoers.d/acmeuser
acmeuser ALL=NOPASSWD: /bin/systemctl reload nginx.service
EOF

Wechseln Sie in die Shell des neuen Benutzers (acmeuser) um die Zertifikatssoftware zu installieren und verlassen diese Shell direkt im Anchluß wieder:

su - acmeuser
curl https://get.acme.sh | sh
exit

Passen Sie die entsprechenden Datei- und Verzeichnisberechtigungen an, um die neuen Zertifikate darin speichern zu können:

chmod -R 775 /var/www/letsencrypt && chmod -R 770 /etc/letsencrypt && chown -R www-data:www-data /var/www/ /etc/letsencrypt

Setzen Sie Let’s Encrypt als Standard CA für Ihren Server

su - acmeuser -c ".acme.sh/acme.sh --set-default-ca --server letsencrypt"

und wechseln dann erneut in die Shell des neuen Benutzers

su - acmeuser

Beantragen Sie nun die SSL-Zertifikate von Let’s Encrypt und ersetzen dabei ihre.domain.de mit Ihrer realen Domain:

acme.sh --issue -d ihre.domain.de --server letsencrypt --keylength 4096 -w /var/www/letsencrypt --key-file /etc/letsencrypt/rsa-certs/privkey.pem --ca-file /etc/letsencrypt/rsa-certs/chain.pem --cert-file /etc/letsencrypt/rsa-certs/cert.pem --fullchain-file /etc/letsencrypt/rsa-certs/fullchain.pem --reloadcmd "sudo /bin/systemctl reload nginx.service"
acme.sh --issue -d ihre.domain.de --server letsencrypt --keylength ec-384 -w /var/www/letsencrypt --key-file /etc/letsencrypt/ecc-certs/privkey.pem --ca-file /etc/letsencrypt/ecc-certs/chain.pem --cert-file /etc/letsencrypt/ecc-certs/cert.pem --fullchain-file /etc/letsencrypt/ecc-certs/fullchain.pem --reloadcmd "sudo /bin/systemctl reload nginx.service"

Verlassen Sie die Shell des acmeusers.

exit

Es werden nun die Self-Signed-Zertifikate entfernt und der Webserver neu gestartet:

sed -i '/ssl-cert-snakeoil/d' /etc/nginx/conf.d/nextcloud.conf
sed -i s/#\ssl/\ssl/g /etc/nginx/conf.d/ihre.domain.de.conf
systemctl restart nginx.service

Rufen Sie Zammad nun auf und folgen dem Installations-Assistenten.

Weiterführende Informationen findne Sie hier.


Die Installation und Absicherung Ihres Zammad-Ticetsystems wurde erfolgreich abgeschlossen und so wünsche ich Ihnen viel Spaß mit Ihren Daten in Ihrer privaten Cloud. Über Ihre Unterstützung (diese wird ordnungsgemäß versteuert!) würden sich meine Frau, meine Zwillinge und ich sehr freuen!

Carsten Rieger IT-Services | Slogan