fresh install: connection refused #32

Closed
opened 2025-12-29 09:21:45 +01:00 by adam · 13 comments
Owner

Originally created by @perler on GitHub (Feb 3, 2025).

I followed the automatic setup instruction to the dot but get on https "connection refused", on http "forbidden". How do I enable logging to check what's going on?

Originally created by @perler on GitHub (Feb 3, 2025). I followed the automatic setup instruction to the dot but get on https "connection refused", on http "forbidden". How do I enable logging to check what's going on?
adam closed this issue 2025-12-29 09:21:45 +01:00
Author
Owner

@yusing commented on GitHub (Feb 3, 2025):

Hi, you can check the logs with docker compose logs. Please send the logs here so I can check on what happened. Remember to redact sensitive information tho.

@yusing commented on GitHub (Feb 3, 2025): Hi, you can check the logs with `docker compose logs`. Please send the logs here so I can check on what happened. Remember to redact sensitive information tho.
Author
Owner

@perler commented on GitHub (Feb 3, 2025):

hcr.io/yusing/go-proxy-frontend:latest looks good

▲ Next.js 15.1.6
   - Local:        http://localhost:3000
   - Network:      http://0.0.0.0:3000

 ✓ Starting...
 ✓ Ready in 310ms

ghcr.io/yusing/go-proxy:latest bring stuff like this:

02-03 17:43 ERR request error="no such route: b" method=GET remote=106.75.166.28:37290 url=/
02-03 17:43 ERR request error="no such route: b" method=GET remote=106.75.166.28:37496 url=/favicon.ico
02-03 17:43 ERR request error="no such route: a" method=GET remote=106.75.132.208:16886 url=/
02-03 17:43 ERR request error="no such route: a" method=GET remote=106.75.132.208:17162 url=/favicon.ico
02-03 17:43 ERR request error="no such route: b" method=GET remote=106.75.132.208:19596 url=/
02-03 17:43 ERR request error="no such route: b" method=GET remote=106.75.132.208:20326 url=/favicon.ico
02-03 17:46 ERR request error="no such route: a" method=GET remote=106.75.168.236:59198 url=/
02-03 17:46 ERR request error="no such route: a" method=GET remote=106.75.168.236:59582 url=/favicon.ico
02-03 17:49 ERR request error="no such route: www" method=GET remote=216.246.119.114:50704 url=/
02-03 17:49 ERR request error="no such route: www" method=GET remote=216.246.119.114:50704 url=/
@perler commented on GitHub (Feb 3, 2025): hcr.io/yusing/go-proxy-frontend:latest looks good ```` ▲ Next.js 15.1.6 - Local: http://localhost:3000 - Network: http://0.0.0.0:3000 ✓ Starting... ✓ Ready in 310ms ```` ghcr.io/yusing/go-proxy:latest bring stuff like this: ```` 02-03 17:43 ERR request error="no such route: b" method=GET remote=106.75.166.28:37290 url=/ 02-03 17:43 ERR request error="no such route: b" method=GET remote=106.75.166.28:37496 url=/favicon.ico 02-03 17:43 ERR request error="no such route: a" method=GET remote=106.75.132.208:16886 url=/ 02-03 17:43 ERR request error="no such route: a" method=GET remote=106.75.132.208:17162 url=/favicon.ico 02-03 17:43 ERR request error="no such route: b" method=GET remote=106.75.132.208:19596 url=/ 02-03 17:43 ERR request error="no such route: b" method=GET remote=106.75.132.208:20326 url=/favicon.ico 02-03 17:46 ERR request error="no such route: a" method=GET remote=106.75.168.236:59198 url=/ 02-03 17:46 ERR request error="no such route: a" method=GET remote=106.75.168.236:59582 url=/favicon.ico 02-03 17:49 ERR request error="no such route: www" method=GET remote=216.246.119.114:50704 url=/ 02-03 17:49 ERR request error="no such route: www" method=GET remote=216.246.119.114:50704 url=/ ````
Author
Owner

@yusing commented on GitHub (Feb 3, 2025):

What url did you get forbidden from? Are you trying to access WebUI? Also seems like someone is scanning your domain with a.domain.com, b.domain.com, etc.

Could you send me your compose.yml, as well as config/config.yml

