Chapter 7. Configuration
Prev | Part I. Tigase Administration Guide | Next

## Chapter 7. Configuration

When the user tries to setup the client for the first time he comes across 2 configuration files: `tigase.conf` and `config.tdsl` in the `/etc` folder. Here is a brief explanation what all those files are about and in other sections you can learn all the details needed to configure the server.

1. config.tdsl file is a simple text file with server parameters in form: key = value. When the XML configuration file is missing the Tigase server reads `config.tdsl` file and uses parameters found there as defaults for generation of the XML file. Therefore if you change the `config.tdsl` file you normally have to stop the server, remove the XML file and start the server again. All the settings from the `config.tdsl` are read and applied to the XML configuration. The properties file is easy to read and very safe to modify. At the moment this is the recommended way change the server configuration.
2. tigase.conf is the Tigase server startup configuration. It is actually not used by the server itself. It rather contains operating system settings and environment parameters to correctly run the Java Virtual Machine. It is only useful on the unix-like systems with Bash shell. If you run the server on MS Windows systems `tigase.bat` and `wrapper.conf` files are used instead. The `tigase.conf` file is read and loaded by the `scripts/tigase.sh` shell script which also scans the operating system environment for Java VM and other tools needed.

## DSL file format

In previous Tigase XMPP Server releases configuration was stored in properties based configuration file. From Tigase XMPP Server 8.0.0 release it will be required to use new DSL based configuration file format. This file format was inspired by Groovy language syntax and new core feature of Tigase XMPP Server - Tigase Kernel Framework.

### Why new format?

In properties configuration format each line contained key and value with optional definition of type of stored value:

    c2s/ports[i]=5222,5223

where `c2s/ports` was name of property, `[i]` defined that type of value is array of integers, and `5222,5223` was comma separated list of values.

This format worked but in fact `c2s/ports` was not name of property you configured but key which was later split on `/` char to parts which defined by names path to property which name was in last part. From that you can see that it was domain based setting of properties.

Except from this multi-part keys we also used properties starting with `--` which were global properties accessible for every part of application, i.e.: to add new component and set some properties you needed to write:

    --comp-name-1=pubsub
    --comp-class-1=tigase.pubsub.PubSubComponent
    pubsub/test[B]=true
    pubsub/pubsub-repo-url="jdbc:XXXX:XXXX/db_name"

This lead to mistakes like duplicated definition of name and class for same number of component or redefined property value in other place of a configuration file - especially in cases where configuration was big.

In this configuration structure it was hard to tell where is configuration for particular component or what databases this installation uses. This could be defined all over the file.

In this release we are introducing Tigase Kernel Framework, which allows to configure beans in configuration file and even define usage of new beans loaded from external jars which can modify behavior of Tigase components. This would make configuration file even more complex, difficult and less readable.

### What is DSL?

DSL stands for domain-specific language - in this case language created for storage of configuration.

Now we use domain based configuration which means that our configuration file is not a flat key=value storage but it defines objects, it’s properties and assigned values.

To illustrate it better let’s start with a simple example. In properties file in order to configure PubSub component named `pubsub` you would use following properties:

    --comp-name-1=pubsub
    --comp-class-1=tigase.pubsub.PubSubComponent
    pubsub/test[B]=true

In DSL based configuration this would be replaced by following block

    pubsub (class: tigase.pubsub.PubSubComponent) {
        # comment
        test = true
    }

in which we define bean with name `pubsub` and set it’s class inside `()` block to `tigase.pubsub.PubSubComponent`. We also use block between `{}` chars to define properties which are related to bean. Which means this properties will be passed only to this instance of Tigase PubSub Component, same as it was before where we needed to add prefix. Entries after `#` are comments, to pass `#` you need to wrap whole part containing it in `''`, ie. `'test#242'`

### Warning

If a string value assigned to a property contains any char from a following list `=:,[]#+-*/` it needs to be wrapped in a `''`.

### Why DSL?

DSL configuration format provides a number of advantages over the old system of configuration. . All configurations for components are related in a single block, so they are not spread out over several different lines. . No need for long property names, no longer have to invoke a long string of settings for multiple values. . Support is provided for environment variables. . No longer need to escape certain characters, making settings far more readable at a glance. . Values may be set using basic calculations, such as `100 * 200 * 2` rather than `40000`. . Parameter type values are no longer necessary, no more [i], [S], [B] etc.. . Comma separated values can now be simplified lists with separate entries being able to be in multiple lines.

Although the format may seem more complex, looking like a section of java code, the formatting is consistent and can be far more readable. After some experience with DSL format, you’ll find it’s far more intuitive and user friendly than it may appear. Of course if there’s any real confusion, Tigase can automatically convert old style properties files to the DSL format using the following command:

    ./scripts/tigase.sh upgrade-config etc/tigase.conf

#### Setting property

To set property you just write property name followed by `=` and value to set. This is always done in context of bean which configuration property you want to set.

    test=true

