Skip to content

app.config.yaml ​

app.config.yaml holds the instance's settings: sign-in, registration, media, and optional features. Start from app.config.example.yaml. The server checks the whole file when it starts, and refuses to start with a clear message if something is wrong, rather than guessing.

Settings that can also come from the environment (marked below) take the environment's value when both are set.

Sign-in and registration ​

yaml
auth:
  registrationPolicy: open
  adminApprovalRequired: false

  email:
    enabled: true
    methodKey: email
    verificationRequired: false

  authMethods:
    google:
      enabled: false
      methodKey: google
      type: oidc
      oauth:
        clientId: ""
        clientSecret: ""
        authUrl: "https://accounts.google.com/o/oauth2/v2/auth"
        tokenUrl: "https://oauth2.googleapis.com/token"
        userInfoUrl: "https://openidconnect.googleapis.com/v1/userinfo"
        idField: "sub"
        scope: "openid profile email"
SettingWhat it does
registrationPolicyopen lets anyone sign up. invite-only and closed both turn sign-up off, by email and by provider
adminApprovalRequiredNew accounts wait for an admin under Manage instance → Approval before they can use the instance
email.enabledEmail and password sign-in
email.verificationRequiredNew accounts confirm their email address first. Needs email set up
authMethodsSign-in providers, one block each

Sign-in providers ​

Each block under authMethods is one provider, shown as a button on the sign-in page:

  • type: oidc for OpenID Connect, or oauth2.
  • methodKey: the provider's name in URLs. Register https://chat.example.com/oauth/<methodKey>/callback as the redirect URI with the provider.
  • oauth: clientId, clientSecret, authUrl, tokenUrl, userInfoUrl, idField (the user-info field that identifies the person, such as sub or id) and scope. All are required.
  • position: optional, the button's order.

The example file has Google, GitHub, Discord, Steam and Keycloak ready to fill in. Any other OIDC or OAuth 2 provider works the same way.

Servers ​

yaml
config:
  joinDefaultServer: true
  defaultServerId: 1
  usersCanCreateServers: false
  buzz:
    enabled: true
    cooldownSeconds: 60
SettingWhat it does
joinDefaultServerNew accounts join the server defaultServerId. If that server doesn't exist yet, nothing happens
defaultServerIdRequired with joinDefaultServer. On a new instance, the first server created has ID 1
usersCanCreateServersWhether everyone can create servers. Moderators and admins always can
buzz.enabled/buzz, which shakes the other person's window in a direct message
buzz.cooldownSecondsSeconds between one person's buzzes in a conversation, 1 to 86,400. Also BUZZ_COOLDOWN_SECONDS

The whole config: block is optional.

Media ​

yaml
media:
  storage: local
  local:
    dataDir: /data
  uploads:
    maxAttachmentsPerMessage: 10
    # maxFileSizeMb: 100 # operator override of the saved instance setting
    defaultMaxFileSizeMb: 100
    minFileSizeMb: 1
    maxAllowedFileSizeMb: 1024
    jsonBodyLimitBytes: 102400
    emoji:
      maxArchiveBytes: 33554432
      maxImageBytes: 1048576
      maxFilesPerImport: 250
      maxArchiveEntries: 1000

Where uploads are stored, and which files people can upload. See Media storage for local and S3 storage and the uploads: settings.

Upload size, attachment count, JSON size and emoji limits can all be overridden in the server environment. See the commented variables in .env.example and the matching media.uploads values above. Environment values win over YAML; an explicit maxFileSizeMb also overrides the saved administrator setting. Restart backend workers after changing configuration. Clients receive the effective limits from the instance.

Soundboard ​

yaml
soundboard:
  maxDurationSeconds: 30
  maxFileSizeMb: 5
  maxSoundsPerServer: 50
  audioExtensions: [mp3, wav, ogg, webm, m4a, aac, flac, opus]

This optional top-level block sets soundboard limits for every server on the instance. Environment overrides are SOUNDBOARD_MAX_DURATION_SECONDS, SOUNDBOARD_MAX_FILE_SIZE_MB, SOUNDBOARD_MAX_SOUNDS_PER_SERVER and comma-separated SOUNDBOARD_AUDIO_EXTENSIONS. Omitted settings use the defaults above. Restart the backend after changing the file; clients receive the effective limits through instance details.

Duration, file size (in MiB) and sound count must be positive whole numbers. The defaults are deliberately small, not a ceiling: raise them to allow long clips such as full tracks (for example maxDurationSeconds: 600 and maxFileSizeMb: 25). The general upload size limit under Manage instance → Config also applies; the lower size limit wins, so raise it too if it is lower. Durations are limited only by what the database can store (about 24 days). audioExtensions must be a non-empty selection from the formats above. Leading dots and uppercase extensions are normalized. Unsupported formats and unknown settings fail startup.

Each member's browser decodes a sound into memory the first time it plays, at roughly 20 MB per minute of stereo audio, so very long clips cost memory on every listener's device.

The upload form checks these limits and decodes the audio to measure its duration. Files must use a codec the browser can decode; accepting an M4A container does not transcode its contents. The backend checks file size, format signatures, reported duration and sound count. Existing sounds remain available when limits are lowered.

yaml
gifs:
  enabled: true
  contentFilter: medium

The composer's GIF button searches KLIPY and gifgooder. It stays off until one of them is set up, and offers each one that is, as tabs when there are two. For KLIPY, set KLIPY_API_KEY in the environment (preferred), apiKey: here, or the key in Manage instance → Config. For gifgooder, set GIFGOODER_URL and GIFGOODER_TOKEN in the environment; they can't be set here. contentFilter is high, medium, low or off, and applies to KLIPY only.

Bots ​

yaml
bots:
  maxPerServer: 50
  maxPerCreator: 10

How many bots a server can have, and how many one person can create in it, from 1 to 1,000. Disabled and suspended bots count too. Optional.

Federation ​

yaml
federation:
  enabled: false
  privateKeyPath: /data/federation/instance-ed25519.pem
  allowedInstances: []
  blockedInstances: []
  approvalRequired: false
  allowInsecureHttp: false
  queueWorkers: separate
  media:
    prune:
      daysSinceLastAccess: 30
      maxOverallSizeGB: 10

Off unless enabled. See Federation for what each setting does. In Docker, keep privateKeyPath on /data and queueWorkers: separate, since the image runs the federation workers itself.

Released under the GNU Affero General Public License v3.0.