Skip to content

Configuration

The HOCON reference for a self-hosted Kalendee server: config-file precedence, ${?ENV} substitutions, and every key in ktor, database, auth, app, oauth, mail, storage, and keel.

Kalendee is configured with a single HOCON file loaded by Ktor’s EngineMain. The authoritative defaults live in server/src/main/resources/application.conf, baked into the fat jar. Operators normally supply their own copy; the commented starting points are application.conf.example (production) and application.conf.dev.example (development).

For the environment-variable view of the same keys see Environment variables.

How configuration is loaded

Precedence

The Docker entrypoint (docker/entrypoint.sh) resolves the config file before starting the JVM. Highest priority first:

OrderSourceNotes
1-config=/path passed after the image nameExplicit operator choice; passed through untouched. Both -config=/p and -config /p are detected.
2KALENDEE_CONFIG environment variableSet in .env; compose defaults it to /config/application.conf.
3/config/application.confThe file compose mounts read-only from ./application.conf.
4/app/application.confBaked into the image (a copy of application.conf.example).
5Jar defaultsserver/src/main/resources/application.conf on the classpath.

docker-compose.yml mounts ./application.conf:/config/application.conf:ro and sets KALENDEE_CONFIG=/config/application.conf, so entry 2 normally selects entry 3. With nothing mounted, the image still boots on the baked config. The standalone (non-Docker) paths are covered in Standalone binary and Docker Compose.

When you run ./gradlew :server:run directly, the Gradle run task loads .env.local into the process (real environment variables win) and the -config argument is threaded through KALENDEE_CONFIG.

HOCON essentials

A few rules cover everything you will write:

  • The file is a tree of objects. The top level is implicit; blocks use braces: database { url = "..." } is database.url.
  • Strings must be quoted when they contain :, spaces, @, or other special characters. Booleans and numbers may be unquoted.
  • Comments start with # or //.
  • Arrays use square brackets, e.g. modules = [ dev.kolektiv.kalendee.ApplicationKt.module ].
  • Repeating the same key assigns twice. Combined with an optional substitution (below), the idiom key = <default> followed by key = ${?ENV} lets the environment override the default while leaving the default in place when the variable is unset.
  • This server has no duration syntax: lifetimes are plain integers with a unit in the key name (sessionDays, emailVerificationTtlHours, timeoutSeconds).

${?ENV} substitution

Every tunable in the baseline config ends with an optional substitution:

auth {
    sessionDays = 30
    sessionDays = ${?KALENDEE_AUTH_SESSION_DAYS}
}

${?VAR} is Typesafe Config syntax and resolves from JVM system properties and process environment variables. If VAR is unset the substitution is undefined and the preceding value (30) remains; if it is set, its value replaces the default. Because the substitution only overrides keys that already exist in the loaded file, environment variables cannot introduce keys your HOCON file does not contain. A fully standalone config must therefore carry every key you want to set from the environment — which is why both example files repeat the ${?VAR} lines.

A standalone config file also has to carry the Ktor module entry point, because it is loaded instead of the jar’s config rather than merged with it:

ktor {
    application {
        modules = [ dev.kolektiv.kalendee.ApplicationKt.module ]
    }
}

ktor.deployment.*

KeyTypeDefaultEnv fallbackMeaning
ktor.deployment.portinteger8080KALENDEE_HTTP_PORTTCP port the server binds. Can also be overridden with -port=<n>.
ktor.deployment.hoststring"0.0.0.0"KALENDEE_HTTP_HOSTInterface to bind. 0.0.0.0 listens on all interfaces, correct for a container behind a proxy.
ktor.application.modulesarray[ dev.kolektiv.kalendee.ApplicationKt.module ]Ktor module entry point. Required in a standalone config.

The container always exposes port 8080; the host-side mapping is the compose-only KALENDEE_HOST_PORT (see Environment variables).

database.*

Full operational detail is in Database.

