From 8e25a37f0e1d0b2584b3de2439df47f6b47e4d4c Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Mon, 8 Nov 2021 10:14:13 +0100 Subject: [PATCH] Add documentation for nginx --- doc/book/src/connect/apps.md | 30 +---- doc/book/src/cookbook/exposing_websites.md | 2 +- doc/book/src/cookbook/reverse_proxy.md | 136 ++++++++++++++++++++- 3 files changed, 133 insertions(+), 35 deletions(-) diff --git a/doc/book/src/connect/apps.md b/doc/book/src/connect/apps.md index 7bb0fc7f..20075f43 100644 --- a/doc/book/src/connect/apps.md +++ b/doc/book/src/connect/apps.md @@ -253,35 +253,7 @@ Make sure you (will) have a corresponding DNS entry for them. Now we will configure a reverse proxy in front of Garage. This is required as we have no other way to serve CORS headers yet. -For our example, we will use nginx: - -```nginx -server { - # In production you should use TLS instead of plain HTTP - listen [::]:80; - - server_name peertube-video.web.garage peertube-playlist.web.garage; - - location / { - add_header Access-Control-Allow-Origin *; - add_header Access-Control-Max-Age 3600; - add_header Access-Control-Expose-Headers Content-Length; - add_header Access-Control-Allow-Headers Range; - - # We do not forward OPTIONS request to Garage - # as it does not know how to interpret them. - # Instead, we simply answers 200. - if ($request_method !~ ^(GET|HEAD)$ ) { - return 200; - } - - # If your do not have a Garage instance on the reverse proxy, change the URL here. - proxy_pass http://127.0.0.1:3902; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $host; - } -} -``` +Check the [Configuring a reverse proxy](/cookbook/reverse_proxy.html) section to know how. Now make sure that your 2 dns entries are pointing to your reverse proxy. diff --git a/doc/book/src/cookbook/exposing_websites.md b/doc/book/src/cookbook/exposing_websites.md index 96a9aebe..0cbb1150 100644 --- a/doc/book/src/cookbook/exposing_websites.md +++ b/doc/book/src/cookbook/exposing_websites.md @@ -1,4 +1,4 @@ -# Exposing websites +# Exposing buckets as websites You can expose your bucket as a website with this simple command: diff --git a/doc/book/src/cookbook/reverse_proxy.md b/doc/book/src/cookbook/reverse_proxy.md index b4674852..14633ae8 100644 --- a/doc/book/src/cookbook/reverse_proxy.md +++ b/doc/book/src/cookbook/reverse_proxy.md @@ -1,19 +1,142 @@ # Configuring a reverse proxy +The main reason to add a reverse proxy in front of Garage is to provide TLS to your users. + +In production you will likely need your certificates signed by a certificate authority. +The most automated way is to use a provider supporting the [ACME protocol](https://datatracker.ietf.org/doc/html/rfc8555) +such as [Let's Encrypt](https://letsencrypt.org/), [ZeroSSL](https://zerossl.com/) or [Buypass Go SSL](https://www.buypass.com/ssl/products/acme). + +If you are only testing Garage, you can generate a self-signed certificate to follow the documentation: + +```bash +openssl req \ + -new \ + -x509 \ + -keyout /tmp/garage.key \ + -out /tmp/garage.crt \ + -nodes \ + -subj "/C=XX/ST=XX/L=XX/O=XX/OU=XX/CN=localhost/emailAddress=X@X.XX" \ + -addext "subjectAltName = DNS:localhost, IP:127.0.0.1" + +cat /tmp/garage.key /tmp/garage.crt > /tmp/garage.pem +``` + +Be careful as you will need to allow self signed certificates in your client. +For example, with minio, you must add the `--insecure` flag. +An example: + +```bash +mc ls --insecure garage/ +``` + +## socat (only for testing purposes) + +If you want to test Garage with a TLS frontend, socat can do it for you in a single command: + +```bash +socat \ +"openssl-listen:443,\ +reuseaddr,\ +fork,\ +verify=0,\ +cert=/tmp/garage.pem" \ +tcp4-connect:localhost:3900 +``` + ## Nginx +Nginx is a well-known reverse proxy suitable for production. +We do the configuration in 3 steps: first we define the upstream blocks ("the backends") +then we define the server blocks ("the frontends") for the S3 endpoint and finally for the web endpoint. + +The following configuration blocks can be all put in the same `/etc/nginx/sites-available/garage.conf`. +To make your configuration active, run `ln -s /etc/nginx/sites-available/garage.conf /etc/nginx/sites-enabled/`. +If you directly put the instructions in the root `nginx.conf`, keep in mind that these configurations must be enclosed inside a `http { }` block. + +And do not forget to reload nginx with `systemctl reload nginx` or `nginx -s reload`. + +### Defining backends + +First, we need to tell to nginx how to access our Garage cluster. +Because we have multiple nodes, we want to leverage all of them by spreading the load. + +In nginx, we can do that with the upstream directive. +Because we have 2 endpoints: one for the S3 API and one to serve websites, +we create 2 backends named respectively `s3_backend` and `web_backend`. + +A documented example for the `s3_backend` assuming you chose port 3900: + +```nginx +upstream s3_backend { + # if you have a garage instance locally + server 127.0.0.1:3900; + # you can also put your other instances + server 192.168.1.3:3900; + # domain names also work + server garage1.example.com:3900; + # you can assign weights if you have some servers + # that are more powerful than others + server garage2.example.com:3900 weight=2; +} +``` + +A similar example for the `web_backend` assuming you chose port 3902: + +```nginx +upstream web_backend { + server 127.0.0.1:3902; + server 192.168.1.3:3902; + server garage1.example.com:3902; + server garage2.example.com:3902 weight=2; +} +``` + +### Exposing the S3 API + +The configuration section for the S3 API is simple as we only support path-access style yet. +We simply configure the TLS parameters and forward all the requests to the backend: + ```nginx server { - # In production you should use TLS instead of plain HTTP - listen [::]:80; + listen [::]:443 http2 ssl; + ssl_certificate /tmp/garage.crt; + ssl_certificate_key /tmp/garage.key; - # We + # should be the endpoint you want + # aws uses s3.amazonaws.com for example + server_name garage.example.com; + + location / { + proxy_pass http://s3_backend; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + } +} + +``` + +### Exposing the web endpoint + +The web endpoint is a bit more complicated to configure as it listens on many different `Host` fields. +To better understand the logic involved, you can refer to the [Exposing buckets as websites](/cookbook/exposing_websites.html) section. +Also, for some applications, you may need to serve CORS headers: Garage can not serve them directly but we show how we can use nginx to serve them. +You can use the following example as your starting point: + +```nginx +server { + listen [::]:443 http2 ssl; + ssl_certificate /tmp/garage.crt; + ssl_certificate_key /tmp/garage.key; + + # We list all the Hosts fields that can access our buckets server_name *.web.garage example.com my-site.tld ; location / { + # Add these headers only if you want to allow CORS requests + # For production use, more specific rules would be better for your security add_header Access-Control-Allow-Origin *; add_header Access-Control-Max-Age 3600; add_header Access-Control-Expose-Headers Content-Length; @@ -25,8 +148,7 @@ server { return 200; } - # If your do not have a Garage instance on the reverse proxy, change the URL here. - proxy_pass http://127.0.0.1:3902; + proxy_pass http://web_backend; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; } @@ -36,4 +158,8 @@ server { ## Apache httpd +@TODO + ## Traefik + +@TODO