124 lines
3 KiB
Markdown
124 lines
3 KiB
Markdown
|
---
|
||
|
tags: [S3, AWS]
|
||
|
created: Monday, August 11, 2025
|
||
|
---
|
||
|
|
||
|
## What is Garage?
|
||
|
|
||
|
Garage is software that enables you to create an S3-like object storage solution
|
||
|
outside of the AWS infrastructure on servers you maintain yourself.
|
||
|
|
||
|
It incorporates methods and operations from the S3 API and SDK (e.g.
|
||
|
`GetBucket`, `ListBuckets` etc. ) and is compatible with the `awscli` tool.
|
||
|
|
||
|
I set Garage up on my VPS so that I can leverage object storage as and when I
|
||
|
need it. My primary motivation was to be able to access images from a public URL
|
||
|
from within my home-made Zettelkasten software. Configuring unauthenticated
|
||
|
public access is not as straightforward as S3 but it is possible, as I will
|
||
|
demonstrate.
|
||
|
|
||
|
## Installation
|
||
|
|
||
|
First I installed Garage and added the binary to the `$PATH` on my VPS running
|
||
|
Debian.
|
||
|
|
||
|
```sh
|
||
|
wget https://garagehq.deuxfleurs.fr/_releases/v2.0.0/x86_64-unknown-linux-musl/garage
|
||
|
chmod +x garage
|
||
|
sudo mv garage /usr/local/bin
|
||
|
```
|
||
|
|
||
|
## Configuration file
|
||
|
|
||
|
I created the following config file at `/etc/garage.toml`:
|
||
|
|
||
|
```toml
|
||
|
metadata_dir = "/data/sqlite/garage-metadata"
|
||
|
data_dir = "/mnt/storagebox_alpha/garage"
|
||
|
db_engine = "sqlite"
|
||
|
|
||
|
replication_factor = 1
|
||
|
|
||
|
rpc_bind_addr = "[::]:3901"
|
||
|
rpc_public_addr = "127.0.0.1:3901"
|
||
|
rpc_secret = "<uuid>"
|
||
|
|
||
|
[s3_api]
|
||
|
s3_region = "garage"
|
||
|
api_bind_addr = "0.0.0.0:3900"
|
||
|
root_domain = ".s3.garage.localhost"
|
||
|
|
||
|
[s3_web]
|
||
|
bind_addr = "[::]:3902"
|
||
|
root_domain = ".web.garage.localhost"
|
||
|
index = "index.html"
|
||
|
```
|
||
|
|
||
|
The key points:
|
||
|
|
||
|
- `data_dir` is where the bucket data will be stored. This is mapped to my
|
||
|
network-attached storage device on the VPS (`storagebox_alpha`)
|
||
|
- Garage allows you to replicate and distribute your data over multiple zones
|
||
|
for security and redundancy. I don't need this so the `replication_factor` is
|
||
|
`1`
|
||
|
- Garage runs locally on the server on the `3901` port. Later I will expose this
|
||
|
to the Internet via my reverse proxy.
|
||
|
|
||
|
## Running the Garage server
|
||
|
|
||
|
Having created the config file, I can start the server:
|
||
|
|
||
|
```sh
|
||
|
garage server
|
||
|
```
|
||
|
|
||
|
You'll notice all the standard AWS S3 methods being invoked in the logs:
|
||
|
|
||
|
// ADD PICTURE
|
||
|
|
||
|
I also confirm the instance is running:
|
||
|
|
||
|
```sh
|
||
|
garage status
|
||
|
|
||
|
==== HEALTHY NODES ====
|
||
|
ID Hostname Address Tags Zone Capacity DataAvail Version
|
||
|
<redacted> self-host-server 127.0.0.1:3901 NO ROLE ASSIGNED v2.0.0
|
||
|
```
|
||
|
|
||
|
In order to start the Garage server automatically on boot, I created a `systemd`
|
||
|
service. This way I don't need to restart Garage whenever I restart my VPS.
|
||
|
|
||
|
```
|
||
|
[Unit]
|
||
|
Description=Garage Object Storage
|
||
|
After=network.target
|
||
|
Wants=network.target
|
||
|
|
||
|
[Service]
|
||
|
Type=simple
|
||
|
User=thomas
|
||
|
Group=thomas
|
||
|
ExecStart=/usr/local/bin/garage server
|
||
|
WorkingDirectory=/data/sqlite
|
||
|
Restart=always
|
||
|
RestartSec=5
|
||
|
StandardOutput=journal
|
||
|
StandardError=journal
|
||
|
|
||
|
[Install]
|
||
|
WantedBy=multi-user.target
|
||
|
```
|
||
|
|
||
|
I killed the earlier instance of the server and then activated the `systemd`
|
||
|
service:
|
||
|
|
||
|
```sh
|
||
|
sudo systemctl enable garage
|
||
|
sudo systemctl start garage
|
||
|
```
|
||
|
|
||
|
## Creating a layout
|
||
|
|
||
|
## Creating a bucket
|