diff --git a/content/docs/guides/ad-guard.mdx b/content/docs/guides/ad-guard.mdx
index 4d4979b0c..946460027 100644
--- a/content/docs/guides/ad-guard.mdx
+++ b/content/docs/guides/ad-guard.mdx
@@ -8,11 +8,12 @@ description: Put AdGuard Home behind Pomerium for single sign-on, injecting its
# cSpell:ignore adguardhome
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/ad-guard/config.yaml.md';
-import Compose from '/content/examples/guides/ad-guard/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/ad-guard/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/ad-guard/docker-compose.yaml';
# Secure AdGuard Home with Pomerium
@@ -65,7 +66,9 @@ Zero manages the route's TLS certificate behind your starter domain, so there's
Create a `config.yaml`. It routes `adguard.yourdomain.com` to the AdGuard container and injects the basic-auth header on every upstream request.
-
+
+ {Config}
+
Replace `adguard.yourdomain.com` with your domain, `you@example.com` with your email, and the `Authorization` value with the base64 string from the command above.
@@ -82,7 +85,9 @@ The username and password you pick here are exactly the credentials you base64-e
The Compose file runs Pomerium Core and AdGuard together. Pomerium publishes ports 80 and 443 for the protected route, and AdGuard publishes only port 53 for DNS; the AdGuard web UI on port 3000 stays on the internal network so it's reachable only through Pomerium. For Zero, drop the `pomerium` service and use the `compose.yaml` from the Quickstart with your `POMERIUM_ZERO_TOKEN`, keeping the `adguard` service below.
-
+
+ {Compose}
+
Start it:
diff --git a/content/docs/guides/cockpit.mdx b/content/docs/guides/cockpit.mdx
index 8d1808a83..f88a15af9 100644
--- a/content/docs/guides/cockpit.mdx
+++ b/content/docs/guides/cockpit.mdx
@@ -7,11 +7,12 @@ keywords:
description: Put Cockpit, the web-based Linux server management GUI, behind Pomerium so single sign-on gates access before Cockpit's own login screen.
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/cockpit/config.yaml.md';
-import Compose from '/content/examples/guides/cockpit/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/cockpit/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/cockpit/docker-compose.yaml';
# Secure Cockpit with Pomerium
@@ -54,7 +55,9 @@ In the [Zero Console](https://console.pomerium.app):
Create a `config.yaml`. It routes `cockpit.yourdomain.com` to the Cockpit container, allows the WebSocket upgrade Cockpit needs, and preserves the host header so Cockpit's origin check passes.
-
+
+ {Config}
+
Replace `cockpit.yourdomain.com` with your domain and `you@example.com` with your email.
@@ -81,7 +84,9 @@ On a Linux host running Cockpit as a system service, this file lives at `/etc/co
The Compose file runs Pomerium Core and Cockpit together. Cockpit runs in plain-HTTP "bastion" mode (`--no-tls`) because Pomerium terminates TLS in front of it (for Zero, drop the `pomerium` service and use the `compose.yaml` from the Quickstart with your `POMERIUM_ZERO_TOKEN`, keeping the `cockpit` service below):
-
+
+ {Compose}
+
Put the `cockpit.conf` from the previous section next to the Compose file, then start it:
diff --git a/content/docs/guides/code-server.mdx b/content/docs/guides/code-server.mdx
index 1d65c7fde..04a94f9c5 100644
--- a/content/docs/guides/code-server.mdx
+++ b/content/docs/guides/code-server.mdx
@@ -8,11 +8,12 @@ keywords: [pomerium, code-server, vscode, sso, oidc, identity aware proxy]
description: Run code-server (VS Code in the browser) in Docker and put authentication and authorization in front of it with Pomerium.
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/code-server/config.yaml.md';
-import Compose from '/content/examples/guides/code-server/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/code-server/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/code-server/docker-compose.yaml';
# Secure code-server with Pomerium
@@ -72,7 +73,9 @@ Pomerium Zero uses the hosted authenticate service, so there is nothing else to
Add the route below to your Pomerium `config.yaml`. It uses the hosted authenticate service, so you don't run a separate identity provider, and it requests TLS certificates automatically from Let's Encrypt.
-
+
+ {Config}
+
Replace `code-server.yourdomain.com` with your own external hostname and `you@example.com` with the email that should be allowed in. `allow_websockets: true` keeps the editor's live connection working through the proxy, and `preserve_host_header: true` forwards the original host so code-server accepts that WebSocket; it checks the connection's origin against the host and rejects it otherwise.
@@ -95,7 +98,9 @@ If you prefer not to disable code-server's own login, you can instead set `PASSW
The Compose file runs Pomerium and code-server together on a shared network; the `To` address `http://code-server:8080` works because both containers share it.
-
+
+ {Compose}
+
Wire up Pomerium for your deployment, then bring the stack up:
diff --git a/content/docs/guides/forgejo.mdx b/content/docs/guides/forgejo.mdx
index 5277764f7..b291eb433 100644
--- a/content/docs/guides/forgejo.mdx
+++ b/content/docs/guides/forgejo.mdx
@@ -19,11 +19,12 @@ keywords:
description: Put a Forgejo instance behind Pomerium and use reverse-proxy header authentication so users sign in once and are auto-provisioned from their Pomerium identity.
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/forgejo/config.yaml.md';
-import Compose from '/content/examples/guides/forgejo/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/forgejo/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/forgejo/docker-compose.yaml';
# Secure Forgejo with Pomerium
@@ -74,7 +75,9 @@ In the [Zero Console](https://console.pomerium.app):
Create a `config.yaml`. It routes `forgejo.yourdomain.com` to the Forgejo container, forwards the identity claims as headers, and removes the total request timeout so long Git smart-HTTP transfers aren't cut off.
-
+
+ {Config}
+
Replace `forgejo.yourdomain.com` with your domain and `you@example.com` with your user or domain. A few notes:
@@ -100,7 +103,9 @@ Configure Forgejo to trust and consume the headers. These map to `app.ini` setti
The Compose file runs Pomerium Core and Forgejo together (for Zero, drop the `pomerium` service and use the `compose.yaml` from the Quickstart with your `POMERIUM_ZERO_TOKEN`, keeping the `forgejo` service and its network below):
-
+
+ {Compose}
+
Start it:
diff --git a/content/docs/guides/gitlab.mdx b/content/docs/guides/gitlab.mdx
index 5015fbc9b..d3d4974cb 100644
--- a/content/docs/guides/gitlab.mdx
+++ b/content/docs/guides/gitlab.mdx
@@ -8,11 +8,12 @@ keywords: [pomerium, gitlab, sso, oidc, identity aware proxy, self-hosted]
description: Put self-hosted GitLab behind Pomerium so every request is authenticated and authorized at the front door before it reaches GitLab.
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/gitlab/config.yaml.md';
-import Compose from '/content/examples/guides/gitlab/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/gitlab/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/gitlab/docker-compose.yaml';
# Secure GitLab with Pomerium
@@ -70,7 +71,9 @@ In the [Zero Console](https://console.pomerium.app):
Create a `config.yaml`. It routes `gitlab.yourdomain.com` to the GitLab container and preserves the host header so GitLab's redirects stay correct.
-
+
+ {Config}
+
Replace `gitlab.yourdomain.com` with your domain and `you@example.com` with the email (or switch to a group or domain match) that should be allowed through.
@@ -108,7 +111,9 @@ Keep the `pomerium` service shown below and place the `config.yaml` from the pre
-
+
+ {Compose}
+
```bash
docker compose up -d
diff --git a/content/docs/guides/grafana.mdx b/content/docs/guides/grafana.mdx
index d48eb24b9..4caa63c06 100644
--- a/content/docs/guides/grafana.mdx
+++ b/content/docs/guides/grafana.mdx
@@ -17,11 +17,12 @@ keywords:
description: Add single sign-on and per-route authorization to Grafana with Pomerium, forwarding a signed identity JWT so Grafana signs users in automatically.
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/grafana/config.yaml.md';
-import Compose from '/content/examples/guides/grafana/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/grafana/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/grafana/docker-compose.yaml';
# Secure Grafana with Pomerium
@@ -88,7 +89,9 @@ Zero manages the route's TLS certificate and the signing key behind its starter
Create a `config.yaml`. It routes `grafana.yourdomain.com` to the Grafana container, passes identity headers, and sets a `signing_key` so Pomerium publishes a JWKS that Grafana can verify the forwarded assertion against.
-
+
+ {Config}
+
Replace `grafana.yourdomain.com` with your domain, `you@example.com` with your email, and generate your own `signing_key` with the command in the comment. With Core, Grafana's JWKS URL is the route's own well-known endpoint (`https://grafana.yourdomain.com/.well-known/pomerium/jwks.json`), which is what the Compose file below uses.
@@ -121,7 +124,9 @@ Keep the `pomerium` service shown below and place the `config.yaml` from the pre
-
+
+ {Compose}
+
```bash
docker compose up -d
diff --git a/content/docs/guides/guacamole.mdx b/content/docs/guides/guacamole.mdx
index 19c0d9085..9147e20af 100644
--- a/content/docs/guides/guacamole.mdx
+++ b/content/docs/guides/guacamole.mdx
@@ -8,11 +8,12 @@ description: Put Apache Guacamole behind Pomerium and sign users in automaticall
# cSpell:ignore guacd guacamole guacadmin initdb POSTGRESQL psql
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/guacamole/config.yaml.md';
-import Compose from '/content/examples/guides/guacamole/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/guacamole/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/guacamole/docker-compose.yaml';
# Secure Apache Guacamole with Pomerium
@@ -51,7 +52,9 @@ In the [Zero Console](https://console.pomerium.app):
Create a `config.yaml`. It routes `guacamole.yourdomain.com` to the Guacamole container, passes identity headers, and forwards the user's email as `X-Pomerium-Claim-Email`:
-
+
+ {Config}
+
Replace `guacamole.yourdomain.com` with your domain and `you@example.com` with your email. The `jwt_claims_headers` mapping is what produces the `X-Pomerium-Claim-Email` header that Guacamole's header-auth extension expects.
@@ -86,7 +89,9 @@ The Compose file below mounts that `init/` directory into PostgreSQL so the sche
The Compose file runs Pomerium Core alongside Guacamole's three services (for Zero, drop the `pomerium` service and use the `compose.yaml` from the Quickstart with your `POMERIUM_ZERO_TOKEN`, keeping the rest below):
-
+
+ {Compose}
+
Start it:
diff --git a/content/docs/guides/hedgedoc.mdx b/content/docs/guides/hedgedoc.mdx
index 3c76ebda4..3618bf9f6 100644
--- a/content/docs/guides/hedgedoc.mdx
+++ b/content/docs/guides/hedgedoc.mdx
@@ -7,11 +7,12 @@ description: Put HedgeDoc behind Pomerium so single sign-on and per-route author
# cSpell:ignore hedgedoc USESSL ADDPORT
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/hedgedoc/config.yaml.md';
-import Compose from '/content/examples/guides/hedgedoc/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/hedgedoc/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/hedgedoc/docker-compose.yaml';
# Secure HedgeDoc with Pomerium
@@ -54,7 +55,9 @@ In the [Zero Console](https://console.pomerium.app):
Create a `config.yaml`. It routes `hedgedoc.yourdomain.com` to the HedgeDoc container, allows the WebSocket upgrade the editor needs, and limits access with a policy.
-
+
+ {Config}
+
Replace `hedgedoc.yourdomain.com` with your domain and `you@example.com` with the email (or group, or domain) that should be allowed in. The `allow_websockets: true` line is required: without it HedgeDoc's real-time editor can't open its connection.
@@ -75,7 +78,9 @@ HedgeDoc stores its notes in PostgreSQL, so the Compose file below also runs a `
The Compose file runs Pomerium Core, HedgeDoc, and its PostgreSQL database together. For Zero, drop the `pomerium` service and use the `compose.yaml` from the Quickstart with your `POMERIUM_ZERO_TOKEN`, keeping the `hedgedoc` and `database` services below. Either way, the Pomerium container and the `hedgedoc` container must share a Docker network so that `to: http://hedgedoc:3000` resolves.
-
+
+ {Compose}
+
Start it:
diff --git a/content/docs/guides/jellyfin.mdx b/content/docs/guides/jellyfin.mdx
index 247d30d65..19e6dff38 100644
--- a/content/docs/guides/jellyfin.mdx
+++ b/content/docs/guides/jellyfin.mdx
@@ -16,11 +16,12 @@ description: Put a self-hosted Jellyfin media server behind Pomerium so every br
# cSpell:ignore jellyfin chromecast DLNA
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/jellyfin/config.yaml.md';
-import Compose from '/content/examples/guides/jellyfin/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/jellyfin/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/jellyfin/docker-compose.yaml';
# Secure Jellyfin with Pomerium
@@ -72,7 +73,9 @@ In the [Zero Console](https://console.pomerium.app):
Create a `config.yaml`. It routes `jellyfin.yourdomain.com` to the Jellyfin container, allows WebSockets for the web client, preserves the host header so Jellyfin's links stay correct, and removes the total request-time cap for long playback and downloads.
-
+
+ {Config}
+
Replace `jellyfin.yourdomain.com` with your domain and `you@example.com` with the email (or switch to a group or domain match) that should be allowed through. Restart Pomerium after saving.
@@ -88,7 +91,9 @@ Two settings in the Compose file keep Jellyfin's URLs correct behind the proxy:
The Compose file runs Pomerium Core and Jellyfin together. For Zero, drop the `pomerium` service and use the `compose.yaml` from the [Quickstart](/docs/get-started/quickstart) with your `POMERIUM_ZERO_TOKEN`, keeping the `jellyfin` service; put `jellyfin` on the same Docker network as the Quickstart's `pomerium` service (the Quickstart names it `main`) so Pomerium can resolve `jellyfin` by name.
-
+
+ {Compose}
+
## Run the stack
diff --git a/content/docs/guides/jenkins.mdx b/content/docs/guides/jenkins.mdx
index 471ca182e..d8328ddca 100644
--- a/content/docs/guides/jenkins.mdx
+++ b/content/docs/guides/jenkins.mdx
@@ -8,11 +8,12 @@ keywords: [pomerium, jenkins, sso, oidc, jwt, identity aware proxy]
description: Put Jenkins behind Pomerium for single sign-on, forwarding a signed identity JWT that the Jenkins JWT Auth plugin verifies to sign users in automatically.
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/jenkins/config.yaml.md';
-import Compose from '/content/examples/guides/jenkins/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/jenkins/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/jenkins/docker-compose.yaml';
# Secure Jenkins with Pomerium
@@ -62,7 +63,9 @@ Zero manages the route's TLS certificate and the signing key behind its starter
Create a `config.yaml`. It routes `jenkins.yourdomain.com` to the Jenkins container, passes identity headers, and sets a `signing_key` so Pomerium publishes a JWKS that the JWT Auth plugin can verify the forwarded assertion against.
-
+
+ {Config}
+
Replace `jenkins.yourdomain.com` with your domain, `you@example.com` with your email, and generate your own `signing_key` with the command in the comment. With Core, the JWKS URL is the route's own well-known endpoint (`https://jenkins.yourdomain.com/.well-known/pomerium/jwks.json`).
@@ -102,7 +105,9 @@ Save and restart Jenkins.
The Compose file runs Pomerium Core and Jenkins together (for Zero, drop the `pomerium` service and use the `compose.yaml` from the Quickstart with your `POMERIUM_ZERO_TOKEN`, keeping the `jenkins` service below):
-
+
+ {Compose}
+
Start it:
diff --git a/content/docs/guides/jit.mdx b/content/docs/guides/jit.mdx
index 9c626f473..41df3dab8 100644
--- a/content/docs/guides/jit.mdx
+++ b/content/docs/guides/jit.mdx
@@ -6,7 +6,9 @@ keywords: [pomerium, jit, just-in-time access, ppl, date matcher, authorization]
description: Grant time-limited, Just-In-Time access with Pomerium by using the PPL date matcher, and automate the request and approve workflow with the jit-example app.
---
-import Compose from '/content/examples/guides/jit/docker-compose.yaml.md';
+import CodeBlock from '@theme/CodeBlock';
+
+import Compose from '!!raw-loader!/content/examples/guides/jit/docker-compose.yaml';
# Just-In-Time Access With Pomerium
@@ -94,7 +96,9 @@ With this setup, any user reaches `https://jit-example.yourdomain.com`, but only
The Compose file below runs Pomerium Zero (driven by your `POMERIUM_ZERO_TOKEN`) alongside `jit-example`. Zero is used because the `date` matcher is a Zero/Enterprise feature; routes and the time-limited policy are managed in the Zero Console as described above, not in a local config file. `jit-example` is itself the application the date-gated policy protects.
-
+
+ {Compose}
+
Clone the app, save the file above next to it as `docker-compose.yaml`, replace the `REPLACE_WITH_*` values with your own, then start the stack:
diff --git a/content/docs/guides/llm.mdx b/content/docs/guides/llm.mdx
index ec2e99f71..0f8597b12 100644
--- a/content/docs/guides/llm.mdx
+++ b/content/docs/guides/llm.mdx
@@ -6,11 +6,12 @@ keywords: [pomerium, open webui, llm, sso, oidc, identity aware proxy]
description: Run a self-hosted LLM interface (Open WebUI) behind Pomerium with SSO and trusted-header identity.
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/llm/config.yaml.md';
-import Compose from '/content/examples/guides/llm/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/llm/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/llm/docker-compose.yaml';
# Secure Open WebUI with Pomerium
@@ -62,7 +63,9 @@ In the [Zero Console](https://console.pomerium.app), create a policy and a route
With Pomerium Core you supply a `config.yaml`. `jwt_claims_headers` emits the user's email as `X-Pomerium-Claim-Email`, the route's `pass_identity_headers` forwards it to Open WebUI, and `allow_websockets` keeps streamed responses working. Note that `pass_identity_headers` on its own only forwards the signed assertion; the `X-Pomerium-Claim-Email` header comes from `jwt_claims_headers`, so both are required.
-
+
+ {Config}
+
`autocert: true` provisions TLS from Let's Encrypt for the route host. Replace `llm.yourdomain.com` with your domain and the `email` allow rule with the users or groups that should have access. This config uses the hosted authenticate service; to run your own identity provider instead, see the [Keycloak fallback](/docs/integrations/user-identity/oidc).
@@ -90,7 +93,9 @@ Trusted-header SSO is only safe when the app is unreachable except through Pomer
The compose file runs Pomerium and Open WebUI together. Open WebUI listens on `8080`, which Pomerium routes to internally; only Pomerium publishes ports to the host.
-
+
+ {Compose}
+
```bash
docker compose up -d
diff --git a/content/docs/guides/tiddlywiki.mdx b/content/docs/guides/tiddlywiki.mdx
index 7b1c1002b..b279f198d 100644
--- a/content/docs/guides/tiddlywiki.mdx
+++ b/content/docs/guides/tiddlywiki.mdx
@@ -6,11 +6,12 @@ keywords: [pomerium, tiddlywiki, wiki, sso, oidc, identity aware proxy]
description: Put TiddlyWiki on Node.js behind Pomerium for single sign-on, and forward the authenticated user's email so TiddlyWiki recognizes who is signed in.
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/tiddlywiki/config.yaml.md';
-import Compose from '/content/examples/guides/tiddlywiki/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/tiddlywiki/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/tiddlywiki/docker-compose.yaml';
# Secure TiddlyWiki with Pomerium
@@ -53,7 +54,9 @@ In the [Zero Console](https://console.pomerium.app):
Create a `config.yaml`. It routes `tiddlywiki.yourdomain.com` to the TiddlyWiki container, passes identity headers, and uses `jwt_claims_headers` to forward the user's email in an unsigned `X-Pomerium-Claim-Email` header.
-
+
+ {Config}
+
Replace `tiddlywiki.yourdomain.com` with your domain and `you@example.com` with your email. The [`jwt_claims_headers`](/docs/reference/jwt-claim-headers) setting forwards the email claim in the named header, and [`pass_identity_headers`](/docs/reference/routes/pass-identity-headers-per-route) tells Pomerium to attach the identity headers to every upstream request.
@@ -73,7 +76,9 @@ The Compose file below runs a one-shot init step that creates the wiki folder wi
The Compose file runs Pomerium Core and TiddlyWiki together (for Zero, drop the `pomerium` service and use the `compose.yaml` from the Quickstart with your `POMERIUM_ZERO_TOKEN`, keeping the `tiddlywiki` services below):
-
+
+ {Compose}
+
Start it:
diff --git a/content/docs/guides/tooljet.mdx b/content/docs/guides/tooljet.mdx
index 045517d11..4bd46823c 100644
--- a/content/docs/guides/tooljet.mdx
+++ b/content/docs/guides/tooljet.mdx
@@ -6,11 +6,12 @@ keywords: [pomerium, tooljet, sso, oidc, identity aware proxy, internal tools]
description: Put ToolJet behind Pomerium so only authenticated users can reach your low-code internal tools.
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/tooljet/config.yaml.md';
-import Compose from '/content/examples/guides/tooljet/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/tooljet/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/tooljet/docker-compose.yaml';
# Secure ToolJet with Pomerium
@@ -51,7 +52,9 @@ That's the whole Pomerium side. Zero manages the hosted authenticate service and
Create a `config.yaml` for Pomerium Core:
-
+
+ {Config}
+
Replace `tooljet.yourdomain.com` with your hostname and `you@example.com` with the identity that should be allowed in. The `preserve_host_header: true` setting is what makes ToolJet accept the proxied request: ToolJet rejects any request whose `Host` header does not match `TOOLJET_HOST`. Because the route's external hostname already equals `TOOLJET_HOST`, preserving the incoming `Host` forwards the right value to the upstream.
@@ -87,7 +90,9 @@ See ToolJet's [environment variable reference](https://docs.tooljet.com/docs/set
The Compose file below runs Pomerium Core, ToolJet, and PostgreSQL together:
-
+
+ {Compose}
+
Start everything:
diff --git a/content/docs/guides/transmission.mdx b/content/docs/guides/transmission.mdx
index 9249d67bf..ddeb432aa 100644
--- a/content/docs/guides/transmission.mdx
+++ b/content/docs/guides/transmission.mdx
@@ -6,11 +6,12 @@ keywords: [pomerium, transmission, bittorrent, sso, oidc, identity aware proxy]
description: Put Transmission's RPC and web interface behind Pomerium for single sign-on, TLS, and per-user authorization.
---
+import CodeBlock from '@theme/CodeBlock';
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';
-import Config from '/content/examples/guides/transmission/config.yaml.md';
-import Compose from '/content/examples/guides/transmission/docker-compose.yaml.md';
+import Config from '!!raw-loader!/content/examples/guides/transmission/config.yaml';
+import Compose from '!!raw-loader!/content/examples/guides/transmission/docker-compose.yaml';
# Secure Transmission with Pomerium
@@ -54,7 +55,9 @@ Zero manages the route's TLS certificate behind your starter domain, so there's
Create a `config.yaml`. It routes `transmission.yourdomain.com` to the Transmission container and allows a single authorized user:
-
+
+ {Config}
+
Replace `transmission.yourdomain.com` with your domain and `you@example.com` with the email (or group) that should have access. Restart Pomerium after saving.
@@ -82,7 +85,9 @@ The host whitelist pins the daemon to the exact hostname you serve from Pomerium
The Compose file runs Pomerium Core and Transmission together (for Zero, drop the `pomerium` service and use the `compose.yaml` from the Quickstart with your `POMERIUM_ZERO_TOKEN`, keeping the `transmission` service below):
-
+
+ {Compose}
+
Start it:
diff --git a/content/examples/guides/ad-guard/config.yaml.md b/content/examples/guides/ad-guard/config.yaml.md
deleted file mode 100644
index 11f1944e6..000000000
--- a/content/examples/guides/ad-guard/config.yaml.md
+++ /dev/null
@@ -1,26 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for AdGuard Home. Uses the hosted authenticate
-# service, so you don't run your own identity provider. To self-host the IdP, see
-# the Keycloak guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-routes:
- - from: https://adguard.yourdomain.com
- to: http://adguard:3000
- allow_websockets: true
- # Pomerium authenticates the user, then injects AdGuard's single basic-auth
- # credential on every upstream request so AdGuard never shows its own login
- # prompt. Replace the placeholder below with your own value, generated with:
- # printf 'admin:YOUR_ADGUARD_PASSWORD' | base64
- # Keep this secret: anyone who can send it to AdGuard directly is admin.
- set_request_headers:
- Authorization: Basic
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/ad-guard/docker-compose.yaml.md b/content/examples/guides/ad-guard/docker-compose.yaml.md
deleted file mode 100644
index 95a9cf13b..000000000
--- a/content/examples/guides/ad-guard/docker-compose.yaml.md
+++ /dev/null
@@ -1,43 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- # Pomerium bridges both networks: `default` for autocert/Let's Encrypt and the
- # hosted authenticate service, and the internal-only network to reach AdGuard.
- networks:
- - default
- - adguard-internal
- restart: always
-
- adguard:
- image: adguard/adguardhome@sha256:e6f2b8bcda06064ab055b44933a4f0e983c35558b9cdb8d2e7ab1efcee36d890 # v0.107.77
- volumes:
- - adguard-work:/opt/adguardhome/work
- - adguard-conf:/opt/adguardhome/conf
- ports:
- # DNS, served straight from AdGuard. The web UI stays private behind Pomerium.
- - 53:53/tcp
- - 53:53/udp
- # Internal-only network: AdGuard's web UI is reachable only through Pomerium,
- # never directly, so a leaked basic-auth credential can't bypass Pomerium.
- networks:
- - adguard-internal
- restart: always
-
-networks:
- # No route to the outside; only services attached here (Pomerium and AdGuard)
- # can reach AdGuard's web port.
- adguard-internal:
- internal: true
-
-volumes:
- pomerium-cache:
- adguard-work:
- adguard-conf:
-```
diff --git a/content/examples/guides/cockpit/config.yaml.md b/content/examples/guides/cockpit/config.yaml.md
deleted file mode 100644
index d88409f75..000000000
--- a/content/examples/guides/cockpit/config.yaml.md
+++ /dev/null
@@ -1,23 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for Cockpit. Uses the hosted authenticate service, so
-# you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-routes:
- - from: https://cockpit.yourdomain.com
- to: http://cockpit:9090
- # Cockpit upgrades to a WebSocket once you log in, so the route must allow it.
- allow_websockets: true
- # Cockpit checks the Host header against its configured Origins, so forward the
- # original host instead of rewriting it to the upstream address.
- preserve_host_header: true
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/cockpit/docker-compose.yaml.md b/content/examples/guides/cockpit/docker-compose.yaml.md
deleted file mode 100644
index 029377f19..000000000
--- a/content/examples/guides/cockpit/docker-compose.yaml.md
+++ /dev/null
@@ -1,25 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
-
- cockpit:
- image: quay.io/cockpit/ws@sha256:ff018a28d50912dec3a1f6071e69cb6a7c252b68f1b8ec6964c3c6741c7dd96f # v361
- # Run cockpit-ws in plain-HTTP "bastion" mode. Pomerium terminates TLS, so
- # Cockpit doesn't need its own certificate; it trusts the X-Forwarded-Proto
- # header (set in cockpit.conf) to know the original request was HTTPS.
- entrypoint: ['/container/label-run', '--no-tls']
- volumes:
- - ./cockpit.conf:/etc/cockpit/cockpit.conf:ro
- restart: always
-
-volumes:
- pomerium-cache:
-```
diff --git a/content/examples/guides/code-server/config.yaml.md b/content/examples/guides/code-server/config.yaml.md
deleted file mode 100644
index aab2fb3de..000000000
--- a/content/examples/guides/code-server/config.yaml.md
+++ /dev/null
@@ -1,24 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for code-server. Uses the hosted authenticate service,
-# so you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-routes:
- - from: https://code-server.yourdomain.com
- to: http://code-server:8080
- # code-server uses WebSockets for the editor connection, so the route must
- # allow them.
- allow_websockets: true
- # code-server checks the WebSocket Origin against the Host header and rejects the
- # editor connection if they differ, so forward the original Host upstream.
- preserve_host_header: true
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/code-server/docker-compose.yaml.md b/content/examples/guides/code-server/docker-compose.yaml.md
deleted file mode 100644
index bf90f37f9..000000000
--- a/content/examples/guides/code-server/docker-compose.yaml.md
+++ /dev/null
@@ -1,25 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
-
- code-server:
- image: codercom/code-server@sha256:6d46b83ea0687ab1826ec029b6d0e6342bbd55cc5c29b98258463e7faee16d1e
- command: --auth none --disable-telemetry /home/coder/project
- volumes:
- - code-server-project:/home/coder/project
- - code-server-config:/home/coder/.config
- restart: always
-
-volumes:
- pomerium-cache:
- code-server-project:
- code-server-config:
-```
diff --git a/content/examples/guides/forgejo/config.yaml.md b/content/examples/guides/forgejo/config.yaml.md
deleted file mode 100644
index 3eb20e1a4..000000000
--- a/content/examples/guides/forgejo/config.yaml.md
+++ /dev/null
@@ -1,32 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for Forgejo. Uses the hosted authenticate service, so
-# you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-# Forward the user's identity claims to Forgejo as request headers. Forgejo
-# usernames cannot contain every character that is valid in an email address, so
-# this uses the stable OIDC sub claim for the username and carries the real
-# address in X-Pomerium-Claim-Email.
-jwt_claims_headers:
- X-Pomerium-Sub: sub
- X-Pomerium-Claim-Email: email
- X-Pomerium-Claim-Name: name
-
-routes:
- - from: https://forgejo.yourdomain.com
- to: http://forgejo:3000
- pass_identity_headers: true
- # Git transfers can be large and long-running; don't cap total request time.
- timeout: 0s
- idle_timeout: 600s
- policy:
- - allow:
- or:
- - email:
- # Replace with the users or domain you want to allow
- is: you@example.com
-```
diff --git a/content/examples/guides/forgejo/docker-compose.yaml.md b/content/examples/guides/forgejo/docker-compose.yaml.md
deleted file mode 100644
index 5e91f2f4f..000000000
--- a/content/examples/guides/forgejo/docker-compose.yaml.md
+++ /dev/null
@@ -1,71 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- networks:
- default: {}
- forgejo-internal:
- ipv4_address: 172.30.0.2
- restart: always
-
- forgejo:
- image: codeberg.org/forgejo/forgejo@sha256:db04c7114b656f896e206ba3873fe8d3a7adf2daa44907037f0274f4ba653fb9 # v15
- # Reverse-proxy auth trusts the identity header from ANY peer that can reach
- # forgejo:3000, and REVERSE_PROXY_TRUSTED_PROXIES does NOT change that (it only
- # affects X-Forwarded-For parsing). Network isolation is the trust boundary:
- # forgejo sits on an internal-only network with Pomerium and nothing else.
- networks:
- forgejo-internal: {}
- volumes:
- - forgejo-data:/data
- environment:
- FORGEJO__server__ROOT_URL: 'https://forgejo.yourdomain.com/'
- FORGEJO__database__DB_TYPE: 'sqlite3'
- FORGEJO__security__INSTALL_LOCK: 'true'
- FORGEJO__service__REQUIRE_SIGNIN_VIEW: 'true'
-
- # Reverse-proxy SSO: Forgejo trusts the identity header Pomerium forwards.
- FORGEJO__service__ENABLE_REVERSE_PROXY_AUTHENTICATION: 'true'
- # Web UI sign-in only. Keep header auth off the API so tokens/SSH stay the
- # path for Git and API clients (set explicitly, not relying on the default).
- FORGEJO__service__ENABLE_REVERSE_PROXY_AUTHENTICATION_API: 'false'
- FORGEJO__service__ENABLE_REVERSE_PROXY_AUTO_REGISTRATION: 'true'
- FORGEJO__service__ENABLE_REVERSE_PROXY_EMAIL: 'true'
- FORGEJO__service__ENABLE_REVERSE_PROXY_FULL_NAME: 'true'
- # Allow provisioning via the proxy, but keep the local sign-up form closed.
- FORGEJO__service__DISABLE_REGISTRATION: 'false'
- FORGEJO__service__ALLOW_ONLY_EXTERNAL_REGISTRATION: 'true'
- FORGEJO__service__SHOW_REGISTRATION_BUTTON: 'false'
-
- # Header names must match what Pomerium sends (config.yaml above).
- FORGEJO__security__REVERSE_PROXY_AUTHENTICATION_USER: 'X-Pomerium-Sub'
- FORGEJO__security__REVERSE_PROXY_AUTHENTICATION_EMAIL: 'X-Pomerium-Claim-Email'
- FORGEJO__security__REVERSE_PROXY_AUTHENTICATION_FULL_NAME: 'X-Pomerium-Claim-Name'
- # For X-Forwarded-For client-IP parsing, list only Pomerium. This does not
- # restrict which peer the reverse-proxy auth header is trusted from. Must
- # be an IP/CIDR, not a hostname; the Compose network gives Pomerium a
- # fixed address.
- FORGEJO__security__REVERSE_PROXY_TRUSTED_PROXIES: '172.30.0.2/32'
- FORGEJO__security__REVERSE_PROXY_LIMIT: '1'
- restart: always
-
-networks:
- # internal: true keeps Forgejo off the host and reachable only by Pomerium, which
- # the reverse-proxy-auth trust model requires. The fixed subnet gives Pomerium a
- # stable address for REVERSE_PROXY_TRUSTED_PROXIES.
- forgejo-internal:
- internal: true
- ipam:
- config:
- - subnet: 172.30.0.0/24
-
-volumes:
- pomerium-cache:
- forgejo-data:
-```
diff --git a/content/examples/guides/gitlab/config.yaml.md b/content/examples/guides/gitlab/config.yaml.md
deleted file mode 100644
index 6f4aedbe5..000000000
--- a/content/examples/guides/gitlab/config.yaml.md
+++ /dev/null
@@ -1,21 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for GitLab. Uses the hosted authenticate service, so
-# you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-routes:
- - from: https://gitlab.yourdomain.com
- to: http://gitlab:80
- # GitLab builds redirect URLs from its own external_url, so forward the
- # original Host header to keep those redirects pointing at the public name.
- preserve_host_header: true
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/gitlab/docker-compose.yaml.md b/content/examples/guides/gitlab/docker-compose.yaml.md
deleted file mode 100644
index 5045bd605..000000000
--- a/content/examples/guides/gitlab/docker-compose.yaml.md
+++ /dev/null
@@ -1,33 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
-
- gitlab:
- image: gitlab/gitlab-ce@sha256:c7082004a0f64123634fda345e849453d52956621893bed7d2218fa6f088247f # 19.0.1-ce
- environment:
- GITLAB_OMNIBUS_CONFIG: |
- external_url 'https://gitlab.yourdomain.com'
- letsencrypt['enable'] = false
- nginx['listen_port'] = 80
- nginx['listen_https'] = false
- volumes:
- - gitlab-config:/etc/gitlab
- - gitlab-logs:/var/log/gitlab
- - gitlab-data:/var/opt/gitlab
- shm_size: '256m'
- restart: always
-
-volumes:
- pomerium-cache:
- gitlab-config:
- gitlab-logs:
- gitlab-data:
-```
diff --git a/content/examples/guides/grafana/config.yaml.md b/content/examples/guides/grafana/config.yaml.md
deleted file mode 100644
index 1483acb73..000000000
--- a/content/examples/guides/grafana/config.yaml.md
+++ /dev/null
@@ -1,25 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for Grafana. Uses the hosted authenticate service, so
-# you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-# Signs the identity assertion Pomerium forwards to Grafana, and is published at the
-# route's /.well-known/pomerium/jwks.json for Grafana to verify against. Generate
-# your own and keep it secret:
-# openssl ecparam -genkey -name prime256v1 -noout | base64
-signing_key: REPLACE_WITH_BASE64_ENCODED_EC_P256_PRIVATE_KEY
-
-routes:
- - from: https://grafana.yourdomain.com
- to: http://grafana:3000
- pass_identity_headers: true
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/grafana/docker-compose.yaml.md b/content/examples/guides/grafana/docker-compose.yaml.md
deleted file mode 100644
index c6feba3bc..000000000
--- a/content/examples/guides/grafana/docker-compose.yaml.md
+++ /dev/null
@@ -1,31 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
-
- grafana:
- image: grafana/grafana@sha256:8b37a2f028f164ce7b9889e1765b9d6ee23fec80f871d156fbf436d6198d32b7
- environment:
- - GF_AUTH_JWT_ENABLED=true
- - GF_AUTH_JWT_HEADER_NAME=X-Pomerium-Jwt-Assertion
- - GF_AUTH_JWT_EMAIL_CLAIM=email
- - GF_AUTH_JWT_USERNAME_CLAIM=email
- - GF_AUTH_JWT_JWK_SET_URL=https://grafana.yourdomain.com/.well-known/pomerium/jwks.json
- - GF_AUTH_JWT_AUTO_SIGN_UP=true
- - GF_AUTH_JWT_CACHE_TTL=60m
- - GF_AUTH_SIGNOUT_REDIRECT_URL=https://grafana.yourdomain.com/.pomerium/sign_out
- volumes:
- - grafana-storage:/var/lib/grafana
- restart: always
-
-volumes:
- pomerium-cache:
- grafana-storage:
-```
diff --git a/content/examples/guides/guacamole/config.yaml.md b/content/examples/guides/guacamole/config.yaml.md
deleted file mode 100644
index bfac40b9e..000000000
--- a/content/examples/guides/guacamole/config.yaml.md
+++ /dev/null
@@ -1,24 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for Apache Guacamole. Uses the hosted authenticate
-# service, so you don't run your own identity provider. To self-host the IdP, see
-# the Keycloak guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-# Forward the authenticated user's email as an unsigned X-Pomerium-Claim-Email
-# header. Guacamole's header-auth extension reads this header to sign the user in.
-jwt_claims_headers:
- X-Pomerium-Claim-Email: email
-
-routes:
- - from: https://guacamole.yourdomain.com
- to: http://guacamole:8080
- pass_identity_headers: true
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/guacamole/docker-compose.yaml.md b/content/examples/guides/guacamole/docker-compose.yaml.md
deleted file mode 100644
index 73e248e98..000000000
--- a/content/examples/guides/guacamole/docker-compose.yaml.md
+++ /dev/null
@@ -1,66 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- # The guacd daemon renders remote desktop protocols (VNC, RDP, SSH) for the web app.
- guacd:
- image: guacamole/guacd@sha256:8974eaa9ba32f713daf311e7cc8cd7e4cdfba1edea39eed75524e78ef4b08f4f # 1.6.0
- restart: always
- networks: [guac-internal]
-
- # PostgreSQL stores Guacamole's users, connections, and history. The schema is
- # loaded once from ./init on first boot; generate it with:
- # docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgresql > init/initdb.sql
- postgres:
- image: postgres@sha256:df7bca0066e6f60cc3dd32faa70caddec20e2c22b58932f79498e5704b23854a # 15-alpine
- environment:
- POSTGRES_DB: guacamole_db
- POSTGRES_USER: guacamole_user
- POSTGRES_PASSWORD: ChooseYourOwnPasswordHere1234
- volumes:
- - ./init:/docker-entrypoint-initdb.d:ro
- - guacamole-data:/var/lib/postgresql/data
- restart: always
- networks: [guac-internal]
-
- # The Guacamole web application. HEADER_ENABLED turns on header authentication and
- # HTTP_AUTH_HEADER tells it which header carries the already-authenticated user.
- guacamole:
- image: guacamole/guacamole@sha256:f344085e618bb05e22b964b0208dbd06d3468275bac70206f93805245e067b40 # 1.6.0
- depends_on:
- - guacd
- - postgres
- environment:
- GUACD_HOSTNAME: guacd
- POSTGRESQL_HOSTNAME: postgres
- POSTGRESQL_DATABASE: guacamole_db
- POSTGRESQL_USERNAME: guacamole_user
- POSTGRESQL_PASSWORD: ChooseYourOwnPasswordHere1234
- HEADER_ENABLED: 'true'
- HTTP_AUTH_HEADER: X-Pomerium-Claim-Email
- # Serve the app at / so the route host maps straight to it (no /guacamole prefix).
- WEBAPP_CONTEXT: ROOT
- restart: always
- networks: [guac-internal]
-
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
- # Pomerium is the only service with published ports and the only one bridging to
- # the internal network, so Guacamole is reachable only through Pomerium.
- networks: [default, guac-internal]
-
-networks:
- # No host access: keeps guacd/postgres/guacamole off the host and reachable only by
- # pomerium, which the header-auth trust model requires.
- guac-internal:
- internal: true
-
-volumes:
- guacamole-data:
- pomerium-cache:
-```
diff --git a/content/examples/guides/hedgedoc/config.yaml.md b/content/examples/guides/hedgedoc/config.yaml.md
deleted file mode 100644
index 60b440000..000000000
--- a/content/examples/guides/hedgedoc/config.yaml.md
+++ /dev/null
@@ -1,21 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for HedgeDoc. Uses the hosted authenticate service, so
-# you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-routes:
- - from: https://hedgedoc.yourdomain.com
- to: http://hedgedoc:3000
- # HedgeDoc's collaborative editor keeps a live connection open, so the route
- # has to allow WebSocket upgrades.
- allow_websockets: true
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/hedgedoc/docker-compose.yaml.md b/content/examples/guides/hedgedoc/docker-compose.yaml.md
deleted file mode 100644
index e51cef37c..000000000
--- a/content/examples/guides/hedgedoc/docker-compose.yaml.md
+++ /dev/null
@@ -1,44 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
-
- hedgedoc:
- # Check https://hedgedoc.org/latest-release for the current stable release.
- image: quay.io/hedgedoc/hedgedoc@sha256:abdb6b08815d5bc5832b52d983d983ac678895e9fa0d76aaad80d08c5d70812b # 1.10.8
- environment:
- - CMD_DB_URL=postgres://hedgedoc:password@database:5432/hedgedoc
- - CMD_DOMAIN=hedgedoc.yourdomain.com
- - CMD_PROTOCOL_USESSL=true
- - CMD_URL_ADDPORT=false
- # Replace this with your own value: head -c32 /dev/urandom | base64
- - CMD_SESSION_SECRET=replace-with-a-random-session-secret
- volumes:
- - hedgedoc-uploads:/hedgedoc/public/uploads
- restart: always
- depends_on:
- - database
-
- database:
- image: postgres@sha256:16bc17c64a573ef34162af9298258d1aec548232985b33ed7b1eac33ba35c229 # 16-alpine
- environment:
- - POSTGRES_USER=hedgedoc
- # Change this before running anything beyond a local demo.
- - POSTGRES_PASSWORD=password
- - POSTGRES_DB=hedgedoc
- volumes:
- - hedgedoc-database:/var/lib/postgresql/data
- restart: always
-
-volumes:
- pomerium-cache:
- hedgedoc-uploads:
- hedgedoc-database:
-```
diff --git a/content/examples/guides/jellyfin/config.yaml.md b/content/examples/guides/jellyfin/config.yaml.md
deleted file mode 100644
index fa2fe5216..000000000
--- a/content/examples/guides/jellyfin/config.yaml.md
+++ /dev/null
@@ -1,28 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for Jellyfin. Uses the hosted authenticate service, so
-# you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-routes:
- - from: https://jellyfin.yourdomain.com
- to: http://jellyfin:8096
- # The Jellyfin web client streams events over WebSockets; without this the UI
- # loads but playback state and remote control never update.
- allow_websockets: true
- # Forward the original Host so Jellyfin's absolute URLs (web client, casting)
- # match the public name instead of the container name.
- preserve_host_header: true
- # Direct-play streams and downloads are long plain HTTP responses, separate
- # from the web client's WebSocket control channel.
- timeout: 0s
- idle_timeout: 600s
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/jellyfin/docker-compose.yaml.md b/content/examples/guides/jellyfin/docker-compose.yaml.md
deleted file mode 100644
index 1f7f71019..000000000
--- a/content/examples/guides/jellyfin/docker-compose.yaml.md
+++ /dev/null
@@ -1,28 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium:v0.32.7@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
-
- jellyfin:
- image: jellyfin/jellyfin:10.10.7@sha256:7ae36aab93ef9b6aaff02b37f8bb23df84bb2d7a3f6054ec8fc466072a648ce2
- environment:
- # Jellyfin builds absolute URLs (DLNA, casting, the web client) from this
- # value, so it must be the public route, not the container name.
- JELLYFIN_PublishedServerUrl: https://jellyfin.yourdomain.com
- volumes:
- - jellyfin-config:/config
- - jellyfin-cache:/cache
- restart: always
-
-volumes:
- pomerium-cache:
- jellyfin-config:
- jellyfin-cache:
-```
diff --git a/content/examples/guides/jenkins/config.yaml.md b/content/examples/guides/jenkins/config.yaml.md
deleted file mode 100644
index ce68178ee..000000000
--- a/content/examples/guides/jenkins/config.yaml.md
+++ /dev/null
@@ -1,25 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for Jenkins. Uses the hosted authenticate service, so
-# you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-# Signs the identity assertion Pomerium forwards to Jenkins, and is published at the
-# route's /.well-known/pomerium/jwks.json for the JWT Auth plugin to verify against.
-# Generate your own and keep it secret:
-# openssl ecparam -genkey -name prime256v1 -noout | base64
-signing_key: REPLACE_WITH_BASE64_ENCODED_EC_P256_PRIVATE_KEY
-
-routes:
- - from: https://jenkins.yourdomain.com
- to: http://jenkins:8080
- pass_identity_headers: true
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/jenkins/docker-compose.yaml.md b/content/examples/guides/jenkins/docker-compose.yaml.md
deleted file mode 100644
index 50e4621f4..000000000
--- a/content/examples/guides/jenkins/docker-compose.yaml.md
+++ /dev/null
@@ -1,26 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
-
- jenkins:
- image: jenkins/jenkins@sha256:01c992ffef29dcf41c7164e8c16285c657c2368c4943dda8d68c93fdf54447d5 # lts (2.555.2)
- # Jenkins is reached only through Pomerium, so no host ports are published.
- # 8080 stays on the internal Docker network. You complete the first-run
- # setup wizard and install the JWT Auth plugin through the browser, as the
- # guide describes.
- volumes:
- - jenkins-home:/var/jenkins_home
- restart: always
-
-volumes:
- pomerium-cache:
- jenkins-home:
-```
diff --git a/content/examples/guides/jit/docker-compose.yaml.md b/content/examples/guides/jit/docker-compose.yaml.md
deleted file mode 100644
index 6a77a73c4..000000000
--- a/content/examples/guides/jit/docker-compose.yaml.md
+++ /dev/null
@@ -1,31 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- # Pomerium Zero is driven by your cluster token; routes and the time-limited
- # date-matcher policy live in the Zero Console, not a local config file.
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- environment:
- - POMERIUM_ZERO_TOKEN=REPLACE_WITH_YOUR_POMERIUM_ZERO_TOKEN
- volumes:
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
-
- # jit-example has no published image; build it from the repo:
- # git clone https://github.com/pomerium/jit-example
- # This is also the application the date-gated policy protects.
- jit-example:
- build: ./jit-example
- environment:
- - PORT=8000
- - ORGANIZATION_ID=REPLACE_WITH_YOUR_ORGANIZATION_ID
- - CLUSTER_ID=REPLACE_WITH_YOUR_CLUSTER_ID
- - API_USER_TOKEN=REPLACE_WITH_YOUR_API_USER_TOKEN
- - JWKS_ENDPOINT=https://jit-example.yourdomain.com/.well-known/pomerium/jwks.json
- restart: always
-
-volumes:
- pomerium-cache:
-```
diff --git a/content/examples/guides/llm/config.yaml.md b/content/examples/guides/llm/config.yaml.md
deleted file mode 100644
index 4dada84b0..000000000
--- a/content/examples/guides/llm/config.yaml.md
+++ /dev/null
@@ -1,28 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for Open WebUI. Uses the hosted authenticate service,
-# so you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-# Emit the user's claims as X-Pomerium-Claim-* headers. pass_identity_headers alone
-# only forwards the signed assertion; Open WebUI's trusted-header SSO needs these
-# explicit claim headers.
-jwt_claims_headers:
- X-Pomerium-Claim-Email: email
-
-routes:
- - from: https://llm.yourdomain.com
- to: http://open-webui:8080
- # Forward the identity headers (including X-Pomerium-Claim-Email) to Open WebUI.
- pass_identity_headers: true
- # Open WebUI streams responses over WebSockets.
- allow_websockets: true
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/llm/docker-compose.yaml.md b/content/examples/guides/llm/docker-compose.yaml.md
deleted file mode 100644
index e7f2aa470..000000000
--- a/content/examples/guides/llm/docker-compose.yaml.md
+++ /dev/null
@@ -1,45 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- # Pomerium is the only service on the default network (where its ports are
- # published) and is also on the internal network so it can reach Open WebUI.
- networks:
- default: {}
- internal: {}
- restart: always
-
- open-webui:
- image: ghcr.io/open-webui/open-webui@sha256:7f1b0a1a50cfbac23da3b16f96bc968fd757b26dc9e54e93813d61768ea9184e # main
- environment:
- # Trust the email Pomerium forwards and skip Open WebUI's own login screen.
- - WEBUI_AUTH_TRUSTED_EMAIL_HEADER=X-Pomerium-Claim-Email
- - WEBUI_URL=https://llm.yourdomain.com
- # The first provisioned user becomes admin; later users default to "pending" and
- # must be approved. Uncomment to make new SSO users active immediately instead.
- # - DEFAULT_USER_ROLE=user
- volumes:
- - open-webui-data:/app/backend/data
- # Open WebUI is ONLY on the internal network, so nothing but Pomerium can reach it
- # and the trusted email header cannot be forged by going around Pomerium.
- networks:
- internal: {}
- restart: always
-
-volumes:
- pomerium-cache:
- open-webui-data:
-
-networks:
- default: {}
- # internal: true has no route to the host or outside world; only services attached
- # to it (Pomerium and Open WebUI) can talk on it.
- internal:
- internal: true
-```
diff --git a/content/examples/guides/tiddlywiki/config.yaml.md b/content/examples/guides/tiddlywiki/config.yaml.md
deleted file mode 100644
index 7b938b33f..000000000
--- a/content/examples/guides/tiddlywiki/config.yaml.md
+++ /dev/null
@@ -1,24 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for TiddlyWiki. Uses the hosted authenticate service,
-# so you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-# Forward the authenticated user's email to TiddlyWiki in an unsigned request header.
-# TiddlyWiki's listen command trusts this header as the logged-in username.
-jwt_claims_headers:
- X-Pomerium-Claim-Email: email
-
-routes:
- - from: https://tiddlywiki.yourdomain.com
- to: http://tiddlywiki:8080
- pass_identity_headers: true
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/tiddlywiki/docker-compose.yaml.md b/content/examples/guides/tiddlywiki/docker-compose.yaml.md
deleted file mode 100644
index e971c5bda..000000000
--- a/content/examples/guides/tiddlywiki/docker-compose.yaml.md
+++ /dev/null
@@ -1,55 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- networks:
- default: {}
- tiddlywiki-internal: {}
- restart: always
-
- # One-shot: create the wiki folder with the Node.js server edition if it doesn't
- # already exist, then exit. The guard keeps repeated `docker compose up` runs working.
- tiddlywiki-init:
- image: elasticdog/tiddlywiki@sha256:6fdb8c46c92680c48be5eca5d35cf477b111285481e2ce1717c7dfa131476b17 # v5.1.23
- entrypoint: ['/bin/sh', '-c']
- command:
- - 'test -f /tiddlywiki/mywiki/tiddlywiki.info || tiddlywiki mywiki --init server'
- volumes:
- - tiddlywiki-data:/tiddlywiki
- networks:
- tiddlywiki-internal: {}
-
- tiddlywiki:
- image: elasticdog/tiddlywiki@sha256:6fdb8c46c92680c48be5eca5d35cf477b111285481e2ce1717c7dfa131476b17 # v5.1.23
- volumes:
- - tiddlywiki-data:/tiddlywiki
- # authenticated-user-header tells TiddlyWiki to trust the email Pomerium
- # forwards as the logged-in user. It must match the jwt_claims_headers name.
- command:
- - mywiki
- - --listen
- - host=0.0.0.0
- - authenticated-user-header=x-pomerium-claim-email
- depends_on:
- tiddlywiki-init:
- condition: service_completed_successfully
- # Internal-only network with no published ports: TiddlyWiki trusts the identity
- # header, so the only thing allowed to reach it is Pomerium.
- networks:
- tiddlywiki-internal: {}
- restart: always
-
-networks:
- tiddlywiki-internal:
- internal: true
-
-volumes:
- pomerium-cache:
- tiddlywiki-data:
-```
diff --git a/content/examples/guides/tooljet/config.yaml.md b/content/examples/guides/tooljet/config.yaml.md
deleted file mode 100644
index d9f5b2859..000000000
--- a/content/examples/guides/tooljet/config.yaml.md
+++ /dev/null
@@ -1,21 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for ToolJet. Uses the hosted authenticate service, so
-# you don't run your own identity provider. To self-host the IdP, see the Keycloak
-# guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-routes:
- - from: https://tooljet.yourdomain.com
- to: http://tooljet:80
- # ToolJet validates the Host header against TOOLJET_HOST. The route's from-host
- # already equals TOOLJET_HOST, so forward that incoming Host to the upstream.
- preserve_host_header: true
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/tooljet/docker-compose.yaml.md b/content/examples/guides/tooljet/docker-compose.yaml.md
deleted file mode 100644
index 90d19ea94..000000000
--- a/content/examples/guides/tooljet/docker-compose.yaml.md
+++ /dev/null
@@ -1,62 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
-
- tooljet:
- image: tooljet/tooljet-ce@sha256:bc3f53b35a6264742f30384463ed062d9e6325c539805efd603281d899e943e6
- tty: true
- stdin_open: true
- command: npm run start:prod
- environment:
- # The public URL Pomerium serves ToolJet on. ToolJet rejects requests whose
- # Host header doesn't match, which is why the route preserves the Host header.
- TOOLJET_HOST: https://tooljet.yourdomain.com
- PORT: '80'
- SERVE_CLIENT: 'true'
- # Encryption keys. Generate your own and keep them secret:
- # openssl rand -hex 32 (LOCKBOX_MASTER_KEY)
- # openssl rand -hex 64 (SECRET_KEY_BASE)
- LOCKBOX_MASTER_KEY: REPLACE_WITH_64_CHAR_HEX
- SECRET_KEY_BASE: REPLACE_WITH_128_CHAR_HEX
- # PostgreSQL connection. The bundled entrypoint runs migrations on first boot.
- PG_HOST: postgres
- PG_PORT: '5432'
- PG_USER: postgres
- PG_PASS: postgres
- PG_DB: tooljet_production
- # ToolJet's built-in database. It reuses the same PostgreSQL server here.
- TOOLJET_DB: tooljet_db
- TOOLJET_DB_HOST: postgres
- TOOLJET_DB_USER: postgres
- TOOLJET_DB_PASS: postgres
- depends_on:
- postgres:
- condition: service_healthy
- restart: always
-
- postgres:
- image: postgres@sha256:4b7183ac05f8ef417db21fd72d71047a4238340c261d3cc3ddb6d579ab5071ae # 16
- environment:
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: postgres
- volumes:
- - postgres-data:/var/lib/postgresql/data
- healthcheck:
- test: ['CMD-SHELL', 'pg_isready -U postgres']
- interval: 5s
- timeout: 5s
- retries: 20
- restart: always
-
-volumes:
- pomerium-cache:
- postgres-data:
-```
diff --git a/content/examples/guides/transmission/config.yaml.md b/content/examples/guides/transmission/config.yaml.md
deleted file mode 100644
index 0a7a37e1f..000000000
--- a/content/examples/guides/transmission/config.yaml.md
+++ /dev/null
@@ -1,18 +0,0 @@
-```yaml title="config.yaml"
-# Pomerium Core configuration for Transmission. Uses the hosted authenticate
-# service, so you don't run your own identity provider. To self-host the IdP, see
-# the Keycloak guide: https://www.pomerium.com/docs/integrations/user-identity/oidc
-authenticate_service_url: https://authenticate.pomerium.app
-
-# Obtain TLS certificates automatically from Let's Encrypt.
-autocert: true
-
-routes:
- - from: https://transmission.yourdomain.com
- to: http://transmission:9091
- policy:
- - allow:
- or:
- - email:
- is: you@example.com
-```
diff --git a/content/examples/guides/transmission/docker-compose.yaml.md b/content/examples/guides/transmission/docker-compose.yaml.md
deleted file mode 100644
index be0ba6540..000000000
--- a/content/examples/guides/transmission/docker-compose.yaml.md
+++ /dev/null
@@ -1,28 +0,0 @@
-```yaml title="docker-compose.yaml"
-services:
- pomerium:
- image: pomerium/pomerium@sha256:e10d1d267af24f581157f485d9b0bc08469e2428675b696a08e42ceb09b2279c # v0.32.7
- volumes:
- - ./config.yaml:/pomerium/config.yaml:ro
- - pomerium-cache:/data
- ports:
- - 443:443
- - 80:80
- restart: always
-
- transmission:
- image: lscr.io/linuxserver/transmission@sha256:aa4926b22bc25e89820acf427f8a5d1426c34a7ae9bd834e06eda43b12d839c3 # 4.1.2
- environment:
- - PUID=1000
- - PGID=1000
- - TZ=Etc/UTC
- volumes:
- - transmission-config:/config
- - transmission-downloads:/downloads
- restart: always
-
-volumes:
- pomerium-cache:
- transmission-config:
- transmission-downloads:
-```