KeyTypeDefaultEnv fallbackMeaning
database.urlstring"jdbc:postgresql://127.0.0.1:5432/kalendee"KALENDEE_DATABASE_URLJDBC URL. May embed user:password@; the server splits and strips it.
database.userstring"kalendee" (or parsed from the URL)KALENDEE_DATABASE_USERDatabase role.
database.passwordstringrequired, no defaultKALENDEE_DATABASE_PASSWORDDatabase password. An empty value is allowed for trust/peer auth.
database.migrationsstring"classpath:db/migration"Flyway migration location. Not present in the example config; only useful for tests or external migrations. Values without a classpath:/filesystem: prefix are treated as filesystem paths.

If database.password is unset and the JDBC URL carries no password, startup fails with KALENDEE_DATABASE_PASSWORD is required.

auth.*

KeyTypeDefaultEnv fallbackMeaning
auth.registrationenum string"first-user"KALENDEE_AUTH_REGISTRATIONPublic sign-up policy: first-user, open, or closed. Case-insensitive; first_user/firstuser also parse as first-user.
auth.sessionDaysinteger30KALENDEE_AUTH_SESSION_DAYSSession lifetime in days.
auth.cookieNamestring"kalendee_session"KALENDEE_SESSION_COOKIE_NAMESession cookie name.
auth.cookieSecureboolean!developmentKALENDEE_COOKIE_SECURERequire HTTPS for the session cookie. Defaults to secure outside development; set false only when serving plain HTTP.
auth.adminUsernamestring"admin"KALENDEE_ADMIN_USERNAMEUsername created as the first admin on startup.
auth.adminPasswordstringunsetKALENDEE_ADMIN_PASSWORDPassword for that admin. Blank/unset disables seeding.
auth.superadminUsernamestringunsetKALENDEE_SUPERADMIN_USERNAMEUsername granted superadmin rights, if it exists. Lowercased.
auth.emailVerificationenum string"optional"KALENDEE_AUTH_EMAIL_VERIFICATIONEmail verification policy: optional, soft, or required. Only required blocks login until verified.
auth.emailVerificationTtlHoursinteger24KALENDEE_AUTH_EMAIL_VERIFICATION_TTL_HOURSVerification-link lifetime in hours. Non-positive values fall back to 24.
auth.oauthRegistrationbooleanfalseKALENDEE_AUTH_OAUTH_REGISTRATIONAllow OAuth sign-ins to create accounts. Still gated by auth.registration.
auth.argon2.memoryKibinteger19456KALENDEE_ARGON2_MEMORY_KIBArgon2id memory cost in KiB.
auth.argon2.iterationsinteger2KALENDEE_ARGON2_ITERATIONSArgon2id iteration count.
auth.argon2.parallelisminteger1KALENDEE_ARGON2_PARALLELISMArgon2id parallelism factor.

Notes:

  • auth.registration is the initial policy. An admin can change it at runtime from the admin page; the stored value wins over the config. Likewise emailVerification and oauthRegistration have runtime overrides.
  • first-user keeps sign-ups open only while the users table is empty, so seeding an admin with auth.adminPassword closes public registration.
  • soft verification sends a verification link and shows a prompt but does not block login; required does. There is no off value despite older comments in the example files.
  • Argon2id is used for password hashing with a 16-byte random salt and a 32-byte hash. Raising the costs makes new hashes slower; existing hashes keep verifying with the parameters they were created with.

app.*

