Skip to content

Configuration

When the application boots up, configuration values are gathered in the following manner:

  1. Values are read from the file system at <CONFIG_DIR>/<VARIABLE_NAME>.
  2. If no file is found at the appropriate location, the existence of a system environment variable is checked next.
  3. If neither strategy produces a value, the application fails when a value is required, uses a default or ignores it when optional.
VariableDescriptionRequiredDefault
CONFIG_DIRAbsolute path from which to load config valuesNo/run/secrets

For example, if a file exists at /run/secrets/DATABASE_URL, its contents is used as the value for that configuration parameter. If it doesn't, the application code will check for a system variable named DATABASE_URL. If none is found, the application will raise an exception, as an explicit value for this variable is required.

The loading of .env files as system variables is made more convenient with the use of the with_env.sh script:

shell
./with_env.sh mix phx.server # will load config values from `.env`
./with_env.sh --env .env.test mix test # will load config values from `.env.test`

An example of such a file is found in .env.sample.

Application

Database

VariableDescriptionRequiredDefault
DATABASE_URLPostgres connection string, e.g. postgres://user:pass@host:port/db❗Yes-
DB_SSLWhether to use SSL/TLS to connect to the database, true or falseNofalse
POOL_SIZESize of the pool used by the database connection moduleNo10
QUEUE_TARGETTarget wait-time used by the database connection moduleNo5_000

More information about the DATABASE_URL variable can be found in the Ecto.Repo docs. The DB_SSL config maps to the :ssl Postgrex option. The variables POOL_SIZE and QUEUE_TARGET affect the behaviour of the underlying database connection module.

Server

VariableDescriptionRequiredDefault
SECRET_KEY_BASESecret key base, generate with mix phx.gen.secret or openssl rand -base64 48❗Yes-
BASE_URLServer's base URL, e.g. https://claper.example.com❗Yes-
PORTServer's portNo4000
LISTEN_IPIP to bind the server to, as a stringNo0.0.0.0
SAME_SITE_COOKIESameSite attribute for cookies, Lax or NoneNoLax
SECURE_COOKIESecure attribute for cookies, true or falseNofalse

The LISTEN_IP variable corresponds with the :ip option for Plug.Cowboy.

Features

VariableDescriptionRequiredDefault
ENABLE_ACCOUNT_CREATIONEnable/disable user registration, true or falseNotrue
EMAIL_CONFIRMATIONEnable/disable sign-up confirmation email, true or falseNofalse
LOGOUT_REDIRECT_URLURL to redirect the user to after logoutNo/
LANGUAGESList of languages users will be able to choose fromNoen,fr,es,it,de

Languages are specified as a comma-separated list of ISO 639 language codes. The current list of supported languages—thanks to our generous contributors—is German (de), English (en), Spanish (es), French (fr), Hungarian (hu), Italian (it), Latvian (lv) and Dutch (nl). Translation of Claper is a community effort. If you find some translation lacking, feel free to contribute.

Presentation storage

When a user creates and event and adds a presentation to it, a unique hash is created from the file using the following two steps:

elixir
hash = :erlang.phash2("#{code}-#{name}")
final_hash = :erlang.phash2("#{hash}-#{System.system_time(:second)}")

Each page of the input file is transformed into a JPG image and stored, together with the presentation file, in a folder named after this computed hash. These files can be stored on the file system of the server running the application or on S3-compatible object storage.

VariableDescriptionRequiredDefault
PRESENTATION_STORAGESelect storage type to use: local or s3Nolocal
MAX_FILE_SIZE_MBMax size allowed for uploads in MBNo15
GS_JPG_RESOLUTIONDPI of generated JPG presentation slidesNo300x300

Using the file system

When PRESENTATION_STORAGE=local, the following variable can be used to customise the path where presentation files are stored. With the default value, each presentation will have its files stored under priv/static/uploads/<hash>. The uploads folder will be created automatically if it doesn't exist.

