go-proxy
go-proxy copied to clipboard
Easy to use reverse proxy with docker integration
go-proxy
A simple auto docker reverse proxy for home use. Written in Go
In the examples domain x.y.z
is used, replace them with your domain
Table of content
- Table of content
- Key Points
- How to use
-
Tested Services
- HTTP/HTTPs Reverse Proxy
- TCP Proxy
- UDP Proxy
-
Command-line args
- Commands
- Use JSON Schema in VSCode
- Environment variables
-
Config File
- Fields
- Provider Kinds
- Provider File
- Supported DNS Challenge Providers
- Troubleshooting
- Benchmarks
- Known issues
- Memory usage
- Build it yourself
Key Points
-
Fast (See benchmarks)
-
Auto certificate obtaining and renewal (See Config File and Supported DNS Challenge Providers)
-
Auto detect reverse proxies from docker
-
Auto hot-reload on container
start
/die
/stop
or config file changes -
Custom proxy entries with
config.yml
and additional provider files -
Subdomain matching + Path matching (domain name doesn't matter)
-
HTTP(s) reverse proxy + TCP/UDP Proxy
-
HTTP(s) round robin load balance support (same subdomain and path across different hosts)
-
Web UI on port 8080 (http) and port 8443 (https)
-
a simple panel to see all reverse proxies and health
-
a config editor to edit config and provider files with validation
Validate and save file with Ctrl+S
-
🔼Back to top
How to use
-
Setup DNS Records to your machine's IP address
- A Record:
*.y.z
->10.0.10.1
- AAAA Record:
*.y.z
->::ffff:a00:a01
- A Record:
-
Start
go-proxy
by- Running from binary or as a system service
- Running as a docker container
-
Start editing config files
- with text editor (i.e. Visual Studio Code)
- or with web config editor by navigate to
http://ip:8080
🔼Back to top
Tested Services
HTTP/HTTPs Reverse Proxy
- Nginx
- Minio
- AdguardHome Dashboard
- etc.
TCP Proxy
- Minecraft server
- PostgreSQL
- MariaDB
UDP Proxy
- Adguardhome DNS
- Palworld Dedicated Server
🔼Back to top
Command-line args
go-proxy [command]
Commands
- empty: start proxy server
- validate: validate config and exit
- reload: trigger a force reload of config
Examples:
- Binary:
go-proxy reload
- Docker:
docker exec -it go-proxy /app/go-proxy reload
🔼Back to top
Use JSON Schema in VSCode
Copy .vscode/settings.example.json
to .vscode/settings.json
and modify to fit your needs
{
"yaml.schemas": {
"https://github.com/yusing/go-proxy/raw/main/schema/config.schema.json": [
"config.example.yml",
"config.yml"
],
"https://github.com/yusing/go-proxy/raw/main/schema/providers.schema.json": [
"providers.example.yml",
"*.providers.yml"
]
}
}
🔼Back to top
Environment variables
-
GOPROXY_DEBUG
: set to1
ortrue
to enable debug behaviors (i.e. output, etc.) -
GOPROXY_HOST_NETWORK
: (Docker only) set to1
whennetwork_mode: host
-
GOPROXY_NO_SCHEMA_VALIDATION
: disable schema validation on config load / reload (for testing new DNS Challenge providers)
🔼Back to top
Config File
See config.example.yml for more
Fields
-
autocert
: autocert configuration-
email
: ACME Email -
domains
: a list of domains for cert registration -
provider
: DNS Challenge provider, see Supported DNS Challenge Providers -
options
: provider specific options
-
-
providers
: reverse proxy providers configuration-
kind
: provider kind (string), see Provider Kinds -
value
: provider specific value
-
🔼Back to top
Provider Kinds
-
docker
: load reverse proxies from dockervalues:
-
FROM_ENV
: value from environment (DOCKER_HOST
) - full url to docker host (i.e.
tcp://host:2375
)
-
-
file
: load reverse proxies from provider filevalue: relative path of file to
config/
🔼Back to top
Provider File
Fields are same as docker labels starting from scheme
See providers.example.yml for examples
🔼Back to top
Supported DNS Challenge Providers
-
Cloudflare
-
auth_token
: your zone API token
Follow this guide to create a new token with
Zone.DNS
read and edit permissions -
-
CloudDNS
-
client_id
-
email
-
password
-
-
DuckDNS (thanks earvingad)
-
token
: DuckDNS Token
-
To add more provider support, see this
🔼Back to top
Troubleshooting
Q: How to fix when it shows "no matching route for subdomain <subdomain>"?
A: Make sure the container is running, and <subdomain> matches any container name / alias
🔼Back to top
Benchmarks
Benchmarked with wrk
connecting traefik/whoami
's /bench
endpoint
Remote benchmark (client running wrk and go-proxy
server are different devices)
-
Direct connection
root@yusing-pc:~# wrk -t 10 -c 200 -d 10s -H "Host: bench.6uo.me" --latency http://10.0.100.3:8003/bench Running 10s test @ http://10.0.100.3:8003/bench 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 94.75ms 199.92ms 1.68s 91.27% Req/Sec 4.24k 1.79k 18.79k 72.13% Latency Distribution 50% 1.14ms 75% 120.23ms 90% 245.63ms 99% 1.03s 423444 requests in 10.10s, 50.88MB read Socket errors: connect 0, read 0, write 0, timeout 29 Requests/sec: 41926.32 Transfer/sec: 5.04MB
-
With reverse proxy
root@yusing-pc:~# wrk -t 10 -c 200 -d 10s -H "Host: bench.6uo.me" --latency http://10.0.1.7/bench Running 10s test @ http://10.0.1.7/bench 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 79.35ms 169.79ms 1.69s 92.55% Req/Sec 4.27k 1.90k 19.61k 75.81% Latency Distribution 50% 1.12ms 75% 105.66ms 90% 200.22ms 99% 814.59ms 409836 requests in 10.10s, 49.25MB read Socket errors: connect 0, read 0, write 0, timeout 18 Requests/sec: 40581.61 Transfer/sec: 4.88MB
Local benchmark (client running wrk and go-proxy
server are under same proxmox host but different LXCs)
-
Direct connection
root@http-benchmark-client:~# wrk -t 10 -c 200 -d 10s --latency http://10.0.100.1/bench Running 10s test @ http://10.0.100.1/bench 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 434.08us 539.35us 8.76ms 85.28% Req/Sec 67.71k 6.31k 87.21k 71.20% Latency Distribution 50% 153.00us 75% 646.00us 90% 1.18ms 99% 2.38ms 6739591 requests in 10.01s, 809.85MB read Requests/sec: 673608.15 Transfer/sec: 80.94MB
-
With
go-proxy
reverse proxyroot@http-benchmark-client:~# wrk -t 10 -c 200 -d 10s -H "Host: bench.6uo.me" --latency http://10.0.1.7/bench Running 10s test @ http://10.0.1.7/bench 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 1.23ms 0.96ms 11.43ms 72.09% Req/Sec 17.48k 1.76k 21.48k 70.20% Latency Distribution 50% 0.98ms 75% 1.76ms 90% 2.54ms 99% 4.24ms 1739079 requests in 10.01s, 208.97MB read Requests/sec: 173779.44 Transfer/sec: 20.88MB
-
With
traefik-v3
root@traefik-benchmark:~# wrk -t10 -c200 -d10s -H "Host: benchmark.whoami" --latency http://127.0.0.1:8000/bench Running 10s test @ http://127.0.0.1:8000/bench 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 2.81ms 10.36ms 180.26ms 98.57% Req/Sec 11.35k 1.74k 13.76k 85.54% Latency Distribution 50% 1.59ms 75% 2.27ms 90% 3.17ms 99% 37.91ms 1125723 requests in 10.01s, 109.50MB read Requests/sec: 112499.59 Transfer/sec: 10.94MB
🔼Back to top
Known issues
- Cert "renewal" is actually obtaining a new cert instead of renewing the existing one
🔼Back to top
Memory usage
It takes ~15 MB for 50 proxy entries
🔼Back to top
Build it yourself
-
Install / Upgrade go (>=1.22) and
make
if not already -
Clear cache if you have built this before (go < 1.22) with
go clean -cache
-
get dependencies with
make get
-
build binary with
make build
-
start your container with
make up
(docker) orbin/go-proxy
(binary)
🔼Back to top