KeyTypeDefaultEnv fallbackMeaning
app.baseUrlstring""KALENDEE_PUBLIC_URL and KALENDEE_BASE_URLCanonical public URL used for email links, RSS, and OAuth redirect URIs. Trailing slash is trimmed. KALENDEE_PUBLIC_URL is the preferred spelling; KALENDEE_BASE_URL is a deprecated alias. If both are set, the later substitution (KALENDEE_BASE_URL) wins — set only KALENDEE_PUBLIC_URL.
app.developmentbooleanfalseKALENDEE_DEVELOPMENTPretty HTML error page and development baseUrl default. Must stay false in production.
app.publicAccessenum string"public"KALENDEE_PUBLIC_ACCESSInstance default for anonymous access to public calendars: public or signed_in. Per-user and per-calendar overrides win.
app.seedDemobooleanfalseKALENDEE_SEED_DEMOSeed demo users (demo, sam, alex) with sample data. Development/screenshots only.
app.demoPasswordstring"demo"KALENDEE_DEMO_PASSWORDPassword for the seeded demo users.
app.demoTimezonestring"Europe/Berlin"KALENDEE_DEMO_TIMEZONETime zone for seeded demo data.

app.baseUrl behavior when blank:

ConditionResult
app.development = truehttp://127.0.0.1:<ktor.deployment.port> (default http://127.0.0.1:8080).
app.development = falseEmpty; email links are logged as relative paths and logged-out RSS/OAuth flows will not have an absolute origin. Set it explicitly in production.

The value should start with http:// or https://; the server logs a warning but uses it as-is otherwise. Ktor’s own development flag (for engine dev-mode behaviour) is separate from app.development; the dev example sets ktor.development = true as well.

oauth.*

Discord is the only implemented provider. A blank clientId disables it. See Discord OAuth for the end-to-end setup.

KeyTypeDefaultEnv fallbackMeaning
oauth.discord.clientIdstringunset (disabled)KALENDEE_DISCORD_CLIENT_IDDiscord OAuth application client id. Blank disables the provider.
oauth.discord.clientSecretstringunsetKALENDEE_DISCORD_CLIENT_SECRETDiscord OAuth client secret.
oauth.discord.botTokenstringunsetKALENDEE_DISCORD_BOT_TOKENBot token for reading guild scheduled events. Optional: account linking works without it, event import does not.
oauth.secretKeystringunsetKALENDEE_SECRET_KEYBase64 AES key (16/24/32 bytes) stored as token-vault version 1. Required before any provider can be connected. Generate with openssl rand -base64 32.
oauth.secretKeysJSON object stringunsetKALENDEE_SECRET_KEYSOptional {"<version>":"<base64>","<version>":"<base64>"} map for key rotation. Highest version is the sealing key; older versions remain readable.

Values are trimmed and blank strings are treated as unset. Losing every key makes existing encrypted connection tokens unreadable; connections must be re-authorized.

mail.*

See Email for provider selection and testing.

KeyTypeDefaultEnv fallbackMeaning
mail.enabledbooleanfalseKALENDEE_MAIL_ENABLEDInput to provider auto-detection. When false and mail.provider is blank, the logging mailer is used. An explicit mail.provider overrides it.
mail.providerenum string"" (auto)KALENDEE_MAIL_PROVIDERsmtp, cloudflare, mailgun, or log. Unknown values warn and fall back to log. Blank auto-detects.
mail.hoststring""KALENDEE_SMTP_HOSTSMTP host. Blank disables SMTP in auto-detection.
mail.portinteger587KALENDEE_SMTP_PORTSMTP port.
mail.usernamestring""KALENDEE_SMTP_USERSMTP username. Blank disables authentication (useful for a local relay).
mail.passwordstring""KALENDEE_SMTP_PASSWORDSMTP password. Blank becomes absent; the authenticator sends an empty string.
mail.fromstring"Kalendee <no-reply@localhost>"KALENDEE_MAIL_FROMFrom header for every message.
mail.startTlsbooleantrueKALENDEE_SMTP_STARTTLSEnable STARTTLS on the SMTP connection.
mail.cloudflare.endpointstring""KALENDEE_MAIL_CLOUDFLARE_ENDPOINTBase URL of the deployed mailer Worker.
mail.cloudflare.tokenstring""KALENDEE_MAIL_CLOUDFLARE_TOKENBearer token sent in Authorization. Must equal the Worker’s MAILER_TOKEN.
mail.cloudflare.timeoutSecondsinteger10KALENDEE_MAIL_CLOUDFLARE_TIMEOUT_SECONDSHTTP connect/request timeout. Non-positive values fall back to 10.
mail.mailgun.apiKeystringunsetKALENDEE_MAILGUN_API_KEYMailgun private API key. Blank disables Mailgun in auto-detection.
mail.mailgun.domainstringunsetKALENDEE_MAILGUN_DOMAINVerified Mailgun sending domain; also the {domain} segment of the request path.
mail.mailgun.regionstring"us"KALENDEE_MAILGUN_REGIONus or eu. Picks api.mailgun.net or api.eu.mailgun.net when baseUrl is blank. Anything other than eu is treated as US.
mail.mailgun.baseUrlstring""KALENDEE_MAILGUN_BASE_URLOptional API base URL override for a custom Mailgun endpoint. Trailing slashes are trimmed; blank derives the host from region.
mail.mailgun.timeoutSecondsinteger10KALENDEE_MAILGUN_TIMEOUT_SECONDSHTTP connect/request timeout. Non-positive values fall back to 10.