@yusing commented on GitHub (Feb 3, 2025): What url did you get forbidden from? Are you trying to access WebUI? Also seems like someone is scanning your domain with a.domain.com, b.domain.com, etc. Could you send me your `compose.yml`, as well as `config/config.yml`
Author
Owner

@yusing commented on GitHub (Feb 3, 2025):

Personally I suggest you not to expose GoDoxy to the internet, should use VPN like tailscale or Wireguard.

@yusing commented on GitHub (Feb 3, 2025): Personally I suggest you not to expose GoDoxy to the internet, should use VPN like tailscale or Wireguard.
Author
Owner

@perler commented on GitHub (Feb 3, 2025):

domain is patsplanet.cc, I try to access the web ui on https://gp.patsplanet.cc/

I had some docker containers run previously on the host but meanwhile apt remove --purged docker and reainstalled it..

compose.yml

---
services:
  frontend:
    image: ghcr.io/yusing/go-proxy-frontend:latest
    container_name: godoxy-frontend
    restart: unless-stopped
    network_mode: host
    env_file: .env
    depends_on:
      - app
    # modify below to fit your needs
    labels:
      proxy.aliases: gp
      proxy.#1.port: 3000
      # proxy.#1.middlewares.cidr_whitelist.status: 403
      # proxy.#1.middlewares.cidr_whitelist.message: IP not allowed
      # proxy.#1.middlewares.cidr_whitelist.allow: |
      #     - 127.0.0.1
      #     - 10.0.0.0/8
      #     - 192.168.0.0/16
      #     - 172.16.0.0/12
  app:
    image: ghcr.io/yusing/go-proxy:latest
    container_name: godoxy
    restart: always
    network_mode: host
    env_file: .env
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./config:/app/config
      - ./error_pages:/app/error_pages

      # (Optional) choose one of below to enable https
      # 1. use existing certificate

      # - /path/to/certs/cert.crt:/app/certs/cert.crt
      # - /path/to/certs/priv.key:/app/certs/priv.key

      # 2. use autocert, certs will be stored in ./certs
      #    you can also use a docker volume to store it

      - ./certs:/app/certs

config.yml

# Autocert (choose one below and uncomment to enable)
#
# 1. use existing cert
#
# autocert:
#   provider: local
#
#   cert_path: certs/cert.crt         # optional, uncomment only if you need to change it
#   key_path: certs/priv.key          # optional, uncomment only if you need to change it
#
# 2. cloudflare
#
# autocert:
#   provider: cloudflare
#   email: abc@gmail.com                            # ACME Email
#   domains:                                        # a list of domains for cert registration
#     - "*.y.z"                                     # remember to use double quotes to surround wildcard domain
#   options:
#     auth_token: c1234565789-abcdefghijklmnopqrst  # your zone API token
#
# 3. other providers, check docs/dns_providers.md for more

entrypoint:
  middlewares:
    # this part blocks all non-LAN HTTP traffic
    # remove if you don't want this
    - use: CIDRWhitelist
      allow:
        - "127.0.0.1"
        - "10.0.0.0/8"
        - "172.16.0.0/12"
        - "192.168.0.0/16"
      status: 403
      message: "Forbidden"
    # end of CIDRWhitelist

    # this part redirects HTTP to HTTPS
    # remove if you don't want this
    - use: RedirectHTTP

  # access_log:
  #   buffer_size: 1024
  #   path: /var/log/example.log
  #   filters:
  #     status_codes:
  #       values:
  #         - 200-299
  #         - 101
  #     method:
  #       values:
  #         - GET
  #     host:
  #       values:
  #         - example.y.z
  #     headers:
  #       negative: true
  #       values:
  #         - foo=bar
  #         - baz
  #     cidr:
  #       values:
  #         - 192.168.10.0/24
  #   fields:
  #     headers:
  #       default: keep
  #       config:
  #         foo: redact
  #     query:
  #       default: drop
  #       config:
  #         foo: keep
  #     cookies:
  #       default: redact
  #       config:
  #         foo: keep

