42 KiB
Breaking Changes
Upcoming releases
String#utf8_encode and Object#to_utf8 will be removed
Who is affected? Developers of third-party packages, patches or add-ons that still call
String#utf8_encode or Object#to_utf8.
Both core extensions, deprecated since Zammad 7.3, will be removed in Zammad 8.0. Code still calling
them will then raise NoMethodError.
⚠️ Switch such code to TextEncoding.utf8_encode before updating to Zammad 8.0.
Related issue: #6371
Debian 11 will no longer be supported
Who is affected? Admins of instances installed from the Zammad package repository on Debian 11 ("bullseye").
Debian 11 reached its LTS end of life on 2026-08-31 and no longer receives security updates. A future release will therefore no longer be built for it, and the package repository will provide no Debian 11 packages for that release and later ones. Zammad 7.1 keeps receiving Debian 11 packages until it goes out of maintenance.
⚠️ Upgrade the operating system to a supported Debian release before updating.
Related issue: #6360
Inline attachments will be listed separately in ticket article API responses
Who is affected? Integrations that read inline images from the attachments list of ticket article
REST API responses.
Ticket article responses such as GET /api/v1/ticket_articles/{id} currently include inline image
attachments in the attachments list. In a future release they will no longer be part of that list and
will be returned in a dedicated inline_attachments key instead.
⚠️ Update such integrations to read inline images from the new inline_attachments key.
Related issue: #6254
Exceptions::UnprocessableEntity will be removed
Who is affected? Developers of custom packages, patches or add-ons that still reference
Exceptions::UnprocessableEntity.
The constant, deprecated since Zammad 7.1, will be removed in Zammad 8.0. Code still using it will then
raise NameError: uninitialized constant Exceptions::UnprocessableEntity.
⚠️ Switch to Exceptions::UnprocessableContent before updating to Zammad 8.0.
Related issue: #6198
The deprecated Rails.application.config.db_* values will be removed
Who is affected? Developers of custom packages, patches or add-ons that read database preferences from the Rails configuration.
The values deprecated with the removal of MySQL support in Zammad 7.0 will be removed in Zammad 8.0. Until then they emit a deprecation warning and return the value that always applies to PostgreSQL:
Rails.application.config.db_null_byte— alwaysfalseRails.application.config.db_case_sensitive— alwaystrueRails.application.config.db_like— alwaysILIKERails.application.config.db_column_array— alwaystrue
⚠️ Remove branches that depend on these values from custom code and rely on the PostgreSQL behaviour instead.
Related issue: #5580
7.3
String#utf8_encode and Object#to_utf8 were deprecated in favour of TextEncoding.utf8_encode
Who is affected? Developers of third-party packages, patches or add-ons that call
String#utf8_encode, String#utf8_encode! or Object#to_utf8.
Encoding resolution moved out of lib/core_ext/string.rb into a dedicated class, TextEncoding,
which takes the string as an argument: string.utf8_encode(from: 'iso-8859-1') became
TextEncoding.utf8_encode(string, from: 'iso-8859-1'), and object.to_utf8 became
TextEncoding.utf8_encode(object.to_s). String no longer requires the rchardet and mail gems.
String#utf8_encode and Object#to_utf8 still work and now emit a deprecation warning.
String#utf8_encode! was removed without a deprecation period, since TextEncoding.utf8_encode
never modifies its argument and always returns a new string.
⚠️ Replace calls to String#utf8_encode and Object#to_utf8 with TextEncoding.utf8_encode, and
replace String#utf8_encode! with an assignment from it.
Related issue: #6371
Import mode also enables maintenance mode
Who is affected? Admins of instances that are left in import mode while users are expected to work in them.
Import mode was never intended for productive environments. An instance running in import mode now
automatically runs in maintenance mode as well: while the import_mode setting is enabled, every
authenticated request of a user without the admin.maintenance permission is refused. REST and API
requests get 403 Forbidden, and GraphQL treats the session as logged out. This covers new logins,
sessions that were already open, and API access via token or HTTP basic authentication alike. An
impersonated session is only exempt when the administrator who switched into it holds
admin.maintenance; this also applies to the classic maintenance mode.
⚠️ Disable import mode before letting users work in the instance.
Related issue: #6237
The knowledge base search index was switched from HTML-escaped text to plain text
Who is affected? Admins of instances with Elasticsearch enabled that use the knowledge base, and
integrations that call POST /api/v1/knowledge_bases/search.
Knowledge base titles and answer bodies were written into the search index HTML-escaped, so a
category named Warranty & Returns was indexed as Warranty & Returns. The escape sequences
were searchable in their own right: amp, lt, gt and nbsp matched content that contains no
such word, and a search matching one of them, the wildcard * among them, highlighted it and left
the sequence visible in the result list (#6369).
Both texts are now indexed as plain text. Markup in a title is still dropped on its way into the
index, and the title columns themselves keep what was written to them.
The details returned by POST /api/v1/knowledge_bases/search changed with it: title, body and
subtitle are now always HTML, with every character escaped and, when highlight_enabled is on,
<em> marking the matched runs. Previously only a highlighted fragment was guaranteed to look like
this. A detail without a match in its field came back the way its fallback produced it: HTML-escaped
for the answer body, the category and knowledge base title and the subtitle, and as written
for the answer title, with highlighting on or off.
The result list no longer carries the highlight key of each hit. The raw fragments it held mark
their matches with characters that only the details rendering above knows how to interpret.
⚠️ Integrations that read the answer title as text have to decode it as HTML, like every other detail.
⚠️ Rebuild the search index after the update: zammad run rake zammad:searchindex:rebuild
Related issue: #6399
Deleting organizations via API requires the admin.organization permission
Who is affected? Integrations that call DELETE /api/v1/organizations/:id with a token that only
has the ticket.agent permission.
The endpoint has historically been permitted for users with only the ticket.agent permission, which
contradicted the API documentation. That behaviour was deprecated in Zammad 7.2: the endpoint now
requires admin.organization, and agent tokens receive 403 Forbidden.
⚠️ Switch such integrations to an account with the admin.organization permission.
Related issue: #6315
7.2
Verifying a signup email address no longer signs the user in
Who is affected? Integrations that redeem a signup verification token through
POST /api/v1/users/email_verify or the userSignupVerify GraphQL mutation and rely on the session
that the redemption used to establish, and admins who send a verification or password reset link to a
deactivated account.
Redeeming the token established a fully authenticated session for the account, without the account's
password and without the second factor configured for it. Both endpoints now only mark the email
address as verified and establish no session. The REST endpoint still answers
200 {"message":"ok","user_email":"…"}, but the response no longer carries a session cookie. The
mutation's payload field session was replaced by a boolean success, so a client selecting
session { id } receives a GraphQL error.
A non-persistent token — Signup, PasswordReset, AdminAuth, KnowledgeBasePreview — is now
rejected when it belongs to an inactive user. Previously only persistent tokens were checked this
way. The mail carrying such a link is still sent, but the link itself no longer works while the
account is deactivated.
⚠️ Sign in through POST /api/v1/signin or the login mutation after redeeming a verification
token, and pass the configured second factor there. Change GraphQL clients to select success
instead of session. Activate a deactivated account before sending it a verification or password
reset link.
Related advisory: GHSA-f3qr-94c2-7mx2
The getting started endpoints require admin.wizard once the system is set up
Who is affected? Integrations that read GET /api/v1/getting_started or
GET /api/v1/getting_started/auto_wizard while authenticated as a user without the admin.wizard
permission, and any integration that reads them while a migration is running.
On a system that is set up, both endpoints returned the list of active groups and of active email
addresses, the branding config and the available email channel drivers to every authenticated user,
customers included. That data is only of use to a user who may run the setup wizard, and it is
restricted on its own endpoints: GET /api/v1/email_addresses answers a customer with 403, and
GET /api/v1/groups/:id field-scopes its response. Both endpoints now answer a user without
admin.wizard with 403 Forbidden instead.
Before the setup, and while a migration is running, the endpoints stay reachable without
authentication: a migration is started anonymously from the installer, and its progress screens have
no user to authenticate as. While a migration is running the response is now reduced to the setup and
migration state — setup_done, import_mode, import_backend and system_online_service — which
is all those screens read; the group and email address list, the branding config and the email
channel drivers are no longer part of it, for any caller. A migration only clears its import mode
when it succeeds, so a failed one would otherwise keep that data readable without authentication
indefinitely. Outside a migration the response is unchanged for users with admin.wizard.
⚠️ Switch integrations that read the group or email address list from these endpoints to an account
with the admin.wizard permission — an API token needs that permission in its scope as well — or to
GET /api/v1/groups respectively GET /api/v1/email_addresses.
Related advisory: GHSA-x3fm-p95w-xj7v
The legacy WebSocket login is authenticated from the session cookie and signshow no longer returns session_id
Who is affected? Developers of custom clients that connect to the legacy WebSocket server and
authenticate with a session_id in the login event, integrations that read session_id from the
GET /api/v1/signshow response, and admins whose http_type and fqdn settings do not match the URL
users open Zammad with.
The GET /api/v1/signshow response contained the ID of the current session for logged-in users, and the
legacy frontend sent that ID in the login event of the WebSocket connection to authenticate it. Exposing
the session ID to page scripts was unnecessary and made it easier to steal a session. The session_id
key was removed from the response, and the WebSocket server now ignores any session_id in the login
payload. Instead it resolves the user from the session cookie sent with the WebSocket handshake, in the
same way ActionCable already does for the new frontend, and only if the handshake Origin header matches
<http_type>://<fqdn> or a localhost origin. A login event without a matching cookie and origin creates
an unauthenticated WebSocket session that receives no user-specific data.
⚠️ Send the session cookie with the WebSocket handshake instead of a session_id in the login payload,
and make sure the http_type and fqdn settings match the origin users open Zammad with.
Related advisory: GHSA-23hj-h8w6-rgm3
Zammad's reverse proxy configuration is authoritative for the request scheme
Who is affected? Admins running the Docker images or a newly installed nginx behind a proxy
that reports the request scheme via the Forwarded or X-Forwarded-Ssl header, and admins of a
newly installed Apache behind any TLS-terminating proxy.
Rack evaluates X-Forwarded-Ssl and Forwarded with a higher priority than X-Forwarded-Proto, so
an outer proxy could silently override the scheme that Zammad's own web server configuration had set.
The nginx and Apache configurations shipped with Zammad therefore now clear Forwarded,
X-Forwarded-Scheme and X-Forwarded-Ssl, which leaves X-Forwarded-Proto as the only place where
the scheme is decided.
The Apache configurations did not set X-Forwarded-Proto at all before, so an instance behind an
SSL-terminating Apache was never seen as HTTPS. They now set it explicitly, to http in the non-SSL
and to https in the SSL virtual host, which also means an outer proxy's value is no longer passed
through.
The Docker images rebuild their nginx configuration from the shipped one on every start, so the change applies to them automatically. Package installations keep the web server configuration they already have; only newly installed ones receive the updated files.
⚠️ If Zammad was reachable over HTTPS only because the proxy in front of it sent Forwarded or
X-Forwarded-Ssl — or, on Apache, X-Forwarded-Proto — configure the scheme in Zammad's own web
server instead: set NGINX_SERVER_SCHEME=https for the Docker images, or the X-Forwarded-Proto line
in the nginx respectively Apache configuration file.
Related issue: #6305
Links between an object and itself are rejected, and failed link creations answer 422
Who is affected? Integrations that create links via POST /api/v1/links/add.
An object can no longer be linked to itself: a link whose source and target are the same ticket or
knowledge base answer is rejected with the validation error An object cannot be linked to itself..
Such a link was never usable — it showed up twice in the link list and was not clickable.
At the same time the endpoint reports failed link creations correctly. Previously it answered
201 Created as soon as the source object was found, even when the link was not stored at all, so an
already existing link looked like a success. A rejected link now answers 422 Unprocessable Content
with the reason in the error key, for example {"error":"Link already exists"}.
⚠️ Update integrations that treat every response of the endpoint as a success, and stop sending self-links.
Related issue: #6319
Dates with a year outside 1 to 9999 are no longer accepted
Who is affected? Integrations that write date or datetime values with a year outside the range 1
to 9999, for example a ticket object attribute set via PUT /api/v1/tickets/:id.
Date and datetime attributes of all objects are now validated against the year range that
Elasticsearch and RFC 3339 support. Previously such a value was stored, but broke the indexing of the
whole record afterwards, so the affected ticket, user or organization could no longer be found via
search at all. Saving a value like 20026-08-18 now fails with the validation error
must have a year between 1 and 9999 instead.
Only attributes that are actually changed by a save are validated, so existing records keep their out-of-range values until the affected attribute is written again.
⚠️ Update integrations that send such values, and correct existing out-of-range dates to make the affected records findable again.
Related issue: #6306
Import mode is reported as an issue by the health check
Who is affected? Admins of instances that are left in import mode after a migration, and monitoring
setups that alert on the health_check endpoint.
Import mode is only meant for bulk imports and migrations, never for productive operation. The
health_check endpoint and the "Monitoring" section therefore now report an issue while import_mode
is enabled, which turns a previously green monitoring check red. The same applies while
system_init_done is still false.
⚠️ Disable import mode once a migration is finished, or expect the monitoring check to stay red.
Related issue: #6236
Knowledge Base answers index a new publication_state field
Who is affected? Admins of systems with Elasticsearch enabled who update to Zammad 7.2 without rebuilding the search index.
The "Suggested searches" shortcut menu added to the Knowledge Base search introduced a new
publication_state field for KnowledgeBase::Answer::Translation, reflecting an answer's current
state (draft, internal, published, archived). Existing indices do not contain the field, so
publication_state queries such as publication_state:draft return no results.
⚠️ Rebuild the search index after the update: zammad run rake zammad:searchindex:rebuild
Related issue: #6142
Elasticsearch 7 is no longer supported, 8.15 is the new minimum
Who is affected? Admins of systems that run an Elasticsearch older than 8.15, including every Elasticsearch 7 installation.
Elasticsearch 7 has reached its end of life and was deprecated with Zammad 7.1. Support for it was
removed with this release, so the supported range is now Elasticsearch 8.15 up to, but not
including, 10 — 8.15 and later 8.x releases and every 9.x release. The requirement is enforced
where Zammad reads the server version: the zammad:searchindex:* rake tasks, including
zammad:searchindex:rebuild, and the "Elasticsearch version" system report abort with
Version <x> of configured elasticsearch is not supported.
⚠️ Upgrade the Elasticsearch installation to 8.15 or newer before updating to Zammad 7.2. Note that Elasticsearch 10 and later are not supported either.
Related issue: #6314
Local file paths are no longer supported as calendar iCal feed source
Who is affected? Admins of instances with a calendar whose iCalendar feed points to a local .ics
file instead of an HTTP(S) URL.
Calendars can no longer read their iCal feed from the local file system. Only http:// and https://
URLs are accepted, which is now enforced by a validation of the ical_url attribute. Calendars that
still hold a local path stop syncing their public holidays, and saving them fails until the value is
changed.
⚠️ Host the .ics file on an HTTP(S) server and update the calendar's iCalendar feed accordingly.
Related issue: #6316
The deprecated es-ca locale was inactivated
Who is affected? Admins of instances with users or a Knowledge Base still set to the deprecated
Catalan locale es-ca.
The es-ca locale, deprecated since Zammad 7.0 in favour of the correct code ca, is no longer
offered for selection. Users still set to it are migrated to ca automatically. Knowledge Base locales
referencing es-ca are left untouched, because changing the locale of a Knowledge Base changes its
public URLs.
⚠️ Migrate a Knowledge Base that still uses the deprecated locale manually:
zammad run rails r "KnowledgeBase::Locale.find_by(system_locale: Locale.find_by(locale: 'es-ca'))&.update!(system_locale: Locale.find_by(locale: 'ca'))"
Related issue: #5886
The default Content-Security-Policy became stricter
Who is affected? Setups that embed the Zammad web interface in an <iframe> on a different origin.
A frame-ancestors 'self' directive was added to the default Content-Security-Policy response
header. Setups that previously re-enabled embedding by overriding the X-Frame-Options header at the
reverse proxy are blocked again by it.
⚠️ To allow embedding from trusted origins, adjust the frame-ancestors directive of the
Content-Security-Policy response header at the reverse proxy as well.
Related issue: #6087
7.1
X-Forwarded-Proto takes precedence over X-Forwarded-Scheme
Who is affected? Admins running Zammad behind a reverse proxy that terminates TLS and reports the
request scheme via the X-Forwarded-Scheme header only, such as Nginx Proxy Manager.
Zammad was updated from Rack 2 to Rack 3, which changed which header decides whether a request is
seen as HTTPS: Rack 2 evaluated X-Forwarded-Scheme first, Rack 3 evaluates X-Forwarded-Proto
first. Zammad's own nginx configuration sets X-Forwarded-Proto from the scheme of the connection it
receives, in the Docker images via the NGINX_SERVER_SCHEME variable, which defaults to $scheme.
Behind a proxy that terminates TLS and forwards plain HTTP, that value is http, so such requests
are now seen as plain HTTP even though the proxy reported X-Forwarded-Scheme: https.
With the http_type setting set to https, the session cookie is marked Secure, and a Secure
cookie is not written on a request that is seen as plain HTTP. No session is created at all, and
logging in fails with "CSRF token verification failed!". Sessions that already hold a cookie keep
working, so the problem only surfaces after a logout.
⚠️ Configure the scheme in Zammad's own web server rather than in the proxy in front of it, whose
X-Forwarded-Proto header is overwritten: set NGINX_SERVER_SCHEME=https for the Docker images, or
the X-Forwarded-Proto line in the nginx configuration file.
Related issue: #6305
Elasticsearch 7 was deprecated
Who is affected? Admins of systems that run Elasticsearch 7.
Elasticsearch 7 has reached its end of life and was deprecated with this release. It is still supported in Zammad 7.1, but a later release requires Elasticsearch 8 or later.
⚠️ Plan the upgrade of the Elasticsearch installation to version 8 or later.
Related issue: #6314
Exceptions::UnprocessableEntity was deprecated in favour of Exceptions::UnprocessableContent
Who is affected? Developers of custom packages, patches or add-ons that reference
Exceptions::UnprocessableEntity.
The exception was renamed to Exceptions::UnprocessableContent, following the rename of the HTTP
status code itself. The old constant still resolves, but it is deprecated and emits a deprecation
warning.
⚠️ Replace references to Exceptions::UnprocessableEntity with Exceptions::UnprocessableContent.
Related issue: #6198
7.0
MySQL support was removed and database-related settings were deprecated
Who is affected? Admins of instances still running on MySQL or MariaDB, and developers of custom packages that read database preferences from the Rails configuration.
After a long period of deprecation, support for the MySQL and MariaDB databases was removed — PostgreSQL is the only supported database. Alongside, the following configuration values were deprecated and will be removed with Zammad 8.0:
Rails.application.config.db_null_byteRails.application.config.db_case_sensitiveRails.application.config.db_likeRails.application.config.db_column_array
⚠️ Migrate a MySQL or MariaDB installation to PostgreSQL before updating to Zammad 7.0, following the migration documentation.
Related issue: #5580
Fulltext search ignores diacritics by default
Who is affected? Admins of systems with Elasticsearch enabled, especially those who rely on searches matching diacritics exactly.
The global search and other fulltext searches now use the Elasticsearch
asciifolding analyzer, which is enabled by default:
searching for Munchen matches München and vice versa. With the analyzer disabled, searching for
Munchen does not match München.
The new behaviour only applies to a rebuilt search index. To keep the previous behaviour instead,
disable the es_asciifolding setting — no rebuild is needed in that case:
zammad run rails r "Setting.set('es_asciifolding', false)"
Thanks to Jano Suchal for the contribution.
⚠️ Rebuild the search index after the update: zammad run rake zammad:searchindex:rebuild
Related issue: #3782
nginx configuration requires proxy_http_version 1.1
Who is affected? Admins of installations that use an nginx reverse proxy with a configuration file from an earlier Zammad version.
The nginx configuration shipped with Zammad sets proxy_http_version 1.1; for the main location as
well, so that all proxied requests use HTTP/1.1 like the websocket and cable locations already did.
Existing configuration files are not changed by the update.
⚠️ Add the line to the location / section of the nginx configuration:
location / {
+ proxy_http_version 1.1;
proxy_set_header Host $http_host;
Related issue: #6317
Assigning the same organization as primary and secondary is no longer allowed
Who is affected? Integrations that write user records via API and set the same organization as both primary and secondary organization.
The same organization can no longer be a user's primary and secondary organization at the same time. Such requests now fail with a validation error, and an automatic migration brings existing user data into a consistent state during the update.
⚠️ Update API calls that put users into this state before updating.
Related issue: #5254
The Catalan locale moved to the correct ca locale code
Who is affected? Admins of instances with users using the Catalan locale, and especially those with a Catalan Knowledge Base.
The previously available Catalan locale used the wrong internal locale code es-ca and was deprecated;
it will be removed in a future release. A new Catalan locale with the correct code ca is available,
and a migration switches the language preference of all Catalan user profiles to the new
"Catalan (Català)" locale.
Knowledge Base locales are not migrated automatically, because changing the locale of a Knowledge Base changes its public URLs.
⚠️ Migrate a Knowledge Base using the Catalan language at your own pace:
zammad run rails r "KnowledgeBase::Locale.find_by(system_locale: Locale.find_by(locale: 'es-ca'))&.update!(system_locale: Locale.find_by(locale: 'ca'))"
Related issue: #5886
The Slack integration was removed
Who is affected? Admins of instances that still use the Slack integration.
The Slack integration was removed from the codebase; existing configurations stop working and are not migrated automatically. Everything the integration did can be achieved with webhooks, see Slack notifications via webhook.
⚠️ Recreate existing Slack notifications as webhooks, if not already done.
Related issue: #5583
The Twitter integration was removed
Who is affected? Admins of instances that still have a Twitter/X channel configured.
The Twitter integration was removed due to problems with the API licensing, and there is no replacement available. Existing tickets and articles stay accessible, but no messages are fetched or sent any more.
Related issue: #5581
6.5.2
The following breaking changes occurred due to a security fix.
PGPController parameter name changes
The field key of the "key add" endpoint was renamed to private_key.
SMIMEController parameter name changes
- The field
dataof the "certificate add" endpoint was renamed tocertificate. - The field
dataof the "private key add" endpoint was renamed toprivate_key.
HttpLogsController access control
Logging subsystem (HttpLog) API access control is now more fine grained.
In the past, any admin.* permission was sufficient to access this data.
Now, only the relevant parts can be accessed (e.g. admin.webhook)
6.5
Textarea object manager attribute values
When used as template variables, the textarea object
manager attributes are now replaced with an HTML representation of their value. This is a consequence of a bugfix for
#5330, which expects newline characters are respected for these
attributes in all contexts, including the rich text article body. The administrators are advised to check for usage of
such variables in their objects (e.g. triggers, text modules, etc), by making sure the new value type will not break
their existing workflows.
Changes to search API endpoints
All search endpoints (/:object/search) have been revised, extended and unified. This will also result in breaking
changes in the existing endpoints. Be prepared that the structure in the responses may change (have a look at the
API documentation where you can find updated examples).
The standard search (e.g. /ticket/search) returned a hash for some objects, such as the ticket. This will no
longer be the case.
The structure for the expanded search (e.g. /ticket/search?expand=true) remains the same.
The structure of the full search (e.g. /ticket/search?full=true) remains the same, but is supplemented by a
total_count, which counts all results.
Some objects used an object-related hash key, such as ticket_ids. This is now always record_ids.
The count search (e.g. /ticket/search?only_total_count=true) is a new feature.
API performance optimization of asset return data
Most API endpoints have some parameter called full=true which returns the data with all related assets. In order to improve the front end performance, we decided to reduce certain assets which are populated on the login. Normally this parameter is mainly used to show additional data to our legacy app. We have some static data which rarely changes and are currently added on every object like:
- Ticket Priority
- Ticket State
- Ticket Group
- Role
This information will not be added in the future any more when requesting a user or a ticket. If you have an external script which is for example requesting tickets with assets and using the group name or some role information out of the assets, you need to adjust your code to do either:
- Do a separate request to the object specific endpoint e.g.
/api/v1/groups - Get the global assets before requesting the ticket e.g.
/api/v1/signshow
Limit to one merged state
It will not be possible to have more than one state of the merged type. Additional states will be changed to the
closed type automatically with that update. If you want to prevent that, make sure to only have one state of the type
merged before you make an update to the next release.
APP_RESTART_CMD and Zammad self-shutdown
Zammad will now cause a self-shutdown of all running processes after certain configuration changes by default. It is the responsibility of the controlling process manager (e.g. Docker, Kubernetes, systemd) to bring them up again by way of a proper restart policy. This is the default for vanilla Docker, Kubernetes or Package deployments of Zammad.
The previous environment variable APP_RESTART_CMD is not supported any more.
For systems where this behaviour is not wanted, it can be disabled by setting the Zammad Setting auto_shutdown to
false.
ZAMMAD_SESSION_JOBS_CONCURRENT was renamed to ZAMMAD_PROCESS_SESSIONS_JOBS_WORKERS
The background worker shutdown handling was improved to be more graceful and allow processes to finish first.
Together with this change, the session jobs logic that computes the ticket overviews was moved to be
a first-class background service. Therefore the name of its configuration variable changed
from ZAMMAD_SESSION_JOBS_CONCURRENT to ZAMMAD_PROCESS_SESSIONS_JOBS_WORKERS. The old one will continue
to work for now, but emit a deprecation warning.
nginx configuration update
Please update your nginx configuration file to insert the line proxy_set_header Host $http_host; to the location /ws
and location /cable sections like in the example below:
@@ -38,10 +38,11 @@ server {
# legacy web socket server
location /ws {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
+ 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_read_timeout 86400;
proxy_pass http://zammad-websocket;
@@ -50,10 +51,11 @@ server {
# action cable
location /cable {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
+ 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_read_timeout 86400;
proxy_pass http://zammad-railsserver;
6.4
JavaScript Package Manager Change
This version changes the JavaScript toolchains to be based on pnpm rather than yarn. This is only relevant for source installations, where you need to provide a recent version of pnpm in order to run the assets:precompile command.
Changed CSV-format for user/organization import/export
We slightly changed the format of the CSV-files you use for importing/exporting users and organizations. If you somehow do that in an automated process via our REST-API, you will need to review that process before updating to Zammad 6.4. Check the details in our documentation.
6.3
Knowledge base granular permissions setup changed
Zammad allows configuration of a granular permission structure for knowledge base access. Previous Zammad versions allowed to misconfigure this in cases of allowing agents editor access to only some, but not all categories: it was possible to grant editor access at a higher level in the category tree, and then restricting access to reader or none for sub-categories. This was not effective due to permission inheritance.
Such a misconfiguration is no longer possible in Zammad 6.3. Administrators with existing knowledge base granular permission structures should review their configuration to ensure that at top-level only reader access is granted, and editor access only for the relevant sub-categories.
Permissions for Ticket State and Priority REST-API
With this release, we will introduce new permissions for the ticket state and priority management. It will no longer be possible to access the corresponding REST-API with "admin.object" permission. Existing roles and/or access tokens that are used for these specific REST-API endpoints need to be updated to include the new permissions ("admin.ticket_state" and "admin.ticket_priority").
6.2
Default SSL Verification in UserAgent
The default SSL behaviour of the UserAgent class in Zammad was changed. Previously, it would not perform SSL verification unless explicitly requested. Now, it will perform SSL verification unless explicitly rejected.
This may cause issues on systems with custom addons using the UserAgent to access other systems via https, if these systems have self-signed certificates. In such cases, these certificates or the CA certificates used for their generation should be uploaded via the new SSL Certificates management screen of Zammad. Alternatively, custom code can be adjusted to pass verify_ssl: false to UserAgent calls to restore the old behaviour.
Oversized Email Handling
The handling of emails larger than the size limit changed. Previously, Zammad would send a reply and save the emails locally in var/spool/oversized_email (if the setting postmaster_send_reject_if_mail_too_large is true). No ticket is created in this case.
The new behaviour is that Zammad sends the reply like before, but no longer creates files for these emails locally - they are discarded.
Reserved Delimiter in Group Name
The double colon (::) is now a reserved delimiter in the group name, in order to facilitate nested structure for
complex hierarchies. Previously, it was possible to freely use this set of characters as part of the group name, but
now it is forbidden.
On existing systems, the group names that contain the now reserved delimiter will be renamed, with sets of double colons
being replaced by a dash (-) during the migration process.
Additionally, existing custom group object attributes named name_last and parent_id will be renamed too, by adding an underscore in front (_name_last and _parent_id). This is due to these attributes now being part of the group model, requiring dedicated table columns under the reserved names.
Disallowed URL Values in User's Name Attributes
Text values that resemble valid URI addresses are now disallowed for user's first and last name attributes. Previously, it was possible to save any text in these attributes. The administrators should take a note of this change since it can have an impact on existing user data.
No migration will be run for existing users on update to Zammad 6.2. In case there are user records that contain URLs in their name attributes, they will be sanitized during subsequent updates. No manual action from administrator will be required, as the URI scheme or protocol will be automatically stripped from offending values.
6.1
New Organization Attribute vip
Zammad 6.1 creates a new vip attribute for organizations. For systems with previously created vip attributes, there
is special caution needed. In case of boolean attributes, Zammad will adjust them to the new settings and keep using
them. For attributes of other types, Zammad will rename the existing attribute to _vip and add a new vip boolean
attribute. This may cause issues if the previous attribute was used in other parts of the system, e.g. Triggers.
In such cases, the relevant configurations must be reviewed and adjusted.
Support for the Unicorn Web Server is removed
It seems that the Unicorn Web Server is no longer really used with Zammad. Therefore, we have decided to remove it with Zammad 6.1 after it was deprecated in Zammad 6.0.
6.0
nginx configuration update
When updating to Zammad 6.0 from a previous version, the system administrator needs to add some content to the configuration of the reverse proxy.
Example for Apache:
ProxyPass /cable ws://127.0.0.1:3000/cable
Example for nginx:
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;
}
This is required to enable the new Rails Action Cable based realtime communication. You can find more details about this change at this github commit.
Mandatory Redis Dependency
Starting with Zammad version 6.0, Redis is required to run Zammad. For package-based installations, the new dependency is automatically installed in the system during the update.
Note: Hosted customers do not need to take any further action regarding this change!
Health Check API Changes
Starting with Zammad 6.0, the "health check" monitoring API at /api/v1/monitoring/health_check will no longer echo the
used authentication token in the response payload.
Excel Export Format Change
Starting with Zammad version 6.0, all Excel exports will be exported exclusively in xlsx format. The original xls format will no longer be supported.
Storage location of unprocessable/oversized emails
Zammad stores emails that were unprocessable or rejected due to size constraints in the file system. The location of
such emails changed from tmp/unprocessable_mail and tmp/oversized_mail to var/spool/unprocessable_mail and
var/spool/oversized_mail within the /opt/zammad directory. Existing emails are automatically moved to the new
location.
Naming change in Token model and EmailAddress model
The token model is used to store access tokens and had field names which may have caused confusion for developers
using them. Therefore, the field previously called name: now has the correct identifier token: (as it stores the
actual token value), and the field previously called label: is now called name: for better consistency with other
models. The EmailAddress model is used to information about email addresses Zammad receives mail for. For consistency
reasons, its realname: field is now called name:.
This means that the attribute via the REST API also changes: from token or realname to "name".
Docker image zammad-docker was archived
The repository zammad-docker was intended for testing / development purposes only. This repository was archived and will receive no further updates. Please use zammad-docker-compose instead.