Garage

Garage is a lightweight geo-distributed data store that implements the Amazon S3 object storage protocol. It enables applications to store large blobs such as pictures, video, images, documents, etc., in a redundant multi-node setting. S3 is versatile enough to also be used to publish a static website.

Setup

This first configuration file should allow you to get started easily with the simplest possible Garage deployment.

We will create it with the following command line to generate unique and private secrets for security reasons:

cat > garage.toml <<EOF
metadata_dir = "/tmp/meta"
data_dir = "/tmp/data"
db_engine = "sqlite"
 
replication_factor = 1
 
rpc_bind_addr = "[::]:3901"
rpc_public_addr = "127.0.0.1:3901"
rpc_secret = "$(openssl rand -hex 32)"
 
[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"
root_domain = ".s3.garage.localhost"
 
[s3_web]
bind_addr = "[::]:3902"
root_domain = ".web.garage.localhost"
index = "index.html"
 
[k2v_api]
api_bind_addr = "[::]:3904"
 
[admin]
api_bind_addr = "[::]:3903"
admin_token = "$(openssl rand -base64 32)"
metrics_token = "$(openssl rand -base64 32)"
EOF

See the Configuration file format documentation for complete options and values.

Now that your configuration file has been created, you may save it to the directory of your choice. By default, Garage looks for /etc/garage.toml. You can also store it somewhere else, but you will have to specify -c path/to/garage.toml at each invocation of the garage binary (for example: garage -c ./garage.toml server, garage -c ./garage.toml status).

As you can see, the rpc_secret is a 32 bytes hexadecimal string. You can regenerate it with openssl rand -hex 32. If you target a cluster deployment with multiple nodes, make sure that you use the same value for all nodes.

As you can see in the metadata_dir and data_dir parameters, we are saving Garage’s data in /tmp which gets erased when your system reboots. This means that data stored on this Garage server will not be persistent. Change these to locations on your local disk if you want your data to be persisted properly.

Use the following command to launch the Garage server:

garage -c path/to/garage.toml server

Alternatively, if you cannot or do not wish to run the Garage binary directly, you may use Docker to run Garage in a container using the following command:

docker run \
  -d \
  --name garaged \
  -p 3900:3900 -p 3901:3901 -p 3902:3902 -p 3903:3903 \
  -v /path/to/garage.toml:/etc/garage.toml \
  -v /path/to/garage/meta:/var/lib/garage/meta \
  -v /path/to/garage/data:/var/lib/garage/data \
  dxflrs/garage:v2.0.0

The garage utility is also used as a CLI tool to configure your Garage deployment. It uses values from the TOML configuration file to find the Garage daemon running on the local node, therefore if your configuration file is not at /etc/garage.toml you will again have to specify -c path/to/garage.toml at each invocation.

If you are running Garage in a Docker container, you can set alias garage="docker exec -ti <container name> /garage" to use the Garage binary inside your container.

If the garage CLI is able to correctly detect the parameters of your local Garage node, the following command should be enough to show the status of your cluster:

garage status

This should show something like this:

==== HEALTHY NODES ====
ID                 Hostname  Address         Tag                   Zone  Capacity
563e1ac825ee3323   linuxbox  127.0.0.1:3901  NO ROLE ASSIGNED

Creating a cluster layout for a Garage deployment means informing Garage of the disk space available on each node of the cluster, -c, as well as the name of the zone (e.g. datacenter), -z, each machine is located in.

For our test deployment, we are have only one node with zone named dc1 and a capacity of 1G, though the capacity is ignored for a single node deployment and can be changed later when adding new nodes.

garage layout assign -z dc1 -c 1G <node_id>

where <node_id> corresponds to the identifier of the node shown by garage status (first column). You can enter simply a prefix of that identifier. For instance here you could write just garage layout assign -z dc1 -c 1G 563e.

The layout then has to be applied to the cluster, using:

garage layout apply --version 1

In this section, we will suppose that we want to create a bucket named nextcloud-bucket that will be accessed through a key named nextcloud-app-key.

First, create a bucket with the following command:

garage bucket create nextcloud-bucket

Check that everything went well:

garage bucket list
garage bucket info nextcloud-bucket

The nextcloud-bucket bucket now exists on the Garage server, however it cannot be accessed until we add an API key with the proper access rights.

Note that API keys are independent of buckets: one key can access multiple buckets, multiple keys can access one bucket.

Create an API key using the following command:

garage key create nextcloud-app-key

The output should look as follows:

Key name: nextcloud-app-key
Key ID: GK3515373e4c851ebaad366558
Secret key: 7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34
Authorized buckets:

Check that everything works as intended:

garage key list
garage key info nextcloud-app-key

Now that we have a bucket and a key, we need to give permissions to the key on the bucket:

garage bucket allow \
  --read \
  --write \
  --owner \
  nextcloud-bucket \
  --key nextcloud-app-key

You can check at any time the allowed keys on your bucket with:

garage bucket info nextcloud-bucket