Skip to main content

Nginx Routing

Nginx acts as the single entry point for all HTTP/HTTPS traffic. It performs TLS termination, path-based routing, and technician-only access enforcement for Snipe-IT.

The configuration is defined as a template in infra/nginx/templates/default.conf.template, which is processed by envsubst at container startup to substitute environment variables from the x-deployment block.


Upstream definitions

upstream api       { server api:8000; }
upstream snipeit { server snipeit:80; }
upstream frontend { server web:3000; }

All upstream services are referenced by their Docker service names.


HTTP → HTTPS redirect

server {
listen 80;
server_name ${MAKERLAB_DOMAIN};
return 301 https://$host$request_uri;
}

All HTTP requests are permanently redirected to HTTPS.


HTTPS server block routes

SSO callback — /auth/auth

location = /auth/auth {
proxy_pass http://api/auth/sso/callback$is_args$args;
...
}

This is a fixed path, independent of any base path prefix. It must match the callback URL registered with the University SSO provider (identity.ua.pt).

Internal auth subrequest — /auth-verify

location = /auth-verify {
internal;
proxy_pass http://api/auth/snipeit/verify$is_args$args;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
proxy_set_header Cookie $http_cookie;
}

This location is marked internal — it cannot be accessed from the browser directly. It is used exclusively by the auth_request directive on the Snipe-IT route.

API — ${NEXT_PUBLIC_API_URL}/

location ^~ ${NEXT_PUBLIC_API_URL}/ {
rewrite ^${NEXT_PUBLIC_API_URL}/(.*) /$1 break;
proxy_pass http://api;
...
}

Strips the path prefix before forwarding to FastAPI. For example, /api/projects/projects at the API container.

Snipe-IT (with auth gate) — ${SNIPEIT_PATH}/

location ^~ ${SNIPEIT_PATH}/ {
auth_request /auth-verify;
auth_request_set $sso_user $upstream_http_x_remote_user;
proxy_set_header X-Remote-User $sso_user;
...
error_page 401 = @error401_snipeit;
error_page 403 = @error403_snipeit;
rewrite ^${SNIPEIT_PATH}/(.*) /$1 break;
proxy_pass http://snipeit;
}

Every request to Snipe-IT triggers a subrequest to /auth-verify. If the subrequest returns:

  • 200 OK — the request is proxied to Snipe-IT with the X-Remote-User header.
  • 401 — the user is redirected to the SSO login.
  • 403 — a Forbidden error is returned (non-technician user).

Error handlers for Snipe-IT

location @error401_snipeit {
return 302 ${API_PUBLIC_URL}/auth/sso/login/mobile?web_redirect=${SNIPEIT_PUBLIC_URL}/;
}
location @error403_snipeit {
return 403 "Forbidden: Only lab technicians have access to SnipeIT.";
}

Frontend — ${NEXT_PUBLIC_BASE_PATH} (regex)

location ~ ^${NEXT_PUBLIC_BASE_PATH}(/|$) {
proxy_pass http://frontend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
...
}

A regex location prevents Nginx's automatic trailing-slash 301 redirect (which would conflict with Next.js's own redirect behavior).

Root redirect

location ~ ^(?!${NEXT_PUBLIC_BASE_PATH}(/|$)).*$ {
return 301 ${FRONTEND_URL};
}

When NEXT_PUBLIC_BASE_PATH is set (e.g., /new), this redirects any path not under the base path to the frontend root. When NEXT_PUBLIC_BASE_PATH is empty, this regex never matches any valid path.


Snipe-IT proxy headers

The Snipe-IT service requires these headers to generate correct absolute URLs:

proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-Prefix ${SNIPEIT_PATH};
proxy_set_header X-Forwarded-Proto https;

X-Forwarded-Prefix tells Snipe-IT what path prefix it is served under, so it generates correct links in the admin UI.


TLS configuration

ssl_certificate     /etc/nginx/certs/selfsigned.crt;
ssl_certificate_key /etc/nginx/certs/selfsigned.key;

Replace with real certificates for production. See Environment Configuration.


Common routing issues

SymptomLikely cause
SSO callback fails with 404Nginx does not have the /auth/auth location block or SSO callback URL mismatch
Snipe-IT shows 401 in a loopCookie not being passed to /auth-verify
Next.js returns 404 for all routesNEXT_PUBLIC_BASE_PATH mismatch between build and Nginx config
API returns 404 for all routesPath prefix rewrite issue; check NEXT_PUBLIC_API_URL in docker-compose
Snipe-IT generates wrong URLsAPP_URL or X-Forwarded-Prefix not set correctly

See Troubleshooting for detailed solutions.