VariableDescriptionRequiredDefault
PRESENTATION_STORAGE_DIRRelative file system pathNopriv/static (/app/uploads for Docker)

Using S3

When PRESENTATION_STORAGE=s3, the following variables are required. When a user uploads a new presentation, the destination file is uploaded to the specified S3 bucket under presentations/<hash>.

VariableDescriptionRequiredDefault
S3_ACCESS_KEY_IDS3 service access key ID❓Yes, if using S3-
S3_SECRET_ACCESS_KEYS3 service secret access key❓Yes, if using S3-
S3_REGIONRegion where the bucket is located❓Yes, if using S3-
S3_BUCKETBucket name❓Yes, if using S3-

When using an S3-compatible service as an alternative to AWS, these additional variables can be used to define a custom S3 endpoint:

VariableDescriptionRequiredDefault
S3_SCHEMEURI scheme, typically https:// or http://❓Yes, if using AWS alternative-
S3_HOSTHost name❓Yes, if using AWS alternative-
S3_PORTPortNo-

If the S3-compatible service uses different URLs for writes and public reads (like Cloudflare R2 development URLs, for example), the following variable can be used to define that:

VariableDescriptionRequiredDefault
S3_PUBLIC_URLS3 public read URLNo-

Email delivery

The following are some configuration parameters common to all email setups:

VariableDescriptionRequiredDefault
MAIL_TRANSPORTHow to send emails, local, smtp or postmarkNolocal
MAIL_FROMEmail address for the From field in outbound emailsNonoreply@claper.co
MAIL_FROM_NAMEName for the From field in outbound emailsNoClaper

The value of local for MAIL_TRANSPORT is typically only useful during development used in conjunction with the web-based mailbox feature. The smtp and postmark options are explained below.

Using SMTP

When MAIL_TRANSPORT=smtp, the following configuration parameters exist:

VariableDescriptionRequiredDefault
SMTP_RELAYHost name of SMTP relay, e.g. smtp.example.com❓Yes, if using SMTP-
SMTP_PORTPort of SMTP relayNo465
SMTP_RETRIESRetries upon server connection failureNo1
SMTP_NO_MX_LOOKUPSWhether to perform an MX lookup on the relay domain, true or falseNotrue

These options are provided to Swoosh, which itself then forwards them to gen_smtp. gen_smtp by default checks the domain given in SMTP_RELAY for MX records and attempts delivery using those servers rather than the host given, if any are found.

Authentication for the SMTP relay server is configured with the following variables:

VariableDescriptionRequiredDefault
SMTP_AUTHWhether to use authentication, always, if_available, neverNoalways
SMTP_USERNAMESMTP username❓Yes, if using authenticated SMTP-
SMTP_PASSWORDSMTP password❓Yes, if using authenticated SMTP-

The connection to the SMTP relay server can be configured with the following variables:

VariableDescriptionRequiredDefault
SMTP_SSLEnable SSL over 465, true or falseNotrue
SMTP_TLSEnable usage of StartTLS, always, if_available or neverNoif_available
SMTP_SSL_DEPTHMax depth allowed for certificate chainNo2
SMTP_SSL_SERVERReferenceID, i.e. hostname, to check on the SSL certificateNoValue of SMTP_RELAY

Possibly due to historical reasons, the connection security can be a bit tricky or confusing to set up. According to the SMTP adapter documentation, if the client should connect to the server using StartTLS, the SMTP_SSL option should be set to false. The following are some configuration examples that we tested.

Using Resend:

dotenv
SMTP_RELAY=smtp.resend.com
SMTP_PORT=465
# SMTP_RETRIES=1
# SMTP_NO_MX_LOOKUPS=false

# SMTP_AUTH=always
SMTP_USERNAME=xxx
SMTP_PASSWORD=xxx

# SMTP_SSL=true
# SMTP_TLS=if_available
# SMTP_SSL_DEPTH=2
SMTP_SSL_SERVER=*.resend.com

Using Postmark (over SMTP):

