ZuploZuplo
LoginStart for Free
  • Documentation
  • API Reference
Introduction
Getting Started
    Develop on the web portal
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
    Develop locally with the CLI
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
Concepts
Development
Policies
Handlers
API Keys
Rate Limiting
MCP Server
MCP Gateway
AI Gateway
Developer Portal
Monetization
Deploying & Source Control
Analytics
Observability
Networking & Infrastructure
    Overview
    Managed Dedicated
    Managed EdgeSelf Hosted
    Custom Domains
    Securing Your Backend
      Securing your backendGateway to Origin mTLS AuthenticationConnect to an AWS ALB with mTLSGCP Backend with Upstream Auth
      Secure Tunnel
    Web Application Firewalls
    DDoS Protection
Account Management
Programming API
Build with AI
Zuplo CLI
Migration Guides
Platform LimitsSecuritySupportTrust & ComplianceChangelog
powered by Zudoku
Securing Your Backend

Connect to an AWS ALB with mTLS

Enterprise Feature

mTLS Client Certificates is available as an add-on as part of an enterprise plan. If you would like to purchase this feature, please contact us at sales@zuplo.com or reach out to your account manager.

Most enterprise features can be used in a trial mode for a limited time. Feel free to use enterprise features for development and testing purposes.

When your backend sits behind an AWS Application Load Balancer (ALB), you can lock the ALB down so it only accepts requests that prove they came from your Zuplo gateway. ALB mutual TLS (mTLS) in verify mode requires every client to present an X.509 certificate that chains to a Certificate Authority (CA) in the ALB's trust store. Zuplo presents that client certificate on each outbound request, and the ALB rejects anything that can't.

This guide covers the Zuplo side of that connection: uploading a client certificate and presenting it on requests to the ALB. It does not cover configuring the ALB itself — for that, follow the AWS documentation linked in Configure the ALB.

How it works

The ALB's HTTPS listener is configured for mTLS verify mode and backed by a trust store that contains the CA which issued Zuplo's client certificate. On each request, the gateway presents its client certificate, the ALB verifies it against the trust store, and only then forwards the request to the target group.

AWS VPC
ALB (mTLS verify)
Backend targets
Client
Zuplo Gateway
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

This gives you two guarantees at once:

  • The ALB trusts the gateway. The load balancer rejects requests that don't present a valid client certificate before they reach your application.
  • The gateway trusts the ALB. Standard TLS still verifies the ALB's server certificate, so the gateway knows it's talking to the real backend.

For background on the gateway-to-origin direction in general, see Gateway to Origin mTLS Authentication.

Prerequisites

Before you begin, you need:

  • A client certificate and private key (PEM-encoded) issued by a CA. The same CA must be uploaded to the ALB's trust store.
  • An AWS Application Load Balancer with an HTTPS listener you can configure for mTLS.
  • The Zuplo CLI installed and authenticated.

1/ Configure the ALB

On the AWS side, configure the ALB's HTTPS listener to use mutual TLS in verify mode and create a trust store that contains the CA which signed your client certificate. Verify mode is what makes the ALB perform X.509 client certificate authentication during the TLS handshake.

Follow the AWS documentation:

  • Mutual authentication with TLS in Application Load Balancer — concepts, verify vs. passthrough mode, and trust stores.
  • Configuring mutual TLS on an Application Load Balancer — step-by-step listener and trust store setup.

Use verify mode, not passthrough. In passthrough mode the ALB forwards the client certificate to your targets without checking it, so the load balancer does not enforce trust. Verify mode is what rejects untrusted callers at the edge.

2/ Upload your client certificate to Zuplo

Use the Zuplo CLI to upload the client certificate and private key to your project. The CA that issued this certificate must already be in the ALB's trust store.

TerminalCode
zuplo mtls-certificate create \ --cert client-cert.pem \ --key client-key.pem \ --name aws-alb-cert \ --account your-account \ --project your-project \ --environment-type development \ --environment-type preview \ --environment-type production

