new simpler setup method, readme and doc update

This commit is contained in:
yusing 2024-09-23 22:10:13 +08:00
parent 109c2460fa
commit 79ae26f1b5
12 changed files with 231 additions and 113 deletions

View file

@ -19,6 +19,9 @@ COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /src/go-proxy /app/ COPY --from=builder /src/go-proxy /app/
COPY schema/ /app/schema COPY schema/ /app/schema
# copy cert required for setup
COPY --from=builder /etc/ssl/certs /etc/ssl/certs
ENV DOCKER_HOST=unix:///var/run/docker.sock ENV DOCKER_HOST=unix:///var/run/docker.sock
ENV GOPROXY_DEBUG=0 ENV GOPROXY_DEBUG=0

View file

@ -32,11 +32,12 @@ A lightweight, easy-to-use, and [performant](docs/benchmark_result.md) reverse p
- Easy to use - Easy to use
- Effortless configuration - Effortless configuration
- Simple multi-node setup
- Error messages is clear and detailed, easy troubleshooting - Error messages is clear and detailed, easy troubleshooting
- Auto certificate obtaining and renewal (See [Supported DNS Challenge Providers](docs/dns_providers.md)) - Auto certificate obtaining and renewal (See [Supported DNS Challenge Providers](docs/dns_providers.md))
- Auto configuration for docker containers - Auto configuration for docker containers
- Auto hot-reload on container state / config file changes - Auto hot-reload on container state / config file changes
- Stop containers on idle, wake it up on traffic _(optional, see [showcase](#idlesleeper))_ - **idlesleeper**: stop containers on idle, wake it up on traffic _(optional, see [showcase](#idlesleeper))_
- HTTP(s) reserve proxy - HTTP(s) reserve proxy
- TCP and UDP port forwarding - TCP and UDP port forwarding
- Web UI for configuration and monitoring (See [screenshots](https://github.com/yusing/go-proxy-frontend?tab=readme-ov-file#screenshots)) - Web UI for configuration and monitoring (See [screenshots](https://github.com/yusing/go-proxy-frontend?tab=readme-ov-file#screenshots))
@ -48,18 +49,23 @@ A lightweight, easy-to-use, and [performant](docs/benchmark_result.md) reverse p
### Setup ### Setup
1. Setup DNS Records, e.g. 1. Pull docker image `docker pull ghcr.io/yusing/go-proxy:latest`
- A Record: `*.y.z` -> `10.0.10.1` 2. Create new directory, `cd` into it, then run setup
- AAAA Record: `*.y.z` -> `::ffff:a00:a01`
2. Setup `go-proxy` [See here](docs/docker.md) `docker run --rm -v .:/setup ghcr.io/yusing/go-proxy /app/go-proxy setup`
3. Setup `docker-socket-proxy` (see [example](docs/docker_socket_proxy.md) other machine that is running docker (if any) 3. Setup DNS Records point to machine which runs `go-proxy`, e.g.
4. Configure `go-proxy` - A Record: `*.y.z` -> `10.0.10.1`
- with text editor (e.g. Visual Studio Code) - AAAA Record: `*.y.z` -> `::ffff:a00:a01`
- or with web config editor via `http://gp.y.z`
4. Setup `docker-socket-proxy` other docker nodes _(if any)_ (see [example](docs/docker_socket_proxy.md)) and then them inside `config.yml`
5. Done. You may now do some extra configuration
- With text editor (e.g. Visual Studio Code)
- With Web UI via `gp.y.z`
- For more info, [See docker.md](docs/docker.md)
[🔼Back to top](#table-of-content) [🔼Back to top](#table-of-content)

View file

@ -15,14 +15,14 @@
# options: # options:
# - auth_token: c1234565789-abcdefghijklmnopqrst # your zone API token # - auth_token: c1234565789-abcdefghijklmnopqrst # your zone API token
# 3. other providers, check readme for more # 3. other providers, check docs/dns_providers.md for more
providers: providers:
include: # include:
- providers.yml # config/providers.yml # - providers.yml # config/providers.yml
# add some more below if you want # # add some more below if you want
# - file1.yml # config/file_1.yml # - file1.yml # config/file_1.yml
# - file2.yml # - file2.yml
docker: docker:
# for value format, see https://docs.docker.com/reference/cli/dockerd/ # for value format, see https://docs.docker.com/reference/cli/dockerd/
# $DOCKER_HOST implies unix:///var/run/docker.sock by default # $DOCKER_HOST implies unix:///var/run/docker.sock by default
@ -30,8 +30,7 @@ providers:
# add more docker providers if needed # add more docker providers if needed
# remote-1: tcp://10.0.2.1:2375 # remote-1: tcp://10.0.2.1:2375
# remote-2: ssh://root:1234@10.0.2.2 # remote-2: ssh://root:1234@10.0.2.2
# Fixed options (optional, non hot-reloadable) # Fixed options (optional, non hot-reloadable)
# timeout_shutdown: 5 # timeout_shutdown: 5
# redirect_to_https: false # redirect_to_https: false # redirect http requests to https (if enabled)

View file

@ -11,42 +11,70 @@
## Cloudflare ## Cloudflare
```yaml
autocert:
provider: cloudflare
options:
auth_token:
```
`auth_token` your zone API token `auth_token` your zone API token
Follow [this guide](https://cloudkul.com/blog/automcatic-renew-and-generate-ssl-on-your-website-using-lego-client/) to create a new token with `Zone.DNS` read and edit permissions Follow [this guide](https://cloudkul.com/blog/automcatic-renew-and-generate-ssl-on-your-website-using-lego-client/) to create a new token with `Zone.DNS` read and edit permissions
## CloudDNS ## CloudDNS
- `client_id` ```yaml
autocert:
- `email` provider: clouddns
options:
- `password` client_id:
email:
password:
```
## DuckDNS ## DuckDNS
- `token`: DuckDNS Token ```yaml
autocert:
provider: duckdns
options:
token:
```
Tested by [earvingad](https://github.com/earvingad) Tested by [earvingad](https://github.com/earvingad)
## OVHCloud ## OVHCloud
```yaml
autocert:
provider: ovh
options:
api_endpoint:
application_key:
application_secret:
consumer_key:
oauth2_config:
client_id:
client_secret:
```
_Note, `application_key` and `oauth2_config` **CANNOT** be used together_ _Note, `application_key` and `oauth2_config` **CANNOT** be used together_
- `api_endpoint`: Endpoint URL, or one of - `api_endpoint`: Endpoint URL, or one of
- `ovh-eu`, - `ovh-eu`,
- `ovh-ca`, - `ovh-ca`,
- `ovh-us`, - `ovh-us`,
- `kimsufi-eu`, - `kimsufi-eu`,
- `kimsufi-ca`, - `kimsufi-ca`,
- `soyoustart-eu`, - `soyoustart-eu`,
- `soyoustart-ca` - `soyoustart-ca`
- `application_secret` - `application_secret`
- `application_key` - `application_key`
- `consumer_key` - `consumer_key`
- `oauth2_config`: Client ID and Client Secret - `oauth2_config`: Client ID and Client Secret
- `client_id` - `client_id`
- `client_secret` - `client_secret`
## Implement other DNS providers ## Implement other DNS providers

View file

@ -6,7 +6,7 @@
- [Docker compose guide](#docker-compose-guide) - [Docker compose guide](#docker-compose-guide)
- [Table of content](#table-of-content) - [Table of content](#table-of-content)
- [Setup](#setup) - [Additional setup](#additional-setup)
- [Labels](#labels) - [Labels](#labels)
- [Syntax](#syntax) - [Syntax](#syntax)
- [Fields](#fields) - [Fields](#fields)
@ -16,34 +16,11 @@
- [Docker compose examples](#docker-compose-examples) - [Docker compose examples](#docker-compose-examples)
- [Services URLs for above examples](#services-urls-for-above-examples) - [Services URLs for above examples](#services-urls-for-above-examples)
## Setup ## Additional setup
1. Install `wget` if not already 1. Enable HTTPs _(optional)_
- Ubuntu based: `sudo apt install -y wget` Mount a folder to store obtained certs or to load existing cert
- Fedora based: `sudo yum install -y wget`
- Arch based: `sudo pacman -Sy wget`
2. Run setup script
`bash <(wget -qO- https://github.com/yusing/go-proxy/raw/main/setup-docker.sh)`
It will setup folder structure and required config files
3. Verify folder structure and then `cd go-proxy`
```plain
go-proxy
├── certs
├── compose.yml
└── config
├── config.yml
└── providers.yml
```
4. Enable HTTPs _(optional)_
Mount a folder (to store obtained certs) or (containing existing cert)
```yaml ```yaml
services: services:
@ -69,15 +46,16 @@
```yaml ```yaml
autocert: autocert:
provider: local
cert_path: /app/certs/cert.crt cert_path: /app/certs/cert.crt
key_path: /app/certs/priv.key key_path: /app/certs/priv.key
``` ```
5. Modify `compose.yml` to fit your needs 2. Modify `compose.yml` to fit your needs
6. Run `docker compose up -d` to start the container 3. Run `docker compose up -d` to start the container
7. Navigate to Web panel `http://gp.yourdomain.com` or use **Visual Studio Code (provides schema check)** to edit proxy config 4. Navigate to Web panel `http://gp.yourdomain.com` or use **Visual Studio Code (provides schema check)** to edit proxy config
[🔼Back to top](#table-of-content) [🔼Back to top](#table-of-content)
@ -100,16 +78,16 @@
### Fields ### Fields
| Field | Description | Default | Allowed Values / Syntax | | Field | Description | Default | Allowed Values / Syntax |
| --------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | --------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scheme` | proxy protocol | <ul><li>`http` for numeric port</li><li>`tcp` for `x:y` port</li></ul> | `http`, `https`, `tcp`, `udp` | | `scheme` | proxy protocol | <ul><li>`http` for numeric port</li><li>`tcp` for `x:y` port</li></ul> | `http`, `https`, `tcp`, `udp` |
| `host` | proxy host | <ul><li>Docker: docker client IP / hostname </li><li>File: `localhost`</li></ul> | IP address, hostname | | `host` | proxy host | <ul><li>Docker: docker client IP / hostname </li><li>File: `localhost`</li></ul> | IP address, hostname |
| `port` | proxy port **(http/s)** | first port returned from docker | number in range of `1 - 65535` | | `port` | proxy port **(http/s)** | first port returned from docker | number in range of `1 - 65535` |
| `port` **(required)** | proxy port **(tcp/udp)** | N/A | `x:y` <br><ul><li>**x**: port for `go-proxy` to listen on.<br>**x** can be 0, which means listen on a random port</li><li>**y**: port or [_service name_](../src/common/constants.go#L55) of target container</li></ul> | | `port` | proxy port **(tcp/udp)** | `0:first_port` | `x:y` <br><ul><li>**x**: port for `go-proxy` to listen on.<br>**x** can be 0, which means listen on a random port</li><li>**y**: port or [_service name_](../src/common/constants.go#L55) of target container</li></ul> |
| `no_tls_verify` | whether skip tls verify **(https only)** | `false` | boolean | | `no_tls_verify` | whether skip tls verify **(https only)** | `false` | boolean |
| `path_patterns` | proxy path patterns **(http/s only)**<br> only requests that matched a pattern will be proxied | empty **(proxy all requests)** | yaml style list[<sup>1</sup>](#list-example) of ([path patterns](https://pkg.go.dev/net/http#hdr-Patterns-ServeMux)) | | `path_patterns` | proxy path patterns **(http/s only)**<br> only requests that matched a pattern will be proxied | `/` **(proxy all requests)** | yaml style list[<sup>1</sup>](#list-example) of ([path patterns](https://pkg.go.dev/net/http#hdr-Patterns-ServeMux)) |
| `set_headers` | header to set **(http/s only)** | empty | yaml style key-value mapping[<sup>2</sup>](#key-value-mapping-example) of header-value pairs | | `set_headers` | header to set **(http/s only)** | empty | yaml style key-value mapping[<sup>2</sup>](#key-value-mapping-example) of header-value pairs |
| `hide_headers` | header to hide **(http/s only)** | empty | yaml style list[<sup>1</sup>](#list-example) of headers | | `hide_headers` | header to hide **(http/s only)** | empty | yaml style list[<sup>1</sup>](#list-example) of headers |
[🔼Back to top](#table-of-content) [🔼Back to top](#table-of-content)

View file

@ -23,7 +23,7 @@ docker-proxy:
ports: ports:
- 2375:2375 - 2375:2375
# or more secure # or more secure
- <machine_ip>:2375:2375 - <machine_private_ip>:2375:2375
``` ```
```yml ```yml

View file

@ -1,14 +0,0 @@
#!/bin/sh
set -e
if [ -z "$BRANCH" ]; then
BRANCH="v0.5"
fi
BASE_URL="https://github.com/yusing/go-proxy/raw/${BRANCH}"
mkdir -p go-proxy
cd go-proxy
mkdir -p config
mkdir -p certs
[ -f compose.yml ] || wget -cO - ${BASE_URL}/compose.example.yml > compose.yml
[ -f config/config.yml ] || wget -cO - ${BASE_URL}/config.example.yml > config/config.yml
[ -f config/providers.yml ] || touch config/providers.yml

View file

@ -13,6 +13,7 @@ type Args struct {
const ( const (
CommandStart = "" CommandStart = ""
CommandSetup = "setup"
CommandValidate = "validate" CommandValidate = "validate"
CommandListConfigs = "ls-config" CommandListConfigs = "ls-config"
CommandListRoutes = "ls-routes" CommandListRoutes = "ls-routes"
@ -23,6 +24,7 @@ const (
var ValidCommands = []string{ var ValidCommands = []string{
CommandStart, CommandStart,
CommandSetup,
CommandValidate, CommandValidate,
CommandListConfigs, CommandListConfigs,
CommandListRoutes, CommandListRoutes,

View file

@ -10,29 +10,24 @@ const (
KeepAlive = 5 * time.Second KeepAlive = 5 * time.Second
) )
const (
ProviderKind_Docker = "docker"
ProviderKind_File = "file"
)
// file, folder structure // file, folder structure
const ( const (
ConfigBasePath = "config/" ConfigBasePath = "config"
ConfigFileName = "config.yml" ConfigFileName = "config.yml"
ConfigPath = ConfigBasePath + ConfigFileName ConfigExampleFileName = "config.example.yml"
ConfigPath = ConfigBasePath + "/" + ConfigFileName
) )
const ( const (
TemplatesBasePath = "templates/" SchemaBasePath = "schema"
PanelTemplatePath = TemplatesBasePath + "panel/index.html" ConfigSchemaPath = SchemaBasePath + "/config.schema.json"
ConfigEditorTemplatePath = TemplatesBasePath + "config_editor/index.html" FileProviderSchemaPath = SchemaBasePath + "/providers.schema.json"
) )
const ( const (
SchemaBasePath = "schema/" ComposeFileName = "compose.yml"
ConfigSchemaPath = SchemaBasePath + "config.schema.json" ComposeExampleFileName = "compose.example.yml"
FileProviderSchemaPath = SchemaBasePath + "providers.schema.json"
) )
const DockerHostFromEnv = "$DOCKER_HOST" const DockerHostFromEnv = "$DOCKER_HOST"

View file

@ -7,18 +7,18 @@ import (
) )
var ( var (
NoSchemaValidation = getEnvBool("GOPROXY_NO_SCHEMA_VALIDATION") NoSchemaValidation = GetEnvBool("GOPROXY_NO_SCHEMA_VALIDATION")
IsDebug = getEnvBool("GOPROXY_DEBUG") IsDebug = GetEnvBool("GOPROXY_DEBUG")
ProxyHTTPAddr = getEnv("GOPROXY_HTTP_ADDR", ":80") ProxyHTTPAddr = GetEnv("GOPROXY_HTTP_ADDR", ":80")
ProxyHTTPSAddr = getEnv("GOPROXY_HTTPS_ADDR", ":443") ProxyHTTPSAddr = GetEnv("GOPROXY_HTTPS_ADDR", ":443")
APIHTTPAddr = getEnv("GOPROXY_API_ADDR", "127.0.0.1:8888") APIHTTPAddr = GetEnv("GOPROXY_API_ADDR", "127.0.0.1:8888")
) )
func getEnvBool(key string) bool { func GetEnvBool(key string) bool {
return U.ParseBool(os.Getenv(key)) return U.ParseBool(os.Getenv(key))
} }
func getEnv(key string, defaultValue string) string { func GetEnv(key string, defaultValue string) string {
value, ok := os.LookupEnv(key) value, ok := os.LookupEnv(key)
if !ok { if !ok {
value = defaultValue value = defaultValue

View file

@ -30,6 +30,12 @@ import (
func main() { func main() {
args := common.GetArgs() args := common.GetArgs()
if args.Command == common.CommandSetup {
Setup()
return
}
l := logrus.WithField("module", "main") l := logrus.WithField("module", "main")
onShutdown := F.NewSlice[func()]() onShutdown := F.NewSlice[func()]()

115
src/setup.go Normal file
View file

@ -0,0 +1,115 @@
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"path"
. "github.com/yusing/go-proxy/common"
)
var branch = GetEnv("GOPROXY_BRANCH", "v0.5")
var baseUrl = fmt.Sprintf("https://github.com/yusing/go-proxy/raw/%s", branch)
var requiredConfigs = []Config{
{ConfigBasePath, true, false, ""},
{ComposeFileName, false, true, ComposeExampleFileName},
{path.Join(ConfigBasePath, ConfigFileName), false, true, ConfigExampleFileName},
}
type Config struct {
Pathname string
IsDir bool
NeedDownload bool
DownloadFileName string
}
func Setup() {
log.Println("setting up go-proxy")
log.Println("branch:", branch)
os.Chdir("/setup")
for _, config := range requiredConfigs {
config.setup()
}
log.Println("done")
}
func (c *Config) setup() {
if c.IsDir {
mkdir(c.Pathname)
return
}
if !c.NeedDownload {
touch(c.Pathname)
return
}
fetch(c.DownloadFileName, c.Pathname)
}
func hasFileOrDir(path string) bool {
_, err := os.Stat(path)
return err == nil
}
func mkdir(pathname string) {
_, err := os.Stat(pathname)
if err != nil && os.IsNotExist(err) {
log.Printf("creating directory %q\n", pathname)
err := os.MkdirAll(pathname, 0o755)
if err != nil {
log.Fatalf("failed: %s\n", err)
}
return
}
if err != nil {
log.Fatalf("failed: %s\n", err)
}
}
func touch(pathname string) {
if hasFileOrDir(pathname) {
return
}
log.Printf("creating file %q\n", pathname)
_, err := os.Create(pathname)
if err != nil {
log.Fatalf("failed: %s\n", err)
}
}
func fetch(remoteFilename string, outFileName string) {
if hasFileOrDir(outFileName) {
return
}
log.Printf("downloading %q\n", remoteFilename)
url, err := url.JoinPath(baseUrl, remoteFilename)
if err != nil {
log.Fatalf("unexpected error: %s\n", err)
}
resp, err := http.Get(url)
if err != nil {
log.Fatalf("http request failed: %s\n", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("error reading response body: %s\n", err)
}
err = os.WriteFile(outFileName, body, 0o644)
if err != nil {
log.Fatalf("failed to write to file: %s\n", err)
}
log.Printf("downloaded %q\n", outFileName)
}