Skip to content
This page was translated with AI and may contain inaccuracies. Help improve it on GitHub.

Web Services ​

Serve reverse proxy, redirects, static files and fixed text by domain. This is Gately's unified web entry point. Menu location: sidebar "Web → Web Services".

Structure: listeners, sites and the default site ​

The configuration has three layers:

  1. Listener: one listening port. Fields include network (tcp dual-stack, tcp4, tcp6), listen address (empty for all addresses), port, HTTPS switch, minimum TLS version (1.0 / 1.1 / 1.2 / 1.3), and whether to accept the PROXY protocol.
  2. Site: a site under a listener, matched by domain. Domains can be an exact domain, *.example.com (matches subdomains at any depth) or * (matches everything). Matching priority is exact domain, wildcard, then *.
  3. Default site: used when no site matches. When it is not enabled, a 404 is returned.

Saving a change to a site or to the default site swaps the site list in place: the listener keeps running, open connections (WebSocket included) stay up, and each site keeps its statistics. If the new configuration is invalid, the previous sites keep serving. Changing the listener's own settings (network, address, port, HTTPS, minimum TLS, HTTP/3, PROXY protocol) restarts that listener.

Site types ​

TypeDescription
Reverse proxyForwards to one or more backends. Backend addresses use the form http(s)://host:port, and WebSocket is supported
RedirectRedirects to a full URL with status code 301 / 302 / 307 / 308 (default 302), optionally keeping the original path and query string. The URL may contain {host}, which is replaced by the domain the visitor used: https://{host} with "Keep path" sends every HTTP request to HTTPS on the same domain
Static filesThe directory must be an absolute path. With "Directory listing" off, a directory request returns a response only when index.html exists. "Clean URLs" tries path.html and path/index.html when a file is missing (for VitePress and similar generators, like nginx try_files $uri $uri.html $uri/index.html). "404 page" is a path inside the directory, such as 404.html, returned with status 404
Fixed textCustom content, Content-Type (default text/plain; charset=utf-8) and status code (100-599, default 200)

Other options for reverse proxy sites:

  • Use backend Host: the Host header is changed to the backend address; when off, the Host from the client request is kept;
  • Skip backend certificate verification, disable Keep-Alive;
  • Send the PROXY protocol to the backend (v2 header, passes the real client IP, requires backend support);
  • Add X-Forwarded-For / X-Forwarded-Proto / X-Forwarded-Host / X-Forwarded-Port and X-Real-IP;
  • Use the visited domain as SNI (HTTPS backends only): the handshake carries the domain the visitor used and the certificate is checked against it, like nginx proxy_ssl_server_name on; proxy_ssl_name $host. Turn it on when the backend routes by SNI, for example frp's vhost_https. Every backend has its own connection pool, so connections are never reused across domains.

Sites of every type can set an access log, cross-origin (CORS), custom request and response headers (one Key: Value per line; an empty Value removes that header), and can reference a WAF Firewall instance (if the instance does not exist or is disabled, requests pass through).

Transport and protocols ​

  • HTTPS: uses a certificate from the SSL Certificates module that covers the domain;
  • HTTP/3 (QUIC): turn it on for a listener with HTTPS enabled. HTTP/3 is then also served over UDP on the same port number and advertised to browsers with the Alt-Svc response header; allow that UDP port in your firewall and port mapping;
  • WebSocket: supported automatically by reverse proxy;
  • PROXY protocol: a listener can accept PROXY headers sent by upstream components (such as haproxy and frp). It trusts only the IPs or subnets listed in "Global settings → Trusted PROXY sources"; leaving it empty trusts no source. Reverse proxy can send PROXY headers to the backend.

Authentication ​

Configure it on the "Security" page of the site editor:

  • Web authentication: the browser shows a login page;
  • Basic authentication: HTTP Basic;
  • Users: one username:password per line, and the password can be a bcrypt hash. Basic authentication needs at least one user when enabled; web authentication needs at least one user or third-party login identity when enabled;
  • Third-party login: GitHub, Google, QQ and OIDC are supported, using your own OAuth apps. Allowed identities go one per line in the form provider:account, for example github:octocat and google:me@gmail.com. A # at the end of a line adds a comment, and github:* means any account of that provider.

