|
Download README.md from AnthropicallyHuggingFaces/nginx-api-key-proxy: direct link, hf CLI and curl.
- Browser
- Download file 3.31 kB
-
https://huggingface.co/spaces/AnthropicallyHuggingFaces/nginx-api-key-proxy/resolve/main/README.md
- Command line
-
hf download hf://spaces/AnthropicallyHuggingFaces/nginx-api-key-proxy/README.md
-
curl -L -o README.md https://huggingface.co/spaces/AnthropicallyHuggingFaces/nginx-api-key-proxy/resolve/main/README.md
3.31 kB
metadata
title: Nginx API Key Proxy
emoji: π
colorFrom: gray
colorTo: blue
sdk: docker
app_port: 7860
pinned: false
Nginx API Key Proxy
Builds nginx from source and runs it as a reverse proxy that injects an
upstream API key server-side. Clients never need the key, and the key is
never written into nginx.conf.
What this Space demonstrates
| Concern | Implementation |
|---|---|
| Build | install-nginx.sh compiles nginx 1.25.3 with http_ssl, stream, realip, http_v2, threads, file_aio, stub_status |
| Key discovery | Vault β AWS Secrets Manager β local files β systemd units β placeholder |
| Key at rest | Only /etc/nginx-upstream.env (chmod 600, root) |
| Key in config | No β env upstream_api_key; + map exposes it at runtime |
| Injection | proxy_set_header Authorization "Bearer $api_key_value" overrides any client header |
Verifying the injection
Requests to /model-api/ are proxied to the demo upstream, which echoes the
headers it received:
curl -s https://<space-subdomain>.hf.space/model-api/
The response shows received_headers.Authorization β a value nginx added
server-side. Send your own Authorization header and note it is overridden,
not passed through.
Key sources (in precedence order)
| # | Source | Configuration |
|---|---|---|
| 1 | Explicit env var | UPSTREAM_API_KEY=... |
| 2 | Cached secrets file | /etc/nginx-secrets.env, /etc/nginx-upstream.env |
| 3 | HashiCorp Vault | VAULT_ADDR, VAULT_SECRET_PATH, VAULT_SECRET_FIELD |
| 4 | Vault AppRole | VAULT_ROLE_ID + VAULT_SECRET_ID_FILE |
| 5 | AWS Secrets Manager | AWS_SECRET_ID, AWS_SECRET_FIELD, AWS_REGION |
| 6 | Local files | /etc/myapp/api.key, /etc/myapp/secrets.env, /opt/app/.env, /etc/environment |
| 7 | Backend systemd units | myapp.service, model-api.service |
| 8 | Placeholder | __REPLACE_ME__ (visible, deliberately invalid) |
Tune LOCAL_KEY_SOURCES and BACKEND_UNITS in install-nginx.sh for your
real paths.
Deploying on a systemd host
install-nginx.sh is written for a VM/EC2-style host:
sudo AWS_SECRET_ID=myapp/api-key AWS_REGION=us-east-1 ./install-nginx.sh
It installs the unit at /etc/systemd/system/nginx.service with
EnvironmentFile=/etc/nginx-upstream.env and enables it.
Vault via AppRole, avoiding a static token on disk:
sudo install -m 600 /dev/stdin /etc/vault-approle-secret-id <<< "$SECRET_ID"
sudo VAULT_ADDR=https://vault.example.com:8200 \
VAULT_SECRET_PATH=secret/data/myapp \
VAULT_ROLE_ID=... ./install-nginx.sh
Honest limitations
- The key is still on disk, moved from
nginx.confto a root-only env file. Truly diskless requires a vault agent or custom module. - Env vars are readable by root via
/proc/<pid>/environ. Inherent to theEnvironmentFilemechanism. - Scraping
.env/ systemd files is heuristic β it assumes simpleKEY=valuelines and will miss values fetched from a vault at runtime. - No systemd in this container. The unit file is written for parity but the entrypoint runs nginx in the foreground.
- Build time is several minutes β nginx is compiled from source on every image build rather than installed from a package.