It is also possible to set property in main context by placing property outside of any context. This sets property which value is available to access by any bean.

#### Setting global property

Like in properties file it is still possible to use property names starting with `--` without any context or any other properties at global scope. Format is the same as in case of setting property but they are defined without scope (in global scope). This properties are global and accessible by any bean but also set as system property in JVM.

#### Defining bean

You can configure bean by using following format:

    beanName (class: className, active: activeValue, exportable: exportableValue) {
        # scope of bean properties
    }

where `beanName` is name under which you want to configure bean. `beanName` must be wrapped in `''`, if `beanName` contains characters like `=:,[]#+-*/` and is recommended, if `beanName` is numeric only.

Inside block between `(` and `)` you can define:

- `class` which will be used as a bean, in example above we set class as `className`. (default: if you try to configure bean under name which has default class assigned with it in Tigase framework then this assigned class will be used. In other case you need to pass name of class to use as a bean)
- `active` (boolean) whether you want the bean to be active or not (beans with `active` set to `false` are not loaded). (default: true)
- `exportable` (boolean) defines if this bean should be exported and available for use for beans in inner scopes. This is advanced option in most cases it is recommended to omit this field in configuration. (default: false)

Spaces between `beanName` and block between `()` is optional as well as space between block `()` and block `{}`. It is recommended that properties of bean would be placed in separate lines with indentation and first property will be placed in new line.

### Important

Usage of `()` block is very important. When this block is used in configuration it automatically sets `active` property of bean definition for bean for which it is used to to `true`. This is done due to fact that default value of `active` is `true`.

If you omit it in configuration, you will set bean configuration but it may remain `inactive`. In this state bean will not be loaded and as a result will not be used by Tigase XMPP Server.

#### Configuring bean

If you know that bean is defined and you do not want to change it’s activity or class then you can just pass properties to configure bean in following way:

    beanName {
        # scope of bean properties
        test = true
    }

where `beanName` is name of bean to configure and `test` is name of property to set to `true` in this bean.

#### Format of values

In properties based configuration file every property was defined as a string and only by defining expected format it was properly converted to expected value. In DSL it is possible to set values in two ways:

as an object
  Using this format you set list as a list and integer is set as an integer.

Type | Description
--- | ---
string | Wrap it in `''`, ie. to set `test` as string you use `'test'`
integer | Just put value, ie. to set `543` use `543`
long | Put value and follow it with `L`, ie. to set `23645434` as long use `23645434L`
float | Put value and follow it with `f`, ie. to set `231.342` use `231.342f`
boolean | To set value just use `true` or `false`
list | Lists can be of many types and to make it simple we decided to use as a comma separated list of values in proper format wrapped in `[]`. of strings - `[ 'alfa', 'beta', 'gamma' ]` of integers - `[ 1, 2, 3, 4]` You can write it in multiple lines if you want:
    [
        'alfa'
        'beta'
        'gamma'
    ]
map | Maps can be written as a block of properties wrapped in `{}`. This format of map is the same as used for passing configuration to bean properties. Keys and values can be written in separate lines (recommended):
    {
        test = true
        ssl = false
        ssl-certificate = '/test/cert.pem'
        another-map = {
            key = 'value'
        }
    }
or in single line (separation with spaces is not required):
    { test = true, ssl = false, ssl-certificate = '/test/cert.pem' }

as a plain string
  Very similar to properties based configuration, in fact values are passed in same format and later are converted to correct type by checking type expected by bean. (Not recommended)

Type | Description
--- | ---
string | Just put value, ie. to set `test` use `test`
integer | Just put value, ie. to set `543` use `543`
long | Put value, ie. to set `23645434` as long use `23645434`
float | Put value, ie. to set `231.342` use `231.342`
boolean | To set value just use `true` or `false`
list | List needs to be written as comma separated list of values, ie. `test,abc,efg` or `1,2,3`
map | Not possible

#### Using values from System Properties and Environment Variables

Now it is possible to use values of system properties and environment variables and assign them to bean properties. For this purpose we added functions which can be used in DSL and which will return values of:

system property
  `prop('property-name')` or `prop('property-name','default value')`
environment variable
  `env('variable-name')`

Example of setting value of system property and environment variable to bean `user`.

    user {
      name = env('USER')
      home = prop('user.home')
      paths = [ prop('user.home'), prop('user.dir') ]
    }

### Warning

For properties which accepts lists it is not allowed to set value using variable/property with comma separated values like `value1,value2` wrapped in `[]`, ie. `property = [ env('some-variable') ]`. It needs to be set in following way `property = env('some-variable')`

#### Computed values

With DSL configuration format we introduce support for computable values for properties. It is now possible to set value which is result of a computation, ie. concatenation of a strings or very simple mathematical expression. We currently support only following mathematical operations:

- add
- subtract
- multiply
- divide