The certificate name must follow JavaScript's variable naming constraints because you reference it by name in your configuration. The CLI validates this when you create the certificate.

3/ Present the certificate on requests to the ALB

Reference the uploaded certificate by name when the gateway forwards requests to the ALB. Use the ALB's DNS name (or a custom domain pointed at it) as the backend URL.

The simplest option is the URL Forward Handler, configured directly on a route in config/routes.oas.json:

Code
{ "handler": { "export": "urlForwardHandler", "module": "$import(@zuplo/runtime)", "options": { "baseUrl": "https://my-alb-1234567890.us-east-1.elb.amazonaws.com", "mtlsCertificate": "aws-alb-cert" } } }

If you need to inspect or transform the request before forwarding, use a Function Handler and pass the certificate name in the zuplo options of fetch:

Code
import { ZuploContext, ZuploRequest } from "@zuplo/runtime"; export default async function (request: ZuploRequest, context: ZuploContext) { const response = await fetch( "https://my-alb-1234567890.us-east-1.elb.amazonaws.com/api", { zuplo: { mtlsCertificate: "aws-alb-cert", }, }, ); return response; }

4/ Use environment variables across environments

To use a different certificate per environment, store the certificate name in an environment variable and reference it with the $env() selector:

Code
{ "handler": { "export": "urlForwardHandler", "module": "$import(@zuplo/runtime)", "options": { "baseUrl": "${env.ALB_BACKEND_URL}", "mtlsCertificate": "$env(ALB_MTLS_CERT)" } } }

In a Function Handler, read the same variable from the environment object:

Code
import { ZuploContext, ZuploRequest, environment } from "@zuplo/runtime"; export default async function (request: ZuploRequest, context: ZuploContext) { const response = await fetch(`${environment.ALB_BACKEND_URL}/api`, { zuplo: { mtlsCertificate: environment.ALB_MTLS_CERT, }, }); return response; }

Verify the connection

Deploy your changes to a preview or production environment, then send a request through the gateway to a route that forwards to the ALB. A successful response confirms the ALB accepted the client certificate.

mTLS bindings aren't available in local development. Code that references an mTLS certificate only works once deployed to a Zuplo edge environment — test in a preview environment rather than locally.

Troubleshooting

Requests fail with a 522 or connection error

A 522 means the connection to the ALB failed before an HTTP response was received — usually a TLS handshake problem. Confirm that:

  • The CA that issued Zuplo's client certificate is present in the ALB's trust store.
  • The client certificate hasn't expired.
  • The mtlsCertificate name in your configuration matches the name you used in zuplo mtls-certificate create.

The ALB rejects the certificate

If the handshake completes but the ALB returns a 403, the certificate is being presented but not trusted. Re-check the ALB trust store and confirm the listener is in verify mode, not passthrough. If your client certificate is issued by an intermediate CA, make sure the trust store contains the full chain back to the root.

No certificate appears to be sent

Confirm the upload succeeded and the certificate is enabled for the environment you deployed to:

TerminalCode
zuplo mtls-certificate list \ --account your-account \ --project your-project

Related resources

  • Gateway to Origin mTLS Authentication
  • Securing your backend
  • URL Forward Handler
  • Function Handler
  • Environment Variables
  • Mutual authentication with TLS in Application Load Balancer (AWS)
Edit this page
Last modified on June 23, 2026
Gateway to Origin mTLS AuthenticationGCP Backend with Upstream Auth
On this page
  • How it works
  • Prerequisites
  • 1/ Configure the ALB
  • 2/ Upload your client certificate to Zuplo
  • 3/ Present the certificate on requests to the ALB
  • 4/ Use environment variables across environments
  • Verify the connection
  • Troubleshooting
    • Requests fail with a 522 or connection error
    • The ALB rejects the certificate
    • No certificate appears to be sent
  • Related resources
JSON
TypeScript
JSON
TypeScript