OpenParable
Skip to content
← Back to skills

Configuration HTTP Integrations

DevOps & Security
configuration-http-integrations

Configuration HTTP Integrations is an Agent Skill for devops & security published in the greenpau/caddy-security repository on GitHub: a SKILL.md instruction file an AI agent can load to do this task.

caddy-security HTTP integration Caddyfile configuration. Use when creating, reviewing, or modifying route-level authenticate and authorize directives, portal and protected route separation, matcher forms, same-host or split-host auth wiring, auth URL routing and alignment, auth-path collisions such as upstream /auth routes, dedicated auth hosts with root-mounted portals, portal-owned path prefixes to avoid, or unnecessary global Caddy directive-order overrides.

View on GitHub ↗
QUICK START

How to use this skill

Bring this guide into your coding agent with a prompt tailored to the tool you use.

  1. Open your project in Codex.
  2. Copy and paste the prompt below.
  3. Review files and risks before approving any action.
Prompt to paste
Inspect the Agent Skill at https://github.com/greenpau/caddy-security/blob/HEAD/.codex/skills/configuration-http-integrations/SKILL.md and all supporting files. Report provenance, permissions, scripts, dependencies, and security risks. Propose an exact installation into .agents/skills/configuration-http-integrations, but wait for my approval before writing files or running scripts.

Copying this prompt does not install or run the skill. Review third-party files before use.

Configuration HTTP Integrations

Purpose

Use this skill to wire caddy-security's route-level HTTP integrations: authenticate [<matcher>] with <portal> and authorize [<matcher>] with <policy>.

The security app defines authentication portals and authorization policies; the HTTP integrations attach those configured objects to Caddy routes. Use configuration-authentication for portal internals and configuration-authorization for policy internals.

Prefer names that reveal the referenced object type in generated examples, such as myportal or local_portal for portals and app_policy or local_policy for policies. Policy names are not required to end in _policy, but the suffix makes authorize with <policy> intent clear.

Read these files when details matter:

  • plugin_authn.go for authenticate syntax and directive order.
  • plugin_authz.go for authorize syntax and directive order.
  • assets/config/Caddyfile, assets/config/home.Caddyfile, and assets/config/multiportal.Caddyfile for current route shapes.
  • testdata/caddyfile_adapt/testcase_authenticate_ok.Caddyfile, testdata/caddyfile_adapt/testcase_authorize_ok.Caddyfile, and testdata/caddyfile_adapt/testcase_authenticate_with_registration.Caddyfile for focused adapt fixtures.

Route Roles

authenticate serves the authentication portal. Put it on the portal host or portal path, such as /auth*. It is not the access-control layer for a file server or upstream app.

authorize protects resource routes. It loads an authorization policy, checks tokens or configured auth proxy methods, injects authenticated identity where configured, and redirects unauthenticated browser users to the policy's auth URL.

Keep portal and protected-resource routes separate:

example.com {
	route /auth* {
		authenticate with myportal
	}

	route /app* {
		authorize with app_policy
		reverse_proxy 127.0.0.1:8080
	}
}

For same-host browser login, put the portal route before a catch-all protected route so the portal is not itself protected by authorize:

https://localhost:8443 {
	route /auth* {
		authenticate with local_portal
	}

	route {
		authorize with local_policy
		root * /srv/files
		file_server browse
	}
}

The referenced policy should point browser users to the portal:

authorization policy local_policy {
	crypto key verify {env.JWT_SHARED_KEY}
	set auth url /auth
	allow roles authp/user
}

For split-host deployments, put authenticate on the auth host and authorize only on the protected app or asset host. Use a full auth URL when the portal is on a different host.

Portal Path Selection

The authorization policy's set auth url must align with the path where the authentication portal is actually served:

  • Same host: use the portal route path, such as /auth for route /auth*.
  • Same host with path conflict: use /xauth for route /xauth*.
  • Dedicated auth host at root: use the full root URL, such as https://auth.example.com/.

Do not leave set auth url at the /auth default when the portal is mounted at /xauth, /, or a different host. For split-host deployments, prefer the full portal URL over a relative path.

Use /auth as the default portal route path in new examples:

route /auth* {
	authenticate with myportal
}

