Configuration
This file should explain the various App Suite 8 configuration types and how they are represented in the values.yaml files. It should help with transferring legacy App Suite 7 settings into App Suite 8 as well.
Note: the entire configuration mechanism is to be understood as a temporary vehicle in our initial kubernetes implementation for App Suite. We are working on a re-implementation of the entire configuration mechanism.
Overview
The entire configuration happens, as usual, via values.yaml files, given as paramter to the helm install call on the App Suite Helm Chart.
helm install as8 oci://registry.open-xchange.com/appsuite/charts/appsuite --values values.yaml
Single vs multiple values.yaml files
As usual with Helm Charts, it is possible to specify multiple values.yaml files on one helm install command line. helm will then merge the contents on helm install.
While this can be helpful in special situations, in general we do not recommend to split up the values functionally; it reduces readability and is a potential source of errors.
There is one execption, though: It is considered best practices to manage secret settings in a separate file, while keeping the other settings in the main values.yaml file. The values.secret.yaml file can then be managed by appropriate means of version control and deployment automation.
helm install as8 oci://registry.open-xchange.com/appsuite/charts/appsuite --values values.yaml --values values.secret.yaml
YAML High Level Structure
The Core App Suite Stack Chart oci://registry.open-xchange.com/appsuite/charts/appsuite and similar charts expect a values.yaml structure which looks, from high level, as follows:
global:
# global settings here
core-mw:
# core-mw settings here
core-ui:
# core-ui settings here
core-ui-middleware:
# core-ui-middleware settings here
istio:
# istio settings here
There are charts which contain the Stack Chart and deploy it alongside other chars. This includes on the one hand the App Suite Pro chart, Charts for customized versions of App Suite, and also the (open source) Public Sector chart oci://registry.open-xchange.com/appsuite-public-sector/charts/appsuite-public-sector.
Following the structure of the chart itself, these umbrella or meta charts expect a values.yaml structure as follows:
global:
# global settings here
appsuite:
core-mw:
# core-mw settings here
core-ui:
# core-ui settings here
core-ui-middleware:
# core-ui-middleware settings here
istio:
# istio settings here
a-custom-ui:
# settings for a-custom-ui component here
another-custom-ui:
# settings for another-custom-ui component here
Note how the stack chart settings become attached to a top level appsuite: entry, and additional components get configured alongside of it. The global: section remains a top-level section.
Depending on which kind of chart you employ, you need to adjust your values.yaml structure accordingly. If in doubt, consult the helm show values command.
$ helm show values helm show values oci://registry.open-xchange.com/appsuite/charts/appsuite --version ...
# match the output against the structures shown above
Middleware Properties
Middleware properties like com.openexchange.some.property can be set in the properties object:
core-mw:
properties:
com.openexchange.mail.loginSource: "mail"
com.openexchange.mail.mailServerSource: "global"
Secret properties get their own object. These are stored in kubernetes secrets as opposed to configmaps for regular properties. This works the same way for any of the other secret variants later in this document.
core-mw:
secretProperties:
com.openexchange.push.credstorage.passcrypt: "8297f949a39d49618ed957e6cfead030"
The system tries to find the properties file that contains the setting and overrides it. If it can't find such a file, it adds the setting to a generic new additional.properties file, which is home for all such settings.
Most of the settings work regardless of the file they are specified in. Some (legacy) settings however require to be defined in exactly the right file. (Most of these can be identified by looking like SHELL_ENVIRONMENT_VARIABLE variables.)
If you need to force a property to wind up in a certain .properties file, you can use the propertiesFiles or secretPropertiesFiles objects:
core-mw:
propertiesFiles:
/opt/open-xchange/etc/server.properties:
MAX_UPLOAD_SIZE: "92233720368000"
com.openexchange.tools.images.transformations.maxResolution: "30087962"
secretPropertiesFiles:
/opt/open-xchange/etc/mail.properties:
com.openexchange.mail.someSecret: "some secret value"
The property is then overwritten or added to the file referred to in the parent object.
UI Settings
UI settings that are delivered via the JSLob interface live in the .properties files in /opt/open-xchange/etc/settings. These properties can be set using the uiSettings or secretUISettings objects:
core-mw:
uiSettings:
io.ox/mail//dumpster/folder: "default0/DUMPSTER"
io.ox/core//apps/quickLaunchCount: "5"
secretUISettings:
io.ox/core//mySecretName: "Rumpelstilskin"
This again tries to guess the proper .properties file or adds a new one. Similarly to above, you can also force a specific file to be used:
core-mw:
uiSettingsFiles:
/opt/open-xchange/etc/settings/dumpster.properties:
io.ox/mail//dumpster/folder: "default0/DUMPSTER"
secretUISettingsFiles:
/opt/open-xchange/etc/settings/hushush.properties:
io.ox/core//mySecretName: "Rumpelstilskin"
Note though, that these MUST still be placed in /opt/open-xchange/etc/settings/ for the middleware to pick them up.
Meta
The settings that usually live under /opt/open-xchange/etc/meta, like protecting and unprotecting UI properties or aliasing a middleware property to a UI property can be set in a single meta object:
core-mw:
meta:
io.ox/core//design:
protected: true
io.ox/core//someProp:
protected: false
io.ox/core//apps/quickLaunchCount:
protected: false
This winds up as a sinlge .yaml file in the meta directory. If you need to structure these settings, do so with comments in the yaml file.
ContextSets
ContextSets that selectively override settings based on a label on a context are configured in files under /opt/open-xchange/etc/contextSets. To do so in helm, use the contextSets object. This also works as a secretContextSets object.
core-mw:
contextSets:
brand.com:
withTags: brand.com
com.openexchange.sessiond.maxSession: 10
secretContextSets:
brand.com:
withTags: brand.com
com.openexchange.secret: 123abc
as-config.yaml
Certain Properties are handled by /opt/open-xchange/etc/as-config.yml. Just add the yaml you need to the asConfig object:
core-mw:
asConfig:
default:
host: all
myhost:
host: myexchange.myhost.mytld
someConfig: some overriding value
Other YAML Files
You can also specify any other YAML files as-is in either the regular or secret variants. These are added to /opt/open-xchange/etc/:
core-mw:
yamlFiles:
client-onboarding-scenarios.yml:
mailmanual:
# Disbled by default
enabled: true
type: manual
providers: [mail]
alternatives: []
# The comma-separated Font Awesome names
icon: fa-envelope-o
# The translatable display name
displayName_t10e: "eMail"
# The translatable description
description_t10e: "To manually setup your Mail account, please use the following information"
secretYAMLFiles:
globaldb.yml:
default:
groups: [default]
id: 4
Other Files
Text Files
You can also place arbitrary files in /opt/open-xchange/etc/:
core-mw:
etcFiles:
importerExporter.xml: |-
<beans>
<bean id="importerExporter" class="com.openexchange.groupware.importexport.ImporterExporter">
<property name="importers">
<list>
<ref bean="iCalImporter" />
<ref bean="vCardImporter" />
</list>
</property>
<property name="exporters">
<list>
<ref bean="iCalExporter" />
<ref bean="vCardExporter" />
<ref bean="csvContactExporter" />
</list>
</property>
</bean>
<bean id="iCalImporter" class="com.openexchange.groupware.importexport.importers.ICalImporter" />
<bean id="vCardImporter" class="com.openexchange.groupware.importexport.importers.VCardImporter" />
<bean id="iCalExporter" class="com.openexchange.groupware.importexport.exporters.ICalExporter" />
<bean id="vCardExporter" class="com.openexchange.groupware.importexport.exporters.VCardExporter" />
<bean id="csvContactExporter" class="com.openexchange.groupware.importexport.exporters.CSVContactExporter" />
</beans>
secretETCFiles:
tokenlogin-secrets: |-
public-ox-redeem-secret-1337
Binary Files
To add binary files to /opt/open-xchange/etc you need to base64encode their content and put them in the etcBinaries or secretETCBinaries data structure like so:
core-mw:
etcBinaries:
- name: binary1
filename: something.bin
b64Content: <base 64 encoded file content>
secretETCBinaries:
- name: binary2
filename: something-secret.bin
b64Content: <base 64 encoded file content>
These are each put into individual secrets and configmaps, whose respective sizes cannot exceed 1MiB.
Bundle Activation
In the AppSuite 7 days some features would be toggled on or off depending on whether a certain package was installed on the system. Nowadays the appsuite middleware image contains all bundles, but which ones are actually active can be controlled in a variety of ways. We organize bundles into packages and packages into features. Multiple bundles make up a package, multiple packages make up a feature.
To enable a feature, do the following:
core-mw:
features:
status:
plugins: enabled
cloudPlugins: enabled
reseller: enabled
To know which packages are part of the mentioned features, take a look at the values file of the appsuite middleware chart. Here you can see the features.definitionssection that defines a feature:
features:
definitions:
reseller:
- open-xchange-admin-reseller
- open-xchange-admin-soap-reseller
Which means, that the feature reseller consists of the packages open-xchange-admin-reseller and open-xchange-admin-soap-reseller. In that values file you can also see the default activation state for all the packages that we have assembled into features. You can also enable individual packages like so:
core-mw:
packages:
status:
open-xchange-sso: enabled
open-xchange-hostname-config-cascade: enabled
open-xchange-hostname-bla: disabled
By default a package will be enabled unless disabled in either the appsuite middleware's values file as a package or as a member or a disabled feature. You can also see the list of packages disabled by default in the values file of the appsuite middleware chart.
To find out which bundle is part of a package is a little more involved. You don't need this information but in very special cases. It is possible in principle by one of the following means:
- investigating in a running middleware container, via
kubectl exec, as long as it is still possible, orkubectl debug - spinning up a container locally (hint:
podman run -it ... --entrypoint bash). - pulling the middleware image and extracting locally
Regardless the means you use to access the filesystem: The metadata used to determine which bundles to switch on can be found at /opt/open-xchange/osgi/bundle.d
cd /opt/open-xchange/osgi/bundle.d
ls
The directories here correspond to the packages the files inside the directories correspond to individual bundles:
cd open-xchange-admin-reseller/
ls -l
-rw-r--r-- 1 open-xchange open-xchange 68 May 5 07:55 com.openexchange.admin.reseller.ini
-rw-r--r-- 1 open-xchange open-xchange 72 May 5 07:55 com.openexchange.admin.reseller.rmi.ini
-rw-r--r-- 1 open-xchange open-xchange 77 May 5 07:55 com.openexchange.config.cascade.reseller.ini
-rw-r--r-- 1 open-xchange open-xchange 67 May 5 07:58 com.openexchange.reseller.impl.ini
So the open-xchange-admin-reseller packages consists of the bundles com.openexchange.admin.reseller, com.openexchange.admin.reseller.rmi, com.openexchange.config.cascade.reseller and com.openexchange.reseller.impl. If, conversely, you'd like to know which package contains a bundle, use e.g. find:
cd /opt/open-xchange/osgi/bundle.d
find . -name "com.openexchange.reseller.impl.ini"
./open-xchange-admin-reseller/com.openexchange.reseller.impl.ini
which tells you the bundle will be part of open-xchange-admin-reseller.
Deep Dive: How are settings applied to the containers?
All the settings mentioned above find their way into ConfigMaps or Secrets.
Properties
Properties are set using the ox_props command line tool. This tool takes as input a yaml file that looks something like this:
anywhere:
com.openexchange.some.property: Some Value
/opt/open-xchange/etc/settings/theme.properties:
io.ox/core/theme: light
and applies it using either a heuristic to find the file that contains a property (everything below anywhere) or adds the property to a newly created file or uses the file specified. These YAML files are created with input from either the properties or propertiesFiles settings (and created as a ConfigMap) or the secretProperties and secretPropertiesFiles and rendered as a Secret with the appsuite-properties respectively. UI Settings wind up in a ConfigMap or Secret called appsuite-ui-settings. The AppSuite Pods mount these files at /injections/configuration/properties/ and /injections/configuration/ui-settings/ and the entrypoint.sh startup script copies them to /configuartion where the ox_props tool expects to find them. ox_props also uses the go templating engine (similar to how Helm renders its files) prior to parsing the resulting YAML.
Text and binary files below /opt/open-xchange/etc/
All the other settings are likewise stored in either ConfigMaps or Secrets:
meta:becomesappsuite-metaConfigMapand is mounted at/injections/etc/meta/metaasConfig:becomesappsuite-as-configConfigMapand is mounted at/injections/etc/etc-propertiescontextSets:becomesappsuite-context-setsConfigMapand is mounted at/injections/etc/context-sets/contextSetsyamlFiles:,secretYAMLFiles:becomeappsuite-yaml-filesorappsuite-yaml-secretsConfigMapandSecretand is mounted at/injections/etc/yamland/injections/etc/secretYamletcFiles:,secretETCFiles:becomeetc-filesoretc-secretsConfigMapandSecretand is mounted at/injections/etc/etcand/injections/etc/secretEtcetcBinaries:,secretETCBinaries:become individualConfigMapsorSecretscalledappsuite-[NAME]-etc-binarywhich are also mounted at/injections/etc/etcand/injections/etc/secretEtc/like text files above.
These are all copied to /opt/open-xchange/etc by the entrypoint script.
Entrypoint Startup Script
If you want to see the details of what happens before appsuite starts up, see the startup script here: https://gitlab.open-xchange.com/oss/appsuite/core/middleware/-/blob/stable-8.43/docker/entrypoint.sh
Advanced Options
AppSuite Container Hooks
In case the above system misses a feature, we can also configure bash scripts to run at certain points during startup. We can run either at the start, right before the ox_props tool applies the settings stored at /configuration/ in the YAML files, or right before the appsuite process is started:
core-mw:
hooks:
start:
welcome_to_the_machine.sh: |
#! /bin/bash
echo "WELCOME TO THE MACHINE"
beforeApply: {}
beforeAppsuiteStart: {}
And we can also call the ox_props tool in these scripts to generate or set specific properties:
core-mw:
hooks:
start: {}
beforeApply: {}
beforeAppsuiteStart:
welcome_to_the_machine.sh: |
#! /bin/bash
for ((i=20;i<=100;i++));
do
ox_props set --file /opt/open-xchange/etc/scality-filestores.properties --property com.openexchange.filestore.sproxyd.${filestoreId}.baseUrl=http://scality-store/${filestoreId}
done
Extra Mounts
We can also mount our own ConfigMaps with as extra mounts into the container by using extraMounts and extraVolumes
core-mw:
extraMounts:
- mountPath: /filestore
name: filestore
extraVolumes:
- name: filestore
nfs:
server: nfs-server
path: /export/filestore
readOnly: false
Extra Mounts with go templated configuration yaml files
TODO: Example