Nginx Setup¶
Castellum integrates with Nginx via the auth_request module. This page provides the complete Nginx configuration for using Castellum as an authentication provider.
How auth_request Works¶
The Nginx auth_request module makes an internal subrequest to Castellum's /auth endpoint for every incoming request. Based on the response:
- 200 OK: Nginx proxies the request to the upstream application
- 401 Unauthorized: The user is redirected to the guard (login) page
- 403 Forbidden: The request is denied
Full Configuration Example¶
server {
listen 80;
server_name app.example.com;
# All requests require authentication via Castellum
location / {
auth_request /auth;
# On 401, redirect to the guard page for login
error_page 401 = @login_redirect;
# Proxy to the actual application
proxy_pass http://app-backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Internal auth subrequest to Castellum
location = /auth {
internal;
proxy_pass http://127.0.0.1:9999/wall/auth;
# Pass the original domain for authorized domain checking
proxy_set_header X-Forwarded-Host $host;
# Pass the real client IP for IP list checks and rate limiting
proxy_set_header X-Forwarded-For $remote_addr;
# Pass the original URI for git request detection
proxy_set_header X-Original-URI $request_uri;
# Do not send the request body to the auth endpoint
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
# Redirect to guard page when authentication is required
location @login_redirect {
return 302 http://defender.example.com:9999/wall/guard/;
}
}
Configuration Explained¶
The /auth Location Block¶
location = /auth {
internal;
proxy_pass http://127.0.0.1:9999/wall/auth;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Original-URI $request_uri;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
| Directive | Purpose |
|---|---|
internal |
Ensures this location can only be accessed via internal subrequests, not directly by clients |
proxy_pass |
Forwards the auth check to Castellum's /auth endpoint |
X-Forwarded-Host |
Passes the original requested domain so Castellum can perform authorized domain checks |
X-Forwarded-For |
Passes the real client IP for IP list checks and rate limiting |
X-Original-URI |
Passes the original request URI so Castellum can detect git requests for git token authentication |
proxy_pass_request_body off |
The auth check does not need the request body -- this improves performance |
Content-Length "" |
Required when disabling request body forwarding |
X-Forwarded-Host is Required for Authorized Domain Checks
If you use authorized domain access control, the proxy_set_header X-Forwarded-Host $host; directive is essential. Without it, Castellum cannot determine which domain the user is trying to access.
The auth_request Directive¶
This tells Nginx to check with Castellum before serving any content. The auth subrequest carries the original request's headers (including cookies), allowing Castellum to validate the user's session.
Multiple Protected Applications¶
To protect multiple applications behind the same Castellum instance, create a server block for each:
# Application 1
server {
server_name app.example.com;
location / {
auth_request /auth;
proxy_pass http://app-backend;
}
location = /auth {
internal;
proxy_pass http://127.0.0.1:9999/wall/auth;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Original-URI $request_uri;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
}
# Application 2
server {
server_name app2.example.com;
location / {
auth_request /auth;
proxy_pass http://app2-backend;
}
location = /auth {
internal;
proxy_pass http://127.0.0.1:9999/wall/auth;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Original-URI $request_uri;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
}
Use Authorized Domain Access Control
When protecting multiple applications, use authorized domains to control which users can access which services. For example, you can restrict a developer to app.example.com while giving an operations engineer access to *.example.com.
Castellum Admin and Guard Pages¶
The Castellum admin dashboard and guard page are served directly by the Go backend. You may optionally proxy them through Nginx as well:
# Castellum admin and guard
server {
listen 80;
server_name defender.example.com;
location / {
proxy_pass http://127.0.0.1:9999;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Do Not auth_request the Castellum Itself
The Castellum's own admin and guard pages should not be behind auth_request, as this would create a circular dependency. The admin dashboard has its own built-in authentication.