diff --git a/docs/admin/reverse-proxy.md b/docs/admin/reverse-proxy.md index 256076c9..7aed321e 100644 --- a/docs/admin/reverse-proxy.md +++ b/docs/admin/reverse-proxy.md @@ -7,19 +7,25 @@ origin_url: 'https://github.com/go-gitea/gitea/blob/e865de1e9d65dc09797d165a51c8 Forgejo can live standalone, or behind a [reverse proxy](https://en.wikipedia.org/wiki/Reverse_proxy). You may want this for scenarios like: -- Subpath mapping. +- Subpath mapping. If you want Forgejo at something like `https://example.com/code/` or `https://example.com/repositories/` instead of the default `https://example.com`. -- Port mapping. +- Port mapping. If you want to run Forgejo on the standard port, and that port is already taken by another web server. I.e. as `https://example.com` instead of as `https://example.com:3000`. - Proxy authentication. Using an external login service. _Forgejo usually does not need a proxy for this, as it can be configured to talk to many login services directly._ +- rate limiting. + Fail2ban allows to rate-limit TCP connections, but with a load-balancer you can inspect the headers, perform User-Agent detection, match the information provided by an ACL +- advanced security settings. + Using a load balancer you can apply [Content Security policies](https://en.wikipedia.org/wiki/Content_Security_Policy), tweak your SSL ciphers, and configure a [Web Application Firewall](https://en.wikipedia.org/wiki/Web_application_firewall). +- caching and resilience. + load-balancers offer both caching and robustness. For instance, Haproxy can handle millions of simultaneous connections, and caching alleviates the load on the application. Forgejo does not need the help of a proxy to do HTTPS, it can do it directly. Set in `SERVER` section of the configuration `PROTOCOL=https` and either set `CERT_FILE` and `KEY_FILE` or let Forgejo manage the certificates with `ENABLE_ACME=true` -## nginx +## NGINX ### Basic HTTP @@ -209,6 +215,196 @@ Outside the `VirtualHost *:443`, add this configuration: This will redirect anyone visiting the HTTP site to the HTTPS site. +## HAProxy + +### Basic HTTP + +To setup HAProxy on port 80, without a virtualhost, you can add the following stanza to your `haproxy.cfg`: + +```txt +listen forgejo_80 + bind :::80 v4v6 + mode http + timeout connect 10s + timeout client 30s + timeout server 30s + server frogejo 127.0.0.1:3000 +``` + +### HTTPS + +To setup basic HTTPS proxying with HAProxy, you can add these blocks to your haproxy configuration: + +#### Redirection to SSL + +```txt +listen forgejo_80 + bind :::80 v4v6 + mode http + timeout connect 10s + timeout client 30s + timeout server 30s + redirect scheme https code 301 +``` + +#### SSL frontend + +```txt +frontend forgejo_443 + bind :::443 v4v6 ssl crt /etc/haproxy_certs/forgejo.example.org.pem + mode http + option httplog + option forwardfor + timeout client 1m + use_backend forgejo_443 if { ssl_fc_sni forgejo.example.org } +``` + +#### SSL backend + +```txt +backend forgejo_443 + mode http + timeout connect 10s + timeout server 30s + retry-on all-retryable-errors + server frogejo 127.0.0.1:3000 +``` + +### HTTPS with UNIX Socket + +A Unix socket has lower latency compared to TCP. When combined with HAProxy, it provides a highly responsive and excellent user interface experience. + +We assume that: + +- Redirection to SSL and the SSL frontend configuration remain unchanged from the TCP setup +- you are running Forgejo as `git` user and HAProxy as `haproxy` user +- the chroot environment is set to the directory `/var/lib/haproxy` +- you have included the following settings in the `server` stanza of Forgejo: + +```ini +[server] +PROTOCOL = http+unix +HTTP_ADDR = /var/lib/haproxy/forgejo/forgejo.sock +UNIX_SOCKET_PERMISSION = 660 +... +``` + +Now you need to create a directory which can be acceessed either by the chroot environment used by HAProxy, and by Forgejo. + +```bash +install -o git -g haproxy -m 0770 -d /var/lib/haproxy/forgejo +``` + +Finally you can add these blocks into your `haproxy.cfg` + +#### chroot + +you include these lines in the `global` section of your haproxy configuration + +```txt +global + chroot /var/lib/haproxy + user haproxy + group haprox + ... +``` + +#### SSL Backend + +The backend configuration will be as follows: + +```txt +backend forgejo_443 + mode http + timeout connect 10s + timeout server 30s + retry-on all-retryable-errors + server forgejo /forgejo/forgejo.sock tfo +``` + +_**note:** The Unix socket path is relative to the path of the chroot environment_ + +#### HAProxy with UNIX socket using Puppet + +This configuration relies on [Puppetlabs HAProxy](https://forge.puppet.com/modules/puppetlabs/haproxy/readme) module. +This code sample is a compromise for the sake of the conciseness. +The Forgejo backend will be available only at the second execution of Puppet, unless you add a statement to create a user in advance, and you don't need to set the dependency for the 2 directories against the HAProxy class. You also need to push the SSL certificate, but all this goes far beyond the scope of this documentation. + +```puppet + file { + default: + notify => Service['haproxy'], + require => [Class['haproxy'], User['git']]; + '/etc/haproxy_certs': + ensure => directory, + purge => true, + mode => '0700', + owner => haproxy, + group => haproxy, + recurse => true; + '/var/lib/haproxy/forgejo': + ensure => directory, + mode => '0770', + owner => git, + group => haproxy; + } + + class { 'haproxy': + package_ensure => $haproxy_version, + global_options => { + 'log' => "/dev/log local0\n log /dev/log local1 notice", + 'chroot' => '/var/lib/haproxy', + 'maxconn' => '150000', + 'user' => 'haproxy', + 'group' => 'haproxy', + 'stats' => 'socket /var/run/haproxy.sock user root group sensu mode 660 level admin', + 'tune.ssl.default-dh-param' => '2048', + }, + defaults_options => { + 'default-server' => 'init-addr libc,none', + 'log' => 'global', + 'retries' => '5', + 'option' => ['redispatch', 'http-server-close', 'logasap'], + 'timeout' => ['http-request 7s', 'connect 5s', 'check 9s'], + 'maxconn' => '5000', + }; + } + + haproxy::listen { 'forgejo_80': + bind => { ':::80' => ['v4v6'] }, + mode => 'http', + options => [ + { 'timeout' => 'connect 10s' }, + { 'timeout' => 'client 1m' }, + { 'timeout' => 'server 1m' }, + { 'redirect' => 'scheme https code 301' }, + ]; + } + + haproxy::frontend { 'forgejo_socket': + bind => { ':::443' => ['v4v6', 'ssl', 'crt', '/etc/haproxy_certs/forgejo.example.com.pem'] }, + options => [ + { + mode => 'http', + option => ['httplog', 'forwardfor'], + }, + { 'timeout' => 'client 1m' }, + { 'use_backend' => "forgejo if { ssl_fc_sni forgejo.example.com }" }, + ]; + } + + haproxy::backend { 'forgejo_socket': + options => [ + { 'mode' => 'http' }, + { 'timeout' => 'connect 10s' }, + { 'timeout' => 'server 1m' }, + { 'retry-on' => 'all-retryable-errors' }, + { 'server' => 'forgejo /forgejo/forgejo.sock tfo' }, + ]; + } + +``` + ## Caddy ### HTTPS