Skip to main content
This guide covers everything you need to configure, operate, monitor, and troubleshoot Portal Connect in production.

Configuring Plugins

Once you have Portal Connect Agent deployed and running, you can configure your Backstage plugins to access internal services through the Agent. The key principle is simple: configure plugins as if they could access the services directly within the same network.

How It Works

When you configure a Backstage plugin to access an internal service:
  1. Use the internal hostname/URL directly in your plugin configuration (e.g., https://github.internal.company.com, https://artifactory.corp.net)
  2. The Agent registers routes for these internal services with Portal
  3. When Portal makes a request to that URL, Portal Connect automatically tunnels the request through the Agent
  4. The Agent executes the request from within your network and returns the response
No special configuration needed. Portal Connect handles the routing transparently once the Agent has registered the route.

Configuration Approach

Internal Service URLs Configure your plugins with internal URLs exactly as you would if Portal were running inside your network: Example - GitHub Enterprise:
Example - Internal Artifactory:

Authentication and Credentials

For plugin configuration that requires authentication headers or API tokens: Option 1: Use dummy values in plugin configuration Since the Portal Connect Agent injects the real authentication headers (configured in the Agent’s routes), you can use placeholder values in your plugin configuration:
Option 2: Reference environment variables You can reference environment variables in your configuration, but the actual authentication will happen at the Agent level:
The Agent configuration would include the real authentication:

Multi-Step Configuration Example

Step 1: Configure the Agent with the route and real credentials:
Step 2: Configure your plugin to use the internal URL:
Step 3: Deploy or restart the Agent to register the routes. Step 4: Your plugins now work seamlessly—Portal Connect handles the routing and authentication.

Benefits of This Approach

  • Simple plugin configuration - No special proxy settings or complex routing rules in Backstage
  • Centralized credential management - All internal service credentials stay within your network at the Agent level
  • Security - Credentials never leave your network perimeter
  • Transparency - Plugins work as if Portal were running inside your network
  • Maintainability - Plugin configurations remain clean and straightforward

Adding and Managing Routes

This section covers how to add, modify, and remove routes in Portal Connect Agent.

Understanding Routes

Routes define which external URLs the Agent can access on behalf of your applications. Route Components A route consists of:
  • Protocol: http:// or https://
  • Hostname: Domain name or IP address
  • Path: Optional path component (exact or wildcard)
  • Headers: Optional per-route default headers (advanced)
Route Matching Exact match:
  • Matches only: https://api.github.com/users
  • Does not match: https://api.github.com/users/octocat
Wildcard match:
  • Matches: https://api.github.com/users
  • Matches: https://api.github.com/users/octocat
  • Matches: https://api.github.com/repos/owner/repo
  • Does not match: http://api.github.com/users (different protocol)
  • Does not match: https://github.com/users (different hostname)
Route Precedence When multiple routes could match a URL:
  1. Exact matches take precedence over wildcards
  2. More specific wildcards take precedence over less specific
  3. Routes are evaluated in the order configured
Example:
Request to https://api.github.com/users/octocat matches the first route.

Adding Routes

Simple Routes To add routes without custom headers, use the array format:
Routes with Headers To add per-route authentication or custom headers:
Set the referenced environment variables when starting the Agent:

Route Planning

Before adding routes, consider: Scope: Use wildcards appropriately
  • Too broad: https://*/* (avoid - too permissive)
  • Too narrow: Individual endpoints (maintenance overhead)
  • Recommended: API version level https://api.example.com/v1/*
Authentication: Does the service require headers?
  • API keys
  • Bearer tokens
  • Custom authentication headers
Security: Should this route be accessible?
  • Apply principle of least privilege
  • Only add routes that are necessary

Adding a New Route

Step 1: Update configuration Edit app-config.yaml:
Or with headers:
Step 2: Set environment variables (if using headers) Update your deployment to include new environment variables:
Step 3: Restart Agent
Step 4: Verify route registration Check logs:
Expected output:
Check metrics:
Expected output:

Modifying Routes

Changing Route Patterns To change a route pattern (e.g., from exact to wildcard): Before:
After:
Restart the Agent to apply changes. Adding Headers to Existing Route To add headers to a route that previously had none: Before:
After:
Don’t forget to:
  1. Set the GITHUB_TOKEN environment variable
  2. Restart the Agent
Updating Headers To change header values, update the configuration and environment variables: Configuration change:
If changing token values, update the environment variable and restart. Converting Between Formats From array to object format: Before:
After (adding headers to one route):
Format ConsistencyYou cannot mix array and object formats. Choose one format for all routes.

Route Security Best Practices

Principle of Least Privilege Only add routes that are absolutely necessary: Bad - too permissive:
Good - specific routes:
Credential Management Never hardcode credentials: Bad - credentials in config file:
Good - use environment variables:
Credential Rotation When rotating API credentials:
  1. Generate new credential
  2. Update environment variable or secret
  3. Restart Agent
  4. Revoke old credential
Kubernetes example:

Common Route Patterns

GitHub API
GitLab API
Internal REST API
Prometheus Metrics Endpoint
Health Check Endpoints
Multiple API Versions

Troubleshooting Routes

Route Not Registered Symptom: Route doesn’t appear in logs or metrics Diagnostic:
  1. Check configuration syntax:
  2. Validate YAML:
  3. Check for configuration errors in logs:
Solutions:
  • Fix YAML syntax errors
  • Ensure routes are under agent.routes key
  • Restart Agent after configuration changes
Requests Not Matching Route Symptom: Requests returning 404 or not being processed Diagnostic:
  • Verify exact URL being requested
  • Check route pattern matches the URL
  • Review logs for rejected requests
Common mismatches:
  • Protocol mismatch: Route is https:// but request is http://
  • Hostname mismatch: Different subdomain or domain
  • Path mismatch: Wildcard doesn’t cover the requested path
Solutions:
  • Adjust route pattern to match intended URLs
  • Use wildcards appropriately
  • Add specific routes for edge cases
Headers Not Being Sent Symptom: External service returns authentication errors Diagnostic:
  1. Check environment variables are set:
  2. Verify header syntax in configuration
  3. Check logs for request details (debug level)
Solutions:
  • Set missing environment variables
  • Fix header syntax in configuration
  • Ensure variable names match between config and environment
Route with Wrong Credentials Symptom: Authentication failures for specific route Diagnostic: Test the credential directly:
Solutions:
  • Update credential in environment variable
  • Verify credential is valid and not expired
  • Check credential has necessary permissions for the API

Monitoring and Operations

Metrics Endpoint

The Agent exposes Prometheus metrics on port 9466 (configurable via AGENT_METRICS_PORT).
Metrics PortThe metrics endpoint is optional and only needs to be accessible from your monitoring infrastructure within your network. It does not require inbound access from the internet - the Agent still only makes outbound connections for its primary function.
Accessing Metrics:

Key Metrics

Connection Metrics agent_websocket_connected
  • Type: Gauge
  • Description: WebSocket connection state (0 = disconnected, 1 = connected)
  • Use: Monitor gateway connectivity
agent_websocket_reconnections_total
  • Type: Counter
  • Description: Total number of reconnection attempts
  • Use: Track connection stability
Request Metrics agent_http_requests_total
  • Type: Counter
  • Labels: method, status_code, route
  • Description: Total HTTP requests processed
  • Use: Track request volume and status codes
agent_http_request_duration_seconds
  • Type: Histogram
  • Labels: method, route
  • Description: HTTP request duration distribution
  • Use: Monitor request latency
agent_http_request_errors_total
  • Type: Counter
  • Labels: method, route, error_type
  • Description: Total HTTP request errors
  • Use: Monitor error rates
Route Metrics agent_routes_registered
  • Type: Gauge
  • Description: Number of routes currently registered
  • Use: Verify route configuration

Alerting

Recommended Alerts Critical Alerts WebSocket Disconnected:
  • Threshold: Alert if disconnected for > 5 minutes
  • Action: Check network connectivity, Portal status, certificate validity
Certificate Expiring Soon:
  • Threshold: Alert 7 days before expiration
  • Action: Generate and register new certificate
High Error Rate:
  • Threshold: > 5% error rate over 5 minutes
  • Action: Investigate logs, check external service status
Agent Down:
  • Threshold: Alert immediately
  • Action: Restart Agent, check logs for crash reason
Warning Alerts Elevated Error Rate:
  • Threshold: > 1% error rate over 15 minutes
  • Action: Monitor, investigate if sustained
Slow Requests:
  • Threshold: P95 latency > 5 seconds
  • Action: Check external service performance
Frequent Reconnections:
  • Threshold: > 0.1 reconnections/second
  • Action: Investigate network stability

Monitoring WebSocket Connection

The Agent automatically reconnects if the WebSocket connection drops:
  • Initial retry: 1 second
  • Maximum retry interval: 60 seconds
  • Uses exponential backoff with jitter
Monitor connection stability:

Monitoring Request Success

View request metrics:
Calculate error rate:

Health Checks

Docker Health Check
Kubernetes Probes

Troubleshooting

Connection Issues

WebSocket Connection Fails Symptoms:
  • agent_websocket_connected{} == 0
  • Logs show WebSocket connection failed or Connection refused
Diagnostic Steps:
  1. Verify WebSocket URL:
  2. Test network connectivity:
  3. Check firewall rules:
    • Ensure outbound WSS (port 443 or 8080) allowed
    • Test from Agent host
  4. Verify certificates:
Solutions:
  • Fix WebSocket URL in configuration
  • Update firewall rules to allow outbound WSS
  • Renew expired certificates
  • Contact Spotify to verify Portal is operational
Frequent Disconnections Symptoms:
  • agent_websocket_reconnections_total increasing
  • Logs show repeated disconnect/reconnect cycles
Diagnostic Steps:
  1. Check connection stability:
  2. Review network logs:
    • Check for intermittent network issues
    • Look for firewall or proxy interruptions
  3. Verify Portal health:
    • Contact Spotify support
    • Check for Portal maintenance windows
Solutions:
  • Resolve network stability issues
  • Adjust firewall/proxy timeouts for WebSocket connections
  • Coordinate with Spotify on Portal issues
SSL Inspection / Corporate Proxy Intercepting TLS Symptoms:
  • Repeated reconnection failures in logs
  • Error message similar to: Error: self-signed certificate in certificate chain
  • agent_websocket_connected{} == 0 even though broker URL and network access are correct
  • Other outbound HTTPS requests from the Agent may also fail
Diagnostic Steps:
  1. Check whether your organization performs SSL/TLS inspection
    • Firewalls such as Palo Alto, Zscaler, Cisco, or Blue Coat may intercept and re-sign outbound TLS connections
    • If so, Portal Connect’s WebSocket connection will be re-signed using a corporate CA that is not trusted by Node.js by default
  2. Inspect Agent logs for certificate errors:
    or:
  3. Verify whether Node.js trusts your corporate CA Inside the Agent container:
    If your corporate CA is not listed, Node.js will reject the connection.
  4. Ensure you have the correct TLS inspection certificates
    • Export the root + intermediate CA certificates from your firewall
    • Certificates must be PEM-encoded:
Solutions:
  1. Create a CA bundle containing your corporate inspection certificates:
  2. Mount the CA bundle into the Agent container Example:
  3. Tell Node.js to trust your corporate CA using NODE_EXTRA_CA_CERTS Docker run:
    Docker Compose:
    Kubernetes:
  4. Restart or redeploy the Agent:
    or:
  5. Verify WebSocket connectivity:
    Expected:

Request Failures

All Requests Failing Symptoms:
  • High error rate across all routes
  • Logs show consistent request failures
Diagnostic Steps:
  1. Check Agent connectivity:
  2. Verify routes are registered:
  3. Test external service directly from Agent host:
Solutions:
  • Restore WebSocket connection
  • Fix route configuration and restart Agent
  • Resolve network access to external services
Specific Route Failing Symptoms:
  • Errors for specific route/URL pattern
  • Other routes working normally
Diagnostic Steps:
  1. Check route configuration:
  2. Test service directly:
  3. Check service-specific authentication:
    • Verify headers configured correctly
    • Test with actual credentials
Solutions:
  • Fix route pattern (wildcard, exact match)
  • Update authentication headers
  • Verify external service is operational
Timeout Errors Symptoms:
  • Logs show Network timeout or Request timeout
  • Slow response times
Diagnostic Steps:
  1. Check request latency:
  2. Test external service response time:
  3. Review Agent resource usage:
Solutions:
  • Increase timeout configuration (if configurable)
  • Optimize external service performance
  • Scale Agent resources if CPU/memory constrained

Certificate Issues

Certificate Validation Fails Symptoms:
  • mTLS certificate validation failed in logs
  • Agent fails to start
Diagnostic Steps:
  1. Verify certificate files exist:
  2. Check certificate validity:
  3. Verify certificate and key match:
  4. Check file permissions:
Solutions:
  • Generate new certificates
  • Fix file permissions (readable by container user)
  • Ensure certificate is registered with Spotify
  • Verify certificate and key are matching pair
Certificate Expired Symptoms:
  • Certificate expired in logs
  • agent_certificate_expiry_seconds negative or very low
Diagnostic:
Solutions:
  1. Generate new certificate
  2. Register with Spotify
  3. Update certificate files
  4. Restart Agent

Configuration Issues

Configuration File Not Found Symptoms:
  • Configuration file not found or ENOENT error
  • Agent exits immediately
Diagnostic Steps:
  1. Check CONFIG_PATH:
  2. Verify volume mount:
  3. Check file exists in container:
Solutions:
  • Fix CONFIG_PATH environment variable
  • Fix volume mount path
  • Verify file exists on host at mount source
Invalid Configuration Syntax Symptoms:
  • Invalid configuration or YAML parse errors
  • Agent fails to start
Diagnostic Steps:
  1. Validate YAML syntax:
  2. Check for common errors:
    • Incorrect indentation
    • Missing required fields
    • Invalid route patterns
Solutions:
  • Fix YAML syntax errors
  • Validate against configuration reference
  • Use YAML linter
Environment Variable Not Substituted Symptoms:
  • Headers contain literal ${VAR_NAME}
  • Authentication fails for external services
Diagnostic Steps:
  1. Check environment variables are set:
  2. Review configuration:
Solutions:
  • Set missing environment variables when starting container
  • Fix environment variable name mismatch
  • Use correct syntax: ${VAR_NAME} for env vars, ${VAR_NAME_FILE} for file-based

Resource Issues

High CPU Usage Symptoms:
  • Container using > 80% CPU consistently
  • Slow request processing
Diagnostic:
Solutions:
  • Increase CPU limits
  • Scale horizontally (add more Agent replicas)
  • Investigate unusually high request volume
High Memory Usage Symptoms:
  • Container approaching memory limit
  • OOMKilled events (Kubernetes)
Diagnostic:
Solutions:
  • Increase memory limits
  • Check for memory leaks (contact Spotify support)
  • Restart Agent to clear memory
Container Keeps Restarting Symptoms:
  • docker ps shows frequent restarts
  • Pod in CrashLoopBackOff (Kubernetes)
Diagnostic Steps:
  1. Check logs:
  2. Check exit code:
Solutions:
  • Fix configuration errors causing startup failure
  • Resolve certificate validation issues
  • Check resource limits not too restrictive
  • Review logs for specific error messages

Configuration Reference

This reference documents all configuration options for the Portal Connect Agent.

Configuration File Format

The Portal Connect Agent uses YAML format for configuration. The default configuration file location is app-config.yaml, but you can specify a custom path using the CONFIG_PATH environment variable.

Configuration Structure

Configuration Options

agent.brokerUrl

  • Type: String (required)
  • Description: WebSocket URL to connect the Agent to your Portal instance
  • Format: wss://broker.${subdomain}.spotifyportal.com
Example:
Notes:
  • Must use wss:// protocol (secure WebSocket)
  • Connection URL provided by Spotify
  • Do not modify the path component

agent.routes

  • Type: Array or Object (required)
  • Description: Defines which external URLs the Agent can access
Simple Array Format Use this format for routes without custom headers:
Advanced Object Format Use this format to specify per-route headers:
Route Patterns Exact match:
  • Matches only: https://api.example.com/v1/users
Wildcard match:
  • Matches:
    • https://api.example.com/v1/users
    • https://api.example.com/v1/users/123
    • https://api.example.com/v1/anything
  • Does not match:
    • https://api.example.com/v2/users (different path)
    • http://api.example.com/v1/users (different protocol)
Route Requirements
  • Must include protocol (http:// or https://)
  • Must include hostname
  • Path is optional but recommended
  • Wildcards (*) only supported at end of path
  • No query parameters or fragments in route patterns
Valid routes:
Invalid routes:

agent.mtls

  • Type: Object (optional, enabled by default)
  • Description: Mutual TLS (mTLS) configuration for secure authentication
agent.mtls.enabled
  • Type: Boolean (optional)
  • Default: true
  • Description: Enable or disable mTLS authentication
Production UsemTLS is required for production use. Only disable for local development.
agent.mtls.clientCertPath
  • Type: String (required when mTLS enabled)
  • Description: Path to client certificate file in PEM format
Example:
Notes:
  • Must be PEM-encoded X.509 certificate
  • Maximum certificate lifespan: 180 days
  • Certificate must be registered with Spotify
agent.mtls.clientKeyPath
  • Type: String (required when mTLS enabled)
  • Description: Path to private key file in PEM format
Example:
Notes:
  • Must be PEM-encoded RSA or ECDSA private key
  • For ECDSA: P-256 or P-384 elliptical curve (P-384 recommended)
  • For RSA: Minimum 2048-bit key size (4096-bit recommended)
  • Keep file secure with restricted permissions (400 or 600)
agent.mtls.validateOnStartup
  • Type: Boolean (optional)
  • Default: true
  • Description: Validate certificates when Agent starts
Example:
Notes:
  • Recommended to keep enabled
  • Startup will fail if certificates are invalid or expired
  • Helps catch certificate issues early

Environment Variables

CONFIG_PATH
  • Type: String
  • Default: ./app-config.yaml
  • Description: Path to the Agent configuration file
Example:
AGENT_METRICS_PORT
  • Type: Integer
  • Default: 9466
  • Description: Port for Prometheus metrics endpoint
Example:
LOG_LEVEL
  • Type: String
  • Default: info
  • Valid values: debug, info, warn, error
  • Description: Logging verbosity level
Example:

Environment Variable Substitution

Configuration files support environment variable substitution for sensitive values. Using Environment Variables Reference environment variables in configuration with ${VAR_NAME}:
Set the environment variable when running the container:
File-Based Secrets For secrets stored in files (e.g., Kubernetes secrets), use ${VAR_NAME_FILE}:
The Agent will read the secret from the file path:

Complete Configuration Examples

Minimal Configuration
Configuration with Multiple Routes
Configuration with Authentication Headers