Auto-detection order when mail.provider is blank:

  1. mail.enabled = falselog.
  2. mail.host set → smtp.
  3. mail.cloudflare.endpoint set → cloudflare.
  4. mail.mailgun.apiKey and mail.mailgun.domain set → mailgun.
  5. Otherwise → log.

mail.enabled is not a hard kill switch: setting mail.provider explicitly selects that transport even if mail.enabled = false. The server also validates the chosen transport at startup and falls back to the logging mailer if smtp has a blank host, cloudflare is missing its endpoint or token, or mailgun is missing its API key or domain.

Cloudflare’s send_email Email Routing binding is a paid feature, so mailgun is the non-SMTP transport to use when it is unavailable.

storage.*

See Object storage and Cloudflare Workers.

KeyTypeDefaultEnv fallbackMeaning
storage.localDirstring"build/avatars"KALENDEE_AVATAR_DIRDirectory for the local filesystem backend. The image sets this to /data/avatars.
storage.publicBaseUrlstring""KALENDEE_STORAGE_PUBLIC_URLOptional public base URL for objects (R2/CDN). When set, avatar reads 302-redirect to ${publicBaseUrl}/${key}?v=<version> instead of proxying bytes.
storage.s3.enabledbooleanfalseKALENDEE_S3_ENABLEDUse the S3-compatible backend. When disabled (or bucket is blank) storage.localDir is used.
storage.s3.endpointstring""KALENDEE_S3_ENDPOINTS3 endpoint. Set for non-AWS providers such as Cloudflare R2. Blank uses the AWS default.
storage.s3.regionstring"us-east-1"KALENDEE_S3_REGIONS3 region. R2 ignores it but the SDK requires one; use auto.
storage.s3.bucketstring""KALENDEE_S3_BUCKETBucket name.
storage.s3.accessKeystringunsetKALENDEE_S3_ACCESS_KEYAccess key id. If both keys are blank the SDK default credential chain is used.
storage.s3.secretKeystringunsetKALENDEE_S3_SECRET_KEYSecret access key.
storage.s3.pathStylebooleantrueKALENDEE_S3_PATH_STYLEPath-style addressing. Required by Cloudflare R2.

If either S3 credential key is non-null, a static credentials provider is built from both values (accessKey.orEmpty() / secretKey.orEmpty()), so supply both or neither.

keel.*

KeyTypeDefaultEnv fallbackMeaning
keel.packDirstringunsetKALENDEE_KEEL_PACKExploded Keel pack (directory) or a .feb file to load instead of the pack bundled in the jar. Intended for development/watch mode; leave unset in production.

Complete production example

A standalone config ready to mount at /config/application.conf. Replace the placeholder URL and keep secrets in .env.

