Question

How to get Client IP using DO Loadbalancer and APISIX as ingress controller

Hi all,

I’m trying to get client IPs behind a DO loadbalancer using APISIX as an ingress controller / API gateway. I enabled the proxy protocol on the DO loadbalancer but can’t get it to work unfortunately.

My current configuration:

dataPlane:
  service:
    annotations:
      service.beta.kubernetes.io/do-loadbalancer-name: "lb-name"
      service.beta.kubernetes.io/do-loadbalancer-size-unit: "1"
      service.beta.kubernetes.io/do-loadbalancer-tls-passthrough: "true"
      service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
    extraConfig:
      apisix:
        proxy_protocol:
          listen_http_port: 9181
          listen_https_port: 9182
      nginx_config:
        http:
          real_ip_header: proxy_protocol

I’m hosting multiple domains including TLS certificates (from Let’s Encrypt) on the current loadbalancer configuration, but I would like to get the client IPs. Also would like to avoid creating a loadbalancer with TLS terminiation per domain as this could increase costs unnecessarily.

Any help appreciated, thanks !


Submit an answer


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Bobby Iliev
Site Moderator
Site Moderator badge
February 27, 2025

Hi there,

Usually enabling PROXY Protocol is the way to get the real client IP, but APISIX needs to be configured properly to handle it.

You should be able to do that by:

  1. First, enable PROXY Protocol on the LB. Add this annotation to your Kubernetes Service:

    service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
    service.beta.kubernetes.io/do-loadbalancer-tls-passthrough: "true"
    

    This ensures the LB sends the original client IP.

  2. Then configure APISIX to expect the PROXY Protocol. Update your APISIX config:

    apisix:
      proxy_protocol:
        listen_http_port: 80
        listen_https_port: 443
      enable_tcp_pp: true
    nginx_config:
      http:
        real_ip_header: proxy_protocol
    

    Without this, APISIX won’t interpret the client IP correctly.

  3. Also, set externalTrafficPolicy: Local. This prevents Kubernetes from SNAT’ing the source IP:

    spec:
      externalTrafficPolicy: Local
    

As far as I can tell from the docs, APISIX requires dedicated ports for PROXY Protocol, so your existing listeners may need adjustments.

If PROXY Protocol isn’t working as expected, an alternative is to let the LB handle TLS termination and use X-Forwarded-For, but DigitalOcean LBs don’t support multiple TLS certificates, which could be a dealbreaker.

- Bobby

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.