Skip to main content
Version: v2.10

Configuration

Tobira will check for config.toml (in the working directory) and /etc/tobira/config.toml and use the first one it finds. You can set an explicit config path with the environment variable TOBIRA_CONFIG_PATH or the -c CLI flag. If none of these is found, Tobira will exit with an error.

You usually have some additional files that Tobira needs access to (e.g. the logo). All file paths you use in the configuration file are relative to the configuration file itself.

The Tobira binary is able to emit a "configuration template", i.e. the empty structure of the config file without any values set, but with descriptions of all possible options. It's a great starting point to configure your Tobira. You can generate it with ./tobira write-config, but that file is also attached to each release as config.toml. Or you can just copy it from below.

For configuring the [theme] section, see the next chapter.

Known roles

You can provide a mapping from role (e.g. ROLE_STUDENT_MASTER) to label (e.g. "M.Sc. Students"). This enables Tobira to show access rights (ACLs) in a more user-friendly way. Unlike all other configurations, these known roles are not stored in config.toml, but in the database. They are manipulated/configured via the CLI. This was done to make it easier to modify them via scripts.

Known groups

There are only three built-in known groups: ROLE_ANONYMOUS (everyone), ROLE_USER (logged in users) and ROLE_ADMIN (administrators). To configure additional known non-user roles, these four commands exist:

  • tobira known-groups clear: deletes all know groups (except the built-in ones).
  • tobira known-groups remove <role...>: removes one or more known groups identified by their role.
  • tobira known-groups list: lists all known groups (except built-in ones).
  • tobira known-groups upsert <groups.json>: adds/updates the groups in the given JSON file.

Groups are specified in a JSON file in this format (list outputs the same format):

{
"ROLE_STUDENT": { "label": { "en": "Students", "de": "Studierende" }, "implies": [], "large": true },
"ROLE_STAFF": { "label": { "en": "Staff", "de": "Angestellte" }, "implies": [], "large": true },
"ROLE_LECTURER": { "label": { "en": "Lecturers", "de": "Vortragende" }, "implies": ["ROLE_STAFF"], "large": true },
"ROLE_TOBIRA_MODERATOR": { "label": { "en": "Moderators", "de": "Moderierende" }, "implies": ["ROLE_STAFF"], "large": false }
}

Field explanation:

  • label: a user-friendly label in different languages (identified by 2 letter language code).
  • implies: lists roles that a user with the role in question always also has. Example: all lecturers are staff (always!). So all users with ROLE_LECTURER always also have the role ROLE_STAFF. This information is used to improve the user interaction with the ACL interface. All roles automatically imply ROLE_USER and ROLE_ANONYMOUS.
  • large: set to true if this group is considered so large that giving write access to it is unusual enough to show a warning in the ACL interface. ROLE_USER and ROLE_ANONYMOUS are both considered large.

Note that upsert is idempotent, so you can simply call this as part of your Ansible script, for example.

All configuration options

This is the the configuration template described above:

# Configuration for Tobira.
#
# All relative paths are relative to the location of this configuration file.
# Duration values are specified as string with a unit, e.g. "27s". Valid
# units: 'ms', 's', 'min', 'h' and 'd'.
#
# All user-facing texts you can configure here have to be specified per
# language, with two letter language key. Only English ('en') is required.
# Take `general.site_title` for example:
#
# [general]
# site_title.en = "My university"
# site_title.de = "Meine Universität"
#

[general]
# The main title of the video portal. Used in the HTML `<title>`, as main
# heading on the home page, and potentially more.
#
# Required! This value must be specified.
#site_title =

# Public URL to Tobira (without path).
# Used for RSS feeds, as those require specifying absolute URLs to resources.
#
# Example: "https://tobira.my-uni.edu".
#
# Required! This value must be specified.
#tobira_url =

# Terms and conditions that a user has to agree to in order to use Tobira.
# This consists of a title, a markdown rendered text explaining what a user
# is agreeing to, and a button label for confirmation.
# These can be specified in multiple languages.
# Consent is prompted upon first use and only if this is configured. It is
# re-prompted when any of these values change.
#
# We recommend not to configure this unless absolutely necessary,
# in order to not degrade the user experience needlessly.
#
# Example:
#
# ```
# [general.initial_consent]
# title.en = "Terms & Conditions"
# button_label.en = "Agree"
# text.en = """
# To use Tobira, you need to agree to our terms and conditions:
# - [Terms](https://www.our-terms.de)
# - [Conditions](https://www.our-conditions.de)
# """
# ```
#initial_consent =