ktor {
    deployment {
        port = 8080
        port = ${?KALENDEE_HTTP_PORT}
        host = "0.0.0.0"
        host = ${?KALENDEE_HTTP_HOST}
    }
    application {
        modules = [ dev.kolektiv.kalendee.ApplicationKt.module ]
    }
}

database {
    url = "jdbc:postgresql://postgres:5432/kalendee"
    url = ${?KALENDEE_DATABASE_URL}
    user = "kalendee"
    user = ${?KALENDEE_DATABASE_USER}
    password = ${?KALENDEE_DATABASE_PASSWORD}
}

auth {
    registration = "first-user"
    registration = ${?KALENDEE_AUTH_REGISTRATION}
    sessionDays = 30
    sessionDays = ${?KALENDEE_AUTH_SESSION_DAYS}
    cookieName = "kalendee_session"
    cookieName = ${?KALENDEE_SESSION_COOKIE_NAME}
    cookieSecure = true
    cookieSecure = ${?KALENDEE_COOKIE_SECURE}
    adminUsername = "admin"
    adminUsername = ${?KALENDEE_ADMIN_USERNAME}
    adminPassword = ${?KALENDEE_ADMIN_PASSWORD}
    superadminUsername = ${?KALENDEE_SUPERADMIN_USERNAME}
    emailVerification = "optional"
    emailVerification = ${?KALENDEE_AUTH_EMAIL_VERIFICATION}
    emailVerificationTtlHours = 24
    emailVerificationTtlHours = ${?KALENDEE_AUTH_EMAIL_VERIFICATION_TTL_HOURS}
    oauthRegistration = false
    oauthRegistration = ${?KALENDEE_AUTH_OAUTH_REGISTRATION}
    argon2 {
        memoryKib = 19456
        memoryKib = ${?KALENDEE_ARGON2_MEMORY_KIB}
        iterations = 2
        iterations = ${?KALENDEE_ARGON2_ITERATIONS}
        parallelism = 1
        parallelism = ${?KALENDEE_ARGON2_PARALLELISM}
    }
}

app {
    baseUrl = "https://calendar.example.com"
    baseUrl = ${?KALENDEE_PUBLIC_URL}
    baseUrl = ${?KALENDEE_BASE_URL}
    development = false
    development = ${?KALENDEE_DEVELOPMENT}
    publicAccess = "public"
    publicAccess = ${?KALENDEE_PUBLIC_ACCESS}
    seedDemo = false
    seedDemo = ${?KALENDEE_SEED_DEMO}
    demoPassword = "demo"
    demoPassword = ${?KALENDEE_DEMO_PASSWORD}
    demoTimezone = "Europe/Berlin"
    demoTimezone = ${?KALENDEE_DEMO_TIMEZONE}
}

oauth {
    discord {
        clientId = ${?KALENDEE_DISCORD_CLIENT_ID}
        clientSecret = ${?KALENDEE_DISCORD_CLIENT_SECRET}
        botToken = ${?KALENDEE_DISCORD_BOT_TOKEN}
    }
    secretKey = ${?KALENDEE_SECRET_KEY}
    secretKeys = ${?KALENDEE_SECRET_KEYS}
}

