Proxy migration guide

This guide explains how to migrate SSO authentication and API proxy handling from the legacy Onify Hub application to Helix.

Overview

By default, Helix is configured to work with the legacy proxy mode, where SSO authentication and API requests are handled by the legacy Onify Hub application. This allows for backward compatibility and a smooth migration path.

To enable the new Helix proxy mode, where Helix handles SSO authentication and proxies API requests directly, you need to update your environment configuration.

Table of Contents

Development Environment Setup

Default Configuration (Legacy Mode)

By default, Helix uses the legacy proxy configuration:

# Default values - Legacy mode
HELIX_API_URL="/api/v2"
HELIX_LOGIN_URL="/login"
HELIX_LOGOUT_URL="/logout"
ONIFY_HUB_API_PATH="/api/v2"

VITE_LOCAL_API_PROXY_TARGET="http://localhost:3000/api/v2"
VITE_LOCAL_API_PROXY_ENDPOINT="/api/v2"
VITE_SSO_CALLBACK_PROXY_ENDPOINT="/helix/sso/callback"

In this mode:

  • Login requests go to /login (handled by legacy app)
  • API requests go to /api/v2 (handled by legacy app)
  • Vite dev server proxies to localhost:3000 (legacy app)

Enabling New Helix Proxy Mode

To enable Helix to handle SSO and API proxying, you need to uncomment the proxy configuration section in your .env file:

Step 1: Locate the commented section in your .env or .env.local file:

# Uncomment the lines below (remove #) when SSO login flow and proxy API requests should be handled by Helix instead of the legacy app
# This will override the values above since environment variables use the last defined value
#HELIX_API_URL="/helix/api/v2"
#HELIX_LOGIN_URL="/helix/login"
#HELIX_LOGOUT_URL="/helix/logout"
#ONIFY_HUB_API_PATH="/helix/api/v2"
#VITE_LOCAL_API_PROXY_TARGET="http://localhost:8181/api/v2"
#VITE_LOCAL_API_PROXY_ENDPOINT="/helix/api/v2"
#VITE_SSO_CALLBACK_PROXY_ENDPOINT="/helix/sso/callback"

Step 2: Remove the ## prefix from each line to activate the new configuration (or add these variables to the end of your file if the section doesn't exist):

# Helix Proxy Mode - Enable SSO and API proxy via Helix
HELIX_API_URL="/helix/api/v2"
HELIX_LOGIN_URL="/helix/login"
HELIX_LOGOUT_URL="/helix/logout"
ONIFY_HUB_API_PATH="/helix/api/v2"
VITE_LOCAL_API_PROXY_TARGET="http://localhost:8181/api/v2"
VITE_LOCAL_API_PROXY_ENDPOINT="/helix/api/v2"
VITE_SSO_CALLBACK_PROXY_ENDPOINT="/helix/sso/callback"

Step 3: Restart your Vite dev server:

npm run dev

How It Works

Development Mode (Vite Dev Server)