dotenv
SMTP_RELAY=smtp.postmarkapp.com
SMTP_PORT=587
# SMTP_RETRIES=1
# SMTP_NO_MX_LOOKUPS=false

# SMTP_AUTH=always
SMTP_USERNAME=xxx
SMTP_PASSWORD=xxx

SMTP_SSL=false
SMTP_TLS=always
# SMTP_SSL_DEPTH=2
SMTP_SSL_SERVER=postmarkapp.com

Locally, with not connection security, with Mailpit:

dotenv
SMTP_RELAY=localhost
SMTP_PORT=1025
# SMTP_RETRIES=1
SMTP_NO_MX_LOOKUPS=true

SMTP_AUTH=never
# SMTP_USERNAME=xxx
# SMTP_PASSWORD=xxx

SMTP_SSL=false
SMTP_TLS=never
# SMTP_SSL_DEPTH=2
# SMTP_SSL_SERVER=*.example.com

Using Postmark

When MAIL_TRANSPORT=postmark, the application will use the Postmark HTTP API for email delivery. An API key is required:

VariableDescriptionRequiredDefault
POSTMARK_API_KEYPostmark's API key❓Yes, if using Postmark-

Web-based mailbox

When in development environment (MIX_ENV=dev), the server provides a web-based mailbox displaying emails that would have normally be sent in production. This mailbox is accessible on the /dev/mailbox route and can be disabled and protected with Basic HTTP authentication.

VariableDescriptionRequiredDefault
ENABLE_MAILBOX_ROUTEEnable local mailbox route, true or falseNofalse
MAILBOX_USERBasic auth mailbox route user nameNo-
MAILBOX_PASSWORDBasic auth mailbox route passwordNo-

OpenID Connect

This section details the configuration values available when using the OIDC or LTI integrations.

VariableDescriptionRequiredDefault
OIDC_ISSUEROIDC issuer URL❓Yes, if using OIDChttps://accounts.google.com
OIDC_CLIENT_IDOIDC client ID❓Yes, if using OIDC-
OIDC_CLIENT_SECRETOIDC client secret❓Yes, if using OIDC-

The name and logo can be customised on the OIDC login page:

VariableDescriptionRequiredDefault
OIDC_LOGO_URLLogo URL to use for the login page buttonNo-
OIDC_PROVIDER_NAMEName of the OIDC provider to use for the login page buttonNoOpenID Connect

The following aspects of the integration can be controlled too:

VariableDescriptionRequiredDefault
OIDC_SCOPESScopes to useNoopenid email profile
OIDC_PROPERTY_MAPPINGSMapping of Claper user properties to OIDC user propertiesNo-
OIDC_AUTO_REDIRECT_LOGINRedirect user to the OIDC authentication process instead of the default login page, true or falseNofalse
ALLOW_UNLINK_EXTERNAL_PROVIDERAllow unlinking of external provider from email/password credentials, true or falseNofalse

The OIDC_PROPERTY_MAPPINGS defines the mapping of Claper user properties to OIDC user properties (mainly organisation and user roles). A key-value pair where the key is the Claper property and the value is the property name contained in the OIDC claims. For example:

roles:additional_infos.roles,organization:organization

Given this example, a working setup would have the OIDC provider returning the following claims:

json
{
  "acr": "goauthentik.io/providers/oauth2/default",
  "aud": "kGPN2rhtUO2PC3GAZOsnRmsGUjEdV4MMj7EO8vMu",
  "email": "user@example.com",
  "email_verified": true,
  "exp": 1722352313,
  "given_name": "John Doe",
  "groups": ["user"],
  "iat": 1722352013,
  "iss": "https://myprovider.com/application/o/claper/",
  "name": "John Doe",
  "nickname": "johndoe",
  "organization": "acme",
  "preferred_username": "johndoe",
  "additional_infos": {
    "roles": "1, 2, 3"
  },
  "sub": "e038a2dce4819247f6d0d3aacdde4a9ad2988daa66bf6372713a13babfa61aa4"
}