Example of setting environment variable related path and computed timeout.

    bean {
      # setting path to `some-subdirectory` of user home directory
      path = prop('user.home') + '/some-subdirectory/'

      # setting timeout to 5 minutes (setting value in milliseconds)
      timeout = 5L * 60 * 1000
      # previously it would need to be configured in following way:
      # timeout = 300000L
    }

### Warning

For properties which accepts lists it is not allowed to set value using computed values with comma separated values like `value1,value2` wrapped in `[]`, ie. `property = [ env('some-variable') + ',other-value' ]`. It needs to be set in following way `property = env('some-variable') + ',other-value'`.

#### Period / Duration values

Some configuration options allow control of execution of tasks with particular period or within certain duration. DSL file format accepts strings denoting particular amount of time, which follows Java’s native structures (see: Period and Duration for detailed explanation).

- `Duration` formats accepted are based on the ISO-8601 duration format `PnDTnHnMn.nS` with days considered to be exactly 24 hours, for example:

  - `PT20.345S` - 20.345 seconds
  - `PT15M` - 15 minutes (where a minute is 60 seconds)
  - `PT10H` - 10 hours (where an hour is 3600 seconds)
  - `P2D` - 2 days (where a day is 24 hours or 86400 seconds)
  - `P2DT3H4M` - 2 days, 3 hours and 4 minutes

- `Period` format is based on the ISO-8601 period formats PnYnMnD and PnW, for example, the following are valid inputs:

  - `P2Y` - 2 years
  - `P3M` - 3 months
  - `P4W` - 4 weeks
  - `P5D` - 5 days
  - `P1Y2M3D` - 1 year, 2 months, 3 days
  - `P1Y2M3W4D` - 1 year, 2 months, 3 weeks, 4 days

### Example configuration file in DSL

    # Enable cluster mode
    --cluster-mode = true
    # Enable debugging for server and xmpp.impl
    --debug = 'server,xmpp.impl'
    # Set list of virtual hosts (old way)
    --virt-hosts = 'example.com,test-1.example.com,test-2.example.com'

    # Configure list of administrator jids
    admins = [ 'admin@zeus', 'http@macbook-pro-andrzej.local' ]
    # Set config type
    config-type = '--gen-config-def'

    # Configure dataSource bean with database configuration
    dataSource {
        # Configure default data source (using default implementation so class is omitted)
        default () {
            uri = 'jdbc:postgresql://127.0.0.1/tigase?user=test&password=test&autoCreateUser=true'
        }

        # Configure data source with name exaple.com (will be used by domain example.com)
        'example.com' () {
            uri = 'jdbc:mysq://127.0.0.1/example?user=test&password=test&autoCreateUser=true'
        }
    }

    # Configure C2S component
    c2s {
        # Enable Stream Management bean
        'urn:xmpp:sm:3' () {}

        # Register tigase.server.xmppclient.SeeOtherHostDualIP as seeOtherHost bean
        seeOtherHost (class: tigase.server.xmppclient.SeeOtherHostDualIP) {}

        # Add additional port 5224 which is SSL port and disable port 5223
        connections () {
            '5224' () {
    	         socket = ssl
    	      }
            '5223' (active: false) {}
        }
    }

    # Configure HTTP API component
    http {
        # Set list of API keys
        api-keys = [ 'test1234', 'test2356' ]
        rest {
            # Set value of environment property as a path to look for REST scripts
            rest-scripts-dir = env('TIGASE_REST_SCRIPTS_DIR')
        }
    }

    # Register pubsub-2 (class is passed as pubsub-2 name do not have default class assigned)
    pubsub-2 (class: tigase.pubsub.cluster.PubSubComponentClustered) {
        # Set configuration bean properties
        pubsubConfig {
            persistentPep = true
        }
        # Use tigase.pubsub.cluster.ClusteredNodeStrategy as advanced clustering strategy
        strategy (class: tigase.pubsub.cluster.ClusteredNodeStrategy) {}
    }

    # Configure Session Manager
    sess-man {
        # Here we enable pep, urn:xmpp:mam:1 processors and disable message-archive-xep-0136 processor
        pep () {}
        'urn:xmpp:mam:1' () {}
        message-archive-xep-0136 (active: false) {}

        # Define class used as clustering strategy (it is different than default so class is required)
        strategy (class: tigase.server.cluster.strategy.OnlineUsersCachingStrategy) {}
    }

### Default configuration

Tigase XMPP Server is packaged with a basic `config.tdsl` file that tells the server to start up in setup mode.

    'config-type' = 'setup'

    http () {
        setup () {
            'admin-user' = 'admin'
        'admin-password' = 'tigase'
        }
    }

This tells Tigase to operate in a setup mode, and tells the http component to allow login with the username and password admin/tigase. With this you can enter the setup process that is covered in this section.

There are other options for config-type: `default`, `session-manager`, `connection-managers`, and `component`. For more information, visit Config Type property description.

Prev | Up | Next
Upgrading to v8.0.0 from v7.1.0 | Home | Startup File for tigase.sh - tigase.conf