When you start the Vite development server with the new proxy configuration enabled:

  1. Vite Configuration (apps/helix-app/vite.config.js) loads the proxy configuration
  2. Proxy Generator (@onify/helix-tools) provides the generateViteProxyConfiguration() function
  3. Proxy Routes are configured based on environment variables:
    • HELIX_LOGIN_URL → Proxied to backend /my/login endpoint
    • VITE_SSO_CALLBACK_PROXY_ENDPOINT/* → Proxied to backend /sso/callback/* endpoint
    • VITE_LOCAL_API_PROXY_ENDPOINT → Proxied to VITE_LOCAL_API_PROXY_TARGET

The Vite dev server will now handle:

  • SSO authentication flow via /helix/login
  • SSO callback handling via /helix/sso/callback/*
  • API requests via /helix/api/v2

All proxied to your backend API server (default: http://localhost:8181).

Key Components

1. Vite Configuration (apps/helix-app/vite.config.js)

import { generateViteProxyConfiguration } from '@onify/helix-tools';

export default async ({ mode }) => {
  // ...

  // Generate proxy configuration (only for dev mode)
  let proxyConfiguration = {};
  if (mode === 'development') {
    try {
      const { generateViteProxyConfiguration } = await import('@onify/helix-tools');
      proxyConfiguration = generateViteProxyConfiguration();
    } catch (e) {
      console.warn('Could not load generateViteProxyConfiguration, proxy will not be configured');
    }
  }

  return defineConfig({
    // ...
    server: {
      proxy: proxyConfiguration,
    },
    preview: {
      proxy: proxyConfiguration,
    },
  });
};

2. Proxy Configuration Generator (packages/helix-tools/src/shared/utils/generate-vite-proxy-configuration.ts)

This is the most important file for development proxy configuration. It:

  • Reads environment variables to configure proxy routes
  • Handles authentication cookies and forwards them as Bearer tokens
  • Adds required headers (onify-app-origin, Authorization)
  • Configures SSO callback handling with redirect support
  • Rewrites URLs to match backend API routes

The function creates three main proxy routes:

  1. Login Route: HELIX_LOGIN_URL/my/login
  2. SSO Callback Route: VITE_SSO_CALLBACK_PROXY_ENDPOINT/*/sso/callback/*
  3. API Route: VITE_LOCAL_API_PROXY_ENDPOINT → Backend API

Environment Variables

Required Variables for New Proxy Mode

VariableDefault (Legacy)New Proxy ModeDescription
HELIX_API_URL/api/v2/helix/api/v2API path used by Helix
HELIX_LOGIN_URL/login/helix/loginLogin page URL
HELIX_LOGOUT_URL/logout/helix/logoutLogout URL
ONIFY_HUB_API_PATH/api/v2/helix/api/v2Onify Hub API path
VITE_LOCAL_API_PROXY_TARGEThttp://localhost:3000/api/v2http://localhost:8181/api/v2Backend API server URL (dev only)
VITE_LOCAL_API_PROXY_ENDPOINT/api/v2/helix/api/v2API endpoint to proxy (dev only)

Additional Variables

VariableDescription
HELIX_BASE_URLBase URL for Helix app (default: /helix)
HELIX_ERROR_URLError page URL for SSO failures
HELIX_INTERNAL_LOGIN_PAGEInternal login page path for fallback

Production Deployment

For production deployments with the new Helix proxy mode, you need to use Dockerfile.proxy and nginx.proxy.conf to handle SSO authentication and API proxying at the nginx level.

Overview

Unlike development mode where Vite handles the proxy configuration, in production:

  • Nginx acts as the reverse proxy
  • SSO authentication flow is handled by nginx forwarding to your backend API
  • API requests are proxied from /helix/api/v2 to your backend API server
  • Static files (built Helix app) are served from nginx

Build Arguments and Environment Variables

The Dockerfile.proxy requires specific build arguments and environment variables:

Build Arguments (required at build time)

ArgumentDescriptionExample
ONIFY_GITHUB_ACCESS_TOKENGitHub Personal Access Token for accessing Onify packagesghp_xxxxx...
ONIFY_API_URL_INTERNALInternal backend API URL (used during build and runtime)http://your-backend-api:8181

Environment Variables (set in Dockerfile.proxy)

The following environment variables are set during the build to configure the Helix app:

ENV HELIX_API_URL="/helix/api/v2"
ENV HELIX_LOGIN_URL="/helix/login"
ENV HELIX_LOGOUT_URL="/helix/logout"
ENV HELIX_ERROR_URL="/helix/error"
ENV HELIX_INTERNAL_LOGIN_PAGE="/helix/login/internal"
ENV HELIX_BASE_URL="/helix"
ENV ONIFY_HUB_APP_URL="/"
ENV ONIFY_HUB_API_PATH="/helix/api/v2"

Building the Docker Image

Step 1: Navigate to the Helix app directory:

cd apps/helix-app

Step 2: Build the Docker image using Dockerfile.proxy:

docker build \
  -f Dockerfile.proxy \
  --build-arg ONIFY_GITHUB_ACCESS_TOKEN=your_github_token \
  -t helix-app:latest \
  .

Running the Container

Step 1: Stop and remove existing container (if any):

docker stop helix-app && docker rm helix-app

Step 2: Run the container with required environment variables:

docker run -d \
  --name helix-app \
  -p 4000:4000 \
  -e ONIFY_API_URL_INTERNAL="http://your-backend-api:8181" \
  helix-app:latest

The Helix app will be available at http://localhost:4000/helix/

How Nginx Proxy Configuration Works

The nginx.proxy.conf file configures nginx to handle three main proxy routes:

1. Login Route (/helix/login)

What it does:

  • Matches requests to /helix/login (or with query parameters)
  • Sets the onify-app-origin header with the original URL for post-login redirect
  • Rewrites the URL to /api/v2/my/login and forwards to backend API
  • Backend initiates SSO flow and redirects user to identity provider

2. SSO Callback Route (/helix/sso/callback/*)

What it does:

  • Handles SSO provider callbacks (e.g., from Azure AD, Okta, etc.)
  • Sets headers for redirect handling and error page
  • Rewrites URL to /api/v2/sso/callback/* and forwards to backend
  • Backend validates SSO token and sets authentication cookie
  • Backend redirects user back to original URL (from onify-app-origin header)

3. API Proxy Route (/helix/api/v2/*)

What it does:

  • Proxies all API requests from Helix to backend
  • Extracts Auth cookie value and converts it to Authorization: Bearer header
  • Rewrites URL from /helix/api/v2/* to /api/v2/*
  • Forwards request to backend API with proper authentication

Common Proxy Headers

All proxy locations include these common headers to ensure:

  • Original host information is preserved
  • Client IP addresses are tracked
  • SSL/TLS information is forwarded
  • Cookies are properly passed through

Nginx Configuration Template Variables

The nginx.proxy.conf uses template variables that are substituted at container startup:

VariableSourceDescription
${HELIX_BASE_URL}ENVBase URL path (default: /helix)
${HELIX_LOGIN_URL}ENVLogin URL path (default: /helix/login)
${HELIX_ERROR_URL}ENVError page URL
${ONIFY_API_URL_INTERNAL}ENVBackend API URL

These are set in the Dockerfile.proxy and can be overridden at runtime using -e flags in docker run.

Authentication Flow

Here's the complete authentication flow in production:

  1. User visits Helix app → Nginx serves static files
  2. Helix makes API call → Receives 401 Unauthorized response
  3. Helix auto-redirects → Automatically redirects to /helix/login
  4. Nginx proxies to backend/api/v2/my/login
  5. Backend initiates SSO → Redirects user to identity provider (Azure AD, Okta, etc.)
  6. User authenticates → Identity provider redirects to /helix/sso/callback/provider
  7. Nginx proxies callback/api/v2/sso/callback/provider
  8. Backend validates token → Sets Auth cookie
  9. Backend redirects user → Back to original URL (from onify-app-origin header)
  10. Helix makes API calls/helix/api/v2/*
  11. Nginx extracts cookie → Converts to Authorization: Bearer header
  12. Nginx proxies to backend/api/v2/* with auth header

Dockerfile.proxy Structure

The Dockerfile.proxy has two stages:

Build Stage

  • Uses Node.js Alpine image
  • Copies package files and installs dependencies
  • Sets build-time environment variables
  • Builds the Vite application
  • Output: /app/dist directory with static files

Production Stage

  • Uses Nginx Alpine image
  • Copies built static files to /etc/nginx/html/helix
  • Copies nginx.proxy.conf as nginx template
  • Sets runtime environment variables
  • Exposes port 4000
  • Starts nginx

Verifying the Deployment

After running the container, verify it's working correctly:

1. Check container is running:

docker ps | grep helix-app

2. Check nginx logs:

docker logs helix-app

3. Test the application:

  • Visit: http://localhost:4000/helix/
  • Click login and verify SSO flow works
  • Check that API requests are working

4. Test specific endpoints:

# Test Helix app - will auto-redirect to login if not authenticated
curl -I http://localhost:4000/helix/

# Should redirect to your SSO provider or backend API if not authenticated

Troubleshooting Production

Issue: 502 Bad Gateway

Solution:

  1. Verify ONIFY_API_URL_INTERNAL is accessible from container
  2. Check backend API is running
  3. Ensure backend API is not using localhost (use proper hostname/IP)

Issue: Login redirects not working

Solution:

  1. Verify HELIX_ERROR_URL is configured correctly
  2. Check onify-app-origin header is being sent to backend
  3. Review nginx logs: docker logs helix-app

Issue: API calls return 401 Unauthorized

Solution:

  1. Check that Auth cookie is being set by backend after login
  2. Verify nginx is extracting cookie correctly (check nginx logs)
  3. Ensure backend API is receiving Authorization header

Key Files

Development Files

FilePurpose
vite.config.jsVite configuration that loads proxy settings
../../packages/helix-tools/src/shared/utils/generate-vite-proxy-configuration.tsMain proxy configuration generator
.env or .env.localEnvironment variables configuration

Production Files

FilePurpose
DockerfileDocker build for legacy mode (simple nginx)
Dockerfile.proxyDocker build for new proxy mode (nginx with proxy)
nginx.confNginx config for legacy mode
nginx.proxy.confNginx config for new proxy mode

Troubleshooting

Development Issues

Issue: Proxy not working after uncommenting environment variables

Solution: Make sure to restart your Vite dev server after changing environment variables:

# Stop the server (Ctrl+C)
npm run dev

Issue: 401 Unauthorized errors

Solution:

  1. Check that your VITE_LOCAL_API_TOKEN is set if you're using token-based auth in development
  2. Verify that VITE_LOCAL_API_PROXY_TARGET points to the correct backend API server
  3. Ensure your backend API is running and accessible

Issue: SSO callback fails

Solution:

  1. Verify HELIX_ERROR_URL is configured correctly
  2. Check that HELIX_INTERNAL_LOGIN_PAGE points to a valid login page
  3. Review browser console and network tab for error details

Migration Checklist

Development

  • Backup current .env configuration
  • Uncomment the new proxy configuration section in .env
  • Verify VITE_LOCAL_API_PROXY_TARGET points to correct backend (port 8181)
  • Restart Vite dev server
  • Test login flow by visiting /helix/ (will auto-redirect if not authenticated)
  • Test API requests to /helix/api/v2
  • Verify SSO callback handling works correctly
  • Test logout functionality

Production

  • Prepare ONIFY_GITHUB_ACCESS_TOKEN for Docker build
  • Determine ONIFY_API_URL_INTERNAL (backend API URL)
  • Build Docker image using Dockerfile.proxy
  • Run container with proper environment variables
  • Verify container is running: docker ps
  • Test application at http://localhost:4000/helix/
  • Test SSO login flow in production environment
  • Verify API calls work with authentication
  • Check nginx logs for any errors

Additional Resources