Files
zammad/BREAKING_CHANGES.md
Mantas Masalskis 1e486439ef Maintenance: Do not establish a session when verifying a signup email address.
Approved-by: Dusan Vuckovic <dv@zammad.com>

Co-authored-by: Mantas <mantas@idev.lt>
2026-10-05 21:41:05 +02:00

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 — always false
  • Rails.application.config.db_case_sensitive — always true
  • Rails.application.config.db_like — always ILIKE
  • Rails.application.config.db_column_array — always true

⚠️ 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 &amp; 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

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

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

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_byte
  • Rails.application.config.db_case_sensitive
  • Rails.application.config.db_like
  • Rails.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 data of the "certificate add" endpoint was renamed to certificate.
  • The field data of the "private key add" endpoint was renamed to private_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:

  1. Do a separate request to the object specific endpoint e.g. /api/v1/groups
  2. 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.