wmantly a9a48c3445 Add self-service API tokens (PATs) with UI + Bearer auth (#119)
Personal access tokens so scripts/CI can call the management API without an
OIDC browser session. Each logged-in user mints their own token; it
authenticates as the creator (groups snapshotted at mint, mirroring the proxy's
browser AuthToken), and the existing authz layer (Permission.effectiveFor /
roles.resolveEffective) applies unchanged. Local groups and owned-domain rights
are recomputed live; only SSO/LDAP group membership is the mint-time snapshot.

- models/api_token.js: new ApiToken model (prx_<id>_<secret> format; id is the
  lookup key, secret bcrypt-hashed + isPrivate, shown once). add()/rotate()/
  authenticate(); optional expires_at; best-effort last_used_on; groups
  snapshot. No _ttl (persists). Deliberately NOT wrapped in ModelPs (so the
  last_used_on write on the auth path doesn't spam the socket).
- routes/api_token.js: self-service CRUD (list/get/update/delete/rotate),
  owner-scoped (created_by === reqUsername(req), 403 otherwise).
- middleware/auth.js + models/auth.js: accept `Authorization: Bearer prx_...`
  (precedence over the auth-token session header). Builds a synthetic req.token
  that satisfies the only three req.token reads (auth.js .user/.groupsArray,
  authz.js reqUsername .created_by) so the authz layer works unchanged.
  checkApiToken collapses every failure to one generic 401 (no leak).
- views/api_tokens.ejs + routes/render.js (GET /api-tokens): self-service page
  (forceLogin, no admin gate) — create (token shown once), rotate, revoke.
- views/top.ejs: "API Tokens" nav entry visible to all logged-in users.
- public/js/app.js: app.apiToken client module.
- DEPLOYMENT.md + docs/docker.md: API tokens section.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-12 17:12:38 -04:00
2025-12-31 16:54:49 -05:00
2023-08-20 14:19:30 -04:00
2019-12-22 14:42:35 -05:00
2024-08-13 01:29:57 +08:00
2026-07-11 21:02:56 -04:00

Proxy

A reverse proxy and HTTPS termination service using OpenResty/nginx with a management API and web GUI.

Documentation: https://theta42.github.io/proxy/

Features

  • Automated HTTPS/SSL certificate management via Let's Encrypt
  • Support for HTTP-01 (auto-ssl) and DNS-01 (wildcard) ACME challenges
  • Multiple DNS provider integrations (CloudFlare, DigitalOcean, PorkBun)
  • Wildcard SSL certificate support with automatic renewal
  • Dynamic host routing with wildcard domain matching (*, **)
  • Web-based management interface
  • RESTful API for automation
  • User authentication and management
  • Unix socket-based host lookup for high-performance routing

Requirements

  • Node.js 18+ (tested with 18.x, 20.x, 22.x)
  • OpenResty (nginx with Lua support)
  • Redis
  • Modern Linux distribution (tested on Ubuntu 20.04+, Debian 11+)
  • Inbound internet access for Let's Encrypt validation
  • Root access (required for user management features)

Quick Install

An automated installer is available for modern Debian-based systems:

wget -O - https://raw.githubusercontent.com/theta42/proxy/master/ops/install.sh | sudo bash

This installer will:

  • Install Node.js 20.x
  • Install OpenResty and required dependencies
  • Install and configure Redis
  • Set up SSL fallback certificates
  • Install Lua dependencies (lua-resty-auto-ssl, luasocket)
  • Clone and install the proxy application
  • Configure systemd service
  • Start the proxy service

Logs (Docker)

The all-in-one image runs OpenResty in the foreground and the Node app in the background, both writing to the container's stdout/stderr. The proxy's nginx access/error logs go to files (/var/log/nginx, on the proxy-logs volume), so they do not show up in docker logs.

# App + OpenResty (stdout/stderr)
docker compose logs -f proxy
# or, by container name:
docker logs -f proxy

# nginx access / error logs (in-container files, not in docker logs)
docker compose exec proxy tail -f /var/log/nginx/access.log
docker compose exec proxy tail -f /var/log/nginx/error.log

# Recent context
docker compose logs --tail=200 --since=10m proxy

Manual Installation

For manual installation or other distributions, see the detailed steps below.

System Dependencies

Ubuntu/Debian:

apt install libpam0g-dev build-essential redis-server luarocks -y

Node.js 20.x:

curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=20
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
apt update && apt install nodejs -y

OpenResty:

wget -O - https://openresty.org/package/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/openresty.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/openresty.gpg] http://openresty.org/package/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/openresty.list
apt update && apt install openresty -y

Lua Dependencies:

luarocks install lua-resty-auto-ssl
luarocks install luasocket

SSL Configuration

Create fallback SSL certificates:

mkdir -p /etc/ssl/
openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
  -subj '/CN=sni-support-required-for-valid-ssl' \
  -keyout /etc/ssl/resty-auto-ssl-fallback.key \
  -out /etc/ssl/resty-auto-ssl-fallback.crt

OpenResty Configuration

Configuration files are provided in ops/nginx_conf/:

  • nginx.conf - Main nginx configuration
  • autossl.conf - Auto-SSL configuration for Let's Encrypt HTTP-01
  • proxy.conf - Proxy server configuration with host lookup
  • targetinfo.lua - Lua module for host lookup via Unix socket

Copy these files to /etc/openresty/:

mkdir -p /etc/openresty/sites-enabled/
cp ops/nginx_conf/nginx.conf /etc/openresty/nginx.conf
cp ops/nginx_conf/autossl.conf /etc/openresty/autossl.conf
cp ops/nginx_conf/proxy.conf /etc/openresty/sites-enabled/000-proxy
cp ops/nginx_conf/targetinfo.lua /usr/local/openresty/lualib/targetinfo.lua

Application Setup

Clone and install:

cd /var/www
git clone https://github.com/theta42/proxy.git
cd proxy/nodejs
npm install

Create systemd service:

cp ops/proxy.service /etc/systemd/system/proxy.service
systemctl daemon-reload
systemctl enable proxy.service
systemctl start proxy.service

DNS Provider Configuration

For wildcard SSL certificates, configure a DNS provider via the web UI or API:

Supported providers:

  • CloudFlare - Requires API token
  • DigitalOcean - Requires API token
  • PorkBun - Requires API key and secret API key

Once configured, create a wildcard host (e.g., *.example.com) and the system will automatically request and manage the DNS-01 challenge certificate.

Architecture

The system consists of three main components:

  1. OpenResty/Nginx - Frontend proxy with Lua-based routing

    • Handles SSL termination via lua-resty-auto-ssl
    • Queries Node.js backend via Unix socket for host routing
    • Proxies requests to configured backend servers
  2. Node.js API - Backend management and control plane

    • RESTful API for host/user/DNS management
    • Wildcard SSL certificate orchestration
    • Host lookup tree with wildcard matching
    • User authentication and authorization
  3. Redis - Data store (using model-redis ORM)

    • Host configurations
    • User accounts and tokens
    • SSL certificate storage
    • Domain and DNS provider configurations

Host Lookup System

The proxy supports sophisticated domain matching:

  • Exact match: example.com matches only example.com
  • Single wildcard: *.example.com matches sub.example.com but not deep.sub.example.com
  • Double wildcard: **.example.com matches any depth (sub.example.com, deep.sub.example.com, etc.)
  • Mixed wildcards: api.*.example.com matches api.v1.example.com, api.v2.example.com, etc.

Priority: Exact match > Single wildcard > Double wildcard

Development

Running locally:

cd nodejs
npm install
npm run dev  # Runs with nodemon for auto-reload

Running tests:

npm test              # Run all tests
npm run test:unit     # Run unit tests only
npm run test:watch    # Watch mode for development

Tests use Node.js built-in test runner (requires Node 18+).

API Documentation

See API Documentation for complete API reference.

Contributing

Pull requests are welcome. The project uses GitHub Actions for CI/CD:

  • Tests run automatically on all PRs
  • All tests must pass before merging to master
  • Tests run on Node.js 18.x, 20.x, and 22.x

License

MIT - See LICENSE file for details.

Project Structure

proxy/
├── nodejs/              # Node.js backend application
│   ├── bin/            # Entry point (www)
│   ├── models/         # Data models (Host, User, DNS providers)
│   ├── routes/         # API routes
│   ├── services/       # Background services (host lookup, scheduler)
│   ├── middleware/     # Express middleware
│   ├── utils/          # Utility functions
│   ├── public/         # Static web assets
│   ├── views/          # EJS templates
│   └── test/           # Test suite
├── ops/                # Operations and deployment
│   ├── nginx_conf/     # OpenResty configuration files
│   ├── install.sh      # Automated installer
│   └── proxy.service   # Systemd service definition
└── .github/workflows/  # CI/CD workflows
S
Description
Simple API and Web front end to configure HTTP/S proxy, auto lets encrypt.
Readme 4.4 MiB
Languages
JavaScript 68.6%
EJS 20.6%
Shell 4.5%
Lua 2.9%
Dockerfile 2.1%
Other 1.3%