# Whether or not to show a download button on the video page.
#
# Default value: true
#show_download_button = true

# Links that are shown in the footer.
#
# By overwriting this default value, you can remove the default links and
# add custom ones. Note that these two default links are special and can
# be specified with only the shown string. To add custom ones, you need
# to define a label and a link. The link is either the same for every language
# or can be specified for each language in the same manner as the label.
# Example:
#
# ```
# footer_links = [
# { label = { en = "Example 1" }, link = "https://example.com" },
# { label = { en = "Example 2" }, link = { en = "https://example.com/en" } },
# "about",
# ]
# ```
#
# Default value: ["about", "graphiql"]
#footer_links = ["about", "graphiql"]

# Additional metadata that is shown below a video. Example:
#
# [general.metadata]
# dcterms.spatial = { en = "Location", de = "Ort" }
# "http://my.domain/xml/namespace".courseLink = { en = "Course", de = "Kurs"}
#
# As you can see, this is a mapping of a metadata location (the XML
# namespace and the name) to a translated label. For the XML namespace
# URL, there is one shortcut: the "http://purl.org/dc/terms/" is
# abbreviated as just "dcterms".
#
# It's likely easier to write this as shown above (as extra section)
# instead of trying to cram it into one line (as shown below with the
# default value).
#
# Instead of the manually translated label, you can use some builtin
# labels like this:
#
# [general.metadata]
# dcterms.license = "builtin:license"
# dcterms.source = "builtin:source"
#
# As soon as you add your own metadata fields, this default is
# overwritten. If you want to keep showing the license and source data,
# you have to add those two lines to your configuration.
#
# Default value: { dcterms = { license = "builtin:license", source = "builtin:source" } }
#metadata = { dcterms = { license = "builtin:license", source = "builtin:source" } }

# A list of URL paths that are reserved for other usages. Users won't be
# able to create top-level realms with those path segments. Tobira also
# has some additional built-in reserved paths (e.g. `/favicon.ico`).
#
# Example: ["/Shibboleth.sso", "/something-else"]
#
# Default value: []
#reserved_paths = []

# Whether users are allowed to search through all known users, e.g. in the
# ACL UI to grant a friend access to a video. If `false`, users in the
# ACL selector can only be added by typing the exact username or email.
# If this is `true` instead, it is possible to search for users by
# (partial) name.
#
# Default value: false
#users_searchable = false


[db]
# The username of the database user.
#
# Default value: "tobira"
#user = "tobira"

# The password of the database user.
#
# Required! This value must be specified.
#password =

# The host the database server is running on.
#
# Default value: "127.0.0.1"
#host = "127.0.0.1"

# The port the database server is listening on. (Just useful if your
# database server is not running on the default PostgreSQL port).
#
# Default value: 5432
#port = 5432

# The name of the database to use.
#
# Default value: "tobira"
#database = "tobira"

# The TLS mode for the database connection.
#
# - "on": encryption is required and the server certificate is validated
# against trusted certificates which are loaded from the system's
# native certificate store. If `server_cert` is set, that's also
# loaded and trusted.
# - "without-verify-cert": encryption is required, but the server
# certificate is not checked. Allows MITM attacks! Discouraged.
# - "off": no encryption. Discouraged even more.
#
# Default value: "on"
#tls_mode = "on"

# Path to the server certificate. This makes sense if you don't want to
# install the certificate globally on the system. Has to be a PEM encoded
# file containing one or more X509 certificates.
#server_cert =


[http]
# The TCP port the HTTP server should listen on.
#
# Default value: 3080
#port = 3080

# The bind address to listen on.
#
# Default value: "127.0.0.1"
#address = "127.0.0.1"

# Unix domain socket to listen on. Specifying this will overwrite
# the TCP configuration. Example: "/tmp/tobira.socket".
#unix_socket =

# Unix domain socket file permissions.
#
# Default value: 493
#unix_socket_permissions = 493


