diff --git a/README.MD b/README.MD index b6ae2e51..c07aa801 100644 --- a/README.MD +++ b/README.MD @@ -127,6 +127,10 @@ Need customization or production setup? Continue reading below ↓ | BRAND_CONFIG | No | Brand config for white labeling. Requires license. In format `{ "name": "Quantum Labs", "shortName": "QL", "website": "https://example.io", mail: "contact@example.io" }` | (empty) | | LDAP_ENABLED | No | Enables or disables LDAP. More variables are needed. You can get the full list [here](./dev-docs/LDAP_SETUP.md) | false | +#### Helm / Kubernetes deployments + +When deploying with Helm, setting an optional variable to an empty string in `values.yaml` causes Kubernetes to strip it from the container entirely. Simply omit optional variables you don't need — the application will treat them as disabled. Avoid using placeholder sentinels like `"-"` as they will be passed as real values to services like Google Analytics or reCAPTCHA and may cause unexpected behaviour. + For production deployments, it’s strongly recommended to use unique credentials and not rely on defaults. #### For remote servers diff --git a/api/src/main/resources/application.yml b/api/src/main/resources/application.yml index f9d6d503..a2343018 100644 --- a/api/src/main/resources/application.yml +++ b/api/src/main/resources/application.yml @@ -80,7 +80,7 @@ security: token: secret-key: ${JWT_SECRET_KEY} expire-length: 1209600000 # 1000*60*60*24*14 - invitation-via-email: ${INVITATION_VIA_EMAIL} + invitation-via-email: ${INVITATION_VIA_EMAIL:false} recaptcha-secret-key: ${RECAPTCHA_SECRET_KEY:} cors: enabled: ${ENABLE_CORS:true} @@ -96,7 +96,7 @@ frontend: home-url: ${PUBLIC_HOME_URL:} mail: recipients: ${MAIL_RECIPIENTS} - enable: ${ENABLE_EMAIL_NOTIFICATIONS} + enable: ${ENABLE_EMAIL_NOTIFICATIONS:false} type: ${MAIL_TYPE:SMTP} superAdmin: role: @@ -129,7 +129,7 @@ enable-sso: ${ENABLE_SSO:false} oauth2: success-redirect-url: ${PUBLIC_FRONT_URL}/oauth2/success failure-redirect-url: ${PUBLIC_FRONT_URL}/oauth2/failure - provider: ${OAUTH2_PROVIDER} + provider: ${OAUTH2_PROVIDER:} license-key: ${LICENSE_KEY:} license-fingerprint-required: ${LICENSE_FINGERPRINT_REQUIRED:true} license-file-path: ${LICENSE_FILE_PATH:} diff --git a/frontend/src/config.ts b/frontend/src/config.ts index 376298b2..0a7eb720 100644 --- a/frontend/src/config.ts +++ b/frontend/src/config.ts @@ -2,9 +2,13 @@ const getRuntimeValue = ( key: string, defaultValue = '' ): string | undefined => { - const envValue = process.env[`REACT_APP_${key}`]; + const envValue = process.env[`REACT_APP_${key}`]?.trim(); const runtimeValue = window.__RUNTIME_CONFIG__?.[key]?.trim(); - return envValue || runtimeValue || defaultValue; + const value = envValue || runtimeValue || defaultValue; + if (!value || value.trim() === '' || value.trim() === '-' || value.trim() === 'disabled') { + return undefined; + } + return value.trim(); }; export const firebaseConfig = { @@ -87,15 +91,13 @@ export const brandRawConfig: BrandRawConfig = getRuntimeValue('BRAND_CONFIG') ? JSON.parse(getRuntimeValue('BRAND_CONFIG')) : null; -export const demoLink: string = getRuntimeValue('DEMO_LINK'); +export const demoLink: string = getRuntimeValue('DEMO_LINK') ?? ''; export const isWhiteLabeled: boolean = !!(customLogoPaths || brandRawConfig); export const IS_ORIGINAL_CLOUD = !isWhiteLabeled && isCloudVersion; -export const PADDLE_SECRET_TOKEN: string = getRuntimeValue( - 'PADDLE_SECRET_TOKEN' -); +export const PADDLE_SECRET_TOKEN: string = getRuntimeValue('PADDLE_SECRET_TOKEN') ?? ''; export const paddleEnvironment = getRuntimeValue('PADDLE_ENVIRONMENT') as | 'sandbox'