Enhance cookbook and integrations #150
7 changed files with 443 additions and 38 deletions
|
@ -7,6 +7,8 @@
|
||||||
- [Cookbook](./cookbook/index.md)
|
- [Cookbook](./cookbook/index.md)
|
||||||
- [Building from source](./cookbook/from_source.md)
|
- [Building from source](./cookbook/from_source.md)
|
||||||
- [Integration with systemd](./cookbook/systemd.md)
|
- [Integration with systemd](./cookbook/systemd.md)
|
||||||
|
- [Gateways](./cookbook/gateways.md)
|
||||||
|
- [Exposing buckets as websites](./cookbook/exposing_websites.md)
|
||||||
- [Configuring a reverse proxy](./cookbook/reverse_proxy.md)
|
- [Configuring a reverse proxy](./cookbook/reverse_proxy.md)
|
||||||
- [Production Deployment](./cookbook/real_world.md)
|
- [Production Deployment](./cookbook/real_world.md)
|
||||||
- [Recovering from failures](./cookbook/recovering.md)
|
- [Recovering from failures](./cookbook/recovering.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.
|
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.
|
This is required as we have no other way to serve CORS headers yet.
|
||||||
For our example, we will use nginx:
|
Check the [Configuring a reverse proxy](/cookbook/reverse_proxy.html) section to know how.
|
||||||
|
|
||||||
```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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Now make sure that your 2 dns entries are pointing to your reverse proxy.
|
Now make sure that your 2 dns entries are pointing to your reverse proxy.
|
||||||
|
|
||||||
|
@ -346,13 +318,114 @@ https://docs.joinmastodon.org/admin/config/#cdn
|
||||||
|
|
||||||
## Matrix
|
## Matrix
|
||||||
|
|
||||||
### synapse-s3-storage-provider
|
Matrix is a chat communication protocol. Its main stable server implementation, [Synapse](https://matrix-org.github.io/synapse/latest/), provides a module to store media on a S3 backend. Additionally, a server independent media store supporting S3 has been developped by the community, it has been made possible thanks to how the matrix API has been designed and will work with implementations like Conduit, Dendrite, etc.
|
||||||
|
|
||||||
https://github.com/matrix-org/synapse-s3-storage-provider
|
### synapse-s3-storage-provider (synapse only)
|
||||||
|
|
||||||
### matrix-media-repo
|
Supposing you have a working synapse installation, you can add the module with pip:
|
||||||
|
|
||||||
https://github.com/turt2live/matrix-media-repo
|
```bash
|
||||||
|
pip3 install --user git+https://github.com/matrix-org/synapse-s3-storage-provider.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Now create a bucket and a key for your matrix instance (note your Key ID and Secret Key somewhere, they will be needed later):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
garage key new --name matrix-key
|
||||||
|
garage bucket create matrix
|
||||||
|
garage bucket allow matrix --read --write --key matrix-key
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you must edit your server configuration (eg. `/etc/matrix-synapse/homeserver.yaml`) and add the `media_storage_providers` root key:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
media_storage_providers:
|
||||||
|
- module: s3_storage_provider.S3StorageProviderBackend
|
||||||
|
store_local: True # do we want to store on S3 media created by our users?
|
||||||
|
store_remote: True # do we want to store on S3 media created
|
||||||
|
# by users of others servers federated to ours?
|
||||||
|
store_synchronous: True # do we want to wait that the file has been written before returning?
|
||||||
|
config:
|
||||||
|
bucket: matrix # the name of our bucket, we chose matrix earlier
|
||||||
|
region_name: garage # only "garage" is supported for the region field
|
||||||
|
endpoint_url: http://localhost:3900 # the path to the S3 endpoint
|
||||||
|
access_key_id: "GKxxx" # your Key ID
|
||||||
|
secret_access_key: "xxxx" # your Secret Key
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that uploaded media will also be stored locally and this behavior can not be deactivated, it is even required for
|
||||||
|
some operations like resizing images.
|
||||||
|
In fact, your local filesysem is considered as a cache but without any automated way to garbage collect it.
|
||||||
|
|
||||||
|
We can build our garbage collector with `s3_media_upload`, a tool provided with the module.
|
||||||
|
If you installed the module with the command provided before, you should be able to bring it in your path:
|
||||||
|
|
||||||
|
```
|
||||||
|
PATH=$HOME/.local/bin/:$PATH
|
||||||
|
command -v s3_media_upload
|
||||||
|
```
|
||||||
|
|
||||||
|
Now we can write a simple script (eg `~/.local/bin/matrix-cache-gc`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
## CONFIGURATION ##
|
||||||
|
AWS_ACCESS_KEY_ID=GKxxx
|
||||||
|
AWS_SECRET_ACCESS_KEY=xxxx
|
||||||
|
S3_ENDPOINT=http://localhost:3900
|
||||||
|
S3_BUCKET=matrix
|
||||||
|
MEDIA_STORE=/var/lib/matrix-synapse/media
|
||||||
|
PG_USER=matrix
|
||||||
|
PG_PASS=xxxx
|
||||||
|
PG_DB=synapse
|
||||||
|
PG_HOST=localhost
|
||||||
|
PG_PORT=5432
|
||||||
|
|
||||||
|
## CODE ##
|
||||||
|
PATH=$HOME/.local/bin/:$PATH
|
||||||
|
cat > database.yaml <<EOF
|
||||||
|
user: $PG_USER
|
||||||
|
password: $PG_PASS
|
||||||
|
database: $PG_DB
|
||||||
|
host: $PG_HOST
|
||||||
|
port: $PG_PORT
|
||||||
|
EOF
|
||||||
|
|
||||||
|
s3_media_upload update-db 1d
|
||||||
|
s3_media_upload --no-progress check-deleted $MEDIA_STORE
|
||||||
|
s3_media_upload --no-progress upload $MEDIA_STORE $S3_BUCKET --delete --endpoint-url $S3_ENDPOINT
|
||||||
|
```
|
||||||
|
|
||||||
|
This script will list all the medias that were not accessed in the 24 hours according to your database.
|
||||||
|
It will check if, in this list, the file still exists in the local media store.
|
||||||
|
For files that are still in the cache, it will upload them to S3 if they are not already present (in case of a crash or an initial synchronisation).
|
||||||
|
Finally, the script will delete these files from the cache.
|
||||||
|
|
||||||
|
Make this script executable and check that it works:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x $HOME/.local/bin/matrix-cache-gc
|
||||||
|
matrix-cache-gc
|
||||||
|
```
|
||||||
|
|
||||||
|
Add it to your crontab. Open the editor with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
crontab -e
|
||||||
|
```
|
||||||
|
|
||||||
|
And add a new line. For example, to run it every 10 minutes:
|
||||||
|
|
||||||
|
```cron
|
||||||
|
*/10 * * * * $HOME/.local/bin/matrix-cache-gc
|
||||||
|
```
|
||||||
|
|
||||||
|
*External link:* [Github > matrix-org/synapse-s3-storage-provider](https://github.com/matrix-org/synapse-s3-storage-provider)
|
||||||
|
|
||||||
|
### matrix-media-repo (server independent)
|
||||||
|
|
||||||
|
*External link:* [matrix-media-repo Documentation > S3](https://docs.t2bot.io/matrix-media-repo/configuration/s3-datastore.html)
|
||||||
|
|
||||||
## Pixelfed
|
## Pixelfed
|
||||||
|
|
||||||
|
|
|
@ -1 +1,77 @@
|
||||||
# Websites (Hugo, Jekyll, Publii...)
|
# Websites (Hugo, Jekyll, Publii...)
|
||||||
|
|
||||||
|
Garage is also suitable to host static websites.
|
||||||
|
While they can be deployed with traditional CLI tools, some static website generators have integrated options to ease your workflow.
|
||||||
|
|
||||||
|
## Hugo
|
||||||
|
|
||||||
|
Add to your `config.toml` the following section:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[deployment.targets]]
|
||||||
|
URL = "s3://<bucket>?endpoint=<endpoint>&disableSSL=<bool>&s3ForcePathStyle=true®ion=garage"
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[deployment.targets]]
|
||||||
|
URL = "s3://my-blog?endpoint=localhost:9000&disableSSL=true&s3ForcePathStyle=true®ion=garage"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then inform hugo of your credentials:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export AWS_ACCESS_KEY_ID=GKxxx
|
||||||
|
export AWS_SECRET_ACCESS_KEY=xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
And finally deploy your website:
|
||||||
|
|
||||||
|
```bsh
|
||||||
|
hugo deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
*External links:*
|
||||||
|
- [gocloud.dev > aws > Supported URL parameters](https://pkg.go.dev/gocloud.dev/aws?utm_source=godoc#ConfigFromURLParams)
|
||||||
|
- [Hugo Documentation > hugo deploy](https://gohugo.io/hosting-and-deployment/hugo-deploy/)
|
||||||
|
|
||||||
|
## Publii
|
||||||
|
|
||||||
|
It would require a patch either on Garage or on Publii to make both systems work.
|
||||||
|
|
||||||
|
Currently, the proposed workaround is to deploy your website manually:
|
||||||
|
- On the left menu, click on Server, choose Manual Deployment (the logo looks like a compressed file)
|
||||||
|
- Set your website URL, keep Output type as "Non-compressed catalog"
|
||||||
|
- Click on Save changes
|
||||||
|
- Click on Sync your website (bottom left of the app)
|
||||||
|
- On the new page, click again on Sync your website
|
||||||
|
- Click on Get website files
|
||||||
|
- You need to synchronize the output folder you see in your file explorer, we will use minio client.
|
||||||
|
|
||||||
|
Be sure that you [configured minio client](cli.html#minio-client-recommended).
|
||||||
|
|
||||||
|
Then copy this output folder
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mc mirror --overwrite output garage/my-site
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generic (eg. Jekyll)
|
||||||
|
|
||||||
|
Some tools do not support sending to a S3 backend but output a compiled folder on your system.
|
||||||
|
We can then use any CLI tool to upload this content to our S3 target.
|
||||||
|
|
||||||
|
First, start by [configuring minio client](cli.html#minio-client-recommended).
|
||||||
|
|
||||||
|
Then build your website:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jekyll build
|
||||||
|
```
|
||||||
|
|
||||||
|
And copy jekyll's output folder on S3:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mc mirror --overwrite _site garage/my-site
|
||||||
|
```
|
||||||
|
|
48
doc/book/src/cookbook/exposing_websites.md
Normal file
48
doc/book/src/cookbook/exposing_websites.md
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# Exposing buckets as websites
|
||||||
|
|
||||||
|
You can expose your bucket as a website with this simple command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
garage bucket website --allow my-website
|
||||||
|
```
|
||||||
|
|
||||||
|
Now it will be **publicly** exposed on the web endpoint (by default listening on port 3902).
|
||||||
|
|
||||||
|
Our website serving logic is as follow:
|
||||||
|
- Supports only static websites (no support for PHP or other languages)
|
||||||
|
- Does not support directory listing
|
||||||
|
- The index is defined in your `garage.toml`. ([ref](/reference_manual/configuration.html#index))
|
||||||
|
|
||||||
|
Now we need to infer the URL of your website through your bucket name.
|
||||||
|
Let assume:
|
||||||
|
- we set `root_domain = ".web.example.com"` in `garage.toml` ([ref](/reference_manual/configuration.html#root_domain))
|
||||||
|
- our bucket name is `garagehq.deuxfleurs.fr`.
|
||||||
|
|
||||||
|
Our bucket will be served if the Host field matches one of these 2 values (the port is ignored):
|
||||||
|
|
||||||
|
- `garagehq.deuxfleurs.fr.web.example.com`: you can dedicate a subdomain to your users (here `web.example.com`).
|
||||||
|
|
||||||
|
- `garagehq.deuxfleurs.fr`: your users can bring their own domain name, they just need to point them to your Garage cluster.
|
||||||
|
|
||||||
|
You can try this logic locally, without configuring any DNS, thanks to `curl`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# prepare your test
|
||||||
|
echo hello world > /tmp/index.html
|
||||||
|
mc cp /tmp/index.html garage/garagehq.deuxfleurs.fr
|
||||||
|
|
||||||
|
curl -H 'Host: garagehq.deuxfleurs.fr' http://localhost:3902
|
||||||
|
# should print "hello world"
|
||||||
|
|
||||||
|
curl -H 'Host: garagehq.deuxfleurs.fr.web.example.com' http://localhost:3902
|
||||||
|
# should also print "hello world"
|
||||||
|
```
|
||||||
|
|
||||||
|
Now that you understand how website logic works on Garage, you can:
|
||||||
|
|
||||||
|
- make the website endpoint listens on port 80 (instead of 3902)
|
||||||
|
- use iptables to redirect the port 80 to the port 3902:
|
||||||
|
`iptables -t nat -A PREROUTING -p tcp -dport 80 -j REDIRECT -to-port 3902`
|
||||||
|
- or configure a [reverse proxy](reverse_proxy.html) in front of Garage to add TLS (HTTPS), CORS support, etc.
|
||||||
|
|
||||||
|
You can also take a look at [Website Integration](/connect/websites.html) to see how you can add Garage to your workflow.
|
31
doc/book/src/cookbook/gateways.md
Normal file
31
doc/book/src/cookbook/gateways.md
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Gateways
|
||||||
|
|
||||||
|
Gateways allow you to expose Garage endpoints (S3 API and websites) without storing data on the node.
|
||||||
|
|
||||||
|
## Benefits
|
||||||
|
|
||||||
|
You can configure Garage as a gateway on all nodes that will consume your S3 API, it will provide you the following benefits:
|
||||||
|
|
||||||
|
- **It removes 1 or 2 network RTT** Instead of (querying your reverse proxy then) querying a random node of the cluster that will forward your request to the nodes effectively storing the data, your local gateway will directly knows which node to query.
|
||||||
|
|
||||||
|
- **It ease server management** Instead of tracking in your reverse proxy and DNS what are the current Garage nodes, your gateway being part of the cluster keeps this information for you. In your software, you will always specify `http://localhost:3900`.
|
||||||
|
|
||||||
|
- **It simplifies security** Instead of having to maintain and renew a TLS certificate, you leverage the Secret Handshake protocol we use for our cluster. The S3 API protocol will be in plain text but limited to your local machine.
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
Currently it will not work with minio client. Follow issue [#64](https://git.deuxfleurs.fr/Deuxfleurs/garage/issues/64) for more information.
|
||||||
|
|
||||||
|
## Spawn a Gateway
|
||||||
|
|
||||||
|
The instructions are similar to a regular node, the only option that is different is while configuring the node, you must set the `--gateway` parameter:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
garage node configure --gateway --tag gw1 xxxx
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use `http://localhost:3900` when a S3 endpoint is required:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
aws --endpoint-url http://127.0.0.1:3900 s3 ls
|
||||||
|
```
|
|
@ -1 +1,165 @@
|
||||||
# Configuring a reverse proxy
|
# 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 {
|
||||||
|
listen [::]:443 http2 ssl;
|
||||||
|
ssl_certificate /tmp/garage.crt;
|
||||||
|
ssl_certificate_key /tmp/garage.key;
|
||||||
|
|
||||||
|
# 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;
|
||||||
|
add_header Access-Control-Allow-Headers Range;
|
||||||
|
|
||||||
|
# We do not forward OPTIONS requests to Garage
|
||||||
|
# as it does not support them but they are needed for CORS.
|
||||||
|
if ($request_method = OPTIONS) {
|
||||||
|
return 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy_pass http://web_backend;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Apache httpd
|
||||||
|
|
||||||
|
@TODO
|
||||||
|
|
||||||
|
## Traefik
|
||||||
|
|
||||||
|
@TODO
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
# Starting Garage with systemd instead of Docker
|
# Starting Garage with systemd
|
||||||
|
|
||||||
|
We make some assumptions for this systemd deployment.
|
||||||
|
|
||||||
|
- Your garage binary is located at `/usr/local/bin/garage`.
|
||||||
|
|
||||||
|
- Your configuration file is located at `/etc/garage.toml`.
|
||||||
|
|
||||||
|
- Your `garage.toml` must be set with `metadata_dir=/var/lib/garage/meta` and `data_dir=/var/lib/garage/data`. This is mandatory to use `systemd` hardening feature [Dynamic User](https://0pointer.net/blog/dynamic-users-with-systemd.html). Note that in your host filesystem, Garage data will be held in `/var/lib/private/garage`.
|
||||||
|
|
||||||
NOTE: This guide is incomplete. Typicall you would also want to create a separate
|
|
||||||
Unix user to run Garage.
|
|
||||||
|
|
||||||
Make sure you have the Garage binary installed on your system (see [quick start](../quick_start/index.md)), e.g. at `/usr/local/bin/garage`.
|
|
||||||
|
|
||||||
Create a file named `/etc/systemd/system/garage.service`:
|
Create a file named `/etc/systemd/system/garage.service`:
|
||||||
|
|
||||||
|
@ -15,12 +20,18 @@ Wants=network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Environment='RUST_LOG=garage=info' 'RUST_BACKTRACE=1'
|
Environment='RUST_LOG=garage=info' 'RUST_BACKTRACE=1'
|
||||||
ExecStart=/usr/local/bin/garage server -c /etc/garage/garage.toml
|
ExecStart=/usr/local/bin/garage server
|
||||||
|
StateDirectory=garage
|
||||||
|
DynamicUser=true
|
||||||
|
ProtectHome=true
|
||||||
|
NoNewPrivileges=true
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
```
|
```
|
||||||
|
|
||||||
|
*A note on hardening: garage will be run as a non privileged user, its user id is dynamically allocated by systemd. It cannot access (read or write) home folders (/home, /root and /run/user), the rest of the filesystem can only be read but not written, only the path seen as /var/lib/garage is writable as seen by the service (mapped to /var/lib/private/garage on your host). Additionnaly, the process can not gain new privileges over time.*
|
||||||
|
|
||||||
To start the service then automatically enable it at boot:
|
To start the service then automatically enable it at boot:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
Loading…
Reference in a new issue