[auth]
# How incoming HTTP requests are authenticated. See the documentation!
#
# Default value: "none"
#source = "none"

# Link of the login button. If not set, the login button internally
# (not via `<a>`, but through JavaScript) links to Tobira's own login page.
#login_link =

# Link of the logout button.
#logout_link =

# A shared secret for **trusted** external applications. Send this value
# as the `x-tobira-trusted-external-key`-header to use certain APIs
# without having to invent a user. Note that this should be hard to
# guess, and kept secret. Specifically, you are going to want to encrypt
# every channel this is sent over.
#trusted_external_key =

# Determines whether or not Tobira users are getting pre-authenticated against
# Opencast when they visit external links like the ones to Opencast Studio
# or the Editor. If you have an SSO-solution, you don't need this.
#
# Default value: false
#pre_auth_external_links = false


# Tobira's built-in session management. Only relevant if `auth.source = "tobira-session"`.
[auth.session]
# How to create sessions from login credentials (userid + password).
#
# Default value: "none"
#from_login_credentials = "none"

# How `POST /~session` requests are authenticated.
#
# Default value: "none"
#from_session_endpoint = "none"

# Duration of a Tobira-managed login session.
#
# Default value: "30d"
#duration = "30d"


[auth.callback]
# Headers relevant for the auth callback. See docs.
#relevant_headers =

# Cookies relevant for the auth callback. See docs.
#relevant_cookies =

# For how long a callback's response is cached. The key of the cache is
# the set of headers forwarded to the callback. Set to 0 to disable
# caching.
#
# Default value: "5min"
#cache_duration = "5min"


# Configuration related to the built-in login page.
[auth.login_page]
# Label for the user-ID field. If not set, "User ID" is used.
#user_id_label =

# Label for the password field. If not set, "Password" is used.
#password_label =

# An additional note that is displayed on the login page. If not set, no
# additional note is shown.
#note =


# JWT configuration. See documentation for more information.
[auth.jwt]
# Signing algorithm for JWTs.
#
# Valid values: "ES256", "ES384"
#
# Default value: "ES384"
#signing_algorithm = "ES384"

# Path to the secret signing key. The key has to be PEM encoded. If not
# specified, a key is generated everytime Tobira is started. The randomly
# generated key is fine for most use cases.
#secret_key =

# The duration for which a JWT is valid. JWTs are just used as temporary
# ways to authenticate against Opencast, so they just have to be valid
# until the frontend received the JWT and used it with Opencast.
#
# Default value: "30s"
#expiration_time = "30s"


[auth.roles]
# The role giving a user "Tobira admin" status, giving them all
# Tobira-related privileges, i.e. everything for which a role can be
# configured below. Unlike ROLE_ADMIN, this does not give the user access
# to all content.
#
# Default value: "ROLE_TOBIRA_ADMIN"
#tobira_admin = "ROLE_TOBIRA_ADMIN"

# The role granting permission to use Tobira's uploader.
#
# Default value: "ROLE_TOBIRA_UPLOAD"
#upload = "ROLE_TOBIRA_UPLOAD"

# The role granting permission to use Opencast Studio from Tobira.
#
# Default value: "ROLE_TOBIRA_STUDIO"
#studio = "ROLE_TOBIRA_STUDIO"

# The role granting permission to use the Opencast Editor from Tobira.
#
# Default value: "ROLE_TOBIRA_EDITOR"
#editor = "ROLE_TOBIRA_EDITOR"

# The role granting permission to create one's own "user page".
#
# Default value: "ROLE_USER"
#user_realm = "ROLE_USER"

# The role granting permission to find unlisted events and series when
# editing page content. Usually, only very few people should have this
# privilege. Everyone can always find listed items and items they have
# write access to. This does not affect the search results of the main
# search.
#
# Default value: "ROLE_TOBIRA_CAN_FIND_UNLISTED"
#can_find_unlisted = "ROLE_TOBIRA_CAN_FIND_UNLISTED"

# The role granting "page admin" privileges on all non-user pages.
#
# Default value: "ROLE_TOBIRA_GLOBAL_PAGE_ADMIN"
#global_page_admin = "ROLE_TOBIRA_GLOBAL_PAGE_ADMIN"

