Application Routing
The Productify Proxy uses custom Caddy plugins to associate routes with applications registered in the Manager. Routes themselves are defined in the Caddyfile; the plugins add per-application authentication, monitoring, and context injection.
Overview
Application routing enables:
- Manager Integration - Credentials validated via the Productify Manager API
- Application-Specific Middleware - Custom logic per application
- Authentication Flow - OAuth2 before application access
- Machine User Support - Bearer token validation for ESB routes
Productify Plugin
The custom productify Caddy plugin integrates with the Manager.
Global Configuration
{
productify {
manager http://manager:8080
token supersecrettoken
}
}Parameters:
manager- URL of the Productify Manager APItoken- Authentication token sent as a bearer token on Manager API requests
Application Routing
route /* {
authorize with pocketpolicy
productify with 123
reverse_proxy backend:8080
}The productify with 123 directive:
- Tags the request with application ID
123 - Writes a structured access log entry (when
enable_access_logis set) - Records Prometheus metrics for the application (when
enable_metricsis set)
Authentication Integration
Before Authentication
Use productify_before_auth for pre-authentication logic:
route @auth {
productify_before_auth with 123
authenticate with pocketportal
}This tracks users in the authentication flow.
After Authentication
Standard productify directive runs after authorization:
route /* {
authorize with pocketpolicy
productify with 123
reverse_proxy backend:8080
}Complete Example
{
security {
oauth identity provider generic {
realm generic
driver generic
client_id ab098fe1-9bc0-4780-81c6-2ea17f49a3cb
client_secret pU3ZrOyPTtd4A3ex16dBzBTlDrlxqfpU
scopes openid email profile
base_auth_url http://pocketid.localhost
metadata_url http://pocketid.localhost/.well-known/openid-configuration
}
authentication portal pocketportal {
crypto default token lifetime 3600
enable identity provider generic
cookie insecure on
transform user {
match realm generic
action add role user
}
}
authorization policy pocketpolicy {
set auth url /auth/oauth2/generic
allow roles user
validate bearer header
inject headers with claims
enable strip token
}
}
productify {
manager http://172.17.0.1:8080
token supersecrettoken
}
}
http://app.localhost {
@auth {
path /auth/*
}
route @auth {
productify_before_auth with 123
authenticate with pocketportal
}
route /* {
authorize with pocketpolicy
productify with 123
file_server {
root /usr/share/caddy
browse
}
}
}Metrics
The Productify plugin exposes Prometheus metrics on port 2112:
Available Metrics
pfy_authentication_awaiting_users- Users currently on authentication pagepfy_total_requests- Total requests processed per applicationpfy_response_time_seconds- Response time histogram per application
Query Metrics
curl http://localhost:2112/metricsExample output:
# HELP pfy_authentication_awaiting_users Currently on authentication page users
# TYPE pfy_authentication_awaiting_users gauge
pfy_authentication_awaiting_users{app="123"} 2
# HELP pfy_total_requests Total number of requests processed
# TYPE pfy_total_requests counter
pfy_total_requests{app="123",method="GET"} 1543
# HELP pfy_response_time_seconds Response time in seconds
# TYPE pfy_response_time_seconds histogram
pfy_response_time_seconds_bucket{app="123",method="GET",le="0.005"} 1234
pfy_response_time_seconds_bucket{app="123",method="GET",le="0.01"} 1432Manager API Integration
The proxy communicates with these Manager endpoints, authenticating each call with the configured token:
PAT and Machine User Validation
POST /api/validate-proxy-auth
Authorization: Bearer {token}
Content-Type: application/json
{
"authorization_header": "Bearer <client-token>",
"application_id": "123"
}Validates Personal Access Tokens (productify_auth) and machine user credentials (productify_esb_auth); the response includes the user and tenant to inject as headers.
OAuth User Validation
POST /api/validate-oauth-user
Authorization: Bearer {token}
Content-Type: application/json
{
"user_id": "...",
"email": "...",
"name": "...",
"application_id": "123"
}Used by productify_oauth_validation to resolve OAuth-authenticated users to Productify users and tenants.
Frontend Configuration
GET /api/frontend-config/{app_id}
Authorization: Bearer {token}Returns the application's frontend configuration, injected into HTML responses by productify_html_inject.
Multi-Application Setup
Different Applications
http://app1.localhost {
route /* {
authorize with pocketpolicy
productify with 100
reverse_proxy app1-backend:8080
}
}
http://app2.localhost {
route /* {
authorize with pocketpolicy
productify with 200
reverse_proxy app2-backend:8080
}
}Path-Based Routing
http://apps.localhost {
route /app1/* {
authorize with pocketpolicy
productify with 100
uri strip_prefix /app1
reverse_proxy app1-backend:8080
}
route /app2/* {
authorize with pocketpolicy
productify with 200
uri strip_prefix /app2
reverse_proxy app2-backend:8080
}
}