providers:
  # include files are standalone yaml files under `config/` directory
  #
  # include:
  #   - file1.yml
  #   - file2.yml

  docker:
    # $DOCKER_HOST implies environment variable `DOCKER_HOST` or unix:///var/run/docker.sock by default
    local: $DOCKER_HOST
    # explicit only mode
    # only containers with explicit aliases will be proxied
    # add "!" after provider name to enable explicit only mode
    #
    # local!: $DOCKER_HOST
    #
    # add more docker providers if needed
    # for value format, see https://docs.docker.com/reference/cli/dockerd/
    #
    # remote-1: tcp://10.0.2.1:2375
    # remote-2: ssh://root:1234@10.0.2.2

  # notification providers (notify when service health changes)
  #
  # notification:
  #   - name: gotify
  #     provider: gotify
  #     url: https://gotify.domain.tld
  #     token: abcd
  #   - name: discord
  #     provider: webhook
  #     url: https://discord.com/api/webhooks/...
  #     template: discord
  #     # payload: | # discord template implies the following
  #     #   {
  #     #     "embeds": [
  #     #       {
  #     #         "title": $title,
  #     #         "fields": $fields,
  #     #         "color": "$color"
  #     #       }
  #     #     ]
  #     #   }
# if match_domains not defined
# any host = alias+[any domain] will match
# i.e. https://app1.y.z       will match alias app1 for any domain y.z
#  but https://app1.node1.y.z will only match alias "app.node1"
#
# if match_domains defined
# only host = alias+[one of match_domains] will match
# i.e. match_domains = [node1.my.app, my.site]
# https://app1.my.app, https://app1.my.net, etc. will not match even if app1 exists
# only https://*.node1.my.app and https://*.my.site will match
#
#
# match_domains:
#   - my.site
#   - node1.my.app

# homepage config
homepage:
  # use default app categories detected from alias or docker image name
  use_default_categories: true

# Below are fixed options (non hot-reloadable)

# timeout for shutdown (in seconds)
timeout_shutdown: 5
@perler commented on GitHub (Feb 3, 2025): domain is patsplanet.cc, I try to access the web ui on https://gp.patsplanet.cc/ I had some docker containers run previously on the host but meanwhile ``apt remove --purge``d docker and reainstalled it.. compose.yml ```` --- services: frontend: image: ghcr.io/yusing/go-proxy-frontend:latest container_name: godoxy-frontend restart: unless-stopped network_mode: host env_file: .env depends_on: - app # modify below to fit your needs labels: proxy.aliases: gp proxy.#1.port: 3000 # proxy.#1.middlewares.cidr_whitelist.status: 403 # proxy.#1.middlewares.cidr_whitelist.message: IP not allowed # proxy.#1.middlewares.cidr_whitelist.allow: | # - 127.0.0.1 # - 10.0.0.0/8 # - 192.168.0.0/16 # - 172.16.0.0/12 app: image: ghcr.io/yusing/go-proxy:latest container_name: godoxy restart: always network_mode: host env_file: .env volumes: - /var/run/docker.sock:/var/run/docker.sock - ./config:/app/config - ./error_pages:/app/error_pages # (Optional) choose one of below to enable https # 1. use existing certificate # - /path/to/certs/cert.crt:/app/certs/cert.crt # - /path/to/certs/priv.key:/app/certs/priv.key # 2. use autocert, certs will be stored in ./certs # you can also use a docker volume to store it - ./certs:/app/certs ```` config.yml ```` # Autocert (choose one below and uncomment to enable) # # 1. use existing cert # # autocert: # provider: local # # cert_path: certs/cert.crt # optional, uncomment only if you need to change it # key_path: certs/priv.key # optional, uncomment only if you need to change it # # 2. cloudflare # # autocert: # provider: cloudflare # email: abc@gmail.com # ACME Email # domains: # a list of domains for cert registration # - "*.y.z" # remember to use double quotes to surround wildcard domain # options: # auth_token: c1234565789-abcdefghijklmnopqrst # your zone API token # # 3. other providers, check docs/dns_providers.md for more entrypoint: middlewares: # this part blocks all non-LAN HTTP traffic # remove if you don't want this - use: CIDRWhitelist allow: - "127.0.0.1" - "10.0.0.0/8" - "172.16.0.0/12" - "192.168.0.0/16" status: 403 message: "Forbidden" # end of CIDRWhitelist # this part redirects HTTP to HTTPS # remove if you don't want this - use: RedirectHTTP # access_log: # buffer_size: 1024 # path: /var/log/example.log # filters: # status_codes: # values: # - 200-299 # - 101 # method: # values: # - GET # host: # values: # - example.y.z # headers: # negative: true # values: # - foo=bar # - baz # cidr: # values: # - 192.168.10.0/24 # fields: # headers: # default: keep # config: # foo: redact # query: # default: drop # config: # foo: keep # cookies: # default: redact # config: # foo: keep providers: # include files are standalone yaml files under `config/` directory # # include: # - file1.yml # - file2.yml docker: # $DOCKER_HOST implies environment variable `DOCKER_HOST` or unix:///var/run/docker.sock by default local: $DOCKER_HOST # explicit only mode # only containers with explicit aliases will be proxied # add "!" after provider name to enable explicit only mode # # local!: $DOCKER_HOST # # add more docker providers if needed # for value format, see https://docs.docker.com/reference/cli/dockerd/ # # remote-1: tcp://10.0.2.1:2375 # remote-2: ssh://root:1234@10.0.2.2 # notification providers (notify when service health changes) # # notification: # - name: gotify # provider: gotify # url: https://gotify.domain.tld # token: abcd # - name: discord # provider: webhook # url: https://discord.com/api/webhooks/... # template: discord # # payload: | # discord template implies the following # # { # # "embeds": [ # # { # # "title": $title, # # "fields": $fields, # # "color": "$color" # # } # # ] # # } # if match_domains not defined # any host = alias+[any domain] will match # i.e. https://app1.y.z will match alias app1 for any domain y.z # but https://app1.node1.y.z will only match alias "app.node1" # # if match_domains defined # only host = alias+[one of match_domains] will match # i.e. match_domains = [node1.my.app, my.site] # https://app1.my.app, https://app1.my.net, etc. will not match even if app1 exists # only https://*.node1.my.app and https://*.my.site will match # # # match_domains: # - my.site # - node1.my.app # homepage config homepage: # use default app categories detected from alias or docker image name use_default_categories: true # Below are fixed options (non hot-reloadable) # timeout for shutdown (in seconds) timeout_shutdown: 5 ````
Author
Owner

