# Web administration Version: 1.32-stable There are three primary ways of managing Halon Engage & Protect; the web administration, API ([Protocol Buffer](https://docs.halon.io/protobuf-schemas/)) or [CLI](https://docs.halon.io/manual/cli.html). This manual is a guide for the web administration. ## Table of contents * [Installation](#install) * [Distributions](#install:distributions) * [Ubuntu](#install:ubuntu) * [RHEL](#install:rhel) * [Startup](#install:startup) * [Upgrade](#upgrade) * [Configuration](#config) * [Listener directives](#config:listener-directives) * [Host directives](#config:host-directives) * [Group directives](#config:group-directives) * [User directives](#config:user-directives) * [OIDC directives](#config:oidc-directives) * [MCP directives](#config:mcp-directives) * [Database directives](#config:database-directives) * [Elasticsearch directives](#config:elasticsearch-directives) * [Other directives](#config:other-directives) * [Environment directives](#config:environment-directives) * [History logging](#history) * [Install Elasticsearch](#history:install-elasticsearch) * [Import an index template](#history:import-an-index-template) * [Delivery attempts](#history:delivery-attempts) * [Transactions](#history:transactions) * [Add configuration](#history:add-configuration) * [History datamasking](#history:history-datamasking) * [Start sending data](#history:start-sending-data) * [Tips on usage](#tips) * [Saving views persistently](#tips:saving-views-persistently) * [Sharing views with other users](#tips:sharing-views-with-other-users) * [Display of hostnames](#tips:display-of-hostnames) * [!Env - using environment variables](#tips:env-using-environment-variables) * [Changelog](#changelog) # Installation The web administration is installed using a Linux distribution package manager according to the corresponding instructions, or by manually copying the files to the `/opt/halon/web` directory. ## Distributions ### Ubuntu To install the .deb package use the following commands. ```console # apt-get update # apt-get install halon-web ``` ### RHEL To install the .rpm package use the following commands. ```console # yum install halon-web ``` ## Startup When the initial [configuration](#config) is in place, the program can be started with: ```console # systemctl start halon-web ``` # Upgrade In order to upgrade the package, install the new package over the previous installed one (see the installation chapter). After the upgrade the service will be stopped and requires to be manually started. # Configuration *halon-web* loads the non-reloadable configuration from `/etc/halon/web.yaml`. It is described by, and can be validated with, the [web.schema.json](http://lbovet.github.io/docson/index.html#https://docs.halon.io/json-schemas/web/1.32-stable/web.schema.json) [JSON schema](https://docs.halon.io/json-schemas/web/1.32-stable/) (included in our [Visual Studio Code integration](https://docs.halon.io/manual/vscode.html)). The default startup configuration file in `/opt/halon/web/share` can normally be used as a base: ```console # cp /opt/halon/web/share/web.yaml /etc/halon/ ``` ## Listener directives ### listeners[] The web administration must have one or more listen directives, which specify which TCP port and address to listen on. **Required.** ### listeners[].port Which TCP port to listen on. **Required.** ### listeners[].baseurl An optional public base URL (scheme, host and optional port, e.g. [https://web.example.com](https://web.example.com)). ### listeners[].basepath An optional URL path prefix under which the web administration is served, for example /web. ### listeners[].address IPv4 or IPv6 address to listen on. The default is to listen to all IPv4 and IPv6 addresses. ### listeners[].tls TLS settings for the listener. ### listeners[].tls.pki The X.509 certificate and private key. The private key and certificate should have either a `path` or `data` property. ```yaml pki: certificate: data: |- -----BEGIN CERTIFICATE----- ... privatekey: data: |- -----BEGIN PRIVATE KEY----- ... ``` ### listeners[].tls.ciphers Cipher suite specification ### listeners[].tls.protocols.min Minimum TLS version to allow ### listeners[].tls.protocols.max Maximum TLS version to allow ### listeners[].proxy.trust Can either be a boolean or a list of IP addresses and subnets to trust as being reverse proxies. If it’s a boolean and it’s set to *true* it will trust all IP-addresses and subnets as being reverse proxies. > ```yaml > listeners: > - proxy: > trust: > - 1.2.3.4 > ... > ``` ### listeners[].proxy.userheader This setting allows for automatic login when behind a reverse proxy. If configured, this header should be set by the reverse proxy and contain the username for the session. > ```yaml > listeners: > - proxy: > userheader: X-Proxy-User > ... > ``` ### listeners[].proxy.groupheader When logging in via reverse proxy. This header is set to assign group permissions for the user. ## Host directives ### hosts[] The web administration must have one or more host directives, which specify which [HTTP/JSON endpoints](https://docs.halon.io/manual/api_http_json.html) to connect to. **Required.** ### hosts[].port Which TCP port to connect to. **Required.** ### hosts[].address Hostname, IPv4 address or IPv6 address to connect to. **Required.** ### hosts[].name The display name. The default is the address. Cannot be combined with the *expand* option. ### hosts[].expand Add all IP addresses for the hostname as unique hosts. The default is *false*. Mutually exclusive with [`hosts[].kubernetes`](#config:confval-hosts-.kubernetes). ### hosts[].kubernetes The Kubernetes settings. Mutually exclusive with [`hosts[].expand`](#config:confval-hosts-.expand). ### hosts[].kubernetes.namespace The namespace for the smtpd *StatefulSet\`*. ### hosts[].kubernetes.name The name for the smtpd *StatefulSet*. ### hosts[].kubernetes.address How to address each pod: *ip* (default, e.g. *10.42.0.12*), *hostname* (e.g. *halon-smtpd-0.halon-smtpd.default*), or *ip-hostname* (e.g. *10-42-0-12.halon-smtpd.default*). DNS names use the pod’s subdomain and namespace. Resolution requires a matching service endpoint record. CoreDNS uses an endpoint’s hostname when set; the dashed IP is a fallback for unnamed endpoints, so the two DNS forms are not interchangeable. ### hosts[].kubernetes.clusterdomain The cluster DNS domain, e.g. *cluster.local*, used by the DNS address modes. A non-empty value appends *.svc.\*; otherwise the resolver must supply that suffix through its DNS search list. ### hosts[].tls.enabled If TLS should be used for the requests. The default is *false*. ### hosts[].tls.verify If the server certificate should be verified. The default is *true*. ### hosts[].tls.verifyname Hostname to verify against the server certificate’s CN and SAN. ### hosts[].secret The secret that will be sent in the requests using the *X-API-Key* header. ### hosts[].processes[] The processes that are running on the host. The default is *smtpd* and *rated*. ### hosts[].timeout The timeout against the node (in seconds). The default is *5*. ### reresolve Automatically re-resolve the hostnames of the hosts every *x* seconds. ## Group directives ### groups[] You can set up groups to easily manage permissions instead of setting them on each user. Groups can also be used when logging in via reverse proxy. ### groups[].name The name of the group **Required** ### groups[].features.preview.enabled If the user should be able to preview messages. The default is *true*. ### groups[].features.readonly If the user should only have readonly access. The default is *false*. ### groups[].features.writable If *group[].features.readonly* is set to *true* you can set an array of commands that the group should be able to execute. ### groups[].features.memory.enabled If the user should be able to view the memory page. The default is *true*. ### groups[].features.rates.enabled If the user should be able to view the rates page. The default is *true*. ### groups[].features.datamasking Configure the group datamasking settings > **Note** > > Enabling `localpart`, `subject`, `retryreason`, or `saslusername` masking also disables [`groups[].features.preview.enabled`](#config:confval-groups-.features.preview.enabled) > **Warning** > > The `localpart`, `subject`, `retryreason`, and `saslusername` settings do not apply for the [history feature](#history). > Use the `history` datamasking setting to hide history source paths in the web administration. > To redact data in the stored history logs, use the `redact` option in the [history-elastic](https://github.com/halon-extras/history-elastic) plugin. ### groups[].features.datamasking.localpart If the *localpart* of a mail should be masked for the user. The default is *false* ### groups[].features.datamasking.subject If the *subject* of a mail should be masked for the user. The default is *false* ### groups[].features.datamasking.retryreason If the *retryreason* of a mail should be masked for the user. The default is *false* ### groups[].features.datamasking.saslusername If the *salusername* of a mail should be masked for the user. The default is *false* ### groups[].features.datamasking.history History source paths to hide and disallow in queries. True masks the path and its descendants. The timestamp and transaction identifier are reserved. Charts that read or filter on masked paths are hidden. The following example uses the [delivery-attempts](#history:history-delivery-attempts) index template: ```yaml datamasking: history: sender: true senderlocalpart: true recipient: true recipientlocalpart: true smtpreasonnormalized: true smtpreason: true ``` ## User directives ### users[] The web administration must have one or more user directives, which specify which users can log in to the web administration. **Required.** ### users[].username The username. **Required.** ### users[].password The password. > **Note** > > The password needs to be encrypted using bcrypt. You can run the following command to generate a password: > > ```console > $ /opt/halon/web/bin/generatepass > ``` ### users[].group The group the user should be assigned to. ### users[].features.preview.enabled If the user should be able to preview messages. The default is *true*. ### users[].features.readonly If the user should only have readonly access. The default is *false*. ### users[].features.writable If *users[].features.readonly* is set to *true* you can set an array of commands that the user should be able to execute. ### users[].features.memory.enabled If the user should be able to view the memory page. The default is *true*. ### users[].features.rates.enabled If the user should be able to view the rates page. The default is *true*. ### users[].features.datamasking Configure the users datamasking settings > **Note** > > Enabling `localpart`, `subject`, `retryreason`, or `saslusername` masking also disables [`users[].features.preview.enabled`](#config:confval-users-.features.preview.enabled) > **Warning** > > The `localpart`, `subject`, `retryreason`, and `saslusername` settings do not apply for the [history feature](#history). > Use the `history` datamasking setting to hide history source paths in the web administration. > To redact data in the stored history logs, use the `redact` option in the [history-elastic](https://github.com/halon-extras/history-elastic) plugin. ### users[].features.datamasking.localpart If the *localpart* of a mail should be masked for the user. The default is *false* ### users[].features.datamasking.subject If the *subject* of a mail should be masked for the user. The default is *false* ### users[].features.datamasking.retryreason If the *retryreason* of a mail should be masked for the user. The default is *false* ### users[].features.datamasking.saslusername If the *salusername* of a mail should be masked for the user. The default is *false* ### users[].features.datamasking.history History source paths to hide and disallow in queries. True masks the path and its descendants. The timestamp and transaction identifier are reserved. Charts that read or filter on masked paths are hidden. The following example uses the [delivery-attempts](#history:history-delivery-attempts) index template: ```yaml datamasking: history: senderlocalpart: true recipientlocalpart: true smtpreason: true smtpreasonnormalized: true ``` ## OIDC directives ### oidc OpenID Connect (OIDC) settings. This is an object with two required fields: `enabled` and `provider`. ### oidc.enabled If OIDC should be enabled. **Required.** ### oidc.provider The OIDC provider configuration object. **Required.** The provider must contain the unique provider ID, discovery URL, client ID and client secret. ### oidc.provider.providerid The unique provider ID. **Required.** ### oidc.provider.discoveryurl The OIDC discovery URL. **Required.** ### oidc.provider.clientid The OIDC client ID. **Required.** ### oidc.provider.clientsecret The OIDC client secret. **Required.** ### oidc.provider.pkce If PKCE should be used. The default is `true`. ### oidc.provider.groupclaim The claim containing the user’s group(s). Values from this claim are matched against configured groups in the YAML config. If this option is set, [`oidc.provider.allowedgroups[]`](#config:confval-oidc.provider.allowedgroups) becomes required. ### oidc.provider.allowedgroups[] List of allowed config group names that OIDC users may belong to. Each entry is a non-empty string. This option is required when [`oidc.provider.groupclaim`](#config:confval-oidc.provider.groupclaim) is set and must not be present otherwise. ### oidc.provider.displayname The display name for the provider. ### oidc.provider.displayicon An icon for the provider. Two alternatives supported: - Inline data + extension: ```yaml displayicon: data: |- iVBORw0KGgoAAAANSUhEUg... extension: .png ``` - Path to file + extension (optional): ```yaml displayicon: path: /opt/halon/web/share/icons/myprovider.svg ``` Supported extensions are `.png` and `.svg`. ## MCP directives A MCP server that provides tools to interact with Halon hosts and their processes. > **Important** > > When [`mcp.enabled`](#config:confval-mcp.enabled) is *true*, every listener must have a [`listeners[].baseurl`](#config:confval-listeners-.baseurl). > > When both MCP and OAuth are enabled, the following requirements also apply: > > * [`database`](#config:confval-database) must be configured. > * [`environment.session.secret`](#config:confval-environment.session.secret) must be configured. > * A custom [`listeners[].basepath`](#config:confval-listeners-.basepath) is not supported. > * Every listener’s [`listeners[].baseurl`](#config:confval-listeners-.baseurl) must use HTTPS, except for loopback hosts: `localhost` or `[::1]`. > > Use [`users[].features.datamasking`](#config:confval-users-.features.datamasking) or [`groups[].features.datamasking`](#config:confval-groups-.features.datamasking) to hide sensitive data from the LLM when using MCP. ### mcp.enabled If the MCP endpoint should be enabled. The default is *false*. The MCP endpoint will be available at `https:///mcp`. ### mcp.oauth.enabled If OAuth should be enabled for the MCP endpoint. The default is *true*. The MCP client inherits the permissions of the user who signed in. > **Warning** > > Disabling OAuth means no authentication is required to access the MCP endpoint. > Only disable it in a trusted environment or when behind an MCP gateway. ### mcp.oauth.accesstoken.expiresin How long an MCP access token is valid (in seconds). Clients refresh it when it expires. The default is *3600*. ### mcp.oauth.refreshtoken.expiresin How long an MCP client stays signed in without being used (in seconds). Each token refresh starts the period again. The default is *2592000*. ## Database directives ### database The database settings ([knex](https://knexjs.org/guide/#configuration-options)) for storing per-user settings. > **Note** > > A SQLite3 example would look like this. In this example make sure the `/var/lib/halon/web` folder is writeable by the > [`environment.privdrop.user`](#config:confval-environment.privdrop.user) or [`environment.privdrop.group`](#config:confval-environment.privdrop.group). > > > ```yaml > > database: > > client: sqlite3 > > connection: > > filename: /var/lib/halon/web/web.sqlite > > ``` ### database.client The included client drivers are *sqlite3*, *pg* and *mysql*. ### database.connection The client driver connection string or object. See [knex manual](https://knexjs.org/guide/#configuration-options) for specifics of each database driver. ## Elasticsearch directives This enables the [history feature](#history) in the web administration. ### elasticsearch The settings for Elasticsearch. ### elasticsearch.index.history The index pattern for the history logs. ### elasticsearch.index.policyd The index pattern for the policyd logs. ### elasticsearch.nodes[] A list of Elasticsearch nodes. ### elasticsearch.nodes[].url The Elasticsearch URL to connect to. ### elasticsearch.auth Specify any credentials for authentication. ### elasticsearch.auth.username The username for basic authentication. ### elasticsearch.auth.password The password for basic authentication. ### elasticsearch.tls TLS settings ([Node.js](https://nodejs.org/api/tls.html)). ## Other directives ### instance The name that will be shown in the document title. ### solution The solution, can be either *engage* or *protect*. ### accounting If accounting logs should be generated. The default is *false*. ### maxmind.geoip.path The directory to MaxMind’s GeoIP database. The default is */var/lib/GeoIP/GeoLite2-Country.mmdb*. ### policyd.port The port for the `policyd` service. ### policyd.address The address for the `policyd` service. ### policyd.tls.enabled If TLS should be used for the requests. The default is *false*. ### policyd.tls.verify If the server certificate should be verified. The default is *true*. ### policyd.secret The secret that will be sent in the requests using the *X-API-Key* header. ### trustedorigins[] A list of trusted origins. This list should only contain domains or wildcard domains (eg. `*.example.com`). ## Environment directives ### environment.privdrop.user The user to run the process as. ### environment.privdrop.group The group to run the process as. > **Tip** > > The `privdrop.user` and `privdrop.group` settings to use will depend on your Linux distribution: > > * For Ubuntu, suitable values are `nobody` and `nogroup` > * For RHEL and related distibutions, the values are `nobody` and `nobody`. ### environment.session.secret > The secret used for encryption, signing, and hashing. > The default is to generate a unique UUID during startup. > **Note** > > The minimum length is 32 characters. ### environment.session.secure > If secure cookies should be used. The default is `true` if [`listeners[].tls.pki`](#config:confval-listeners-.tls.pki) is configured, otherwise *false*. > **Note** > > It’s recommended to set this to *true* when doing SSL termination at a reverse proxy. # History logging To enable history logging there are some steps that need to be completed which are outlined below. ## Install Elasticsearch Elastic has an article on installing Elasticsearch [here](https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html). ## Import an index template Import one of the index templates below ([Delivery attempts]() **or** [Transactions]()) into Elasticsearch. The differences between these index templates are described in each section. ### Delivery attempts This template will log all delivery attempts and the same message may appear multiple times, once for each delivery attempt. For this template you should set the value for `elasticsearch.index` to `halon-delivery-attempts` in the `web.yaml` file. > ```console > curl -k -X PUT -H "Content-Type: application/json" -d @/opt/halon/web/share/history/elasticsearch/delivery-attempts/halon_timeseries_policy.json http://elastic:elastic@127.0.0.1:9200/_ilm/policy/halon-timeseries-policy > curl -k -X PUT -H "Content-Type: application/json" -d @/opt/halon/web/share/history/elasticsearch/delivery-attempts/halon_delivery_attempts.json http://elastic:elastic@127.0.0.1:9200/_index_template/halon-delivery-attempts > ``` ### Transactions This template will log all transactions and update the state for them instead of creating a new log entry after each delivery attempt. For this template you should set the value for `elasticsearch.index` to `halon-transactions-*` in the `web.yaml` file. > ```console > curl -k -X PUT -H "Content-Type: application/json" -d @/opt/halon/web/share/history/elasticsearch/transactions/halon_transactions_policy.json http://elastic:elastic@127.0.0.1:9200/_ilm/policy/halon-transactions-policy > curl -k -X PUT -H "Content-Type: application/json" -d @/opt/halon/web/share/history/elasticsearch/transactions/halon_transactions.json http://elastic:elastic@127.0.0.1:9200/_index_template/halon-transactions > ``` ## Add configuration The [history feature](#history) **requires** an additional configuration file. This configuration file is used to define fields in Elasticsearch and how they should be rendered. *halon-web* loads the non-reloadable configuration from `/etc/halon/web-history.yaml`. It is described by, and can be validated with, the [web-history.schema.json](http://lbovet.github.io/docson/index.html#https://docs.halon.io/json-schemas/web/1.32-stable/web-history.schema.json) JSON schema. The default startup configuration file in `/opt/halon/web/share` can normally be used as a base (only choose one of them): The following configuration is based on the Elasticsearch index template called **halon-delivery-attempts**: ```console # cp /opt/halon/web/share/history/delivery-attempts.yaml /etc/halon/web-history.yaml ``` The following configuration is based on the Elasticsearch index template called **halon-transactions**: ```console # cp /opt/halon/web/share/history/transactions.yaml /etc/halon/web-history.yaml ``` Use the [`elasticsearch`](#config:confval-elasticsearch) directives to enable history logging in the web administration. Sample *web.yaml* config using the [Delivery attempts]() template: ```yaml elasticsearch: index: 'halon-delivery-attempts' nodes: - url: http://127.0.0.1:9200 auth: username: elastic password: elastic tls: rejectUnauthorized: false ``` ## History datamasking To hide history source paths and disallow them in queries for specific users or groups, use [`users[].features.datamasking.history`](#config:confval-users-.features.datamasking.history) or [`groups[].features.datamasking.history`](#config:confval-groups-.features.datamasking.history). ## Start sending data To start sending data to Elasticsearch from the *smtpd* process using [HSL](https://docs.halon.io/hsl/) you can use the [history-elastic](https://github.com/halon-extras/history-elastic) plugin (supports both index templates). # Tips on usage ## Saving views persistently By default, saved views are stored in browser local storage, meaning they exist only in your current browser on your current device. They do not sync between browsers or devices. To make saved views available across different browsers or devices, configure the [Database directives](#config:database-directives) so the views are stored on the server instead. Note that they are specific to the user that created them. ### Sharing views with other users You can share views with other users. Under Views / Manage Views, select the arrow button. Confirm your choice. ![image](_images/web-share-view.png) Views can be “unshared” afterwards in the same way. ## Display of hostnames In the Overview screen and also in tabbed views, the interface presents the `hostname` from the operating system of each instance. ![image](_images/web-hostnames.png) If no hostname is set, the IP address is shown. You can change this behavior by setting the [`hosts[].name`](#config:confval-hosts-.name) property. This helps when working with clusters of many instances, or with long hostnames. For example, the above system could be presented as: ![image](_images/web-shortnames.png) ## !Env - using environment variables Key / value pairs can be injected into environment variables which can then be used in the YAML config file. The `!Env` functionality is not enabled by default so needs to be set when the process is started. For example, for Docker, the web image file needs to change to include the configuration setting ```console CMD [ "/opt/halon/node/bin/node", "/opt/halon/web/dist/bin/server.js", "--config-env-substitution" ] ``` Variables can then be used in configuration files as per this example ```yaml users: - username: admin password: !Env ${HALON_PASSWORD_WEB} ``` The config can include a default value that would be used if the environment variable is empty. For example ```yaml username: !Env ${HALON_USERNAME_WEB:admin} ``` Any fields can be set using variables, but since fields environment variables are set as strings, they need to be cast if the values are intended to not to be strings (eg booleans and numbers). For instance, to set the port number would need this syntax (showing port 2525 as the default value). ```yaml port: !Env tag:yaml.org,2002:int ${PORT:2525} ``` Options for different cast values are at [yaml.org](https://yaml.org/spec/1.2.1/#id2803231). NB passwords for web UI users still need to be encrypted with bcrypt before they are passed to the variable. Environment variables are set when containers are launched. For example in the [Kubernetes documentation](https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data). # Changelog ## 1.32.1 Released 2026-11-13 - **Fix** Performance improvements on IP warmup page - **Fix** Clearer errors during config file validation - **Pkg** Updated third-party packages ## 1.32.0 Released 2026-10-26 - **Imp** Add MCP server ([`mcp.enabled`](#config:confval-mcp.enabled)) - **Imp** Add history datamasking for users and groups ([`users[].features.datamasking.history`](#config:confval-users-.features.datamasking.history) and [`groups[].features.datamasking.history`](#config:confval-groups-.features.datamasking.history)) - **Imp** Accounting now also covers history and warmup ([`accounting`](#config:confval-accounting)) - **Imp** `web-history.yaml` syntax is now validated on startup - **Bug** Fix crash when grouping queue distribution by metadata - **Bug** Fix field types in history configs to match the Elasticsearch mappings - **Bug** Fix so that partial and regex history filters match whole metadata values - **Pkg** Updated third-party packages ## 1.31.1 Released 2026-10-09 - **Bug** Various bug fixes - **Pkg** Updated third-party packages ## 1.31.0 Released 2026-09-28 - **Imp** Support using pod hostname instead of IP in Kubernetes ([`hosts[].kubernetes.address`](#config:confval-hosts-.kubernetes.address) and [`hosts[].kubernetes.clusterdomain`](#config:confval-hosts-.kubernetes.clusterdomain)) - **Imp** Add optional public base URL setting ([`listeners[].baseurl`](#config:confval-listeners-.baseurl)) - **Pkg** Updated third-party packages ## 1.30.0 Released 2026-09-08 - **Imp** Support proxy env variables like `HTTP_PROXY` and `HTTPS_PROXY` - **Imp** Add support for custom basepath ([`listeners[].basepath`](#config:confval-listeners-.basepath)) - **Bug** Fix metadata search on history page - **Pkg** Updated third-party packages > **Important** > > > Routing method has changed so permalinks you have saved need to be updated. > > > **Warning** > > > > This version bumps the minimum required version of the `halon` and `halon-api` packages to `6.11`. ## 1.29.1 Released 2026-06-23 - **Bug** Fix issue with “Unsupported version” error on queue messages and queue distribution pages ## 1.29.0 Released 2026-06-18 - **Imp** Add casesensitive option for fields in `web-history.yaml` configuration - **Imp** Add explicit secure cookies setting - **Bug** Fix issue with resizing of custom components on dashboard page - **Bug** Fix issue when deleting table components on dashboard page - **Pkg** Updated third-party dependencies ## 1.28.0 Released 2026-05-25 - **Imp** Add alphabetical sorting for metadata on preview page - **Imp** Add health status on overview page - **Imp** Add tooltip that show exact duration for the next retry attempt on messages page - **Imp** Add button to copy IP warmup schedule to clipboard - **Imp** Add button to download CSV for tables on delivery insights and IP warmup pages - **Pkg** Updated third-party dependencies ## 1.27.0 Released 2026-02-22 - **Imp** Add new page to view resolver queue - **Imp** Add `verifyname` TLS setting for hosts - **Imp** Use OpenSSL’s default trusted CA store instead of bundled CA certificates - **Bug** Fix bug with selecting hosts on resolver page - **Pkg** Updated third-party dependencies ## 1.26.0 Released 2026-01-30 - **Imp** Support using Kubernetes API to lookup smtpd hosts - **Imp** Accessibility improvements - **Bug** Fix bug with stale hosts and config cache when using resresolve setting - **Pkg** Updated third-party dependencies > **Warning** > > The minimum length of [`environment.session.secret`](#config:confval-environment.session.secret) is now 32 characters. ## 1.25.0 Released 2025-12-04 - **Imp** Support env substitutions in YAML config files - **Imp** Accessibility improvements - **Bug** Fix issue with version information - **Bug** Improved error handling for process stats endpoint if smtpd is down during startup ## 1.24.0 Released 2025-10-29 - **Imp** Added support for [`oidc`](#config:confval-oidc) (OpenID Connect) - **Imp** Various accessibility improvements on all pages - **Imp** Added ability to export email history as CSV from queue messages page - **Imp** Added more TLS options for HTTPS listeners such as [`listeners[].tls.ciphers`](#config:confval-listeners-.tls.ciphers) and [`listeners[].tls.protocols.min`](#config:confval-listeners-.tls.protocols.min) - **Imp** Make session secret configurable using [`environment.session.secret`](#config:confval-environment.session.secret) (Useful when clustering the web administration) - **Imp** Added support for static policies, server side paging and filtering based on source on queue policies page - **Imp** Show suspended backoff queues on top queues page - **Imp** Usability improvements to IP warmup page - **Dep** Access to raw `smtpd` configuration was removed - **Bug** Fixed rare data padding issue with charts on delivery insights page - **Sec** Updated third-party dependencies > **Warning** > > If you are using multiple hostnames to access the web interface and have trouble logging in it might now be necessary for you to add these hostnames to [`trustedorigins[]`](#config:confval-trustedorigins). > **Warning** > > This version bumps the minimum required version of the `halon` and `halon-api` packages to `6.9`. > **Note** > > Changes to config schema for config version `1.24` > : * `listeners[].pki` should now be configured under `listeners[].tls.pki` instead > * `users[].features.configuration` and `groups[].features.configuration` no longer exists since accessing the raw `smtpd` configuration was removed ## 1.23.1 Released 2026-10-30 - **Bug** Various bug fixes - **Pkg** Updated third-party packages ## 1.23.0 Released 2025-07-04 - **Imp** Integrate with *Delivery Guru - Warmup* component - **Bug** Only atttempt to change permissions of session path if not using database sessions - **Bug** Fix issue with `sqlite3` dependency and Rocky Linux 8 / Ubuntu 22.04 ## 1.22.0 Released 2025-06-25 - **Imp** Added support to show country flags for remote IP (GeoIP) - **Imp** Add support for storing sessions in the database - **Imp** Add page to show running resolver requests on DNS resolver page - **Imp** Added DSN columns for table on messages page - **Imp** Show suspensions triggered by backoff on active backoffs and delivery insights pages - **Imp** Bump bundled Node version - **Bug** Improved navigation behaviour when using the back button - **Bug** Fields selector in inputs did not always show available field combinations - **Bug** Style fixes in dark mode - **Bug** Refresh on pages caused tables to resize > **Warning** > > This version bumps the minimum required version of the `halon` and `halon-api` packages to `6.7`. ## 1.21.0 Released 2025-04-04 - **Imp** Add support for background jobs for queue actions - **Imp** Pre-select field combination on delivery insights page when coming from backoff, top queues or policies pages - **Imp** Show transaction ID and queue ID on message preview page - **Bug** Fix bug with delta value when changing views, interval or filter on reporting page - **Bug** Fix bug where filter was still applied when changing back to default view after saving a new view with a filter - **Bug** Fix rounding errors in queue breakdown on delivery insights page ## 1.20.0 Released 2025-03-26 - **Imp** Reworked delivery insights page as well as added new pages for top queues and active backoffs - **Imp** Added navigation from “History > Reporting” page to “History -> Messages” page with applied filter and time interval - **Imp** Added autocomplete for lists on all supported inputs - **Bug** Fixed bug where saving a new view as favorite caused other favorite views to be unset - **Bug** Fixed bug where save indicator was not showing up on “Save as New…” in views dropdown > **Warning** > > This version bumps the minimum required version of the `halon` and `halon-api` packages to `6.6`. > This release is the last feature release supporting CentOS 7. ## 1.19.0 Released 2025-02-07 - **Imp** In-memory historical graphs on dashboard page - **Imp** Zoomable area charts on history reporting page - **Imp** Support refilling active queue policy rates by deleting their corresponding suspension - **Imp** More search options in omni-search input - **Imp** Validate YAML configuration on startup - **Bug** Fix issue where filters and time interval were not stored in views on history and reporting pages - **Sec** Upgraded bundled Node to 22.13.1 ## 1.18.1 Released 2025-01-09 - **Bug** Fixed issue on policy page when using static policies with *null* values - **Bug** The process could sometimes hang during graceful shutdown ## 1.18.0 Released 2024-12-16 - **Imp** Support new cluster features for queue policies - **Imp** Support new connect interval feature for queue policies - **Imp** New powerful input type with autocomplete for values coming from the configuration - **Imp** Allow custom views to be shared between users - **Imp** Export data in tables as CSV files - **Imp** Add Navigation links to overview components - **Imp** Omni-search input now supports history pages as well - **Imp** Add “On all hosts” checkbox to filter actions on queue messages page - **Imp** “On all hosts” is now the default setting for most form modals - **Imp** Support filtering on seconds for queue messages and queue policies pages - **Imp** Include milliseconds when displaying durations - **Imp** “Add multiple” and “Edit -> Add as new” options on queue policies page - **Imp** Various styling and navigation improvements - **Bug** Selected host is now preserved when navigating to the history pages - **Bug** Fix bug with adding custom columns on overview page - **Bug** Fix bug where default settings for users were overriding configured group settings > **Warning** > > This version bumps the minimum required version of the `halon` and `halon-api` packages to `6.5`. ## 1.17.1 Released 2024-10-04 - **Bug** Fixed issue where new filters added on the messages/statistics pages could get cleared before submitting the form - **Bug** Policy matching did not work on the delivery insights page if no local IP was entered - **Bug** Connection matching did not work on the delivery insights page if no local IP was entered - **Bug** Average delivery time showed incorrect values on reporting page ## 1.17.0 Released 2024-08-26 - **Imp** Add support for group-based permissions ([`groups[]`](#config:confval-groups), [`users[].group`](#config:confval-users-.group) and [`listeners[].proxy.groupheader`](#config:confval-listeners-.proxy.groupheader)) - **Imp** Add support for per-command readonly settings ([`users[].features.writable`](#config:confval-users-.features.writable) and `groups[].features.writeable`) - **Imp** You can now navigate directly to the delivery insights page via the sidebar - **Imp** Delivery insights links from suspends and policies pages - **Imp** Support viewing, adding and updating properties for suspends and policies - **Imp** Support filtering outbound connections based on state - **Imp** Support filtering policies based on source - **Imp** Support filtering suspends based on source - **Imp** Allow adding/editing policies without any fields (global policies) - **Imp** Preserve fields when going to distribution page from policies page - **Imp** More graceful shutdown of process than before - **Bug** Fixed bug where column sizes did not reset when changing views on suspension page - **Bug** Fixed visual bug in list modals when using Chrome - **Bug** Fixed issue where auto refresh could cause you to loose the selected view on the overview page - **Sec** Upgraded bundled Node to 18.20.4 ## 1.16.0 Released 2024-06-20 - **Imp** Support new tenantid policy field > **Warning** > > This version bumps the minimum required version of the `halon` and `halon-api` packages to `6.3`. ## 1.15.0 Released 2024-06-10 - **Imp** Added damasking settings for users to hide sensitive information ([`users[].features.datamasking`](#config:confval-users-.features.datamasking)) - **Imp** Added read-only setting for users ([`users[].features.readonly`](#config:confval-users-.features.readonly)) - **Imp** Added settings to control visibility of rate limiting and memory pages for users ([`users[].features.rates.enabled`](#config:confval-users-.features.rates.enabled) and [`users[].features.memory.enabled`](#config:confval-users-.features.memory.enabled)) - **Imp** Added links to distribution page for entries on suspend and policies pages (with filter applied) - **Imp** Added indicator for if you have changed a custom view but not saved it yet - **Bug** Fixed issue where you couldn’t select individual connection on queue connections page ## 1.14.0 Released 2024-04-29 > **Warning** > > The path for the binary has changed to `/opt/halon/web/dist/bin/server.js`. - **Imp** Added bounce ratio as well as more graphs for existing metrics to history reporting page - **Imp** Added support for filtering on suspended messages as well as using them as group by on on queue distribution page - **Sec** Upgraded bundled Node to 18.20.2 - **Bug** Fix issue with bulk actions and accounting that prevented actions from executing - **Bug** Fixed issue with using states as custom counters on queue distribution page - **Bug** Fixed issue where table columns for checkboxes and icons were too wide on larger browser windows - **Bug** Fixed issue where file viewer did not use a monospace font ## 1.13.0 Released 2024-02-26 - **Imp** Support `remotemx` and `grouping` pooling policies on delivery insights page - **Imp** Host selector on overview page - **Bug** Fix issue with browser history navigation after changing views ## 1.12.0 Released 2024-01-26 - **Imp** Built-in [email history and reporting](#history) - **Imp** Access delivery insights from queue distribution page - **Imp** Bundle Node 18.18.2 LTS ## 1.11.0 Released 2023-12-14 - **Imp** Allow updating jobid for messages in queue - **Imp** Delete dynamic suspensions and dynamic policies based on a filter - **Imp** Add remotemx to filter modal for queue connections - **Imp** Resizable table columns - **Imp** Show license status - **Imp** Various style tweaks ## 1.10.1 Released 2023-10-26 - **Bug** Fix lowest rate calculation on delivery insights page ## 1.10.0 Released 2023-10-24 - **Imp** Support using database instead of local storage for views ([`database`](#config:confval-database)) - **Imp** Create custom counters on distribution page - **Imp** Included SBOM files (`/opt/halon/web/share/sbom`) - **Bug** Fix bug with previewing email body - **Bug** Fix sorting on distribution page ## 1.9.0 Released 2023-10-09 - **Imp** Create custom distribution components for use on overview page - **Imp** Configurable settings file path using ENV variable (`HALON_WEB_SETTINGS_FILE`) - **Imp** Configurable instance name ([`instance`](#config:confval-instance)) - **Imp** Configurable Accounting logs ([`accounting`](#config:confval-accounting)) - **Imp** Bundle Node 18.18.0 LTS - **Imp** Add top Job IDs view to distribution page - **Bug** Fix favicon in Safari - **Bug** Fix bug with summary when using multiple groupby fields on distribution page - **Bug** Fix refresh bug with delta functionality on distribution page ## 1.8.0 Released 2023-08-23 - **Imp** Customizable dashboard - **Imp** Add support for grouping field on queue “Connections” page - **Imp** Improvements to metadata filters on queue “Messages” and “Distribution” pages ## 1.7.1 Released 2023-07-16 - **Bug** Allow setting “Filter all” without conditions - **Bug** Fix duplicate XHR requests on “Messages” page ## 1.7.0 Released 2023-07-12 - **Imp** Bundle Node 16.20.0 LTS - **Imp** “Filter all” option & various request changes - **Imp** Distribution summary - **Imp** Add name setting for hosts - **Imp** Always show delta on overview - **Imp** Add support for reverse proxies - **Imp** Add support for automatic login when behind a reverse proxy - **Imp** Various style changes ## 1.6.0 Released 2023-04-25 - **Imp** Solution branding - **Imp** Dark mode ## 1.5.1 Released 2023-04-11 - **Bug** Fix exception with version property in HelpModal component ## 1.5.0 Released 2023-04-11 - **Imp** Added Remote MX to “Queue > Connections” page - **Imp** Make host timeout configurable - **Imp** Home views and improvements - **Imp** Added selection/filtered count messages on every relevant page - **Imp** Various style changes ## 1.4.1 Released 2023-01-4 - **Bug** Fix bug with “On filter” actions on “Messages” page ## 1.4.0 Released 2022-11-14 - **Imp** Improve searching of messages in multi-host clusters - **Imp** Bulk download of messages (as ZIP) - **Imp** Keep selection of items during table refresh on various pages - **Bug** Logout on 401 errors ## 1.3.1 Released 2022-10-18 - **Bug** Don’t generate build_id links - **Bug** Spinner was always shown when the queue was empty ## 1.3.0 Released 2022-10-12 - **Imp** Redesign UI to match new branding profile - **Imp** Added delivery insights UI - **Imp** Added auto refresh on more pages (and also calcuate rates/deltas) - **Imp** Added queue connections page - **Imp** …and many more improvements ## 1.2.0 Released 2022-05-07 - **Imp** New TLS verify setting for hosts to allow for disabling certificate validation - **Imp** Support setting DSN status and diagnostic code when bouncing messages - **Imp** Support using regex when filtering based on strings - **Imp** Support for showing and updating priorities for messages ## 1.1.0 Released 2022-01-17 - **Imp** Message preview - **Bug** Limit the max number of stored notifications - **Bug** Use latest docs in links ## 1.0.0 Released 2021-12-29 First release