Files
proxy/README.md
T
wmantly 5139fbb79a Documentation cleanup for public release (#123)
Prepares the docs for the public release announcement: removes obsolete/dead
material, fixes drift between the API reference and the actual routes, and
standardizes on the default GitHub Pages URL.

- Remove Vagrant entirely: delete Vagrantfile, docs/dev_setup.md, and stale
  vagrant references in .gitignore/.dockerignore; rewrite openresty/README.md
  to describe the actual (currently unused) directory and point to
  ops/nginx_conf/ for the real OpenResty config.
- Delete docs/Update 4.11.md (personal scratch changelog) and drop both its
  and dev_setup.md's references from docs/README.md's Legacy Documentation
  section.
- Remove checkmark emoji from docs/contributing.md's PR Requirements list.
- Bring the auth model docs up to date with the code: document
  GET /api/auth/oidc/start + /callback, the /api/permission and /api/group
  RBAC routers, the /api/dns/dynamic/* sub-API, and /api/api-token (self
  -service PATs) in both nodejs/api.md and docs/api.md; add the missing
  "Clear Host Cache" section; drop the invite-token/SSH-key endpoints that no
  longer exist in nodejs/routes/user.js; note admin-only routes. Mention
  OIDC/LDAP/RBAC as core features in README.md.
- Keep nodejs/api.md and docs/api.md fully in sync (same body, differing only
  in Jekyll front matter / relative links) instead of letting them drift.
- Fix Node.js version references (20.x -> 22.x) in README.md and
  docs/installation.md to match ops/install.sh and the Dockerfile.
- Note that the manual nginx-conf/systemd install steps in README.md and
  docs/installation.md won't auto-track repo changes the way install.sh's
  symlink approach does, and recommend install.sh.
- Update the stale test/unit file lists in docs/contributing.md and
  nodejs/test/README.md to match the actual directory contents.
- Add npm run test:integration to README.md's Running Tests section.
- Add nodejs/conf/, nodejs/controller/, and nodejs/migrations/ to the project
  structure diagrams in README.md, docs/architecture.md, and
  docs/contributing.md.
- Standardize "CloudFlare" -> "Cloudflare" everywhere to match the actual API
  value in nodejs/models/dns_provider.js.
- Add the missing app_auth__adminGroups row to DEPLOYMENT.md's app_* table.
- Delete docs/CNAME (custom domain) so GitHub Pages serves from the default
  https://theta42.github.io/proxy/, matching docs/README.md.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-13 23:20:59 -04:00

8.8 KiB
Executable File

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
  • OIDC login — the proxy is an OpenID Connect client of an external SSO (e.g. theta42/sso-manager-node)
  • Direct LDAP lookups, independent of the OIDC flow
  • Role-based access control (RBAC) — global admins, local groups, and per-domain permissions (viewer/manager) via /api/permission and /api/group
  • Self-service API tokens (PATs) for scripting/CI without a browser session
  • 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 22.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.

Recommended path: ops/install.sh is idempotent and safe to re-run — it symlinks the OpenResty/systemd config from the repo checkout, so updates stay in sync automatically. The manual steps below copy those same files instead of symlinking them, so they will not auto-track future changes to ops/nginx_conf/ or ops/proxy.service — you'd need to re-copy them yourself after every update. Use the manual path only if install.sh doesn't fit your distribution.

System Dependencies

Ubuntu/Debian:

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

Node.js 22.x:

curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=22
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:integration  # Run integration 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)
│   ├── conf/           # Configuration (base.js, environment overlays, secrets.js)
│   ├── controller/      # App-level wiring (pubsub, startup)
│   ├── migrations/      # One-off Redis data migration scripts
│   ├── 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