PART I — UNDERSTAND THE WORLD BEFORE THE TOOL
Chapter 1. The Big Picture
Imagine a medieval castle. To keep the treasure inside safe, the king builds a massive stone wall and a moat. If you have the key to the front gate, you are allowed inside. Once you are inside, you can walk freely into the armory, the kitchen, and the throne room because the guards assume that anyone inside the walls is trustworthy.
For decades, computer networks were built the exact same way. Companies built a “perimeter” using Firewalls and Virtual Private Networks (VPNs). If you connected to the VPN, you were “inside the network” and trusted.
What changed? The modern world broke this model. Employees now work from coffee shops, not just the office. Applications live in the cloud, not just in the basement server room. Furthermore, if a hacker steals a single employee’s VPN password, they get past the “castle wall” and can freely attack every system inside (this is called lateral movement).
We needed a new approach: Zero Trust. Instead of trusting you because you are inside the network, Zero Trust verifies your identity and device health every single time you try to open an application, regardless of where you are sitting. Pomerium is a tool built to enforce this exact model.
What You Should Understand Before Moving On: The old way of securing applications relied on trusting the network (VPNs). The new way relies on verifying identity and context for every single request (Zero Trust).
Chapter 2. Prerequisite Concepts
To understand Pomerium, you must understand the building blocks it relies on.
| Concept | Simple Definition | Everyday Analogy | Technical Explanation | Why It Matters |
| Reverse Proxy | A middleman that sits in front of your applications and intercepts incoming traffic. | A receptionist who intercepts all visitors, checks their reason for visiting, and then points them to the right office. | A server that retrieves resources on behalf of a client from one or more backend servers. | Pomerium is a reverse proxy. It intercepts your web requests. |
| Identity Provider (IdP) | A service that manages user accounts and proves who you are. | The DMV (Department of Motor Vehicles) that issues your ID card. | A system (like Google Workspace, Okta, or GitHub) that authenticates users and provides tokens via OIDC/SAML. | Pomerium doesn’t store passwords. It asks your IdP to verify you. |
| OIDC / OAuth2 | Open protocols for authentication and authorization. | The standard barcode format used on your ID card so any scanner can read it. | OpenID Connect provides identity verification; OAuth2 provides delegated access. | Pomerium uses these to talk to your IdP securely. |
| JWT (JSON Web Token) | A secure, digitally signed digital ID card. | A wristband at a concert. Once they check your ticket, you get a wristband to prove you are allowed in. | A compact, URL-safe string containing cryptographic claims about a user. | Pomerium reads and passes JWTs to your applications. |
| Zero Trust | The security philosophy of “Never trust, always verify.” | A hotel where your keycard is checked at the front door, the elevator, AND your room door. | A framework requiring all users to be authenticated and authorized continuously before being granted access. | This is the architectural pattern Pomerium helps you achieve. |
Chapter 3. Essential Terminology and Glossary
| Term | Full Form | Simple Meaning | Example | Why It Matters |
| IAP | Identity-Aware Proxy | A proxy that checks who you are before letting you through. | Pomerium, Google Cloud IAP. | This is the specific category of tool Pomerium falls into. |
| Route | N/A | A rule connecting a public URL to a private application. | Connecting admin.company.com to internal IP 10.0.0.5. | You will configure routes for every app you protect. |
| Policy | N/A | The rules deciding who can use a Route. | “Only allow users with the email domain @mycompany.com” | This is how you enforce security. |
| Envoy | Envoy Proxy | The high-performance engine running underneath Pomerium. | A car’s engine, while Pomerium is the steering wheel and dashboard. | Pomerium is technically a control plane that configures an underlying Envoy proxy. |
| Session | N/A | A temporary period of authorized access. | Being logged in for 12 hours before having to re-enter your password. | Pomerium manages session state so users don’t have to log in on every single click. |
Chapter 4. How the Technology Domain Works Without This Tool
Before Identity-Aware Proxies like Pomerium, remote access looked like this:
- The user installs a VPN client on their laptop.
- The user connects to the company VPN gateway.
- The VPN gateway verifies the user’s password and connects their computer to the internal corporate network.
- The user types
[http://internal-wiki.local](http://internal-wiki.local)into their browser. - The request travels through the VPN tunnel to the internal server.
Code snippet
flowchart LR
User["User (Coffee Shop)"] -- 1. Connects to --> VPN["VPN Gateway"]
VPN -- 2. Grants Network Access --> Network["Corporate Internal Network"]
Network -- 3. Access App --> App1["Internal Wiki"]
Network -- 3. Access App --> App2["Admin Dashboard"]
Network -- 3. Access App --> App3["HR System"]
Code language: CSS (css)
The problem with this approach: Once the user passes step 2, they have access to the entire Corporate Internal Network. If they are a malicious actor, they can easily probe App2 or App3, even if they only needed to access App1.
PART II — UNDERSTAND THE TOOL
Chapter 5. What Is Pomerium?
Pomerium is an open-source Identity-Aware Proxy (IAP).
- Primary Purpose: To securely connect users to internal applications without a VPN, by verifying their identity for every single request.
- Who uses it: System Administrators, DevOps engineers, and Security teams.
- Where it runs: Typically deployed at the edge of your network (in Docker, Kubernetes, or on a Linux server) facing the public internet.
- What it does NOT do: It is not an Identity Provider (it doesn’t store passwords—it relies on Google, Okta, GitHub, etc.). It is also not a web application firewall (WAF), though it provides some overlapping protections.
- Definitions:
- One-sentence: Pomerium is an open-source tool that acts as a secure gateway, verifying a user’s identity before letting them access private web applications.
- Technical: Pomerium is an identity-aware access proxy built on Envoy that integrates with OIDC Identity Providers to enforce Zero Trust access control policies at the application layer (Layer 7).
Chapter 6. Why Does This Tool Exist?
Pomerium exists to solve the vulnerabilities of perimeter-based security (VPNs) and the complexity of managing application access.
Situations where it is useful:
- You have a private dashboard (like Grafana or Jenkins) that you want your team to access from home, but you don’t want to expose it to the public internet or force them to use a clunky VPN.
- You want to enforce Two-Factor Authentication (2FA) on an older application that doesn’t support 2FA natively. (Pomerium enforces 2FA at the proxy level via your IdP).
Situations where it is unnecessary:
- You are building a public-facing blog where anyone should have access.
- You only need machine-to-machine TCP routing without user identity (a standard reverse proxy like Nginx or HAProxy is fine).
The Benefit: Fast, seamless user experience. Users just type the URL into their browser, authenticate with their normal work email (via Google/Okta), and are instantly in the app. No VPN clients required.
Chapter 7. How the Tool Works
Pomerium sits between the public internet and your private applications.
- Intercept: A user requests
[https://wiki.company.com](https://wiki.company.com). Pomerium intercepts this request. - Authenticate: Pomerium checks if the user has a valid session cookie. If not, it redirects them to the Identity Provider (e.g., Google).
- Authorize: Once Google says “This is Alice,” Pomerium checks its configuration file: Is Alice allowed to view the wiki?
- Proxy: If Alice is authorized, Pomerium forwards the request to the internal wiki server and returns the result to Alice.
Code snippet
sequenceDiagram
participant U as User Browser
participant P as Pomerium
participant IdP as Identity Provider (e.g. Google)
participant A as Internal App
U->>P: 1. GET https://app.company.com
P->>U: 2. Redirect to IdP for login
U->>IdP: 3. User logs in
IdP->>P: 4. Returns Identity Token (OIDC)
P->>P: 5. Evaluates Policy (Is user allowed?)
P->>A: 6. Proxies request to Internal App
A->>P: 7. Returns Application Data
P->>U: 8. Displays Application to User
Code language: JavaScript (javascript)
Chapter 8. Core Features Explained Simply
| Feature | Simple Explanation | Problem Solved | Beginner or Advanced |
| SSO Integration | Uses your existing login system (Google, Okta, GitHub). | Prevents you from having to create new passwords for internal tools. | Essential |
| Policy Enforcement | Rules like “Only the Dev team can access this app.” | Granular security control per application. | Essential |
| Identity Header Passing | Sends the user’s email to the backend app securely via a JWT. | The backend app knows who you are without you having to log in twice. | Advanced |
| Audit Logging | Records exactly who accessed what, and when. | Compliance and security investigations. | Everyday |
| TCP Support | Secures SSH or database connections, not just websites. | Securing non-web traffic over Zero Trust. | Advanced |
Chapter 9. Similar Tools and Alternatives
| Tool | Primary Purpose | Main Strength | Main Limitation | Best Use Case | Relationship to Pomerium |
| Cloudflare Access | Managed ZTNA | Extremely easy to set up, globally distributed. | It is a proprietary SaaS; you don’t control the data plane. | Small teams wanting instant setup without managing servers. | Direct competitor (SaaS vs Self-hosted). |
| Tailscale | Mesh VPN | Connects devices via Wireguard easily. | Gives network-level access (VPN) rather than just application-level proxying. | Connecting servers and devices directly. | Complementary/Alternative. |
| Google Cloud IAP | Cloud Identity Proxy | Native integration with GCP. | Only works well if your apps are hosted in Google Cloud. | Teams exclusively using Google Cloud infrastructure. | Direct competitor (Platform specific). |
| Nginx / Traefik | Standard Reverse Proxy | Extremely fast, flexible routing. | No native identity awareness; you have to build auth yourself. | Public websites, microservices routing. | Predecessor/Alternative for non-auth needs. |
Which Tool Should You Choose and Why? Choose Pomerium if you want to self-host your security infrastructure, maintain complete control over your data, and require granular identity-aware routing for web applications. Choose Cloudflare Access if you want a managed SaaS. Choose Tailscale if you need machine-to-machine VPN networking.
PART III — ARCHITECTURE AND WORKFLOWS
Chapter 10. Architecture Explained from Simple to Advanced
Pomerium can be deployed in two ways: All-in-One (for beginners) or Distributed (for production).
The Simplest Setup (All-in-One): For smaller setups, Pomerium runs as a single binary or single Docker container. Inside this single process, four distinct services run together:
- Proxy: The front door. It receives the user’s web request.
- Authenticate: Handles the handshake with your Identity Provider (Google, Okta).
- Authorize: The bouncer. It checks the policy to see if the authenticated user is allowed in.
- Databroker: The memory. It stores session data and user information.
Distributed Setup (Production): In high-traffic environments, you split these four components into separate servers or Kubernetes pods so they can scale independently.
Code snippet
flowchart TD
User["User Browser"] --> Proxy["Proxy Service (Edge)"]
Proxy <--> AuthZ["Authorize Service"]
Proxy <--> AuthN["Authenticate Service"]
AuthZ <--> DataBroker["Databroker Service"]
AuthN <--> DataBroker
AuthN <--> IdP["Identity Provider (External)"]
Proxy --> App["Internal Application"]
Code language: CSS (css)
In the diagram above, the Proxy receives the request, asks the Authenticate service to verify identity (which talks to the IdP), asks the Authorize service to verify permissions (which checks the Databroker for policy/state), and finally proxies traffic to the App.
Chapter 11. The Complete Workflow
- Trigger: A user navigates to
[https://grafana.internal.com](https://grafana.internal.com). - Input: The browser sends an HTTP GET request.
- Component: The Pomerium Proxy Service receives it.
- Processing (No Session): Pomerium sees no session cookie. It redirects the user to the IdP.
- Dependency: The external IdP (e.g., Auth0) prompts for a password and 2FA.
- Processing (Authorization): The user returns with a token. The Authorize Service checks the configuration: Does user match policy?
- Result: Access is granted. The Proxy forwards the GET request to the internal Grafana server.
- Failure Path: If the user logs in but is not in the correct group, Pomerium intercepts the request and displays an HTTP 403 Access Denied page, preventing the traffic from ever touching the Grafana server.
PART IV — INSTALLATION AND FIRST SUCCESS
Chapter 13. Prerequisites and Environment Preparation
Before installing Pomerium, you must have:
- A domain name: Pomerium relies heavily on HTTPS and cookies. You need a real domain (e.g.,
example.com). - TLS Certificates: You can use wildcard certs, Let’s Encrypt, or self-signed certs (for local testing).
- An Identity Provider: You need a free account with an IdP like Auth0, GitHub, or a Google Workspace account. You will need a
Client IDandClient Secretfrom them. - Shared Secret: A base64-encoded random string used by Pomerium components to securely talk to each other.
- Cookie Secret: A base64-encoded random string used to encrypt user browser cookies.
Tip: Generate your secrets now in your terminal:
Bash
head -c32 /dev/urandom | base64
(Run this twice: once for SHARED_SECRET and once for COOKIE_SECRET)
Chapter 14. Install on Supported Operating Systems
Pomerium is distributed as a single compiled binary, meaning it does not require complex runtime environments (like Java or Python).
A. Docker (Recommended for all OS / Beginners)
Because Pomerium requires an app to protect and specific configurations, using Docker Compose is the most universal way to run it on Windows, macOS, or Linux.
Bash
# Pull the official Pomerium image
docker pull pomerium/pomerium:latest
Code language: PHP (php)
B. Ubuntu / Debian (Native)
Use the official package repository.
Bash
# Add the signing key and repository
sudo curl -1sLf 'https://dl.cloudsmith.io/public/pomerium/pomerium/gpg.05193B615F3BA22A.key' | sudo gpg --dearmor -o /usr/share/keyrings/pomerium-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/pomerium-archive-keyring.gpg] https://dl.cloudsmith.io/public/pomerium/pomerium/deb/debian any-version main" | sudo tee /etc/apt/sources.list.d/pomerium.list
# Install
sudo apt update && sudo apt install pomerium
Code language: PHP (php)
Configuration will live in /etc/pomerium/config.yaml.
C. macOS (Native via Homebrew)
Bash
brew install pomerium
To start it: brew services start pomerium.
D. Windows
Pomerium does not have a native Windows installer. Windows users must use Docker Desktop or Windows Subsystem for Linux (WSL2) running Ubuntu.
Chapter 15. Your First Working Example
Let’s build a working Identity-Aware Proxy on your local machine using Docker Compose. We will protect a simple Nginx web server using GitHub as our Identity Provider.
Objective: Protect http://localhost:8080 so only YOU (via your GitHub account) can access it.
Step 1: Get GitHub OAuth Credentials
- Go to your GitHub Settings -> Developer settings -> OAuth Apps.
- Click “New OAuth App”.
- Name:
Pomerium Local - Homepage URL:
https://localhost - Authorization callback URL:
https://localhost/.pomerium/callback - Save. Copy the Client ID and generate a Client Secret.
Step 2: Create the config.yaml file Create a folder named pomerium-test. Inside, create config.yaml:
YAML
# config.yaml
authenticate_service_url: https://localhost
# Identity Provider Settings
idp_provider: github
idp_client_id: "YOUR_GITHUB_CLIENT_ID"
idp_client_secret: "YOUR_GITHUB_CLIENT_SECRET"
# Security (Replace with strings generated earlier)
cookie_secret: "OThkNzVkMmEtY2E2OS00ZGUzLTliNGEtYTEwNzE1Y2Vj"
shared_secret: "Zjk1YThkYzUtYmEyNi00MjMzLWI1ZjYtNjkyMmVlOTc"
# Testing settings (bypasses requirement for valid public TLS certs)
insecure_server: true
# The Routing Policy
routes:
- from: https://localhost
to: http://hello-app:80
policy:
- allow:
or:
- claim/email: "YOUR_GITHUB_EMAIL@example.com"
Code language: PHP (php)
(Replace the Client ID, Secret, and your GitHub email address).
Step 3: Create the docker-compose.yml file In the same folder, create this file:
YAML
# docker-compose.yml
version: "3"
services:
pomerium:
image: pomerium/pomerium:latest
volumes:
- ./config.yaml:/pomerium/config.yaml
ports:
- "443:443" # HTTPS
- "80:80" # HTTP
# The internal app we are protecting
hello-app:
image: nginxdemos/hello:plain-text
expose:
- "80"
Code language: PHP (php)
Step 4: Run and Verify
- Open your terminal in the
pomerium-testfolder. - Run:
docker-compose up - Open your web browser and go to
https://localhost - Expected Output: You will be instantly redirected to GitHub to log in. After logging in, you will be redirected back to localhost, where you will see the Nginx hello screen!
- To undo: Press
Ctrl+Cin your terminal, then typedocker-compose down.
Common Mistake: Using http:// instead of https://. Pomerium routes strictly enforce HTTPS for the public-facing side.
PART V — COMMANDS, CONFIGURATION AND DAILY USAGE
Chapter 16. Essential Commands and Operations
If you install Pomerium natively (not Docker), you use the pomerium CLI.
| Command | What It Does | When to Use It | Example |
pomerium | Starts the Pomerium service using defaults. | Running the server manually. | pomerium -config=/etc/pomerium/config.yaml |
pomerium-cli tcp | Starts a local TCP tunnel authenticated via Pomerium. | When you want to SSH into a server secured by Pomerium. | pomerium-cli tcp ssh.internal.com:22 |
Note: Pomerium is primarily controlled via its configuration file, not dynamic CLI commands.
Chapter 17. Configuration Explained
The core of Pomerium is the config.yaml file. It has two main sections: Global Settings and Routes.
YAML
# 1. Global Settings
address: ":443" # Port Pomerium listens on
authenticate_service_url: https://auth.company.com # Where users go to login
idp_provider: okta # Which IdP you are using
idp_client_id: "xyz123" # Provided by your IdP
idp_client_secret: "secret987" # Provided by your IdP
idp_provider_url: "https://mycompany.okta.com" # Required for some IdPs
cookie_secret: "base64-secret" # Encrypts the session cookie
# 2. Routes (The Apps you are protecting)
routes:
- from: https://wiki.company.com # What the user types in their browser
to: http://10.0.1.55:8080 # Where the actual app lives internally
policy: # The security rules
- allow:
or:
- domain: "company.com" # Anyone with a company email can enter
- from: https://admin.company.com
to: http://10.0.1.56:80
policy:
- allow:
or:
- claim/email: "admin@company.com" # Only this specific person can enter
Code language: PHP (php)
Configuration Precedence: Pomerium reads configuration in this order:
- Environment Variables (e.g.,
POMERIUM_IDP_CLIENT_ID) config.yaml- Default values.Best Practice: Store secrets (like
idp_client_secret) as environment variables, and routing rules in the YAML file.
Chapter 18. Logs, Status and Verification
Checking Logs: If Pomerium isn’t working, logs are your best friend. Pomerium outputs JSON-formatted logs by default.
- Docker:
docker logs pomerium_container_name - Ubuntu (Systemd):
journalctl -u pomerium -f
Understanding the Logs: When a user accesses an app successfully, you will see a log entry with "level":"info" and "authorize_result":"allow". If they are blocked, you will see "authorize_result":"deny".
Troubleshooting Status: Pomerium has a built-in special endpoint. If you navigate to [https://app.company.com/.pomerium/](https://app.company.com/.pomerium/) in your browser (notice the /.pomerium/ path), Pomerium will display a status page showing your current session, email, and the claims it received from the Identity Provider.
PART VI — REAL-WORLD APPLICATIONS
Chapter 19. Practical Use Cases
- The Internal Wiki (Small Team):
- Problem: The team relies on an internal Confluence/Wiki server, but VPNs are too slow.
- Solution: Pomerium routes
wiki.company.comto the internal server, allowing access to anyone with a@company.comGoogle Workspace email.
- The Developer Admin Panel (Production):
- Problem: Developers need access to a Jenkins CI/CD dashboard, but it has weak built-in security.
- Solution: Pomerium wraps the Jenkins UI. Only users in the GitHub
DevOpsteam are allowed through. Jenkins is completely hidden from the internet.
- Legacy App Protection (Enterprise):
- Problem: A 15-year-old HR application doesn’t support Two-Factor Authentication.
- Solution: Pomerium is placed in front of it. Pomerium forces the user to log in via Okta (which enforces 2FA). The legacy app is instantly secured without rewriting its code.
Chapter 20. A Complete Hands-On Project
Project: Secure a private Grafana dashboard.Prerequisites: Docker, Docker Compose, a free Auth0 account.
Step 1: Auth0 Setup
- Create a “Regular Web Application” in Auth0.
- Set Allowed Callback URLs to:
[https://grafana.local.test/.pomerium/callback](https://grafana.local.test/.pomerium/callback) - Save Client ID, Client Secret, and your Auth0 Domain.
Step 2: File Structure Create a directory with docker-compose.yaml and config.yaml. Update your computer’s hosts file (e.g., /etc/hosts) to map 127.0.0.1 grafana.local.test.
Step 3: config.yaml
YAML
authenticate_service_url: https://grafana.local.test
idp_provider: auth0
idp_client_id: "YOUR_AUTH0_CLIENT_ID"
idp_client_secret: "YOUR_AUTH0_SECRET"
idp_provider_url: "https://YOUR_AUTH0_DOMAIN.auth0.com"
cookie_secret: "YOUR_COOKIE_SECRET"
shared_secret: "YOUR_SHARED_SECRET"
insecure_server: true
routes:
- from: https://grafana.local.test
to: http://grafana:3000
policy:
- allow:
and:
- authenticated_user: true
Code language: JavaScript (javascript)
Step 4: docker-compose.yaml
YAML
version: "3"
services:
pomerium:
image: pomerium/pomerium:latest
volumes:
- ./config.yaml:/pomerium/config.yaml
ports:
- "443:443"
grafana:
image: grafana/grafana:latest
# Notice we DO NOT map ports here. Grafana is entirely isolated.
Code language: PHP (php)
Step 5: Testing Run docker-compose up. Navigate to [https://grafana.local.test](https://grafana.local.test). You will be intercepted by Auth0. Log in, and you will securely access Grafana!
PART VII — ADVANCED CAPABILITIES
Chapter 21. Advanced Features
- JWT Identity Headers: When Pomerium proxies traffic to the backend app (like Grafana), it injects a HTTP header called
X-Pomerium-Jwt-Assertion. The backend app can read this JWT to automatically log the user in, achieving true Single Sign-On (SSO). The backend never needs to ask for a password again. - Redis / Postgres Databroker Storage: By default, Pomerium stores session data in memory. If Pomerium restarts, everyone gets logged out. In production, you configure Pomerium to use Redis or PostgreSQL to store sessions so it becomes Highly Available (HA).
- TCP Proxying: Pomerium isn’t just for web apps. By using the
pomerium-clion a client machine, you can secure SSH or database (e.g., MySQL) traffic through Pomerium’s Zero Trust policies.
Chapter 22. Security Best Practices
| Insecure Practice | Safer Alternative |
Hardcoding idp_client_secret in config.yaml. | Passing secrets via Environment Variables or a Secret Manager (Kubernetes Secrets). |
| Leaving backend apps exposed to the network. | Blocking all incoming traffic to the backend app except traffic coming from Pomerium’s IP. |
Using basic claim/email policies for large teams. | Using IdP group memberships (e.g., groups: admin) so offboarding is centralized in the IdP. |
insecure_server: true | Only use this for local testing. In production, use valid TLS certificates (like Let’s Encrypt). |
Chapter 23. Production-Ready Architecture
When moving to production, you graduate from the “All-in-One” Docker container to a Distributed Architecture.
- Load Balancer: Place a cloud Load Balancer in front of Pomerium.
- Separate Services: Run the
Proxy,Authenticate,Authorize, andDatabrokeras separate pods in Kubernetes. - Database: Connect the
Databrokerto a managed PostgreSQL database. - Scale: If traffic increases, you can scale just the
Proxyservice horizontally to 5, 10, or 20 instances.
Code snippet
flowchart TD
Internet["Public Internet"] --> LB["Cloud Load Balancer"]
LB --> Proxy1["Pomerium Proxy 1"]
LB --> Proxy2["Pomerium Proxy 2"]
Proxy1 <--> AuthZ["Pomerium Authorize"]
Proxy2 <--> AuthZ
AuthZ <--> DB["PostgreSQL (State)"]
Code language: CSS (css)
PART VIII — TROUBLESHOOTING AND MASTERY
Chapter 24. Common Problems and Solutions
| Problem or Error | Likely Cause | How to Diagnose | Solution |
| Infinite Redirect Loop | The authenticate_service_url doesn’t match the URL you configured in the IdP. | Check browser network tab. Does it bounce between the IdP and Pomerium? | Ensure the callback URL in your IdP exactly matches the authenticate_service_url + /.pomerium/callback. |
| HTTP 403 Access Denied | User authenticated successfully, but policy rejected them. | Go to /.pomerium/ on the app URL and check your “Claims”. | Update config.yaml policy to match the user’s actual email or group claim. |
| HTTP 503 Service Unavailable | Pomerium cannot reach the internal backend app. | Run curl -I http://backend-ip from the machine running Pomerium. | Fix network routing, firewall rules, or Docker networks so Pomerium can reach the to: address. |
| Invalid Certificate Error | Browser warns connection is not private. | Look at the certificate details in the browser. | Provide valid TLS certificates to Pomerium, or set insecure_server: true if testing locally. |
Chapter 25. Best Practices and Common Mistakes
- Habit: Always check the
/.pomerium/endpoint when writing policies. It shows you exactly what data the IdP is sending to Pomerium, making it easy to write correctclaimrules. - Mistake: Forgetting that Pomerium secures the front door, but not the back window. If Pomerium protects an internal server at
10.0.0.5, you MUST configure the firewall on10.0.0.5to drop all traffic that doesn’t come from Pomerium. Otherwise, someone on the internal network can just bypass Pomerium entirely.
Chapter 26. Learning Roadmap
| Stage | Topics | Practical Activity | Expected Skill |
| 1. Fundamentals | Zero Trust, IdPs, Reverse Proxies | Explain why VPNs are vulnerable to lateral movement. | Conceptual understanding |
| 2. First use | Docker Compose, Basic config | Run Pomerium locally with GitHub SSO. | Independent basic use |
| 3. Practical use | Policies, Routes, Headers | Protect multiple apps with different user policies. | Working proficiency |
| 4. Advanced use | PostgreSQL Databroker, TCP | Deploy Pomerium in Kubernetes; SSH via Pomerium. | Applied competence |
Chapter 27. Exercises and Knowledge Assessment
Q1 (Beginner): Why does Pomerium not require a database to store user passwords?Answer: Because Pomerium relies on an external Identity Provider (IdP) like Google or Okta to handle authentication and passwords.
Q2 (Intermediate): Your policy allows domain: company.com, but the CEO gets a 403 Forbidden error. How do you troubleshoot?Answer: Ask the CEO to navigate to [https://app.company.com/.pomerium/](https://app.company.com/.pomerium/) and read the JSON output. Verify that their identity token actually includes the expected domain claim.
Q3 (Advanced): How does Pomerium prevent users from having to log into Google on every single webpage click?Answer: Pomerium utilizes the Databroker and a signed session cookie. Upon the first successful login, Pomerium issues a cookie encrypted with the cookie_secret. Subsequent requests are verified locally by Pomerium without pinging the IdP until the session expires.
Chapter 28. Final Revision and Quick Reference
- What it is: An open-source Identity-Aware Proxy (IAP) that enforces Zero Trust access to internal applications.
- Core mechanism: It intercepts traffic, redirects unauthenticated users to an IdP, evaluates access policies, and proxies authorized traffic to the backend.
- Essential Terminology: IdP (Identity Provider), Route (public to private map), Policy (access rules), JWT (secure identity token).
- Configuration: Driven by
config.yamlcontainingauthenticate_service_url, IdP secrets, and a list ofroutes. - Best Use Case: Replacing clunky client VPNs for employees accessing internal web dashboards, wikis, and administrative tools.
- Alternatives: Cloudflare Access (SaaS ZTNA), Tailscale (Mesh VPN).
Quick Cheat Sheet (config.yaml Route Syntax):
YAML
routes:
- from: https://public-facing-url.com
to: http://internal-server-ip:port
policy:
- allow:
and: # Can be 'and', 'or', 'not'
- domain: "mycompany.com"
Code language: PHP (php)I’m Rajesh Kumar, a DevOps, SRE, DevSecOps, Cloud, and Platform Engineering expert passionate about sharing practical knowledge, real-world experiences, and industry best practices. I have worked at Cotocus and regularly write about technology, travel, investing, health, product reviews, and digital marketing through my various platforms.
I publish technical articles at DevOps School, travel stories at Holiday Landmark, stock market insights at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow, and SEO and digital marketing strategies at Wizbrand.
Find Trusted Cardiac Hospitals
Compare heart hospitals by city and services — all in one place.
Explore Hospitals