Third-party login providers are configured in "Global settings": enter your own Client ID / Secret and enable the provider, and also set a callback address (it must be served by one of Gately's listeners, for example https://auth.example.com). The callback URL to register with GitHub / Google / QQ is:

text
https://auth.example.com/__gately_auth/oauth/callback

Third-party login for the management UI itself is configured separately under "Settings → Account & Security".

Forward auth (Authelia and similar) ​

Hand authentication to an external service, like nginx auth_request or Traefik forwardAuth. Tick "Forward auth" on the "Security" page. It cannot be combined with Basic or web authentication on the same site.

FieldDescription
urlThe check endpoint, such as Authelia's http://127.0.0.1:9091/api/authz/auth-request
loginUrlWhere to send visitors when the endpoint answers 401, such as https://auth.example.com/?rd={url}&rm={method}. {url} is the original address (URL-encoded) and {method} the request method. When empty, the endpoint's response is returned as it is
copyHeadersIdentity headers copied from the endpoint's reply to the backend request; the default is Remote-User, Remote-Groups, Remote-Email and Remote-Name

How it works:

  • Every request first goes to url as a GET without a body, carrying the visitor's headers (cookies, Authorization and so on) plus X-Original-Method, X-Original-URL, X-Forwarded-Method, X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Uri, X-Forwarded-For and X-Real-Ip. The timeout is 10 seconds;
  • A 2xx answer lets the request through, with the identity headers added; a 401 redirects to loginUrl (status 302); other answers such as 403 or a redirect are returned to the visitor; an unreachable service gives 502;
  • Identity headers sent by visitors are always removed, so they cannot be forged;
  • It works with path rules and "Authentication scope", so only some paths (for example /admin) need a login, and with temporary share links.

Shared users: TOTP and single sign-on ​

Define accounts once and use them on several sites, with optional TOTP two-step verification. It covers what many people run Authelia for.

In "Global settings → Shared users":

  • Add users with a username and a password. Passwords are stored as bcrypt hashes and never returned by the API. To add TOTP, click "Enable TOTP", scan the QR code with an authenticator app (Google Authenticator, 1Password and so on) and save. Regenerating the key invalidates the old one;
  • SSO domain, such as example.com: after signing in on any site under that domain or its subdomains, the other sites there need no further sign-in. It uses a parent-domain cookie (gately_sso, valid for 7 days) that is never forwarded to backends. Leave it empty to sign in on each site separately.

On a site, tick "Use shared users" next to web or Basic authentication. The site's own users keep working as well.

Behavior:

  • The login page shows a verification code field when any shared user has TOTP. Each code works once;
  • Changing a user's password or TOTP key ends that user's sessions;
  • Basic authentication accepts only shared users without TOTP, because a browser password prompt has nowhere to enter a code;
  • Failed attempts count towards the same rate limit and automatic ban as other sign-ins.

Access control ​

IP allowlist and blocklist ​

"IP access control" on the site's "Security" page can be off, allowlist or blocklist. The list takes one IP or subnet per line (such as 192.168.1.0/24), and can also reference subscribed IP lists.

Subscribed IP lists ​

Add lists under "Global settings → Subscribed IP lists": enter the URL and refresh interval (24 hours by default). Gately downloads each list on schedule and caches it in the configuration directory, so it works after a restart without network access. The content has one IP, CIDR or start-end range per line; anything after #, ; or // is a comment. For Chinese provinces and cities you can use metowolf/iplist, for example https://metowolf.github.io/iplist/data/cncity/440000.txt (Guangdong).

  • Allowlists and blocklists of sites and path rules can reference several lists, checked together with the manually entered ranges; matching any of them counts as being on the list;
  • If downloaded content cannot be parsed (for example an error page was returned), the previous list is kept, the reason is shown on the list, and the download is retried an hour later;
  • Until a list has downloaded successfully it counts as empty: an allowlist therefore denies access, and a blocklist blocks nothing extra;
  • A list still referenced by a site cannot be deleted.

Path rules ​

In "Path rules" on the "Security" page, override the site's authentication and IP settings by path prefix:

FieldValues
prefixA path prefix starting with /, such as /admin
authInherit from site (empty), off (no authentication), on (authentication required)
ipMode / ipListInherit from site (empty), whitelist or blacklist, with a list of IPs or subnets

Matching rules:

  • The longest prefix wins;
  • Matching follows path segment boundaries: /admin matches /admin and /admin/x, but not /administrator;
  • The request path is normalized first (., .. and duplicate slashes are removed) and then matched, so /public/../admin is treated as /admin;
  • Only one rule can be configured for the same prefix.

The "Authentication scope" option (authOptional): when ticked, authentication applies only to paths marked "Required" in the rules, and all other paths are public. This option needs Basic or web authentication to be enabled first.

After Basic or web authentication is enabled, you can create share links for a site so that visitors can access it without an account:

FieldDescription
NameA label, such as "For Alice"
ExpiryLeave empty for no expiry
Uses maxUsesMaximum number of times the link can be redeemed; 0 means unlimited. The count resets after a restart
Path limit pathPrefixWhen not empty, the link can only access paths under this prefix; it must start with /

A visitor opens https://domain/any-path?_gs=token to redeem a session. After a successful redemption, the server sets a login-free cookie and redirects to the address without the _gs parameter. The session lasts at most 24 hours and never beyond the link's expiry. An invalid token is handled as a normal visit and does not reveal the reason for the failure. Sessions already issued become invalid immediately after the link is deleted. The token is generated after saving (at least 16 characters), and the full link can be copied in the UI.

Authentication failure rate limiting and automatic ban ​

  • After 10 failed authentications from the same source IP within 15 minutes, further attempts are rejected for a while;
  • Under "Global settings → Auto ban → Ban on authentication failure", enter a number of minutes (0 to 43200); the source IP is banned when it reaches 10 failures. 0 means no ban, rate limiting only;
  • An AuthBanned event is published when an automatic ban triggers, and it can be pushed through the Notification Center;
  • IPv6 addresses are counted and banned per /64 subnet.

Ban list ​

The ban list in "Global settings" shows the currently banned IPs, the reason (repeated authentication failures or manual ban) and the expiry time, and each entry can be lifted with "Unban". You can also ban manually: enter an IP and a number of hours (1 to 720, which is at most 30 days); the API defaults to 24 hours.

The ban list is shared with Intrusion Prevention: when the Intrusion Prevention module is on, this section only shows the number of bans and links to the Intrusion Prevention page for managing them. Bans also apply to port forwarding, STUN and other services, and are dropped in the system firewall when firewall sync is on; with "Ignore LAN addresses" on, LAN addresses are never banned automatically.

GeoIP country filter ​

A site's "Country filter" has three modes: off, allow only, and deny. Enter two-letter ISO country codes separated by commas, such as CN, HK, US. At least one country is required when enabled.

  • Filtering depends on a GeoIP database, which you must first import under "Global settings → GeoIP database": upload a .mmdb file, or enter a download URL. MaxMind GeoLite2, DB-IP and other country or city databases are supported; the upload limit is 129 MB;
  • When no database is loaded, filtering has no effect (all visitors pass) and the UI shows a notice;
  • Private network addresses are always allowed;
  • In "Deny" mode, addresses whose country cannot be found in the database are allowed.

Path backends ​

For a reverse proxy site, send requests under a path prefix to other backends, like nginx location /api/ { proxy_pass ...; }. Add them under "Path backends" on the "Basic" page of the site editor.

FieldDescription
prefixA path prefix such as /api/. Matching follows path segment boundaries: /api and /api/ both match /api and /api/x, but not /apix
targetsThe backends for this path, written like the site's backends. When empty, the site's backends are used and only the headers below are added
requestHeadersRequest headers added for this path, one Key: Value per line. They are applied after the site's headers, and a header with the same name overrides the site's
  • The longest prefix wins, and the path is forwarded unchanged (the prefix is not stripped);
  • Other settings of the site, such as the Host option, certificate checks, forwarded headers, the PROXY protocol, the load-balancing policy and health checks, apply to every path backend;
  • Compression, rate limiting, caching and rewrites apply to the whole site.

Reverse proxy enhancements ​

These options are on the "Traffic" page of the site editor.

Backends, weight and backup ​

The backend list takes one address per line, optionally followed by parameters:

text
http://10.0.0.2:8080 weight=3
http://10.0.0.3:8080 backup
  • weight=N: weight, an integer from 1 to 100, default 1;
  • backup: a standby backend that is used only when all non-backup backends are unavailable. When every backend is unavailable, all non-backup backends are tried again.

Load balancing policy ​

UI optionlbPolicyDescription
Round robin (weighted)EmptyDefault
Random (weighted)random
IP hash (sticky sessions)ip_hashThe same client IP always goes to the same backend
Least connectionsleast_connPicks the smallest value of connections / weight

Health checks ​

The active check switch is off by default. Fields and defaults once enabled:

FieldDefaultRange
Mode modehttphttp (requests the check path; a status code below 400 counts as healthy) or tcp (only tests the connection)
Path path/Starts with /, http mode only
Interval interval10 seconds1 to 3600
Timeout timeout3 seconds1 to 60
Consecutive failures fails3 failures mark it unavailable1 to 20
Consecutive successes passes2 successes recover it1 to 20

When sending the PROXY protocol to the backend is enabled, HTTP checks switch to TCP automatically.

Passive checks are always in effect: among multiple backends, a backend with 3 consecutive connection failures is paused for 30 seconds before being probed again (a single backend with no active check is never removed). Once active checks are enabled, recovery is decided entirely by the check results. When a backend's state changes, upstream-down and upstream-recovered events are published, and they can be pushed through the Notification Center.

Compression ​

Compression can be enabled for reverse proxy, static file and fixed text sites (not for redirect sites). Based on Accept-Encoding, br is preferred, then gzip.

  • Only text-like content is compressed: text/*, JSON, JavaScript, XML, XHTML, RSS / Atom, WebAssembly and SVG; text/event-stream is excluded;
  • Responses whose declared Content-Length is below 256 bytes are left as they are;
  • Responses that already have a Content-Encoding are left as they are; WebSocket upgrade requests pass straight through;
  • After compression, strong ETags are converted to weak ETags.

Per-IP rate limiting ​

Token-bucket rate limiting per client IP. Fields:

FieldDescription
rateRequests allowed per second
burstBurst capacity. When rate is set and burst is 0, it defaults to rate rounded down plus 1
maxConnsMaximum concurrent requests per IP; 0 means unlimited

When rate limiting is enabled, at least one of rate and maxConns must be set.

In-memory response cache ​

Applies to reverse proxy sites only. The cache lives in memory and uses LRU eviction.

FieldDefaultRange
ttl default duration00 to 30 days (in seconds). When the upstream declares no cache directive, 200 responses are cached for this long; 0 means only responses the upstream explicitly allows are cached
maxMb cache capacity641 to 4096 MB

Caching rules:

  • Only GET requests are cached, and the request must not contain Authorization, Cookie or Range headers, nor Cache-Control: no-cache;
  • Only responses with status 200 are cached; a response is skipped if it contains Set-Cookie, Vary: *, or a Cache-Control of no-store / private / no-cache;
  • s-maxage is honored first, then max-age;
  • A single entry is limited to 4 MB and also to at most a quarter of the total capacity;
  • A hit returns the X-Cache: HIT and Age headers, and a miss returns X-Cache: MISS;
  • The cache key includes Host, the full request URI and Accept-Encoding.

Path rewrite and redirect ​

Rules are matched in order, and matching stops at the first hit.

FieldDescription
patternA regular expression matched against the request path, such as ^/old/(.*)$
toThe replacement result; use $1 to reference groups
redirectOff for an internal rewrite (the rewritten path is sent to the backend, and the target must start with /); on for a redirect
codeRedirect status code 301 / 302 / 307 / 308, default 302

Redirects keep the original query parameters. A redirect target may contain {host}, the domain the visitor used. Redirect rules run before authentication, like nginx location = / { return 302 ...; }, so a path such as / can send visitors on without asking them to sign in.

Access statistics and monitoring ​

Site statistics ​

For a running listener, click "Stats" on a site row to open the statistics window, where you can choose the last 1 hour, 6 hours or 24 hours:

  • Minute-level access statistics: one point per minute, kept for the last 24 hours, including a request count curve and 4xx / 5xx error curves;
  • Status code distribution (2xx / 3xx / 4xx / 5xx) and cumulative response traffic;
  • Top 10 source IPs and top 10 countries (country statistics need an imported GeoIP database);
  • Reverse proxy sites show the health status, weight, backup flag and current connection count of each backend.

Statistics are kept in memory and start counting again after a restart or after the listener's own settings change. Editing a site keeps its counters. The rankings track at most 5000 distinct sources.

Prometheus metrics ​

The global metrics endpoint GET /api/metrics aggregates metrics from all modules; see Monitoring. The module endpoint below covers Web Services metrics only.

The metrics endpoint is GET /api/webservice/metrics in Prometheus text format, and it requires login credentials or an API token.

bash
curl -H "Authorization: Bearer gtl_xxxx" http://localhost:16680/api/webservice/metrics
MetricTypeDescription
gately_site_requests_totalcounterCumulative requests of a site
gately_site_errors_totalcounterBackend errors of a site
gately_site_active_requestsgaugeRequests in progress
gately_site_response_bytes_totalcounterCumulative response bytes
gately_site_responses_totalcounterResponses counted by status class (label class: 2xx to 5xx)
gately_upstream_upgaugeWhether a backend is healthy: 1 healthy, 0 unavailable (with label upstream)

All metrics carry the labels listener (listener name#listener key) and site (site name, or the first domain when unnamed).

Import nginx config ​

"Import nginx" at the top of the page converts existing nginx sites into Gately listeners and sites. We recommend running nginx -T on the nginx host and pasting the full output: it contains every file pulled in by include, and Gately expands include the same way nginx does.

  • Preview first: sites are grouped by listening port, each with its type, backend or directory, source file and line number, plus anything that needs attention (directives using variables, regex locations, domains without a certificate, and so on). Sites that cannot be converted come with the reason;
  • Sites on the same port are merged into the existing listener, otherwise a new listener is created; domains that already exist are skipped, so importing again is safe;
  • Imports are disabled by default, so you can run alongside nginx and review them one by one before enabling. Tick "Enable right after import" to apply them immediately (a new listener fails to start while nginx still holds the same port);
  • What is converted: proxy_pass (including upstream weights, backup servers and load-balancing policies), root / alias static directories (autoindex, try_files $uri.html, error_page 404), return redirects and fixed content, whole-site rewrite redirects, add_header, proxy_set_header, gzip, allow / deny, location-level path backends, access control and redirects, and listen ... proxy_protocol and quic;
  • auth_request becomes forward auth: the auth endpoint comes from the proxy_pass of the auth subrequest location (set variables are supported) and the login redirect from error_page 401 =302, so common Authelia setups convert directly. When it is enabled only in some locations, the site's "Authentication scope" is limited to those paths, which become path rules set to "Authentication required";
  • auth_basic becomes basic authentication with shared users. nginx user files are not read, so nobody can get through until you add the users;
  • Configure TCP/UDP forwarding from stream in Port Forwarding. Certificates are not imported: when an HTTPS site has no certificate, the preview lists the certificate files nginx uses, and you can add them by file path on the SSL Certificates page.

Replacing haproxy and nginx ​

Port forwarding and Web Services together can replace an haproxy + nginx pair. A common layout is one SNI routing rule on port 443 that sends VPN and other TLS services straight to their backends and everything else to a Web Services listener that accepts the PROXY protocol, plus a Web Services listener on port 80 with a redirect site (https://{host}).

Converting nginx settings:

nginxGately
server with server_namea site with those domains
location with a different proxy_passpath backends
auth_request (Authelia)forward auth, or shared users with TOTP
proxy_ssl_name $hostuse the visited domain as SNI
return 301 https://$host$request_uria redirect site with https://{host} and "Keep path"
return 302 /admin on location = /a rewrite with "Redirect" on, pattern ^/$
try_files $uri $uri.html $uri/index.html and error_page 404static files with clean URLs and a 404 page
add_headerresponse headers

Deployment tip ​

Web Services need to listen on host ports such as 80 / 443. For Docker deployments, --network host is recommended.

Released under the Apache-2.0 license.