# The role granting "page moderator" privileges on all non-user pages.
#
# Default value: "ROLE_TOBIRA_GLOBAL_PAGE_MODERATOR"
#global_page_moderator = "ROLE_TOBIRA_GLOBAL_PAGE_MODERATOR"

# List of prefixes that user roles can have. Used to distinguish user
# roles from other roles. Should probably be the same as
# `role_user_prefix` in `acl.default.create.properties` in OC.
#
# Default value: ["ROLE_USER_"]
#user_role_prefixes = ["ROLE_USER_"]


[log]
# Specifies what log messages to emit, based on the module path and log level.
#
# This is a map where the key specifies a module path prefix, and the
# value specifies a minimum log level. For each log message, the map
# entry with the longest prefix matching the log's module path is chosen.
# If no such entry exists, the log is not emitted. Otherwise, that
# entry's level is used to check whether the log message should be
# emitted.
#
# Take the following example: the following config only allows ≥"info"
# logs from Tobira generally, but also ≥"trace" messages from the `db`
# submodule. But it completely disables all logs from `tobira::db::tx`.
# Finally, it also enabled ≥"debug" messages from one of Tobira's
# dependencies, the HTTP library `hyper`.
#
# [log]
# filters.tobira = "info"
# filters."tobira::db" = "trace"
# filters."tobira::db::tx" = "off"
# filters.hyper = "debug"
#
# Default value: { tobira = "debug" }
#filters = { tobira = "debug" }

# If this is set, log messages are also written to this file. The string
# `${cmd}` in this value is replaced by the subcommand name of the Tobira
# process, e.g. `serve`, `worker` or `other` (for less important
# commands). Example: "/var/log/tobira-${job}.log".
#file =

# If this is set to `false`, log messages are not written to stdout.
#
# Default value: true
#stdout = true

# If set to `true`, HTTP header of each incoming request are logged
# (with 'trace' level).
#
# Default value: false
#log_http_headers = false


[opencast]
# URL to Opencast. Currently used for all purposes (syncing, Studio,
# upload, ...) unless overwritten below. In the future, Tobira might use
# the service registry API to figure out suitable nodes for each
# purpose (again, unless explicitly specified below).
#
# Some HTTP requests to Opencast contain the unencrypted `sync.password`,
# so using HTTPS is strongly encouraged. In fact, HTTP is only allowed if
# the host resolves to a loopback address.
#
# Example: "http://localhost:8080" or "https://oc.my-uni.edu".
#host =

# Explicitly set Opencast node used for data synchronization. The Tobira
# module needs to run on this node.
#sync_node =

# Explicitly set Opencast node used for the video uploader. Has to offer
# the ingest API.
#upload_node =

# Explicitly set base-URL to Opencast Studio.
#
# Example: "https://admin.oc.my-uni.edu/studio".
#studio_url =

# Explicitly set the base-URL to the Opencast editor.
#
# Example: "https://admin.oc.my-uni.edu/editor-ui/index.html".
#editor_url =


[sync]
# Username of the user used to communicate with Opencast for data syncing.
# This user has to have access to all events and series. Currently, that
# user has to be admin.
#
# Required! This value must be specified.
#user =

# Password of the user used to communicate with Opencast.
#
# Required! This value must be specified.
#password =

# A rough estimate of how many items (events & series) are transferred in
# each HTTP request while harvesting (syncing) with the Opencast
# instance.
#
# A very large number might cause problems due to the Opencast or Tobira
# node having to hold that many items in memory, or due to network
# request size restrictions. Too small of a number means that the
# overhead of each request will become more significant, slowing down
# harvesting. But more importantly: if your Opencast instance has more
# items with exactly the same `updated` timestamp than the configured
# `preferred_harvest_size`, Tobira is unable to harvest. The `updated`
# timestamp is has millisecond precision, so this situation is highly
# unlikely to occur naturally. However, this can easily occur with
# artificial timestamps, like when you migrate old Opencast data
# (without an `updated` timestamp). Be aware of that.
#
# Default value: 500
#preferred_harvest_size = 500

# The duration to wait after a "no new data" reply from Opencast. Only
# relevant in `--daemon` mode.
#
# Default value: "30s"
#poll_period = "30s"


