This guide covers deploying S4Kit to SAP BTP Cloud Foundry or any Cloud Foundry environment.
- Cloud Foundry CLI installed
- Logged into CF:
cf login - Target space selected:
cf target -o <org> -s <space>
S4Kit consists of three applications:
| App | Purpose | Port |
|---|---|---|
s4kit-backend |
Admin API + Authentication | 8080 |
s4kit-proxy |
SDK Proxy Service | 8080 |
s4kit-frontend |
Next.js Dashboard | 8080 |
All apps use the Bun buildpack for runtime.
S4Kit requires PostgreSQL and Redis. You can use managed services or external providers.
Create user-provided services with connection strings:
# PostgreSQL
cf create-user-provided-service s4kit-postgres -p '{"uri":"postgresql://user:pass@host:port/database"}'
# Redis
cf create-user-provided-service s4kit-redis -p '{"uri":"redis://user:pass@host:port"}'# PostgreSQL on Hyperscaler
cf create-service postgresql-db standard s4kit-postgres
# Redis on Hyperscaler
cf create-service redis-cache standard s4kit-redisCreate a user-provided service for secrets:
# Generate encryption key (32 bytes hex)
ENCRYPTION_KEY=$(openssl rand -hex 32)
# Generate auth secret
BETTER_AUTH_SECRET=$(openssl rand -base64 32)
cf create-user-provided-service s4kit-secrets -p "{
\"ENCRYPTION_KEY\": \"$ENCRYPTION_KEY\",
\"BETTER_AUTH_SECRET\": \"$BETTER_AUTH_SECRET\"
}"# From monorepo root
cf push -f packages/platform/backend/manifest.ymlSet after deployment (optional):
# Optional: Change mode (default: selfhost)
# - selfhost: Single tenant, no signup
# - saas: Multi-tenant with signup
cf set-env s4kit-backend MODE saas
# Restart to apply
cf restart s4kit-backendNote:
COOKIE_DOMAINandBETTER_AUTH_URLare auto-detected fromVCAP_APPLICATIONon Cloud Foundry. No manual configuration needed.
# From monorepo root
cf push -f packages/platform/proxy/manifest.ymlNo additional configuration needed - proxy reads from bound services.
The frontend requires a build step with the backend URL baked in:
cd packages/platform/frontend
# Set backend URL and deploy
NEXT_PUBLIC_API_URL=https://s4kit-backend.cfapps.us10-001.hana.ondemand.com ./deploy-cf.shThe script:
- Builds Next.js with standalone output
- Packages for nodejs_buildpack
- Deploys to CF
| Variable | Default | Description |
|---|---|---|
MODE |
selfhost |
Platform mode: selfhost or saas |
FRONTEND_URL |
(from manifest) | Frontend URL for CORS/redirects |
COOKIE_DOMAIN |
- | Domain for cross-subdomain cookies |
BETTER_AUTH_URL |
auto-detected | Backend URL for auth callbacks |
| Secret | Description |
|---|---|
ENCRYPTION_KEY |
32-byte hex key for encrypting credentials |
BETTER_AUTH_SECRET |
Secret for session signing |
The apps automatically detect connection strings from bound services:
- PostgreSQL:
s4kit-postgresservice - Redis:
s4kit-redisservice
Edit manifest files to change routes:
# packages/platform/backend/manifest.yml
routes:
- route: your-backend.cfapps.your-region.hana.ondemand.comAfter changing routes, update:
FRONTEND_URLin backend manifestNEXT_PUBLIC_API_URLwhen building frontendCOOKIE_DOMAINif domain changes
# Scale proxy for more throughput
cf scale s4kit-proxy -i 3
# Scale backend
cf scale s4kit-backend -i 2cf logs s4kit-backend --recent
cf logs s4kit-proxy --recent
cf logs s4kit-frontend --recent| App | Endpoint |
|---|---|
| Backend | /health |
| Proxy | /health/live |
| Frontend | / |
The Bun buildpack caches node_modules. Clear cache:
cf restage s4kit-backend --no-cacheCheck that s4kit-redis service is bound and has correct uri in credentials:
cf env s4kit-backend | grep -A5 s4kit-redisCOOKIE_DOMAIN is auto-detected from VCAP_APPLICATION. If issues persist, set manually:
cf set-env s4kit-backend COOKIE_DOMAIN ".cfapps.us10-001.hana.ondemand.com"
cf restart s4kit-backendRebuild frontend with correct URL:
NEXT_PUBLIC_API_URL=https://your-backend-url ./deploy-cf.sh#!/bin/bash
set -e
REGION="us10-001" # Change for your region
DOMAIN="cfapps.${REGION}.hana.ondemand.com"
# 1. Create services (skip if already exist)
cf create-user-provided-service s4kit-postgres -p '{"uri":"YOUR_POSTGRES_URL"}' || true
cf create-user-provided-service s4kit-redis -p '{"uri":"YOUR_REDIS_URL"}' || true
cf create-user-provided-service s4kit-secrets -p "{
\"ENCRYPTION_KEY\": \"$(openssl rand -hex 32)\",
\"BETTER_AUTH_SECRET\": \"$(openssl rand -base64 32)\"
}" || true
# 2. Deploy backend (COOKIE_DOMAIN auto-detected from VCAP_APPLICATION)
cf push -f packages/platform/backend/manifest.yml
# 3. Deploy proxy
cf push -f packages/platform/proxy/manifest.yml
# 4. Deploy frontend
cd packages/platform/frontend
NEXT_PUBLIC_API_URL="https://s4kit-backend.${DOMAIN}" ./deploy-cf.sh
echo "Deployment complete!"
echo "Frontend: https://s4kit-frontend.${DOMAIN}"
echo "Backend: https://s4kit-backend.${DOMAIN}"
echo "Proxy: https://s4kit-proxy.${DOMAIN}"S4Kit includes XSUAA for SAP IDP authentication. Users can log in using "Continue with SAP" button.
XSUAA is automatically created and bound during deployment. The service is configured via xs-security.json.
For manual cf push deployment, create the service first:
cf create-service xsuaa application s4kit-xsuaa -c xs-security.jsonXSUAA provides three role templates defined in xs-security.json:
| Role Template | S4Kit Role | Description |
|---|---|---|
S4KitOwner |
owner | Full access to organization |
S4KitAdmin |
admin | Manage systems and API keys |
S4KitDeveloper |
developer | Read-only dashboard access |
Assign roles to users in SAP BTP Cockpit under Security > Role Collections.
- User clicks "Continue with SAP" on login page
- Redirected to SAP IDP for authentication
- After successful auth, user is created in S4Kit with their own organization
- Admin can adjust user roles via the S4Kit dashboard