Shell Frontend Deployment Guide
The Shell is a Nuxt 4 server-side rendered frontend that provides the platform UI, authentication flows, and service proxying.
Overview
The Shell provides:
- Server-side rendered Vue.js application
- Authentication UI (login, logout, consent flows)
- App container for microfrontends
- GraphQL proxy to AppServer
- Legacy system proxy (Core5 integration)
┌─────────────────────────────────────────────────────────────┐
│ Shell Frontend │
│ (Nuxt 4 / Node.js) │
├─────────────────────────────────────────────────────────────┤
│ Pages & Components │ Server API Routes │
│ ├── /login │ ├── /api/host/me │
│ ├── /logout │ ├── /api/host/logout │
│ ├── /consent │ ├── /api/auth/hydra/* │
│ ├── /apps/* │ ├── /graphql (proxy) │
│ └── /settings │ └── /c5/* (legacy proxy) │
└─────────────────────────────────────────────────────────────┘
│ │
└──────────────┬───────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
Kratos AppServer Legacy (C5)
(Identity) (GraphQL) (Proxy)
Tech Stack
| Technology | Version | Purpose |
|---|---|---|
| Nuxt | 4.x | Meta-framework |
| Vue | 3.5.x | UI framework |
| Tailwind CSS | 4.x | Styling |
| Node.js | 20+ | Runtime |
| Nitro | 2.x | Server engine |
Docker Build
Image Properties
| Property | Value |
|---|---|
| Build image | node:20-alpine |
| Runtime image | node:20-alpine |
| Image size | ~230MB |
| User | nuxt (uid 1001) |
| Port | 3000 |
| Entry point | node .output/server/index.mjs |
Build Commands
With SSH agent (recommended for local development):
docker build --ssh default \
--build-arg NPM_TOKEN="$(grep _authToken ~/.npmrc | head -1 | cut -d= -f2 | tr -d '\"')" \
-f docker/shell/Dockerfile \
-t shell:latest .
With SSH keys as build args (for CI/CD):
docker build \
--build-arg ssh_prv_key="$(cat ~/.ssh/id_rsa)" \
--build-arg ssh_pub_key="$(cat ~/.ssh/id_rsa.pub)" \
--build-arg NPM_TOKEN="${NPM_TOKEN}" \
-f docker/shell/Dockerfile \
-t shell:latest .
Build Arguments
| Argument | Default | Description |
|---|---|---|
NPM_TOKEN | - | Required. Auth token for private npm registry |
NPM_REGISTRY | https://npm.eacore6.de/ | Private npm registry URL |
ssh_prv_key | - | SSH private key for Bitbucket access |
ssh_pub_key | - | SSH public key for Bitbucket access |
Run Container
docker run -p 3000:3000 --env-file docker/.env shell:latest
Environment Variables
The Shell has two types of environment variables:
Server-side variables (e.g., KRATOS_PUBLIC_URL, DATABASE_URL) are read directly from process.env at container runtime. Just set them in your environment.
Client-side variables (browser-accessible, prefixed with NUXT_PUBLIC_) are injected into the HTML by Nuxt at request time. Use the NUXT_PUBLIC_ prefix for these.
In docker-compose, map your standard env vars to the NUXT_PUBLIC_ format:
services:
shell:
environment:
# Server-side (read directly)
KRATOS_PUBLIC_URL: ${KRATOS_PUBLIC_URL}
DATABASE_URL: ${DATABASE_URL}
# Client-side (needs NUXT_PUBLIC_ prefix)
NUXT_PUBLIC_C5_BASE_URL: ${C5_BASE_URL}
NUXT_PUBLIC_APP_SERVER_HTTP_URL: ${APPSERVER_HTTP_URL}
Authentication Services
| Variable | Default | Description |
|---|---|---|
KRATOS_PUBLIC_URL | - | Required. Kratos public API endpoint |
KRATOS_ADMIN_URL | - | Required. Kratos admin API endpoint |
KRATOS_WEBHOOK_SECRET | - | Webhook secret (32+ chars), must match Kratos config |
HYDRA_PUBLIC_URL | - | Required. Hydra public API endpoint |
HYDRA_ADMIN_URL | - | Required. Hydra admin API endpoint |
Authorization
| Variable | Default | Description |
|---|---|---|
OPENFGA_API_URL | - | Required. OpenFGA API endpoint |
OPENFGA_STORE_ID | - | Required. OpenFGA store ID (must match AppServer) |
Database
| Variable | Default | Description |
|---|---|---|
DATABASE_URL | - | PostgreSQL connection string for shell database |
Format: postgresql://user:password@host:5432/database
AppServer Backend
| Variable | Default | Description |
|---|---|---|
NUXT_PUBLIC_APPSERVER_GRAPHQL_URL | /graphql | GraphQL endpoint (browser-accessible) |
NUXT_PUBLIC_APPSERVER_HTTP_URL | - | AppServer HTTP URL for server-side requests |
Legacy Proxy (Optional)
| Variable | Default | Description |
|---|---|---|
C5_BASE_URL | - | Core5 legacy backend URL |
C5_SESSION_COOKIE_NAME | legacy_session | Legacy session cookie name |
Telemetry (Optional)
| Variable | Default | Description |
|---|---|---|
TELEMETRY_ENABLED | false | Enable OpenTelemetry |
TELEMETRY_SERVICE_NAME | core6-shell | Service name in traces |
OTEL_EXPORTER_OTLP_ENDPOINT | - | OTLP HTTP endpoint |
LOG_LEVEL | info | Log level: debug, info, warn, error |
Nginx Reverse Proxy
For production with SSL termination:
upstream shell {
server shell:3000;
}
upstream appserver {
server appserver:8080;
}
server {
listen 443 ssl http2;
server_name app.example.com;
ssl_certificate /etc/ssl/certs/app.crt;
ssl_certificate_key /etc/ssl/private/app.key;
# Shell frontend
location / {
proxy_pass http://shell;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# AppServer API (direct access)
location /api/v1/ {
proxy_pass http://appserver;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# WebSocket support for GraphQL subscriptions
location /graphql {
proxy_pass http://shell;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
Local Development
Setup
cd web/v2/packages/shell
# Install dependencies
pnpm install
# Copy environment template
cp .env.example .env
# Edit .env with your values
# - Set OPENFGA_STORE_ID from: curl http://localhost:8090/stores | jq -r '.stores[0].id'
# - Update DATABASE_URL password from docker/.env
# Start development server
pnpm dev
Production Build (without Docker)
# Build for production
pnpm build
# Output directory: .output/
# Entry point: .output/server/index.mjs
# Start production server
node .output/server/index.mjs
Production Checklist
Required Configuration
- Build with
pnpm buildor Docker - Set
NODE_ENV=production - Configure all auth service URLs:
-
KRATOS_PUBLIC_URL -
KRATOS_ADMIN_URL -
HYDRA_PUBLIC_URL -
HYDRA_ADMIN_URL
-
- Set
KRATOS_WEBHOOK_SECRET(32+ chars, must match Kratos config) - Set
OPENFGA_API_URLandOPENFGA_STORE_ID(must match AppServer) - Configure
DATABASE_URLwith production credentials
Optional Configuration
- Configure
C5_BASE_URLfor legacy proxy (if needed) - Enable telemetry (
TELEMETRY_ENABLED=true) - Set up SSL termination (nginx/load balancer)
- Configure health checks
Security
- Run container as non-root user (default:
nuxt) - Use secrets management for sensitive values
- Enable HTTPS in production
- Set secure cookie policies
Troubleshooting
Login Not Working
Symptom: Login redirects fail or loop
-
Check Kratos URL is accessible:
curl http://kratos:4433/health/ready -
Verify webhook secret matches:
# Shell .env
KRATOS_WEBHOOK_SECRET=...
# docker/.env (must match!)
KRATOS_WEBHOOK_SECRET=... -
Check Kratos configuration has correct browser URLs
GraphQL Proxy Errors
Symptom: GraphQL requests fail
-
Verify AppServer is running:
curl http://appserver:8080/health -
Check network connectivity from shell container:
docker exec shell wget -qO- http://appserver:8080/health
Permission Denied Errors
Symptom: Users can't access certain features
- Verify
OPENFGA_STORE_IDmatches AppServer config - Check user has correct roles in OpenFGA
- Review OpenFGA authorization model
Database Connection Errors
Symptom: Shell fails to start or user lookup fails
- Verify
DATABASE_URLformat:postgresql://user:password@host:5432/database - Check PostgreSQL is accessible
- Ensure database exists (created by migrations)
Container Won't Start
Symptom: Container exits immediately
-
Check logs:
docker logs shell -
Verify all required environment variables are set
-
Test locally first:
node .output/server/index.mjs
Monitoring
Health Check
curl http://localhost:3000/
Logs
# Docker
docker logs shell -f
# Kubernetes
kubectl logs -f deployment/shell
Telemetry
When TELEMETRY_ENABLED=true:
- Traces exported to OpenTelemetry Collector
- Service name:
core6-shell - Logs include correlation IDs
Related Topics
- AppServer Guide - Backend API deployment
- Docker Infrastructure - Full stack setup
- Environment Reference - All environment variables
- Observability Stack - Monitoring setup