Environment Variables & Configuration
Learn how to configure your applications using environment variables, secrets, and runtime configuration.
Environment Variable Types
The Strongly platform supports three types of environment variables:
- Regular Variables: Standard configuration values
- Secrets: Encrypted sensitive data (passwords, API keys)
- Build-time Variables: Values injected during Docker build
Defining Variables in Manifest
Regular Environment Variables
Standard configuration values accessible at runtime:
env:
- name: API_URL
value: "https://api.example.com"
required: false
description: Backend API endpoint
- name: LOG_LEVEL
value: "info"
required: false
description: Application log level (debug, info, warn, error)
Secrets
Sensitive data stored as Kubernetes Secrets and encrypted at rest:
env:
- name: DATABASE_PASSWORD
value: "" # Provided by user during deployment
required: true
secret: true
description: PostgreSQL database password
- name: JWT_SECRET
value: ""
required: true
secret: true
description: Secret for JWT token signing
- name: API_KEY
value: ""
required: true
secret: true
description: Third-party API key
- Never commit secrets to version control
- Always mark sensitive values with
secret: true - Leave
valueempty for secrets - users provide them during deployment - Rotate secrets regularly
Build-time Variables
Values passed to Docker build as --build-arg:
env:
- name: NODE_ENV
value: "production"
buildtime: true
description: Node.js environment
- name: REACT_APP_VERSION
value: "1.0.0"
buildtime: true
description: Application version displayed in UI
- name: REACT_APP_API_URL
value: "https://api.acme.com"
buildtime: true
description: Baked into React build
Using in Dockerfile:
ARG NODE_ENV
ARG REACT_APP_VERSION
ARG REACT_APP_API_URL
ENV NODE_ENV=${NODE_ENV}
ENV REACT_APP_VERSION=${REACT_APP_VERSION}
ENV REACT_APP_API_URL=${REACT_APP_API_URL}
RUN npm run build
Variable Precedence
Environment variables can come from multiple sources. The platform applies them in this order (last wins):
- Manifest defaults (
strongly.manifest.yaml) - Platform injected (
STRONGLY_SERVICES, etc.) - User provided (during deployment)
- .env file (if included in archive)
Platform-Injected Variables
The platform automatically injects these variables into all app pods:
Core Platform Variables
| Variable | Description | Example |
|---|---|---|
STRONGLY_URL | Critical for frontend apps. Full proxy URL for API calls | http://localhost:3000/api/proxy/app-xyz123 |
STRONGLY_HOST | Platform host URL | http://localhost:3000 |
STRONGLY_APP_ID | Unique app identifier | app-xyz123 |
STRONGLY_SERVICES | JSON with all connected services | See below |
STRONGLY_URL (Critical for Frontend Apps)
When your app is displayed in the platform's iframe, frontend code needs to make API calls through the proxy. STRONGLY_URL provides the correct base URL.
Why this matters: Apps are accessed via /apps/app-xyz/view. Without STRONGLY_URL:
- ❌ API calls go to
http://localhost:3000/api/...(wrong - hits the platform, not your app) - ✅ With
STRONGLY_URL, API calls go tohttp://localhost:3000/api/proxy/app-xyz/api/...(correct - proxied to your app)
Server-side: Inject runtime config into HTML
// In your Express server's static file handler
app.get('*', (req, res) => {
const indexPath = path.join(__dirname, '../client/dist/index.html');
fs.readFile(indexPath, 'utf8', (err, data) => {
if (err) return res.status(500).send('Server error');
// Build runtime config from platform environment variables
const runtimeConfig = {
STRONGLY_URL: process.env.STRONGLY_URL || '',
STRONGLY_HOST: process.env.STRONGLY_HOST || '',
STRONGLY_APP_ID: process.env.STRONGLY_APP_ID || '',
API_URL: '/api'
};
// Inject into HTML
const modifiedHtml = data.replace(
'</head>',
`<script>window.__RUNTIME_CONFIG__ = ${JSON.stringify(runtimeConfig)};</script></head>`
);
res.send(modifiedHtml);
});
});
Client-side: Use runtime config for API calls
// In your API service (e.g., api.ts)
function getApiBaseUrl() {
const config = window.__RUNTIME_CONFIG__ || {};
if (config.STRONGLY_URL) {
// STRONGLY_URL = http://localhost:3000/api/proxy/app-xyz
// Append /api for your backend API routes
return `${config.STRONGLY_URL.replace(/\/$/, '')}/api`;
}
// Fallback for local development
return '/api';
}
const api = axios.create({
baseURL: getApiBaseUrl(),
timeout: 30000,
});
STRONGLY_SERVICES
JSON object containing all connected service credentials:
const services = JSON.parse(process.env.STRONGLY_SERVICES || '{}');
// Structure:
{
"services": {
"databases": {
"mongodb": [{
"id": "addon-xyz",
"type": "mongodb",
"connection": {
"connection_string": "mongodb://...",
"host": "addon-xyz.addons.svc.cluster.local",
"port": 27017
}
}]
},
"ai_gateway": {
"base_url": "http://localhost:3000/apps/app-xyz/ai-gateway",
"available_models": [...]
}
}
}
See STRONGLY_SERVICES Integration for detailed usage.
Authentication Headers
The platform injects authentication headers on all requests to your app:
| Header | Description | Example |
|---|---|---|
X-Auth-User-Id | Unique user identifier | FsbHXu34LHShtmb9L |
X-Auth-User-Email | User's email address | user@example.com |
X-Auth-User-Name | User's display name | John Doe |
X-Auth-App-Role | User's role in this app | admin, developer, app |
X-Auth-Platform-Role | Platform-wide role | admin, user |
X-Auth-Authenticated | Authentication status | true or false |
Using auth headers in Express:
// Middleware to extract user from headers
app.use((req, res, next) => {
req.user = {
id: req.headers['x-auth-user-id'] || 'anonymous',
email: req.headers['x-auth-user-email'] || null,
name: req.headers['x-auth-user-name'] || 'Anonymous',
appRole: req.headers['x-auth-app-role'] || 'app',
platformRole: req.headers['x-auth-platform-role'] || null,
authenticated: req.headers['x-auth-authenticated'] === 'true'
};
next();
});
// Use in routes
app.get('/api/profile', (req, res) => {
if (!req.user.authenticated) {
return res.status(401).json({ error: 'Not authenticated' });
}
res.json({ user: req.user });
});
Other Platform Variables
# Application metadata
APP_NAME=my-app
ENVIRONMENT=production # or development
# Kubernetes metadata
POD_NAME=my-app-7d8f6b9c4-x7k9m
POD_NAMESPACE=apps
POD_IP=10.0.2.15
Using .env Files
Include a .env file in your archive for additional variables:
.env:
# Development settings
DEBUG=true
CACHE_TTL=300
# Feature flags
FEATURE_NEW_UI=enabled
FEATURE_BETA_API=disabled
.envfiles are NOT encrypted- Don't put secrets in
.envfiles - Use manifest
secret: truefor sensitive data .envvalues override manifest defaults
Accessing Variables in Code
Node.js
// Access individual variables
const nodeEnv = process.env.NODE_ENV;
const apiKey = process.env.API_KEY;
// Parse STRONGLY_SERVICES
const services = JSON.parse(process.env.STRONGLY_SERVICES || '{}');
const mongoUrl = services.addons['addon-id-1'].connectionString;
Python
import os
import json
# Access individual variables
node_env = os.environ.get('NODE_ENV', 'development')
api_key = os.environ.get('API_KEY')
# Parse STRONGLY_SERVICES
services = json.loads(os.environ.get('STRONGLY_SERVICES', '{}'))
mongo_url = services['addons']['addon-id-1']['connectionString']
React (Build-time)
Variables prefixed with REACT_APP_ are embedded at build time:
// Access in React components
const apiUrl = process.env.REACT_APP_API_URL;
const version = process.env.REACT_APP_VERSION;
console.log('API URL:', apiUrl);
React environment variables must be prefixed with REACT_APP_ and marked as buildtime: true in the manifest.
Runtime Configuration Injection
For React/static apps, inject runtime configuration without rebuilding:
Manifest Configuration
type: react
static:
root: /app/build
config_file: /app/build/config.js
config_placeholder: __APP_CONFIG__
Template File
Create public/config.js with placeholder:
window.__APP_CONFIG__ = __APP_CONFIG__;
HTML Reference
Include in public/index.html:
<!DOCTYPE html>
<html>
<head>
<script src="%PUBLIC_URL%/config.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
Access in React
const config = window.__APP_CONFIG__;
function App() {
const apiUrl = config.REACT_APP_API_URL;
return <div>API: {apiUrl}</div>;
}
At runtime, the platform replaces __APP_CONFIG__ with actual values:
window.__APP_CONFIG__ = {
"REACT_APP_API_URL": "https://api.acme.com",
"REACT_APP_VERSION": "1.0.0"
};
Updating Variables
During Deployment
- Navigate to Apps → Deploy App
- Configure environment variables in the form
- Provide values for required secrets
- Deploy application
After Deployment
- Navigate to app details page
- Click Configuration tab
- Update variable values
- Click Redeploy to apply changes
Environment variable changes require redeployment. The app will restart with new values.
Validation
The platform validates environment variables:
- Required variables must have values
- Secret variables are encrypted before storage
- Build-time variables are passed to Docker build
- Invalid names (spaces, special chars) are rejected
Best Practices
Naming Conventions
env:
# Good: Uppercase with underscores
- name: DATABASE_URL
- name: JWT_SECRET
- name: MAX_CONNECTIONS
# Bad: Lowercase or mixed case
- name: databaseUrl # Avoid
- name: jwtSecret # Avoid
Secret Management
env:
# Store as secret
- name: DB_PASSWORD
secret: true
required: true
# Store as regular variable
- name: DB_HOST
value: "postgres.example.com"
secret: false
Documentation
env:
- name: CACHE_TTL
value: "300"
description: Cache time-to-live in seconds
- name: MAX_RETRIES
value: "3"
description: Maximum number of retry attempts for failed requests
Environment-Specific Values
Use different values for Development vs Production:
# Development manifest
env:
- name: LOG_LEVEL
value: "debug"
- name: CACHE_ENABLED
value: "false"
# Production manifest
env:
- name: LOG_LEVEL
value: "error"
- name: CACHE_ENABLED
value: "true"
Troubleshooting
Variable Not Found
Problem: Application can't find environment variable
Solutions:
- Check variable is defined in manifest
- Verify variable name matches exactly (case-sensitive)
- Ensure app was redeployed after adding variable
- Check pod logs for startup errors
Secret Not Decrypted
Problem: Secret value appears as *** or is empty
Solutions:
- Verify secret value was provided during deployment
- Check secret is marked with
secret: truein manifest - Redeploy application if secret was added later
Build-time Variable Not Available
Problem: Variable not available during Docker build
Solutions:
- Ensure
buildtime: trueis set in manifest - Add
ARGdirective in Dockerfile - Check build logs for variable injection