mail {
    enabled = true
    enabled = ${?KALENDEE_MAIL_ENABLED}
    provider = "cloudflare"
    provider = ${?KALENDEE_MAIL_PROVIDER}
    host = ""
    host = ${?KALENDEE_SMTP_HOST}
    port = 587
    port = ${?KALENDEE_SMTP_PORT}
    username = ""
    username = ${?KALENDEE_SMTP_USER}
    password = ""
    password = ${?KALENDEE_SMTP_PASSWORD}
    from = "Kalendee <no-reply@example.com>"
    from = ${?KALENDEE_MAIL_FROM}
    startTls = true
    startTls = ${?KALENDEE_SMTP_STARTTLS}
    cloudflare {
        endpoint = "https://kalendee-mailer.<subdomain>.workers.dev"
        endpoint = ${?KALENDEE_MAIL_CLOUDFLARE_ENDPOINT}
        token = ${?KALENDEE_MAIL_CLOUDFLARE_TOKEN}
        timeoutSeconds = 10
        timeoutSeconds = ${?KALENDEE_MAIL_CLOUDFLARE_TIMEOUT_SECONDS}
    }
    mailgun {
        apiKey = ${?KALENDEE_MAILGUN_API_KEY}
        domain = ${?KALENDEE_MAILGUN_DOMAIN}
        region = "us"
        region = ${?KALENDEE_MAILGUN_REGION}
        baseUrl = ""
        baseUrl = ${?KALENDEE_MAILGUN_BASE_URL}
        timeoutSeconds = 10
        timeoutSeconds = ${?KALENDEE_MAILGUN_TIMEOUT_SECONDS}
    }
}

storage {
    localDir = "/data/avatars"
    localDir = ${?KALENDEE_AVATAR_DIR}
    publicBaseUrl = "https://kalendee-r2.<subdomain>.workers.dev"
    publicBaseUrl = ${?KALENDEE_STORAGE_PUBLIC_URL}
    s3 {
        enabled = true
        enabled = ${?KALENDEE_S3_ENABLED}
        endpoint = "https://<account-id>.r2.cloudflarestorage.com"
        endpoint = ${?KALENDEE_S3_ENDPOINT}
        region = "auto"
        region = ${?KALENDEE_S3_REGION}
        bucket = "<bucket-name>"
        bucket = ${?KALENDEE_S3_BUCKET}
        accessKey = ${?KALENDEE_S3_ACCESS_KEY}
        secretKey = ${?KALENDEE_S3_SECRET_KEY}
        pathStyle = true
        pathStyle = ${?KALENDEE_S3_PATH_STYLE}
    }
}

keel {
    packDir = ${?KALENDEE_KEEL_PACK}
}

Complete development example

The dev example mirrors the same key set with local defaults. It is mounted at /config/application.conf by docker-compose.dev.yml.

ktor {
    development = true
    deployment {
        port = 8080
        port = ${?KALENDEE_HTTP_PORT}
        host = "0.0.0.0"
        host = ${?KALENDEE_HTTP_HOST}
    }
    application {
        modules = [ dev.kolektiv.kalendee.ApplicationKt.module ]
    }
}

database {
    url = "jdbc:postgresql://postgres:5432/kalendee"
    url = ${?KALENDEE_DATABASE_URL}
    user = "kalendee"
    user = ${?KALENDEE_DATABASE_USER}
    password = "kalendee"
    password = ${?KALENDEE_DATABASE_PASSWORD}
}

auth {
    registration = "first-user"
    registration = ${?KALENDEE_AUTH_REGISTRATION}
    sessionDays = 30
    sessionDays = ${?KALENDEE_AUTH_SESSION_DAYS}
    cookieName = "kalendee_session"
    cookieName = ${?KALENDEE_SESSION_COOKIE_NAME}
    cookieSecure = false
    cookieSecure = ${?KALENDEE_COOKIE_SECURE}
    adminUsername = "admin"
    adminUsername = ${?KALENDEE_ADMIN_USERNAME}
    adminPassword = "admin"
    adminPassword = ${?KALENDEE_ADMIN_PASSWORD}
    superadminUsername = ${?KALENDEE_SUPERADMIN_USERNAME}
    emailVerification = "optional"
    emailVerification = ${?KALENDEE_AUTH_EMAIL_VERIFICATION}
    emailVerificationTtlHours = 24
    emailVerificationTtlHours = ${?KALENDEE_AUTH_EMAIL_VERIFICATION_TTL_HOURS}
    oauthRegistration = false
    oauthRegistration = ${?KALENDEE_AUTH_OAUTH_REGISTRATION}
    argon2 {
        memoryKib = 19456
        memoryKib = ${?KALENDEE_ARGON2_MEMORY_KIB}
        iterations = 2
        iterations = ${?KALENDEE_ARGON2_ITERATIONS}
        parallelism = 1
        parallelism = ${?KALENDEE_ARGON2_PARALLELISM}
    }
}

