# Cluster Configuration

> Octelium documentation. Canonical page: <https://octelium.com/docs/octelium/latest/management/core/cluster-config>.

*Cluster* configuration, or simply *ClusterConfig*, acts as the sole source of truth for all global configurations and settings of the *Cluster*. *ClusterConfig* is created automatically upon the *Cluster* installation and can be updated declaratively via the command `octeliumctl apply` (read more [here](https://octelium.com/docs/octelium/latest/management/core/overview.md)). You can read the entire *Cluster* configuration in the [ClusterConfig JSON Schema](https://octelium.com/schemas/octelium/latest/core.v1.ClusterConfig.schema.json).

You can get the *ClusterConfig* as follows:

```bash
octeliumctl get clusterconfig
# OR Simply
octeliumctl get cc
# OR as JSON
octeliumctl get clusterconfig -o json
```

## Session

*Users* can interact with a *Cluster* and access its *Services* as long as their [*Sessions*](https://octelium.com/docs/octelium/latest/reference/resources.md#session) are valid (read more about *Session* management [here](https://octelium.com/docs/octelium/latest/management/core/session.md)). A *Session* has a duration after which the *Session* expires and automatically gets deleted by the *Cluster*. It's recommended that the *Session*'s duration should be as short as possible without becoming too annoying especially for `HUMAN` *Users*. The current fallback value for access token duration is 4 hours but it might change in the future.

You can set your own *Session* duration configuration as follows:

```yaml
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  session:
    human:
      clientDuration:
        days: 1
      clientlessDuration:
        hours: 10
      maxPerUser: 32
      accessTokenDuration:
        hours: 4
      refreshTokenDuration:
        hours: 18
      defaultState: PENDING
    workload:
      clientDuration:
        months: 6
      clientlessDuration:
        weeks: 1
      maxPerUser: 100
      accessTokenDuration:
        hours: 4
      refreshTokenDuration:
        weeks: 2
      defaultState: ACTIVE
```

These *Cluster*-wide *Session* duration values can be overridden per *User* basis. You can read more [here](https://octelium.com/docs/octelium/latest/management/core/user.md#session-duration).

## Device

Octelium enables you to control *Device* related configurations (read more about *Devices* [here](https://octelium.com/docs/octelium/latest/management/core/device.md)). For example, you can explicitly define the default state of a new registered *Device*. By default, a *Device*'s default state is set to `ACTIVE`, however, you can override that choice to `PENDING` or `REJECTED`. You can also set a per-*User* limit as follows:

```yaml
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  device:
    human:
      maxPerUser: 32
      defaultState: PENDING
    workload:
      maxPerUser: 100
      defaultState: ACTIVE
```

## Gateway

Octelium enables you to control the rotation duration of the [*Gateways*](https://octelium.com/docs/octelium/latest/reference/components.md#gateway-agent) WireGuard keys as follows:

```yaml {6-8}
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  gateway:
    # !mark(1:2)
    wireguardKeyRotationDuration:
      hours: 6
```

## Ingress

You can choose to use the `useForwardedForHeader` field to enable the usage of the X-Forwarded-For header by the *Cluster* to obtain the downstream's public IP address. The downstream's IP address is mainly stored in the *Session* and can be used via your *Policies* to control access to *Services*. This is also useful for geolocation-based access control (read more [here](https://octelium.com/docs/octelium/latest/management/core/session.md#geolocation)). Here is an example:

```yaml {7}
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  ingress:
    # !mark
    useForwardedForHeader: true
```

You can explicitly set the number of trusted hops in the returned value of the `X-Forwarded-For` header (read more [here](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for)) via the `xffNumTrustedHops` field. Here is an example:

```yaml
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  ingress:
    useForwardedForHeader: true
    # !mark
    xffNumTrustedHops: 1
```

## DNS

The *Cluster* automatically serves private DNS, deployed as a typical *Service* that can be accessed by all, to resolve the domain names of the *Cluster*'s *Services* to their IP addresses. Moreover, that private DNS *Service* can also resolve domain names outside the *Cluster* domain by proxying the requests to a server that is chosen randomly from a list of fallback DNS servers. Both UDP as well as DNS-over-TLS servers are supported. Here is an example:

```yaml
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  # !mark(1:8)
  dns:
    fallbackZone:
      servers:
        - dns://8.8.8.8
        - udp://1.1.1.1
        - tls://8.8.8.8
        - tls://1.1.1.1
        - dns://custom-dns-server:8053
```

The private DNS *Service* can also cache the results of the fallback servers. Here is an example:

```yaml
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  dns:
    fallbackZone:
      servers:
        - tls://8.8.8.8
        - tls://1.1.1.1
      #!mark(1:2)
      cacheDuration:
        seconds: 30
    
```

You can also route the DNS queries of specific domains, and all of their subdomains, to their own DNS servers via the `zones` list. This can be useful, for example, to resolve your internal corporate domains via your internal DNS servers while all other queries keep going to the fallback servers. Here is an example:

```yaml
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  dns:
    fallbackZone:
      servers:
        - tls://8.8.8.8
        - tls://1.1.1.1
    #!mark(1:9)
    zones:
      - domains:
          - corp.example.com
          - internal.example.com
        servers:
          - 10.0.0.53
          - tls://dns.corp.example.com
        cacheDuration:
          minutes: 1
```

Each zone must have at least one domain and at least one server, and a domain cannot be used in more than one zone. A query matches a zone if its name is either one of the zone's domains or a subdomain of it. When a query matches multiple zones, the zone with the longest matching domain takes precedence. Queries that do not match any zone are resolved by the `fallbackZone`. Each zone can also cache its own results via its `cacheDuration` field. Note that the domain names of the *Cluster*'s *Services* are always resolved by the *Cluster* itself.

## Authorization

You can define global *Policies* (read more [here](https://octelium.com/docs/octelium/latest/management/core/policy.md#global-policies)) that are always triggered across all the *Cluster*'s requests as follows:

```yaml
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
#!mark(1:9)
  authorization:
    policies: ["pol-1", "pol-2"]
    inlinePolicies:
      - spec:
          rules:
            - effect: DENY
              condition:
                match: '"junior" in ctx.user.spec.groups && ctx.namespace.metadata.name == "production"'
```

## Authentication

### Geolocation

Since version `v0.23.0`, Octelium *Clusters* support geolocation via MaxMind MMDB databases (`enterprise`, `city` and `country`-type databases are supported). This feature sets geolocation info (e.g. country, city, ASN) in the Session on each authentication where you can use such info in your Policies for access control on a per-request basis (read more [here](https://octelium.com/docs/octelium/latest/management/core/session.md#geolocation)). Here is an example using a database that can be fetched from a URL:

```yaml
kind: ClusterConfig
metadata:
  name: cluster-config
spec:
  ingress:
    useForwardedForHeader: true
    xffNumTrustedHops: 1

  # !mark(1:5)
  authentication:
    geolocation:
      mmdb:
        upstream:
          url: https://mmdb-provider.example.com/geoip-city-db.mmdb
```

As shown in the example above, you need to trust `X-Forwarded-For` via the `useForwardedForHeader` field. You can also set the number of trusted hops used in the `X-Forwarded-For` header via the `xffNumTrustedHops` field.

## API Reference

[ClusterConfig JSON Schema (Octelium core/v1, latest documentation)](https://octelium.com/schemas/octelium/latest/core.v1.ClusterConfig.schema.json)
