Skip to content

Releases: yusing/godoxy

v0.8.0

04 Jan 20:10
Compare
Choose a tag to compare

GoDoxy v0.8 changes:

Breaking changes

  • Removed redirect_to_https in config.yml, superseded by redirectHTTP as an entrypoint middleware

  • New notification config format, support webhook notification, support multiple notification providers

    old

    providers:
      notification:
        gotify:
          url: ...
          token: ...

    new

    providers:
      notification:
        - name: gotify
          provider: gotify
          url: ...
          token: ...
        - name: discord
          provider: webhook
          url: https://discord.com/api/webhooks/...
          template: discord

    Webhook notification fields:

    Field Description Required Allowed values
    name name of the provider Yes
    provider Yes webhook
    url webhook URL Yes Full URL
    template webhook template No empty, discord
    token webhook token No
    payload webhook payload No (if template is used) valid json
    method webhook request method No GET POST PUT
    mime_type mime type No
    color_mode color mode No hex dec

    Available payload variables:

    Variable Description Format
    $title message title json string
    $message message in markdown format json string
    $fields extra fields in json format json object
    $color embed color by color_mode 0xff0000 (hex) or 16711680 (dec)

Non-breaking changes

  • services health notification now in markdown format like Uptime Kuma for both webhook and Gotify

    {6CF5D81A-C178-40BA-9441-408AC1FEABA9}
    {4E008AB5-A88F-4D71-8A31-2DD4E23D0D8A}

  • docker services now use docker container health status if possible, fallback to GoDoxy health check on failure / no docker health check, e.g.

    # docker compose
    services:
      app:
        ...
        container_name: app
        healthcheck:
          test: ["CMD-SHELL", "curl --fail http://localhost:8080 || exit 1"]
          interval: 5s

    Health check result will be equivalent to docker inspect --format='{{json .State.Health}}' app

  • proxy.<alias>.path_patterns fully support http.ServeMux patterns [METHOD ][HOST]/[PATH] (See https://pkg.go.dev/net/http#hdr-Patterns-ServeMux)

  • caching ACME private key in order to reuse ACME account, to prevent from ACME rate limit

  • WebUI config editor now validates for middleware compose files

  • New: fully support string as inline YAML for docker labels

    services:
      app:
        ...
        labels:
          # add '|' after colon ':' to treat it as string
          proxy.app: |
            scheme: http
            host: 10.0.0.254
            port: 80
            path_patterns:
              - GET /
              - POST /auth
            healthcheck:
              disabled: false
              path: /
              interval: 5s
          proxy.app1.healthcheck: |
            path: /ping
            use_get: true
          proxy.app1.load_balance: |
            link: app
            mode: ip_hash
  • New: support entrypoint middlewares (applied to all routes, before route middlewares)

    entrypoint:
      middlewares:
        - use: CIDRWhitelist
          allow:
            - "127.0.0.1"
            - "10.0.0.0/8"
            - "192.168.0.0/16"
          status: 403
          message: "Forbidden"
  • New: support exact host matching, i.e.

    # include file
    app1.domain.tld:
      host: 10.0.0.1
    
    # docker compose
    services:
      app1:
        ...
        proxy.aliases: app1.domain.tld

    will only match exactly app1.domain.tld
    match_domains in config will be ignored for this route

  • New: support host matching without a subdomain, i.e.

    app1:
      host: 10.0.0.1

    will now also match app1.tld

  • New: support x-properties (will be ignored, like in docker compose), useful with YAML anchor e.g.

    x-proxy: &proxy # this will be ignored in GoDoxy
      scheme: https
      healthcheck:
        disable: true
      middlewares:
        hideXForwarded:
        modifyRequest:
          setHeaders:
            Host: $req_host
    
    api.openai.com:
      <<: *proxy # extends from x-proxy
      host: api.openai.com
    api.groq.com:
      <<: *proxy # extends from x-proxy
      host: api.groq.com
  • new middleware name aliases:

    • modifyRequest = request
    • modifyResponse = response
  • New: support $ variables in request and response middlewares (like nginx config)

    • $req_method: request http method
    • $req_scheme: request URL scheme (http/https)
    • $req_host: request host without port
    • $req_port: request port
    • $req_addr: request host with port (if present)
    • $req_path: request URL path
    • $req_query: raw query string
    • $req_url: full request URL
    • $req_uri: request URI (encoded path?query)
    • $req_content_type: request Content-Type header
    • $req_content_length: length of request body (if present)
    • $remote_addr: client's remote address (may changed by middlewares like RealIP and CloudflareRealIP)
    • $remote_host: client's remote ip parse from $remote_addr
    • $remote_port: client's remote port parse from $remote_addr (may be empty)
    • $resp_content_type: response Content-Type header
    • $resp_content_length: length response body
    • $status_code: response status code
    • $upstream_name: upstream server name (alias)
    • $upstream_scheme: upstream server scheme
    • $upstream_host: upstream server host
    • $upstream_port: upstream server port
    • $upstream_addr: upstream server address with port (if present)
    • $upstream_url: full upstream server URL
    • $header(name): get request header by name
    • $resp_header(name): get response header by name
    • $arg(name): get URL query parameter by name
  • New: Access Logging (entrypoint and per route), i.e.

    mount logs directory before setting this

    # config.yml
    entrypoint:
      access_log:
        format: json # common, combined, json
        path: /app/logs/access.json.log
        filters:
          cidr:
            negative: true # no log for local requests
            values:
              - 127.0.0.1/32
              - 172.0.0.0/8
              - 192.168.0.0/16
              - 10.0.0.0/16
        fields:
          headers:
            default: drop # drop app headers in log
            config: # keep only these
              X-Real-Ip: keep
              CF-Connecting-Ip: keep
              X-Forwarded-For: keep
    
    # include file
    # same as above but under route config
    app:
      access_log:
        format: json # common, combined, json
        ...
    
    # docker labels
    labels:
      proxy.app.access_log: |
        format: json
        path: /app/logs/access.json.log
        filters:
          cidr:
            negative: true
            values:
              - 127.0.0.1/32
              - 172.0.0.0/8
              - 192.168.0.0/16
              - 10.0.0.0/16

    To integrate with goaccess, currently need to use caddy as a file web server. Below should work with combined log format.

    # compose.yml
    services:
    app:
      image: reg.6uo.me/yusing/goproxy
      ...
      volumes:
        ...
        - ./logs:/app/logs
    caddy:
      image: caddy
      restart: always
      labels:
        proxy.goaccess.port: 80
        proxy.goaccess.middlewares.request.set_headers.Host: goaccess
      volumes:
        - ./Caddyfile:/etc/caddy/Caddyfile:ro
        - ./logs:/var/www/goaccess:ro
      depends_on:
        - goaccess
    goaccess:
      image: hectorm/goaccess:latest
      restart: always
      volumes:
        - ./logs:/srv/logs
      command: > # for combined format
        /srv/logs/access.log
        -o /srv/logs/report.html
        -j 4 # 4 threads
        --real-time-html
        --ws-url=<your goaccess url>:443 # i.e. goaccess.my.app:443
        --log-format='%v %h %^[%d:%t %^] "%r" %s %b "%R" "%u"'

    Caddyfile

    {
        auto_https off
    }
    
    goaccess:80 {
        @websockets {
            header Connection *Upgrade
            header Upgrade websocket
        }
    
        handle @websockets {
            reverse_proxy goaccess:7890
        }
    
        root * /var/www/goaccess
        file_server
        rewrite / /report.html
    }

Fixes

  • duplicated notification after config reload
  • timeout was defaulted to 0 in some cases causing health check to fail
  • redirectHTTP middleware may not work on non standard http port
  • various other small bugs
  • realIP and cloudflareRealIP middlewares
  • prometheus metrics gone after a single route reload
  • WebUI app links now works when match_domains is not set
  • WebUI config editor now display validation errors properly
  • upgraded dependencies to the latest

v0.7.7

10 Nov 22:57
Compare
Choose a tag to compare

What's changed

Changed

  • logging: moved API request log to debug level (introduced in 0.7.6)
  • code: simplified label parsing implementation, more readable, maintainable and also faster
  • code: removed unnecessary mutex and mutex locking
  • healthcheck: health checker now send an user agent indicating GoDoxy and its version

Fixed

  • logging: fixed missing error subject on validation error for routes from include file
  • bug: panic on invalid map value in docker labels
  • bug: healthcheck.disable not being respected
  • bug: incorrect health check returned unhealthy even if it isn't in some scenerios
  • bug: health checker looking for incorrect address for stream routes
  • webui: fixed statistics not loading property

v0.7.6

09 Nov 23:08
Compare
Choose a tag to compare

What's changed

New

Changed

  • Update setup instructions by @codekoala in #30
  • Updated to go1.23.3

Fixed

  • ModifyRequest middleware set_header not working properly for Host header
  • CIDRAllowList middlewares may share there IP cache map between each other

Full Changelog: 0.7.5...0.7.6

v0.7.5

03 Nov 19:53
Compare
Choose a tag to compare

What's changed

New

  • Default app categories detected from alias and docker image name d89d97b
  • Option in config.yml to disable it cf1ecbc

Changed

  • Default config added inside docker image c6a9a81
  • Rebrand as GoDoxy
    • changed env prefix from GOPROXY to GODOXY (old prefix will still work) 99e43fe f5cf716
    • everywhere else that does not break stuff
  • WebUI / API Authentication will be disabled by default if JWT secret is not set or empty b63ebfc

Fixed

v0.7.4

03 Nov 02:17
Compare
Choose a tag to compare

What's changed

New:

Changed:

  • API server is now protected with rate limiter

Fixed:

  • Extra dot in app URLs on WebUI dashboard (introduced in v0.7.3)

v0.7.3

02 Nov 22:27
Compare
Choose a tag to compare

Fixed /stats/ws websocket endpoint error when no match_domains configured 3bf5205

v0.7.2

01 Nov 23:20
Compare
Choose a tag to compare

What's changed

  • Performance improvement for HTTP routes:
    • ~ 3% when match_domains is not used
    • ~ 60% when match_domains is used
  • Fixed API JSON string response quote not escaping

v0.7.1

01 Nov 19:45
Compare
Choose a tag to compare

What's changed

New

  • GOPROXY_API_JWT_TOKEN_TTL: control JWT token time-to-live

Changed

  • Moved environment variables from docker compose to .env.example
  • Updated compose.example.yml

Fixed

  • Incorrect behaviors for ls-* commands
  • several typos

Full Changelog: 0.7.0...0.7.1

v0.7

30 Oct 19:41
Compare
Choose a tag to compare

What's changed

New

  • Health status monitoring feature
    • status and uptime on dashboard
    app:
      healthcheck:
        disabled: false # default false
        path: "" # default empty
        use_get: false # use GET instead of HEAD, default false
        interval: 5s # default 5s
        timeout: 5s # default 5s
  • Gotify support: send notification when service health status changed
    # under config.yml -> providers section
    providers:
      include:
        ...
      docker:
        ...
      notification:
       gotify:
          url: https://gotify.domain.tld
          token: abcdef.12345

Breaking Changes

  • webui: now WebUI and APIs require authentication
  • environment variables: new, required
    • GOPROXY_API_JWT_SECRET: base64 string of jwt secret, generate with openssl rand -base64 32
    • GOPROXY_API_USER: login username (defaults to admin)
    • GOPROXY_API_PASSWORD: login password (defaults to password)

Non-breaking Changes

  • docker: proxy.aliases is now optional, proxy.<alias>.<field> will work without it
  • middleware: ip_hash load balancer now support realIP middleware
  • logging: migrated from sirupsen/logrus to rs/zerolog
  • logging: better output and error formatting
  • logging: suggest "Do you mean ____?" on invalid options
  • code: introduced new task module to manage context and tasks to ensure resources are released and goroutines are stopped correctly
  • code: rewritten error module
  • code: rewritten config and docker reload handling with event queue

Fixed

  • loadbalancer: ip_hash incorrect behavior
  • loadbalancer: services with same alias will no longer cause conflict
  • idlewatcher: load-balanced routes now works with idle_timeout
  • reload: include file reload does not show in log
  • reload: proxy url turns into 127.0.0.1:80 after reload
  • reload: streams stucked forever on stop
  • reload: removed routes persist on config reload
  • webui: loadbalanced routes no longer show up in dashboard (i.e. only loadbalancer nginx is shown but not nginx-1, nginx-2, ... )
  • bug: shutdown stuck causing graceful shutdown to fail
  • bug: various bugs that causing nil deference panic
  • bug: memory leak for stream routes
  • bug: route not removed on container destroy
  • bug: crash on invalid middleware options

Full Changelog: 0.6.4-1...0.7.0

v0.6.4

11 Oct 02:12
Compare
Choose a tag to compare

What's changed

  • Fixed $DOCKER_HOST behaviors in edge cases
  • Changed now proxy host defaults to <containerIP>:<containerPort> instead of localhost:<hostPort> for local docker provider, this does not affect your current configurations