Ditch the VPN: Building an Identity-Aware Proxy with Pomerium

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

Why VPNs Are Fading Away

If you’ve ever spent ten minutes wrestling with a finicky VPN client just to check a Grafana dashboard, you know the frustration. Beyond the user experience, VPNs rely on a ‘castle-and-moat’ security model. Once a user clears the perimeter, they often gain lateral access to the entire network. This creates a massive security hole. Modern infrastructure is moving toward Zero Trust, a model where identity is verified for every single request, regardless of where the user is sitting.

Identity-Aware Proxies (IAP) like Pomerium solve this by moving security to the application layer. Instead of launching a client, users simply visit a URL like internal-tool.company.com. Pomerium intercepts the traffic, validates the user’s session against an Identity Provider (IdP) like GitHub or Okta, and checks specific access policies. It’s faster, safer, and significantly easier to manage.

Why Pomerium Wins in Production

Pomerium acts as a unified gatekeeper for your services. It’s lightweight enough to run as a single binary but robust enough to handle high-traffic enterprise environments. After replacing a legacy OpenVPN setup with Pomerium for a team of 150+ engineers, we saw a 40% drop in access-related support tickets.

Key advantages include:

  • Zero Client Software: If you have a web browser, you have access. No more troubleshooting broken VPN drivers on macOS or Linux.
  • Granular Control: You can write policies that allow access only if a user is in the ‘DevOps’ GitHub team and connecting from a specific country.
  • Deep Audit Trails: Every single click and request is logged with an associated identity. This provides a level of visibility that network-level VPNs simply can’t match.

Setting Up Your Environment

We’ll use Docker Compose to build a proof-of-concept. This setup simulates a real-world environment by protecting a dummy internal application behind the Pomerium proxy. You will need a domain name (or a modified /etc/hosts file) and a GitHub account to act as your IdP.

1. Generate Your Encryption Keys

Pomerium requires two unique 32-byte base64 encoded strings to secure cookies and encrypt internal communication. Generate them quickly with this command:

head -c32 /dev/urandom | base64

Run this twice. Save the first string as your COOKIE_SECRET and the second as your SHARED_SECRET. Keep these safe; they are the keys to your kingdom.

2. The Docker Compose Configuration

Create a directory named pomerium-lab and drop the following into a docker-compose.yaml file. This defines the proxy and a simple ‘Hello World’ app to protect.

version: '3'
services:
  pomerium:
    image: cache.pomerium.io/pomerium/pomerium:latest
    container_name: pomerium
    volumes:
      - ./config.yaml:/pomerium/config.yaml
    ports:
      - "443:443"
    environment:
      - COOKIE_SECRET=YOUR_FIRST_SECRET
      - SHARED_SECRET=YOUR_SECOND_SECRET

  internal-app:
    image: nginxdemos/hello
    container_name: internal-app
    expose:
      - "80"

Defining Your Access Policies

The config.yaml file is where you define your logic. To use GitHub, you must first create an OAuth App in your GitHub Developer Settings. Set the ‘Authorization callback URL’ to https://authenticate.yourdomain.com/oauth2/callback.

Configuring the Proxy

Create a config.yaml in the same folder with this structure:

address: ":443"
authenticate_service_url: https://authenticate.yourdomain.com

idp_provider: github
idp_client_id: "your-github-id"
idp_client_secret: "your-github-secret"

routes:
  - from: https://internal-tool.yourdomain.com
    to: http://internal-app:80
    policy:
      allow:
        and:
          - domain:
              is: yourcompany.com
          - github:
              groups:
                - "engineering-team"

This policy is strict. It ensures that only users with a yourcompany.com email who are also members of your ‘engineering-team’ on GitHub can see the app. Everyone else gets a 403 Forbidden page before they even touch your application server.

Verification and Performance

Launch the stack with docker-compose up -d. When you navigate to your tool’s URL, Pomerium will redirect you to GitHub for a standard OAuth login. Once you approve, you are passed back to the internal app seamlessly.

Monitoring Access

Visibility is a core tenet of Zero Trust. You can watch access decisions in real-time by tailing the logs:

docker logs -f pomerium

A successful entry will show a check_result: allow along with the user’s GitHub ID. This makes auditing for compliance (like SOC2 or ISO27001) significantly easier than digging through firewall logs.

Latency and Scaling

In production tests, Pomerium typically adds less than 5ms to 10ms of overhead per request. For standard web tools, this is imperceptible to users. If you are handling thousands of concurrent users, you can scale horizontally by running multiple proxy instances behind a load balancer. For Kubernetes users, the Pomerium Ingress Controller can automate this entire configuration via standard Ingress resources.

Offboarding Made Simple

The biggest operational win is how this handles employee departures. When an engineer leaves and you remove them from your GitHub organization, their access to every internal tool vanishes instantly. You no longer have to hunt down stale VPN credentials or rotate shared SSH keys. By centralizing access around your primary identity provider, you reduce the attack surface and the administrative burden simultaneously.

Share: