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
values.yaml
files
Single vs multiple 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:
uiSettingFiles:
/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.definitions
section 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-meta
ConfigMap
and is mounted at/injections/etc/meta/meta
asConfig:
becomesappsuite-as-config
ConfigMap
and is mounted at/injections/etc/etc-properties
contextSets:
becomesappsuite-context-sets
ConfigMap
and is mounted at/injections/etc/context-sets/contextSets
yamlFiles:
,secretYAMLFiles:
becomeappsuite-yaml-files
orappsuite-yaml-secrets
ConfigMap
andSecret
and is mounted at/injections/etc/yaml
and/injections/etc/secretYaml
etcFiles:
,secretETCFiles:
becomeetc-files
oretc-secrets
ConfigMap
andSecret
and is mounted at/injections/etc/etc
and/injections/etc/secretEtc
etcBinaries:
,secretETCBinaries:
become individualConfigMaps
orSecrets
calledappsuite-[NAME]-etc-binary
which are also mounted at/injections/etc/etc
and/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.19/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