Use a different portal path, commonly /xauth, when the protected upstream application already owns /auth for its own login, callbacks, API endpoints, or framework routes. In that case, do not shadow the upstream's /auth path with caddy-security's portal route; mount the portal elsewhere and point the authorization policy's set auth url to that path:

authorization policy app_policy {
	crypto key verify {env.JWT_SHARED_KEY}
	set auth url /xauth
	allow roles authp/user
}

app.example.com {
	route /xauth* {
		authenticate with app_portal
	}

	route {
		authorize with app_policy
		reverse_proxy 127.0.0.1:8080
	}
}

Use / when a dedicated auth host serves only the authentication portal for a parent domain. For example, if auth.myfiosgateway.com exists only to serve the portal for the myfiosgateway.com domain and has no upstream app or static content of its own, mounting the portal at root keeps the login URL short and avoids reserving an unnecessary path prefix:

authorization policy app_policy {
	crypto key verify {env.JWT_SHARED_KEY}
	set auth url https://auth.myfiosgateway.com/
	allow roles authp/user
}

auth.myfiosgateway.com {
	route {
		authenticate with domain_portal
	}
}

app.myfiosgateway.com {
	route {
		authorize with app_policy
		reverse_proxy 127.0.0.1:8080
	}
}

Do not mount the portal at / on a host that also needs to serve an upstream application or other site content; use /auth or /xauth in that case.

Avoid Portal-Owned Prefixes

Do not use a portal-owned endpoint family as the public mount prefix for authenticate. These names are valid internal endpoints below the chosen base path, such as /auth/login, but they SHOULD NOT be the base path itself:

  • /api, including /api/refresh_token, /api/profile, and admin API endpoints.
  • /qrcode.
  • /assets and /favicon.
  • /profile.
  • /portal.
  • /recover and /forgot.
  • /register.
  • /whoami.
  • /apps, especially /apps/sso and /apps/mobile-access.
  • /oauth2 and /saml.
  • /basic and /basic/login.
  • /barcode, especially /barcode/mfa.
  • /sandbox.
  • /login and /logout.
  • /beacon for JSON/API-style requests.

go-authcrunch dispatches several portal requests with substring or suffix checks before falling back to generic base-path inference. A mount such as /api, /profile, /portal, or /login can therefore make ordinary portal login, callback, static asset, refresh-token, or JSON requests hit the wrong internal handler.

Prefer /auth for ordinary same-host portals, /xauth when /auth collides with the protected upstream, or / only on a dedicated auth-only host. If an upstream application owns one of the reserved names, leave that upstream path alone and mount the portal at /xauth or a dedicated auth host.

Avoid:

route /api* {
	authenticate with app_portal
}

route /profile* {
	authenticate with app_portal
}

Prefer:

authorization policy app_policy {
	crypto key verify {env.JWT_SHARED_KEY}
	set auth url /xauth
	allow roles authp/user
}

route /xauth* {
	authenticate with app_portal
}

Syntax

Prefer route blocks for clarity:

route /auth* {
	authenticate with myportal
}

route /api/* {
	authorize with api_policy
	reverse_proxy 127.0.0.1:9000
}

The optional matcher form is valid when it keeps the surrounding Caddyfile smaller:

authenticate /auth* with myportal
authorize /api/* with api_policy

The portal or policy name must match a configured object in the security app. Keep subconfiguration inside authentication portal <name> and authorization policy <name> blocks. Do not put policy internals, such as with api key auth ..., under the route-level authorize directive; the route handler parser reads only the directive arguments.

Directive Order

Do not generate global Caddy directive-order overrides for caddy-security:

{
	order authenticate before respond
	order authorize before file_server
}

Also do not generate order authorize before basicauth by default. The plugin already registers its order in code:

  • authenticate before respond
  • authorize before basicauth

Only add global order directives when debugging a proven directive-order conflict with another third-party plugin, and explain the conflicting directive order. Do not use global order directives as a default fix for login failures, redirect loops, or authorization denials.

Legacy docs-site examples and old solution briefs may still include global order authenticate before respond and order authorize before basicauth lines. Treat those examples as historical route-shape references, not as current guidance to copy into new Caddyfiles.

Validation

When changing Caddyfile examples or fixtures, validate with the narrowest adapt-focused test from testing-and-ci. For skill-only edits, run the skill validator from skill-creator.