[meili]
# The access key. This can be the master key, but ideally should be an API
# key that only has the priviliges it needs.
#
# Required! This value must be specified.
#key =

# The host MeiliSearch is running on. As requests include the `key`, you
# should use HTTPS if Meili is running on another machine. In fact, HTTP
# is disallowed unless the host resolves to a loopback address.
#
# Default value: "http://127.0.0.1:7700"
#host = "http://127.0.0.1:7700"

# A prefix for index names in Meili. Useful only to avoid collision if
# other services use Meili as well.
#
# Default value: "tobira_"
#index_prefix = "tobira_"

# How often DB changes are written back to the search index.
#
# Default value: "5s"
#update_interval = "5s"


# See the relevant chapter in our documentation on how to configure this section.
[theme]
# Height of the header. Increasing this size only enlarges the logo, the
# other elements stay the same size and centered.
#
# Default value: 85
#header_height = 85

# Path to an SVG file that is used as favicon.
#
# Required! This value must be specified.
#favicon =


# Logo used in the top left corner of the page. Using SVG logos is recommended.
# See the documentation on theming/logos for more info!
[theme.logo]
# The normal, usually wide logo that is shown on desktop screens. The
# value is a map with a `path` and `resolution` key:
#
# large = { path = "logo.svg", resolution = [20, 8] }
#
# The resolution is only an aspect ratio. It is used to avoid layout
# shifts in the frontend by allocating the correct size for the logo
# before the browser loaded the file.
#
# Required! This value must be specified.
#large =

# A less wide logo used for narrow screens.
#small =

# Large logo for dark mode usage.
#large_dark =

# Small logo for dark mode usage.
#small_dark =


# Colors used in the UI. Specified in sRGB.
[theme.color]
# The primary color used for most colored UI elements. Should have a
# perceived brightness (L in LCH color space) of 35-55.
#
# Default value: "#01758f"
#primary = "#01758f"

# A color used to indicate errors and potentially destructive actions.
# Should be red.
#
# Default value: "#b64235"
#danger = "#b64235"

# Grey tone. This is configurable in case you want to have a slightly
# colored grey, e.g. slightly warm.
#
# Only hue and saturation (or more precisely, hue and chroma in the LCH
# color space) are used from this. The brightness of the configured color
# is ignored. Still try using a color with roughly 50% perceived
# brightness to reduce rounding errors.
#
# Default value: "#777777"
#grey50 = "#777777"

# A color for positive things and "call to action" elements. Only specify
# this color if your primary color is reddish!
#happy =


[theme.font]
# The main font family to use in Tobira. Needs to be a valid CSS value for
# `font-family`.
#
# Default value: "'Open Sans'"
#main_family = "'Open Sans'"

# Path to a CSS file with extra `@font-face` declarations. If you want to
# refer to files included via `font_files` (see below), be sure to to
# include the full path, e.g. `/~assets/fonts/vollkorn-400.woff2`. That's
# required as the font files are served with a hashed filename for
# caching and Tobira needs to fix up the path in your CSS.
#extra_css =

# Additional font files to serve under `/~assets/fonts/`. Prefer using the
# WOFF 2.0 format: it has excellent browser support and great compression.
#
# Default value: []
#files = []


[upload]
# Whether specifying a series is required when uploading.
#
# Default value: false
#require_series = false


# Matomo integration (optional). Currently only used by Paella if configured.
[matomo]
# URL of your Matomo server. Example: "https://matomo.myuni.edu/matomo/".
#
# Note: Adding `matomo.js` to the URL configured here should result in a
# URL to a publicly accessible JS file.
#server =

# Matomo site ID, e.g. `side_id = "1"`
#site_id =


[player]
# Additional Paella plugin configuration (JSON object). This is merged
# into the `plugins` object in the Tobira-internal Paella config.
# Warning: this could break Paella if used incorrectly. This is mostly
# intended to configure user tracking, e.g.:
#
# ```
# paella_plugin_config = """{
# "es.upv.paella.userEventTracker": { ... },
# "es.upv.paella.matomo.userTrackingDataPlugin": { ... }
# }"""
# ```
#
# Default value: "{}"
#paella_plugin_config = "{}"