@perler commented on GitHub (Feb 3, 2025):

Personally I suggest you not to expose GoDoxy to the internet, should use VPN like tailscale or Wireguard.

sure, will do later, when I have this running, it's just a test anyway right now..

@perler commented on GitHub (Feb 3, 2025): > Personally I suggest you not to expose GoDoxy to the internet, should use VPN like tailscale or Wireguard. sure, will do later, when I have this running, it's just a test anyway right now..
Author
Owner

@yusing commented on GitHub (Feb 3, 2025):

  1. You haven't configured autocert part yet so https is not enabled. You need to set email, domains, provider and options to obtain certs from Let's Encrypt.

  2. CIDRWhitelist is forbidding your access, you can remove it as you're just testing it out.

@yusing commented on GitHub (Feb 3, 2025): 1. You haven't configured `autocert` part yet so https is not enabled. You need to set `email`, `domains`, `provider` and `options` to obtain certs from Let's Encrypt. 2. CIDRWhitelist is forbidding your access, you can remove it as you're just testing it out.
Author
Owner

@perler commented on GitHub (Feb 3, 2025):

ok, I see.

re 2. I was under the impression this whitelist is just for internal communication between proxy and frontend.

re 1. for some reason your .yml is not syntax checked in my VS code. something is wrong tho:

02-03 18:27 INF GoDoxy version 0.9.1
02-03 18:27 FTL yaml: line 13: did not find expected key

Image