app {
    baseUrl = "http://localhost:8080"
    baseUrl = ${?KALENDEE_PUBLIC_URL}
    baseUrl = ${?KALENDEE_BASE_URL}
    development = true
    development = ${?KALENDEE_DEVELOPMENT}
    publicAccess = "public"
    publicAccess = ${?KALENDEE_PUBLIC_ACCESS}
    seedDemo = true
    seedDemo = ${?KALENDEE_SEED_DEMO}
    demoPassword = "demo"
    demoPassword = ${?KALENDEE_DEMO_PASSWORD}
    demoTimezone = "Europe/Berlin"
    demoTimezone = ${?KALENDEE_DEMO_TIMEZONE}
}

oauth {
    discord {
        clientId = ${?KALENDEE_DISCORD_CLIENT_ID}
        clientSecret = ${?KALENDEE_DISCORD_CLIENT_SECRET}
        botToken = ${?KALENDEE_DISCORD_BOT_TOKEN}
    }
    secretKey = ${?KALENDEE_SECRET_KEY}
    secretKeys = ${?KALENDEE_SECRET_KEYS}
}

mail {
    enabled = false
    enabled = ${?KALENDEE_MAIL_ENABLED}
    provider = ""
    provider = ${?KALENDEE_MAIL_PROVIDER}
    host = ""
    host = ${?KALENDEE_SMTP_HOST}
    port = 587
    port = ${?KALENDEE_SMTP_PORT}
    username = ""
    username = ${?KALENDEE_SMTP_USER}
    password = ""
    password = ${?KALENDEE_SMTP_PASSWORD}
    from = "Kalendee <no-reply@localhost>"
    from = ${?KALENDEE_MAIL_FROM}
    startTls = true
    startTls = ${?KALENDEE_SMTP_STARTTLS}
    cloudflare {
        endpoint = ""
        endpoint = ${?KALENDEE_MAIL_CLOUDFLARE_ENDPOINT}
        token = ""
        token = ${?KALENDEE_MAIL_CLOUDFLARE_TOKEN}
        timeoutSeconds = 10
        timeoutSeconds = ${?KALENDEE_MAIL_CLOUDFLARE_TIMEOUT_SECONDS}
    }
    mailgun {
        apiKey = ${?KALENDEE_MAILGUN_API_KEY}
        domain = ${?KALENDEE_MAILGUN_DOMAIN}
        region = "us"
        region = ${?KALENDEE_MAILGUN_REGION}
        baseUrl = ""
        baseUrl = ${?KALENDEE_MAILGUN_BASE_URL}
        timeoutSeconds = 10
        timeoutSeconds = ${?KALENDEE_MAILGUN_TIMEOUT_SECONDS}
    }
}

storage {
    localDir = "/src/build/avatars"
    localDir = ${?KALENDEE_AVATAR_DIR}
    publicBaseUrl = ""
    publicBaseUrl = ${?KALENDEE_STORAGE_PUBLIC_URL}
    s3 {
        enabled = false
        enabled = ${?KALENDEE_S3_ENABLED}
        endpoint = ""
        endpoint = ${?KALENDEE_S3_ENDPOINT}
        region = "us-east-1"
        region = ${?KALENDEE_S3_REGION}
        bucket = ""
        bucket = ${?KALENDEE_S3_BUCKET}
        accessKey = ${?KALENDEE_S3_ACCESS_KEY}
        secretKey = ${?KALENDEE_S3_SECRET_KEY}
        pathStyle = true
        pathStyle = ${?KALENDEE_S3_PATH_STYLE}
    }
}

keel {
    packDir = ${?KALENDEE_KEEL_PACK}
}

Edit this page on GitHub