@maxpeterkaya/web-proxy 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.air.toml +58 -0
- package/INSTALL-GUIDE.md +39 -25
- package/README.md +98 -25
- package/USAGE-GUIDE.md +121 -0
- package/bin/install.js +1 -1
- package/bin/run.js +2 -1
- package/package.json +1 -1
- package/views/bootstrap.gohtml +26 -0
- package/views/form.gohtml +41 -0
package/.air.toml
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#:schema https://json.schemastore.org/any.json
|
|
2
|
+
|
|
3
|
+
env_files = []
|
|
4
|
+
root = "."
|
|
5
|
+
testdata_dir = "testdata"
|
|
6
|
+
tmp_dir = "tmp"
|
|
7
|
+
|
|
8
|
+
[build]
|
|
9
|
+
args_bin = []
|
|
10
|
+
bin = "./tmp/main"
|
|
11
|
+
cmd = "go build -o ./tmp/main -ldflags=\"-X 'main.version=dev'\" ."
|
|
12
|
+
delay = 1000
|
|
13
|
+
entrypoint = ["./tmp/main"]
|
|
14
|
+
exclude_dir = ["assets", "tmp", "vendor", "testdata", "web", "storage", "examples"]
|
|
15
|
+
exclude_file = []
|
|
16
|
+
exclude_regex = ["_test.go"]
|
|
17
|
+
exclude_unchanged = false
|
|
18
|
+
follow_symlink = false
|
|
19
|
+
full_bin = ""
|
|
20
|
+
ignore_dangerous_root_dir = false
|
|
21
|
+
include_dir = []
|
|
22
|
+
include_ext = ["go", "tpl", "tmpl", "html", "gohtml"]
|
|
23
|
+
include_file = [".env"]
|
|
24
|
+
kill_delay = "0s"
|
|
25
|
+
log = "build-errors.log"
|
|
26
|
+
poll = false
|
|
27
|
+
poll_interval = 0
|
|
28
|
+
post_cmd = []
|
|
29
|
+
pre_cmd = []
|
|
30
|
+
rerun = false
|
|
31
|
+
rerun_delay = 500
|
|
32
|
+
send_interrupt = false
|
|
33
|
+
stop_on_error = false
|
|
34
|
+
|
|
35
|
+
[color]
|
|
36
|
+
app = ""
|
|
37
|
+
build = "yellow"
|
|
38
|
+
main = "magenta"
|
|
39
|
+
runner = "green"
|
|
40
|
+
watcher = "cyan"
|
|
41
|
+
|
|
42
|
+
[log]
|
|
43
|
+
main_only = false
|
|
44
|
+
silent = false
|
|
45
|
+
time = false
|
|
46
|
+
|
|
47
|
+
[misc]
|
|
48
|
+
clean_on_exit = false
|
|
49
|
+
|
|
50
|
+
[proxy]
|
|
51
|
+
app_port = 0
|
|
52
|
+
app_start_timeout = 0
|
|
53
|
+
enabled = false
|
|
54
|
+
proxy_port = 0
|
|
55
|
+
|
|
56
|
+
[screen]
|
|
57
|
+
clear_on_rebuild = false
|
|
58
|
+
keep_scroll = true
|
package/INSTALL-GUIDE.md
CHANGED
|
@@ -1,56 +1,70 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Install Guide
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This guide covers every way to install and run web-proxy. The README gives a high level overview, and the Usage Guide documents every option in detail.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
version of web-proxy at all times in your build stage without having to tweak your process to manually fetch the latest
|
|
7
|
-
version through commands.
|
|
8
|
-
|
|
9
|
-
### Step 1
|
|
10
|
-
|
|
11
|
-
Install: ``npm i @maxpeterkaya/web-proxy``
|
|
12
|
-
|
|
13
|
-
While running ``npm i``, it will automatically download the latest binary with execution permissions.
|
|
5
|
+
## npm package
|
|
14
6
|
|
|
7
|
+
```bash
|
|
8
|
+
npm i @maxpeterkaya/web-proxy
|
|
9
|
+
```
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
Installation downloads the binary that matches your platform and marks it executable. The binary is pulled at install time, so the npm package always brings the latest release without manual version management.
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
** argument.
|
|
13
|
+
### Run your app through web-proxy
|
|
20
14
|
|
|
21
|
-
Add the following scripts to
|
|
15
|
+
Add the following scripts to package.json.
|
|
22
16
|
|
|
23
17
|
```json
|
|
24
18
|
{
|
|
25
19
|
"scripts": {
|
|
26
|
-
"start:web": "
|
|
20
|
+
"start:web": "next start",
|
|
27
21
|
"start": "npx web-proxy -app"
|
|
28
22
|
}
|
|
29
23
|
}
|
|
30
24
|
```
|
|
31
25
|
|
|
32
|
-
|
|
26
|
+
Then run `npm run start`. web-proxy reads the `start:web` script, starts your app on the internal proxy port, and exposes it on the public port. The proxy accepts public traffic on PORT 3000 and talks to the app on PROXY_PORT 3001. A NextJS start command automatically gets the right port appended. For another framework make sure it listens on PROXY_PORT, or set `PROXY_TARGETS` to point at a different location.
|
|
27
|
+
|
|
28
|
+
### Run your app and web-proxy concurrently
|
|
33
29
|
|
|
34
|
-
|
|
30
|
+
When you want to keep your own process manager, run web-proxy next to your app with concurrently.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm i concurrently
|
|
34
|
+
```
|
|
35
35
|
|
|
36
36
|
```json
|
|
37
37
|
{
|
|
38
38
|
"scripts": {
|
|
39
39
|
"start:proxy": "npx web-proxy",
|
|
40
|
-
"start:web": "
|
|
40
|
+
"start:web": "next start -p 3001",
|
|
41
41
|
"start": "concurrently --prefix none \"npm run start:web\" \"npm run start:proxy\""
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
The app must listen on the proxy target port, PROXY_PORT 3001 by default, so the example pins NextJS there. You can read the concurrently documentation [here](https://github.com/open-cli-tools/concurrently/tree/main/docs).
|
|
47
|
+
|
|
48
|
+
## Container image
|
|
49
|
+
|
|
50
|
+
The image `vc.maxkaya.com/maxpeterkaya/web-proxy:latest` runs the proxy on its own. It is built for linux amd64, arm64, and armv7, and runs from a scratch base with only the proxy binary and CA certificates.
|
|
47
51
|
|
|
48
|
-
|
|
52
|
+
Wire the image into a compose stack to log or protect a sibling service. Set `PROXY_TARGETS` to the service name and port of the upstream, remembering that some tools prepend the stack name to service hostnames.
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
services:
|
|
56
|
+
proxy:
|
|
57
|
+
image: vc.maxkaya.com/maxpeterkaya/web-proxy:latest
|
|
58
|
+
ports:
|
|
59
|
+
- "3000:3000"
|
|
60
|
+
environment:
|
|
61
|
+
PROXY_TARGETS: app:3001
|
|
62
|
+
```
|
|
49
63
|
|
|
50
|
-
|
|
64
|
+
Two container patterns are covered in the examples. The [container proxy example](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/container-proxy) runs web-proxy as a separate container in front of another service, while the [container middleware example](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/container-middleware) embeds web-proxy in the same container as your application.
|
|
51
65
|
|
|
52
|
-
|
|
66
|
+
## Binary downloads
|
|
53
67
|
|
|
54
|
-
|
|
68
|
+
Prebuilt binaries are published for Linux, macOS, FreeBSD, OpenBSD, and NetBSD on amd64, arm, and arm64. Each artifact is named `web-proxy_<os>_<arch>`. The containers and npm package both wrap these binaries, so the binary is useful for embedding web-proxy in a custom base image or running it directly on a host.
|
|
55
69
|
|
|
56
|
-
|
|
70
|
+
For the configuration reference and run modes, see the [Usage Guide](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/USAGE-GUIDE.md).
|
package/README.md
CHANGED
|
@@ -1,55 +1,128 @@
|
|
|
1
|
-
#
|
|
1
|
+
# web-proxy
|
|
2
2
|
|
|
3
3
|
[](https://artifacthub.io/packages/search?repo=web-proxy)   
|
|
4
4
|

|
|
5
|
-
## Introduction
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
These applications all mostly lack a uniform logger that is customizable as well as even non-existent in production
|
|
9
|
-
builds.
|
|
10
|
-
Some of these frameworks may include:
|
|
6
|
+
web-proxy is a reverse proxy that gives production grade structured logs to web applications that were not built with observability in mind. Many popular frameworks log inconsistently, and some production builds drop logging entirely. NextJS and Prisma ORM are typical examples. Instead of editing application code, run web-proxy in front of the application. Every request is logged as structured JSON before it is forwarded upstream, so traffic becomes queryable in Grafana, Loki, and Promtail.
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
- PrismaORM
|
|
8
|
+
## What a request looks like
|
|
14
9
|
|
|
15
|
-
|
|
10
|
+
When a client hits the proxy, web-proxy records the full picture of the exchange.
|
|
16
11
|
|
|
17
|
-
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"level": "info",
|
|
15
|
+
"status": 200,
|
|
16
|
+
"method": "GET",
|
|
17
|
+
"URI": "/api/items?page=2",
|
|
18
|
+
"route": "/api/items",
|
|
19
|
+
"protocol": "HTTP/1.1",
|
|
20
|
+
"remote_ip": "203.0.113.8",
|
|
21
|
+
"host": "example.com",
|
|
22
|
+
"referer": "https://example.com/home",
|
|
23
|
+
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
|
|
24
|
+
"id": "6f9c2ab7e4d84a2f",
|
|
25
|
+
"latency": 2850000,
|
|
26
|
+
"latency_human": "2.85ms",
|
|
27
|
+
"bytes_in": 0,
|
|
28
|
+
"bytes_out": 4182,
|
|
29
|
+
"target": "http://localhost:3001"
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Every log line carries the request ID, the client IP taken from the X-Forwarded-For header, the proxy target that served the request, and latency in nanoseconds plus a human readable form. Requests whose paths carry a file extension are logged separately from application routes, which keeps static asset noise easy to filter. Failed requests produce an error level line with the same fields plus the underlying error.
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- Structured JSON logs for every request with status, method, path, latency, bytes transferred, request ID, and real client IP.
|
|
38
|
+
- Reverse proxying to a single application or load balancing across several upstreams.
|
|
39
|
+
- TCP health checks that drop dead upstreams from rotation and answer 503 when every target is down.
|
|
40
|
+
- Static hosting for frontend builds.
|
|
41
|
+
- Managed mode that starts your web application and forwards public traffic to it.
|
|
42
|
+
- Access control through basic auth, bearer keys, or a branded session login page.
|
|
43
|
+
- Blocking of specific user agents and client IP addresses.
|
|
44
|
+
- Configuration through environment variables with safe defaults and .env support.
|
|
45
|
+
|
|
46
|
+
## Quick start
|
|
18
47
|
|
|
19
|
-
|
|
48
|
+
### npm
|
|
20
49
|
|
|
21
|
-
|
|
50
|
+
web-proxy ships as an npm package that downloads the matching binary during installation.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm i @maxpeterkaya/web-proxy
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Add the scripts below to package.json to let web-proxy run your application.
|
|
22
57
|
|
|
23
58
|
```json
|
|
24
59
|
{
|
|
25
60
|
"scripts": {
|
|
26
|
-
"start": "
|
|
27
|
-
|
|
28
|
-
"start:web": "YOUR COMMAND TO START THE WEB APP"
|
|
29
|
-
// This could be next start, remix-serve build, ng serve, node dist/main, etc.
|
|
61
|
+
"start:web": "next start",
|
|
62
|
+
"start": "npx web-proxy -app"
|
|
30
63
|
}
|
|
31
64
|
}
|
|
32
65
|
```
|
|
33
66
|
|
|
34
|
-
|
|
67
|
+
Start it with `npm run start`. web-proxy reads the `start:web` script, launches your app on an internal port, and serves it on PORT 3000 by default. Detailed setup and the concurrent alternative live in the [Install Guide](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/INSTALL-GUIDE.md).
|
|
68
|
+
|
|
69
|
+
### Docker
|
|
35
70
|
|
|
36
|
-
|
|
71
|
+
The container image `vc.maxkaya.com/maxpeterkaya/web-proxy:latest` runs web-proxy on its own. Wire it into a compose stack to log a sibling service.
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
services:
|
|
75
|
+
proxy:
|
|
76
|
+
image: vc.maxkaya.com/maxpeterkaya/web-proxy:latest
|
|
77
|
+
ports:
|
|
78
|
+
- "3000:3000"
|
|
79
|
+
environment:
|
|
80
|
+
PROXY_TARGETS: app:3001
|
|
81
|
+
|
|
82
|
+
app:
|
|
83
|
+
image: your-app:latest
|
|
84
|
+
expose:
|
|
85
|
+
- "3001"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Replace `your-app` with your own image and match the service name and port to your stack.
|
|
89
|
+
|
|
90
|
+
### Binary
|
|
91
|
+
|
|
92
|
+
Release binaries are published for Linux, macOS, FreeBSD, OpenBSD, and NetBSD across amd64, arm, and arm64. The Install Guide covers every way to obtain web-proxy.
|
|
93
|
+
|
|
94
|
+
## Run modes
|
|
95
|
+
|
|
96
|
+
| Mode | Invocation | What it does |
|
|
97
|
+
| --- | --- | --- |
|
|
98
|
+
| Managed app | `web-proxy -app` | Starts your application from package.json and proxies public traffic to it |
|
|
99
|
+
| Reverse proxy | `web-proxy` | Forwards PORT to an upstream application on PROXY_PORT |
|
|
100
|
+
| Load balancer | `web-proxy` with `PROXY_TARGETS` set | Distributes requests across upstreams that pass health checks |
|
|
101
|
+
| Static site | `web-proxy -static` | Serves the frontend build in `-static-dir` |
|
|
102
|
+
|
|
103
|
+
Container deployments can wrap an existing image as middleware inside the application container or as a separate proxy container. See the [container middleware](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/container-middleware) and [container proxy](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/container-proxy) examples for those setups.
|
|
104
|
+
|
|
105
|
+
## Configuration
|
|
106
|
+
|
|
107
|
+
web-proxy is configured through environment variables and honors a `.env` file in the working directory. Every variable has a default, so the proxy runs without any setup. The [Usage Guide](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/USAGE-GUIDE.md) contains the complete variable reference.
|
|
37
108
|
|
|
38
109
|
## Examples
|
|
39
110
|
|
|
40
111
|
- [Container middleware](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/container-middleware)
|
|
112
|
+
- [Container proxy](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/container-proxy)
|
|
113
|
+
- [Load balancer](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/load-balancer)
|
|
41
114
|
- [Static website](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/static-website)
|
|
42
115
|
- [Authentication](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/authentication)
|
|
43
|
-
- [Container proxy](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/container-proxy)
|
|
44
116
|
|
|
45
117
|
## Roadmap
|
|
46
118
|
|
|
47
|
-
These
|
|
119
|
+
These items are in no particular order.
|
|
48
120
|
|
|
49
|
-
- Install methods
|
|
50
|
-
- Install guide
|
|
51
|
-
- Usage guide
|
|
52
|
-
- Templates
|
|
53
121
|
- Screenshots
|
|
54
122
|
- Benchmarks
|
|
55
|
-
- Configurable logs
|
|
123
|
+
- Configurable logs
|
|
124
|
+
- Templates
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
web-proxy is released under the Apache License 2.0.
|
package/USAGE-GUIDE.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Usage Guide
|
|
2
|
+
|
|
3
|
+
This guide is the full reference for web-proxy. It covers every environment variable, every CLI flag, and the behavior behind each run mode. The README is a good starting point if you have not read it yet.
|
|
4
|
+
|
|
5
|
+
## Configuration basics
|
|
6
|
+
|
|
7
|
+
web-proxy reads configuration from environment variables. Variables can be set in the shell, in a container manifest, or in a `.env` file placed in the working directory. Every variable has a default, so the proxy works without any configuration.
|
|
8
|
+
|
|
9
|
+
A minimal `.env` file looks like this.
|
|
10
|
+
|
|
11
|
+
```dotenv
|
|
12
|
+
PORT=8080
|
|
13
|
+
AUTH_TYPE=basic
|
|
14
|
+
AUTH_USER=admin
|
|
15
|
+
AUTH_PASS=<hex sha256 of your password>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Modes are chosen with CLI flags. Everything else is an environment variable.
|
|
19
|
+
|
|
20
|
+
## Server
|
|
21
|
+
|
|
22
|
+
| Variable | Default | Description |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| `PORT` | `3000` | The port the proxy listens on for public traffic |
|
|
25
|
+
| `DOMAIN` | `localhost` | The brand name shown on the session login page |
|
|
26
|
+
|
|
27
|
+
## Proxying
|
|
28
|
+
|
|
29
|
+
By default web-proxy forwards every request to the single upstream defined by `PROXY_HOST` and `PROXY_PORT`. Setting `PROXY_TARGETS` switches it to load balancing across several upstreams.
|
|
30
|
+
|
|
31
|
+
| Variable | Default | Description |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| `PROXY_HOST` | `localhost` | The upstream host used when `PROXY_TARGETS` is unset |
|
|
34
|
+
| `PROXY_PORT` | `3001` | The upstream port used when `PROXY_TARGETS` is unset, and the port managed mode starts the app on |
|
|
35
|
+
| `PROXY_TARGETS` | unset | A comma separated list of `host:port` upstreams that enables load balancing |
|
|
36
|
+
|
|
37
|
+
Each target in `PROXY_TARGETS` must include a port. A target without a scheme is treated as `http://`.
|
|
38
|
+
|
|
39
|
+
## Load balancing and health checks
|
|
40
|
+
|
|
41
|
+
With several targets configured, web-proxy round robins requests across the targets that pass a TCP health check. Targets start unhealthy and leave rotation after the first failed check. When every target is down the proxy answers with 503.
|
|
42
|
+
|
|
43
|
+
| Variable | Default | Description |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `PROXY_HEALTHCHECK_ENABLED` | `true` | Runs TCP health checks and routes only to healthy targets |
|
|
46
|
+
| `PROXY_HEALTHCHECK_INTERVAL` | `10` | Seconds between health checks per target |
|
|
47
|
+
| `PROXY_HEALTHCHECK_TIMEOUT` | `3` | Seconds a connection attempt waits before the target counts as down |
|
|
48
|
+
|
|
49
|
+
Set `PROXY_HEALTHCHECK_ENABLED` to `false` to distribute across all targets unconditionally. The [load balancer example](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/load-balancer) demonstrates failover with two upstreams.
|
|
50
|
+
|
|
51
|
+
## Managed application mode
|
|
52
|
+
|
|
53
|
+
The `-app` flag makes web-proxy start your application itself. It reads the `start:web` script from package.json, or falls back to the `start` script, and runs that command. The app is then reachable only through the proxy.
|
|
54
|
+
|
|
55
|
+
| Flag | Default | Description |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| `-app` | `false` | Starts the web application from package.json |
|
|
58
|
+
| `-cmd` | unset | Overrides the start command instead of reading package.json |
|
|
59
|
+
| `-log` | `true` | Streams the application stdout into the proxy output |
|
|
60
|
+
|
|
61
|
+
The proxy listens on `PORT` and forwards to the app on `PROXY_PORT`. A NextJS start command that has no explicit port flag gets `-p` appended automatically, so `next start` runs on `PROXY_PORT`. Other frameworks must be told to listen on `PROXY_PORT` themselves. When `-log` is `false` the application stdout is suppressed, while stderr always passes through.
|
|
62
|
+
|
|
63
|
+
## Static files
|
|
64
|
+
|
|
65
|
+
The `-static` flag serves a frontend build instead of proxying.
|
|
66
|
+
|
|
67
|
+
| Flag | Default | Description |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `-static` | `false` | Serves static files at the root path |
|
|
70
|
+
| `-static-dir` | `dist` | The folder that is served in static mode |
|
|
71
|
+
|
|
72
|
+
The [static website example](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/static-website) shows a Dockerfile that builds a frontend and serves it through static mode.
|
|
73
|
+
|
|
74
|
+
## Authentication
|
|
75
|
+
|
|
76
|
+
| Variable | Default | Description |
|
|
77
|
+
| --- | --- | --- |
|
|
78
|
+
| `AUTH_TYPE` | `none` | One of `none`, `basic`, `bearer`, or `forms` |
|
|
79
|
+
| `AUTH_USER` | `admin` | The username for basic and forms auth |
|
|
80
|
+
| `AUTH_PASS` | random | The hex sha256 of the password for basic and forms auth |
|
|
81
|
+
| `AUTH_KEYS` | unset | Comma separated hex sha256 hashes accepted by bearer auth |
|
|
82
|
+
| `AUTH_SESSION_TTL` | `24h` | How long a forms session cookie lasts |
|
|
83
|
+
| `AUTH_FORM_TITLE` | `Sign in` | The heading on the forms login page |
|
|
84
|
+
| `AUTH_FORM_SUBTITLE` | `Enter your credentials to continue` | The tagline on the forms login page |
|
|
85
|
+
| `AUTH_FORM_COLOR` | `#6366f1` | The accent color used on the forms login page |
|
|
86
|
+
| `AUTH_FORM_TEMPLATE` | unset | A path to a custom `.gohtml` that overrides the embedded login template |
|
|
87
|
+
|
|
88
|
+
Passwords and bearer keys are stored as lowercase hex sha256 hashes. Generate one for a password with a standard tool on the shell.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
printf 'secret' | sha256sum
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Set `AUTH_PASS` to that output. When `AUTH_PASS` is left unset a random password is generated instead, so authentication always denies access until you configure one. The [authentication example](https://vc.maxkaya.com/maxpeterkaya/web-proxy/src/branch/main/examples/authentication) shows a container wired up with each auth type.
|
|
95
|
+
|
|
96
|
+
### basic
|
|
97
|
+
|
|
98
|
+
The client supplies the `AUTH_USER` and `AUTH_PASS` pair through standard HTTP basic auth. The password is hashed on every request and compared against `AUTH_PASS`.
|
|
99
|
+
|
|
100
|
+
### bearer
|
|
101
|
+
|
|
102
|
+
The client sends an API key in the Authorization header. The key is hashed and matched against `AUTH_KEYS`. When `AUTH_KEYS` is unset the single `AUTH_PASS` value is accepted. This type is suited to machine clients such as services and monitoring probes.
|
|
103
|
+
|
|
104
|
+
### forms
|
|
105
|
+
|
|
106
|
+
The proxy serves a login page for anything that is not authenticated. A successful login sets a signed session cookie that lasts for `AUTH_SESSION_TTL`. Sessions are verified on every request, and the login page can be restyled through the `AUTH_FORM_*` variables. Point `AUTH_FORM_TEMPLATE` at a custom `.gohtml` that redefines the `form` or `bootstrap` templates for full design control. The value `form` is accepted as an alias of `forms`.
|
|
107
|
+
|
|
108
|
+
## Blocking
|
|
109
|
+
|
|
110
|
+
Blocked requests never reach the upstream and receive a 402 response.
|
|
111
|
+
|
|
112
|
+
| Variable | Default | Description |
|
|
113
|
+
| --- | --- | --- |
|
|
114
|
+
| `BLOCK_USER_AGENTS` | unset | Comma separated user agents that are blocked with an exact match |
|
|
115
|
+
| `BLOCK_IPS` | unset | Comma separated client IPs that are blocked |
|
|
116
|
+
|
|
117
|
+
Client IPs come from the X-Forwarded-For header, matching the IP used in request logs.
|
|
118
|
+
|
|
119
|
+
## Request logs
|
|
120
|
+
|
|
121
|
+
Log entries are emitted as JSON on stderr. A successful request logs at info level and a failed one at error level with the same fields. Each entry includes the fields shown in the README, such as the request ID, latency, bytes, the upstream target, and the route or asset path. The application stdout in managed mode is plain text that passes through separately, so structured proxy logs stay valid JSON for ingestion by Grafana Alloy, Promtail, or any JSON collector.
|
package/bin/install.js
CHANGED
|
@@ -24,7 +24,7 @@ if (!assetName) {
|
|
|
24
24
|
process.exit(1);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const url = `https://vc.maxkaya.com/maxpeterkaya/
|
|
27
|
+
const url = `https://vc.maxkaya.com/maxpeterkaya/web-proxy/releases/download/latest/web-proxy_${assetName}`;
|
|
28
28
|
const destDir = path.join(__dirname);
|
|
29
29
|
const destFile = path.join(destDir, `${platform === "win32" ? "web-proxy.exe" : "web-proxy"}`);
|
|
30
30
|
|
package/bin/run.js
CHANGED
|
@@ -4,4 +4,5 @@ const path = require('path');
|
|
|
4
4
|
const binaryName = process.platform === 'win32' ? 'web-proxy.exe' : 'web-proxy';
|
|
5
5
|
const binaryPath = path.join(__dirname, binaryName);
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
spawnSync(binaryPath, args, {stdio: 'inherit'});
|
package/package.json
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{{define "bootstrap"}}
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="en" class="dark" data-theme="dark">
|
|
4
|
+
<head>
|
|
5
|
+
<title>{{.Title}}</title>
|
|
6
|
+
<meta charset="UTF-8"/>
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
|
9
|
+
<meta name="color-scheme" content="dark"/>
|
|
10
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
11
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
12
|
+
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap"
|
|
13
|
+
rel="stylesheet">
|
|
14
|
+
<style>
|
|
15
|
+
:root {
|
|
16
|
+
--accent: {{.Accent}};
|
|
17
|
+
}
|
|
18
|
+
</style>
|
|
19
|
+
</head>
|
|
20
|
+
<body class='w-full h-full text-center font-["Ubuntu"]'>
|
|
21
|
+
<div class="min-h-screen bg-neutral-950">
|
|
22
|
+
{{template "form" .}}
|
|
23
|
+
</div>
|
|
24
|
+
</body>
|
|
25
|
+
</html>
|
|
26
|
+
{{end}}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{{ define "form"}}
|
|
2
|
+
<div class="flex min-h-screen items-center justify-center px-4 py-12">
|
|
3
|
+
<div class="w-full max-w-sm">
|
|
4
|
+
{{if .Brand}}
|
|
5
|
+
<div class="mb-6 text-center">
|
|
6
|
+
<span class="text-xl font-semibold tracking-tight" style="color: var(--accent)">{{.Brand}}</span>
|
|
7
|
+
</div>
|
|
8
|
+
{{end}}
|
|
9
|
+
<div class="rounded-2xl border border-white/10 bg-white/5 px-8 py-8 shadow-2xl shadow-black/40 backdrop-blur">
|
|
10
|
+
<h1 class="text-lg font-semibold text-white">{{.Title}}</h1>
|
|
11
|
+
{{if .Subtitle}}
|
|
12
|
+
<p class="mt-1 text-sm text-neutral-500">{{.Subtitle}}</p>
|
|
13
|
+
{{end}}
|
|
14
|
+
<form method="post" action="{{.Target}}" class="mt-6 space-y-4">
|
|
15
|
+
<input type="hidden" name="target" value="{{.Target}}"/>
|
|
16
|
+
<div>
|
|
17
|
+
<label for="username" class="block text-xs font-medium uppercase tracking-widest text-white/40">Username</label>
|
|
18
|
+
<input id="username" name="username" type="text" autocomplete="username" required
|
|
19
|
+
class="mt-1.5 w-full rounded-lg border border-white/10 bg-black/20 px-3 py-2 text-sm text-white placeholder-white/30 outline-none transition focus:border-[var(--accent)]"/>
|
|
20
|
+
</div>
|
|
21
|
+
<div>
|
|
22
|
+
<label for="password" class="block text-xs font-medium uppercase tracking-widest text-white/40">Password</label>
|
|
23
|
+
<input id="password" name="password" type="password" autocomplete="current-password" required
|
|
24
|
+
class="mt-1.5 w-full rounded-lg border border-white/10 bg-black/20 px-3 py-2 text-sm text-white placeholder-white/30 outline-none transition focus:border-[var(--accent)]"/>
|
|
25
|
+
</div>
|
|
26
|
+
{{if .Error}}
|
|
27
|
+
<p class="mt-4 rounded-lg px-3 py-2 text-sm font-medium text-red-300">{{.Error}}</p>
|
|
28
|
+
{{end}}
|
|
29
|
+
<button type="submit"
|
|
30
|
+
class="mt-2 w-full rounded-lg px-3 py-2 text-sm font-semibold text-white transition hover:brightness-110 active:scale-[0.99]"
|
|
31
|
+
style="background: var(--accent)">
|
|
32
|
+
Continue
|
|
33
|
+
</button>
|
|
34
|
+
</form>
|
|
35
|
+
</div>
|
|
36
|
+
<p class="mt-6 text-center text-xs text-white/25">Protected by <a
|
|
37
|
+
href="https://vc.maxkaya.com/maxpeterkaya/web-proxy" target="_blank" class="hover:opacity-50"
|
|
38
|
+
style="color: var(--accent)">web-proxy</a></p>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
{{end}}
|