@perler commented on GitHub (Feb 3, 2025): ok, I see. re 2. I was under the impression this whitelist is just for internal communication between proxy and frontend. re 1. for some reason your .yml is not syntax checked in my VS code. something is wrong tho: ```` 02-03 18:27 INF GoDoxy version 0.9.1 02-03 18:27 FTL yaml: line 13: did not find expected key ```` ![Image](https://github.com/user-attachments/assets/737cef1f-d45c-47f4-af17-3ac3a989c0fc)
Author
Owner

@yusing commented on GitHub (Feb 3, 2025):

Sorry for that, I've adjusted the default config.yml. But let me clean it up for you first:

autocert:
  provider: cloudflare
  email: abc@gmail.com # ACME Email
  domains: # a list of domains for cert registration
    - "*.domain.com"
  options:
    auth_token: c1234565789-abcdefghijklmnopqrst # your zone API token

providers:
  docker:
    local: $DOCKER_HOST

homepage:
  use_default_categories: true

timeout_shutdown: 5

Full config.example.yml:

# Autocert (choose one below and uncomment to enable)
#
# 1. use existing cert

# autocert:
#   provider: local

# 2. cloudflare
# autocert:
#   provider: cloudflare
#   email: abc@gmail.com # ACME Email
#   domains: # a list of domains for cert registration
#     - "*.domain.com"
#     - "domain.com"
#   options:
#     auth_token: c1234565789-abcdefghijklmnopqrst # your zone API token

# 3. other providers, see https://github.com/yusing/go-proxy/wiki/Supported-DNS%E2%80%9001-Providers#supported-dns-01-providers

entrypoint:
  # Below define an example of middleware config
  # 1. block non local IP connections
  # 2. redirect HTTP to HTTPS
  #
  # middlewares:
  #   - use: CIDRWhitelist
  #     allow:
  #       - "127.0.0.1"
  #       - "10.0.0.0/8"
  #       - "172.16.0.0/12"
  #       - "192.168.0.0/16"
  #     status: 403
  #     message: "Forbidden"
  #   - use: RedirectHTTP

  # below enables access log
  access_log:
    format: combined
    path: /app/logs/entrypoint.log

providers:
  # include files are standalone yaml files under `config/` directory
  #
  # include:
  #   - file1.yml
  #   - file2.yml

  docker:
    # $DOCKER_HOST implies environment variable `DOCKER_HOST` or unix:///var/run/docker.sock by default
    local: $DOCKER_HOST

    # explicit only mode
    # only containers with explicit aliases will be proxied
    # add "!" after provider name to enable explicit only mode
    #
    # local!: $DOCKER_HOST
    #
    # add more docker providers if needed
    # for value format, see https://docs.docker.com/reference/cli/dockerd/
    #
    # remote-1: tcp://10.0.2.1:2375
    # remote-2: ssh://root:1234@10.0.2.2

  # notification providers (notify when service health changes)
  #
  # notification:
  #   - name: gotify
  #     provider: gotify
  #     url: https://gotify.domain.tld
  #     token: abcd
  #   - name: discord
  #     provider: webhook
  #     url: https://discord.com/api/webhooks/...
  #     template: discord # this means use payload template from internal/notif/templates/discord.json

# Check https://github.com/yusing/go-proxy/wiki/Certificates-and-domain-matching#domain-matching
# for explaination of `match_domains`
#
# match_domains:
#   - my.site
#   - node1.my.app

# homepage config
homepage:
  # use default app categories detected from alias or docker image name
  use_default_categories: true

# Below are fixed options (non hot-reloadable)

# timeout for shutdown (in seconds)
timeout_shutdown: 5
@yusing commented on GitHub (Feb 3, 2025): Sorry for that, I've adjusted the default `config.yml`. But let me clean it up for you first: ```yaml autocert: provider: cloudflare email: abc@gmail.com # ACME Email domains: # a list of domains for cert registration - "*.domain.com" options: auth_token: c1234565789-abcdefghijklmnopqrst # your zone API token providers: docker: local: $DOCKER_HOST homepage: use_default_categories: true timeout_shutdown: 5 ``` Full `config.example.yml`: ```yaml # Autocert (choose one below and uncomment to enable) # # 1. use existing cert # autocert: # provider: local # 2. cloudflare # autocert: # provider: cloudflare # email: abc@gmail.com # ACME Email # domains: # a list of domains for cert registration # - "*.domain.com" # - "domain.com" # options: # auth_token: c1234565789-abcdefghijklmnopqrst # your zone API token # 3. other providers, see https://github.com/yusing/go-proxy/wiki/Supported-DNS%E2%80%9001-Providers#supported-dns-01-providers entrypoint: # Below define an example of middleware config # 1. block non local IP connections # 2. redirect HTTP to HTTPS # # middlewares: # - use: CIDRWhitelist # allow: # - "127.0.0.1" # - "10.0.0.0/8" # - "172.16.0.0/12" # - "192.168.0.0/16" # status: 403 # message: "Forbidden" # - use: RedirectHTTP # below enables access log access_log: format: combined path: /app/logs/entrypoint.log providers: # include files are standalone yaml files under `config/` directory # # include: # - file1.yml # - file2.yml docker: # $DOCKER_HOST implies environment variable `DOCKER_HOST` or unix:///var/run/docker.sock by default local: $DOCKER_HOST # explicit only mode # only containers with explicit aliases will be proxied # add "!" after provider name to enable explicit only mode # # local!: $DOCKER_HOST # # add more docker providers if needed # for value format, see https://docs.docker.com/reference/cli/dockerd/ # # remote-1: tcp://10.0.2.1:2375 # remote-2: ssh://root:1234@10.0.2.2 # notification providers (notify when service health changes) # # notification: # - name: gotify # provider: gotify # url: https://gotify.domain.tld # token: abcd # - name: discord # provider: webhook # url: https://discord.com/api/webhooks/... # template: discord # this means use payload template from internal/notif/templates/discord.json # Check https://github.com/yusing/go-proxy/wiki/Certificates-and-domain-matching#domain-matching # for explaination of `match_domains` # # match_domains: # - my.site # - node1.my.app # homepage config homepage: # use default app categories detected from alias or docker image name use_default_categories: true # Below are fixed options (non hot-reloadable) # timeout for shutdown (in seconds) timeout_shutdown: 5 ```
Author
Owner

@yusing commented on GitHub (Feb 3, 2025):

please let me know if it works for you

@yusing commented on GitHub (Feb 3, 2025): please let me know if it works for you
Author
Owner

@perler commented on GitHub (Feb 5, 2025):

ok, this looks better, certificates are created, but I still get

02-05 07:38 INF server started addr=127.0.0.1:8888 module=server name=api
02-05 07:38 ERR request error="no such route: gp" method=GET remote=95.90.139.129:53219 url=/
02-05 07:38 ERR request error="no such route: gp" method=GET remote=95.90.139.129:53219 url=/favicon.ico
02-05 07:38 ERR request error="no such route: gp" method=GET remote=95.90.139.129:53219 url=/
02-05 07:38 ERR request error="no such route: gp" method=GET remote=40.84.221.225:48256 url=/robots.txt
02-05 07:38 ERR request error="no such route: gp" method=GET remote=40.84.221.225:48256 url=/
02-05 07:38 ERR request error="no such route: gp" method=GET remote=95.90.139.129:53221 url=/
02-05 07:38 ERR request error="no such route: gp" method=GET remote=95.90.139.129:53221 url=/favicon.ico
@perler commented on GitHub (Feb 5, 2025): ok, this looks better, certificates are created, but I still get ```` 02-05 07:38 INF server started addr=127.0.0.1:8888 module=server name=api 02-05 07:38 ERR request error="no such route: gp" method=GET remote=95.90.139.129:53219 url=/ 02-05 07:38 ERR request error="no such route: gp" method=GET remote=95.90.139.129:53219 url=/favicon.ico 02-05 07:38 ERR request error="no such route: gp" method=GET remote=95.90.139.129:53219 url=/ 02-05 07:38 ERR request error="no such route: gp" method=GET remote=40.84.221.225:48256 url=/robots.txt 02-05 07:38 ERR request error="no such route: gp" method=GET remote=40.84.221.225:48256 url=/ 02-05 07:38 ERR request error="no such route: gp" method=GET remote=95.90.139.129:53221 url=/ 02-05 07:38 ERR request error="no such route: gp" method=GET remote=95.90.139.129:53221 url=/favicon.ico ````
Author
Owner

@yusing commented on GitHub (Feb 5, 2025):

try changing proxy.#1.port to proxy..gp.port, some report that this does not work

services:
  frontend:
    ...
    labels:
      proxy.aliases: gp
      proxy.gp.port: 3000 # this line
@yusing commented on GitHub (Feb 5, 2025): try changing `proxy.#1.port` to `proxy..gp.port`, some report that this does not work ```yaml services: frontend: ... labels: proxy.aliases: gp proxy.gp.port: 3000 # this line ```
Author
Owner

@perler commented on GitHub (Feb 5, 2025):

that did the trick, thanks!

@perler commented on GitHub (Feb 5, 2025): that did the trick, thanks!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/godoxy#32