### Golang SDK Installation Source: https://garagehq.deuxfleurs.fr/documentation/build/golang Install the SDK using the go get command. ```bash go get git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang ``` -------------------------------- ### Install Garage Admin SDK Source: https://garagehq.deuxfleurs.fr/documentation/build/javascript Install the Garage Administration SDK using npm. This command installs the SDK directly from the Git repository. ```bash npm install --save git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git ``` -------------------------------- ### Garage Admin SDK Source: https://garagehq.deuxfleurs.fr/documentation/build/python This section provides instructions on installing and using the Garage Admin SDK for Python to manage Garage instances. It includes examples of initializing the client, interacting with nodes, managing layouts, creating keys, and managing buckets. ```APIDOC ## Admin API ### Installation ``` pip3 install --user 'git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-python' ``` ### Usage Example ```python import garage_admin_sdk from garage_admin_sdk.apis import * from garage_admin_sdk.models import * configuration = garage_admin_sdk.Configuration( host = "http://localhost:3903/v1", access_token = "s3cr3t" ) # Init APIs api = garage_admin_sdk.ApiClient(configuration) nodes, layout, keys, buckets = NodesApi(api), LayoutApi(api), KeyApi(api), BucketApi(api) # Display some info on the node status = nodes.get_nodes() print(f"running garage {status.garage_version}, node_id {status.node}") # Change layout of this node current = layout.get_layout() layout.add_layout([ NodeRoleChange( id = status.node, zone = "dc1", capacity = 1000000000, tags = [ "dev" ], ) ]) layout.apply_layout(LayoutVersion( version = current.version + 1 )) # Create key, allow it to create buckets kinfo = keys.add_key(AddKeyRequest(name="openapi")) allow_create = UpdateKeyRequestAllow(create_bucket=True) keys.update_key(kinfo.access_key_id, UpdateKeyRequest(allow=allow_create)) # Create a bucket, allow key, set quotas binfo = buckets.create_bucket(CreateBucketRequest(global_alias="documentation")) binfo = buckets.allow_bucket_key(AllowBucketKeyRequest( bucket_id=binfo.id, access_key_id=kinfo.access_key_id, permissions=AllowBucketKeyRequestPermissions(read=True, write=True, owner=True), )) binfo = buckets.update_bucket(binfo.id, UpdateBucketRequest( quotas=UpdateBucketRequestQuotas(max_size=19029801,max_objects=1500))) # Display key print(f""" cluster ready key id is {kinfo.access_key_id} secret key is {kinfo.secret_access_key} bucket {binfo.global_aliases[0]} contains {binfo.objects}/{binfo.quotas.max_objects} objects """) ``` See also: * sdk repo * examples ``` -------------------------------- ### Install Garage on NixOS Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/binary-packages Use nix-shell to install and run Garage on NixOS. ```bash nix-shell -p garage ``` -------------------------------- ### Install Garage on FreeBSD Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/binary-packages Install the Garage package on FreeBSD using pkg. ```bash pkg install garage ``` -------------------------------- ### Install Garage with Default Options Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/kubernetes Install the Garage Helm chart using default configuration options. Ensure the namespace 'garage' is created. ```bash helm install --create-namespace --namespace garage garage ./garage ``` -------------------------------- ### Golang SDK Example: Nodes, Keys, and Buckets Source: https://garagehq.deuxfleurs.fr/documentation/build/golang This example demonstrates initializing the SDK, managing nodes, creating and updating keys, and creating and updating buckets. It includes error handling and deferred cleanup operations. ```go package main import ( "context" "fmt" "os" "strings" garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang" ) func main() { // Initialization configuration := garage.NewConfiguration() configuration.Host = "127.0.0.1:3903" client := garage.NewAPIClient(configuration) ctx := context.WithValue(context.Background(), garage.ContextAccessToken, "s3cr3t") // Nodes fmt.Println("--- nodes ---") nodes, _, _ := client.NodesApi.GetNodes(ctx).Execute() fmt.Fprintf(os.Stdout, "First hostname: %v\n", nodes.KnownNodes[0].Hostname) capa := int64(1000000000) change := []garage.NodeRoleChange{ garage.NodeRoleChange{NodeRoleUpdate: &garage.NodeRoleUpdate { Id: *nodes.KnownNodes[0].Id, Zone: "dc1", Capacity: *garage.NewNullableInt64(&capa), Tags: []string{ "fast", "amd64" }, }}, } staged, _, _ := client.LayoutApi.AddLayout(ctx).NodeRoleChange(change).Execute() msg, _, _ := client.LayoutApi.ApplyLayout(ctx).LayoutVersion(*garage.NewLayoutVersion(staged.Version + 1)).Execute() fmt.Printf(strings.Join(msg.Message, "\n")) // Layout configured health, _, _ := client.NodesApi.GetHealth(ctx).Execute() fmt.Printf("Status: %s, nodes: %v/%v, storage: %v/%v, partitions: %v/%v\n", health.Status, health.ConnectedNodes, health.KnownNodes, health.StorageNodesOk, health.StorageNodes, health.PartitionsAllOk, health.Partitions) // Key fmt.Println("\n--- key ---") key := "openapi-key" keyInfo, _, _ := client.KeyApi.AddKey(ctx).AddKeyRequest(garage.AddKeyRequest{Name: *garage.NewNullableString(&key) }).Execute() defer client.KeyApi.DeleteKey(ctx).Id(*keyInfo.AccessKeyId).Execute() fmt.Printf("AWS_ACCESS_KEY_ID=%s\nAWS_SECRET_ACCESS_KEY=%s\n", *keyInfo.AccessKeyId, *keyInfo.SecretAccessKey.Get()) id := *keyInfo.AccessKeyId canCreateBucket := true updateKeyRequest := *garage.NewUpdateKeyRequest() updateKeyRequest.SetName("openapi-key-updated") updateKeyRequest.SetAllow(garage.UpdateKeyRequestAllow { CreateBucket: &canCreateBucket }) update, _, _ := client.KeyApi.UpdateKey(ctx).Id(id).UpdateKeyRequest(updateKeyRequest).Execute() fmt.Printf("Updated %v with key name %v\n", *update.AccessKeyId, *update.Name) keyList, _, _ := client.KeyApi.ListKeys(ctx).Execute() fmt.Printf("Keys count: %v\n", len(keyList)) // Bucket fmt.Println("\n--- bucket ---") global_name := "global-ns-openapi-bucket" local_name := "local-ns-openapi-bucket" bucketInfo, _, _ := client.BucketApi.CreateBucket(ctx).CreateBucketRequest(garage.CreateBucketRequest{ GlobalAlias: &global_name, LocalAlias: &garage.CreateBucketRequestLocalAlias { AccessKeyId: keyInfo.AccessKeyId, Alias: &local_name, }, }).Execute() defer client.BucketApi.DeleteBucket(ctx).Id(*bucketInfo.Id).Execute() fmt.Printf("Bucket id: %s\n", *bucketInfo.Id) updateBucketRequest := *garage.NewUpdateBucketRequest() website := garage.NewUpdateBucketRequestWebsiteAccess() website.SetEnabled(true) website.SetIndexDocument("index.html") website.SetErrorDocument("errors/4xx.html") updateBucketRequest.SetWebsiteAccess(*website) quotas := garage.NewUpdateBucketRequestQuotas() quotas.SetMaxSize(1000000000) quotas.SetMaxObjects(999999999) updateBucketRequest.SetQuotas(*quotas) updatedBucket, _, _ := client.BucketApi.UpdateBucket(ctx).Id(*bucketInfo.Id).UpdateBucketRequest(updateBucketRequest).Execute() fmt.Printf("Bucket %v website activation: %v\n", *updatedBucket.Id, *updatedBucket.WebsiteAccess) bucketList, _, _ := client.BucketApi.ListBuckets(ctx).Execute() fmt.Printf("Bucket count: %v\n", len(bucketList)) } ``` -------------------------------- ### Install Golang Garage Admin SDK Source: https://garagehq.deuxfleurs.fr/documentation/build/golang Use this command to install the Golang SDK for the Garage administration API. Ensure your Go environment is set up correctly. ```bash go get git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang ``` -------------------------------- ### Check Nix Installation Source: https://garagehq.deuxfleurs.fr/documentation/development/devenv Verify that Nix is installed and accessible in your environment. ```bash nix-shell --version nix-build --version nix-env --version ``` -------------------------------- ### Install Garage with Custom Values Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/kubernetes Install the Garage Helm chart with custom configurations defined in a 'values.override.yaml' file. ```bash helm install --create-namespace --namespace garage garage ./garage -f values.override.yaml ``` -------------------------------- ### Full Garage TOML Configuration Example Source: https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration This example demonstrates all available configuration options for a Garage daemon. It covers settings for replication, consistency, storage directories, filesystem synchronization, database engine, block size, RPC security and addressing, peer discovery, and integration with Consul, Kubernetes, S3, and admin interfaces. ```toml replication_factor = 3 consistency_mode = "consistent" metadata_dir = "/var/lib/garage/meta" data_dir = "/var/lib/garage/data" metadata_snapshots_dir = "/var/lib/garage/snapshots" metadata_fsync = true data_fsync = false disable_scrub = false use_local_tz = false metadata_auto_snapshot_interval = "6h" db_engine = "lmdb" block_size = "1M" block_ram_buffer_max = "256MiB" block_max_concurrent_reads = 16 block_max_concurrent_writes_per_request =10 lmdb_map_size = "1T" compression_level = 1 rpc_secret = "4425f5c26c5e11581d3223904324dcb5b5d5dfb14e5e7f35e38c595424f5f1e6" rpc_bind_addr = "[::]:3901" rpc_bind_outgoing = false rpc_public_addr = "[fc00:1::1]:3901" # or set rpc_public_adr_subnet to filter down autodiscovery to a subnet: # rpc_public_addr_subnet = "2001:0db8:f00:b00:/64" allow_world_readable_secrets = false bootstrap_peers = [ "563e1ac825ee3323aa441e72c26d1030d6d4414aeb3dd25287c531e7fc2bc95d@[fc00:1::1]:3901", "86f0f26ae4afbd59aaf9cfb059eefac844951efd5b8caeec0d53f4ed6c85f332@[fc00:1::2]:3901", "681456ab91350f92242e80a531a3ec9392cb7c974f72640112f90a600d7921a4@[fc00:B::1]:3901", "212fd62eeaca72c122b45a7f4fa0f55e012aa5e24ac384a72a3016413fa724ff@[fc00:F::1]:3901", ] allow_punycode = false [consul_discovery] api = "catalog" consul_http_addr = "https://127.0.0.1:8500" tls_skip_verify = false service_name = "garage-daemon" ca_cert = "/etc/consul/consul-ca.crt" # for `agent` API mode, unset client_cert and client_key: client_cert = "/etc/consul/consul-client.crt" client_key = "/etc/consul/consul-key.crt" # optionally enable `token` for authentication: # token = "abcdef-01234-56789" tags = [ "dns-enabled" ] meta = { dns-acl = "allow trusted" } datacenters = ["dc1", "dc2", "dc3"] [kubernetes_discovery] namespace = "garage" service_name = "garage-daemon" skip_crd = false [s3_api] api_bind_addr = "[::]:3900" s3_region = "garage" root_domain = ".s3.garage" [s3_web] bind_addr = "[::]:3902" root_domain = ".web.garage" add_host_to_metrics = true [admin] api_bind_addr = "0.0.0.0:3903" metrics_token = "BCAdFjoa9G0KJR0WXnHHm7fs1ZAbfpI8iIZ+Z/a2NgI=" metrics_require_token = true admin_token = "UkLeGWEvHnXBqnueR3ISEMWpOnm40jH2tM2HnnL/0F4=" trace_sink = "http://localhost:4317" ``` -------------------------------- ### Install synapse-s3-storage-provider Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Install the Synapse S3 storage provider module using pip. ```bash pip3 install --user git+https://github.com/matrix-org/synapse-s3-storage-provider.git ``` -------------------------------- ### Start and Enable Garage systemd Service Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/systemd Commands to start the Garage service immediately and enable it to launch automatically on system boot. ```bash sudo systemctl start garage sudo systemctl enable garage ``` -------------------------------- ### Install Minio SDK for S3 Source: https://garagehq.deuxfleurs.fr/documentation/build/python Install the Minio SDK using pip. This is the first step to interact with Garage's S3 compatible API. ```bash pip3 install minio ``` -------------------------------- ### Install Garage on Arch Linux Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/binary-packages Install Garage from the official repositories on Arch Linux using pacman. ```bash pacman -S garage ``` -------------------------------- ### Install Garage Admin SDK Source: https://garagehq.deuxfleurs.fr/documentation/build/python Install the Garage Admin SDK for Python. This command is specific due to the package being in a subfolder. ```bash pip3 install --user 'git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-python' ``` -------------------------------- ### Administration SDK - Bucket API Source: https://garagehq.deuxfleurs.fr/documentation/build/golang Example demonstrating how to create, update, and list buckets using the Bucket API. It includes setting website access, quotas, and deferring bucket deletion. ```go package main import ( "context" "fmt" "os" "strings" garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang" ) func main() { // Initialization configuration := garage.NewConfiguration() configuration.Host = "127.0.0.1:3903" client := garage.NewAPIClient(configuration) ctx := context.WithValue(context.Background(), garage.ContextAccessToken, "s3cr3t") // Key (needed for bucket creation example) key := "openapi-key" keyInfo, _, _ := client.KeyApi.AddKey(ctx).AddKeyRequest(garage.AddKeyRequest{Name: *garage.NewNullableString(&key) }).Execute() defer client.KeyApi.DeleteKey(ctx).Id(*keyInfo.AccessKeyId).Execute() // Bucket fmt.Println("--- bucket ---") global_name := "global-ns-openapi-bucket" local_name := "local-ns-openapi-bucket" bucketInfo, _, _ := client.BucketApi.CreateBucket(ctx).CreateBucketRequest(garage.CreateBucketRequest{ GlobalAlias: &global_name, LocalAlias: &garage.CreateBucketRequestLocalAlias { AccessKeyId: keyInfo.AccessKeyId, Alias: &local_name, }, }).Execute() defer client.BucketApi.DeleteBucket(ctx).Id(*bucketInfo.Id).Execute() fmt.Printf("Bucket id: %s\n", *bucketInfo.Id) updateBucketRequest := *garage.NewUpdateBucketRequest() website := garage.NewUpdateBucketRequestWebsiteAccess() website.SetEnabled(true) website.SetIndexDocument("index.html") website.SetErrorDocument("errors/4xx.html") updateBucketRequest.SetWebsiteAccess(*website) quotas := garage.NewUpdateBucketRequestQuotas() quotas.SetMaxSize(1000000000) quotas.SetMaxObjects(999999999) updateBucketRequest.SetQuotas(*quotas) updatedBucket, _, _ := client.BucketApi.UpdateBucket(ctx).Id(*bucketInfo.Id).UpdateBucketRequest(updateBucketRequest).Execute() fmt.Printf("Bucket %v website activation: %v\n", *updatedBucket.Id, *updatedBucket.WebsiteAccess) bucketList, _, _ := client.BucketApi.ListBuckets(ctx).Execute() fmt.Printf("Bucket count: %v\n", len(bucketList)) } ``` -------------------------------- ### Install C Toolchain on Debian Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/from-source Installs the essential C build tools on Debian-based systems using apt-get. ```bash sudo apt-get update sudo apt-get install build-essential ``` -------------------------------- ### Configure Minio Client for Development Source: https://garagehq.deuxfleurs.fr/documentation/development/scripts Sources the environment for the minio-client (mc) to interact with the development cluster. Includes examples for listing and copying files. ```bash source ./script/dev-env-mc.sh # some examples mc ls garage/ mc cp /proc/cpuinfo garage/eprouvette/cpuinfo.txt ``` -------------------------------- ### Start Test Cluster Daemons Source: https://garagehq.deuxfleurs.fr/documentation/development/scripts Launches three Garage instances with associated configuration files. Also starts a socat-based HTTPS reverse proxy for the S3 endpoint on port 4443. Inspect `/tmp/config.1` for instance-specific details. ```bash ./script/dev-cluster.sh ``` -------------------------------- ### duck CLI Profile Directory Setup Source: https://garagehq.deuxfleurs.fr/documentation/connect/cli Create the necessary directory structure for duck connection profiles. ```bash mkdir -p ~/.duck/profiles/ ``` -------------------------------- ### Administration SDK - Key API Source: https://garagehq.deuxfleurs.fr/documentation/build/golang Example demonstrating how to add, update, and list keys using the Key API. It also includes deferring the deletion of the added key. ```go package main import ( "context" "fmt" "os" "strings" garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang" ) func main() { // Initialization configuration := garage.NewConfiguration() configuration.Host = "127.0.0.1:3903" client := garage.NewAPIClient(configuration) ctx := context.WithValue(context.Background(), garage.ContextAccessToken, "s3cr3t") // Key fmt.Println("--- key ---") key := "openapi-key" keyInfo, _, _ := client.KeyApi.AddKey(ctx).AddKeyRequest(garage.AddKeyRequest{Name: *garage.NewNullableString(&key) }).Execute() defer client.KeyApi.DeleteKey(ctx).Id(*keyInfo.AccessKeyId).Execute() fmt.Printf("AWS_ACCESS_KEY_ID=%s\nAWS_SECRET_ACCESS_KEY=%s\n", *keyInfo.AccessKeyId, *keyInfo.SecretAccessKey.Get()) id := *keyInfo.AccessKeyId canCreateBucket := true updateKeyRequest := *garage.NewUpdateKeyRequest() updateKeyRequest.SetName("openapi-key-updated") updateKeyRequest.SetAllow(garage.UpdateKeyRequestAllow { CreateBucket: &canCreateBucket }) update, _, _ := client.KeyApi.UpdateKey(ctx).Id(id).UpdateKeyRequest(updateKeyRequest).Execute() fmt.Printf("Updated %v with key name %v\n", *update.AccessKeyId, *update.Name) keyList, _, _ := client.KeyApi.ListKeys(ctx).Execute() fmt.Printf("Keys count: %v\n", len(keyList)) } ``` -------------------------------- ### Install Garage Binary Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/from-source Copies the compiled Garage release binary to /usr/local/bin/ to make the 'garage' command available system-wide. ```bash sudo cp target/release/garage /usr/local/bin/garage ``` -------------------------------- ### Clone Repository with Nix Source: https://garagehq.deuxfleurs.fr/documentation/development/devenv Clone the project repository. Install Git using Nix if it's not already available. ```bash git clone https://git.deuxfleurs.fr/Deuxfleurs/garage cd garage ``` -------------------------------- ### Create Ente Bucket and Key with Garage Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Use Garage CLI commands to create a bucket and a key for Ente. The key must be set as owner for temporary CORS setup. ```bash garage bucket create ente garage key create ente-key # For the CORS setup to work, the key needs to be --owner as well, at least temporarily. garage bucket allow ente --read --write --owner --key ente-key ``` -------------------------------- ### Example Garage Status Output Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/real-world This is an example of the expected output when running `garage status` on a single-node cluster before nodes have established communication. ```text Mercury$ garage status ==== HEALTHY NODES ==== ID Hostname Address Tag Zone Capacity 563e1ac825ee3323… Mercury [fc00:1::1]:3901 NO ROLE ASSIGNED ``` -------------------------------- ### Get Help for Garage CLI Commands Source: https://garagehq.deuxfleurs.fr/documentation Use the `help` command to get general assistance or `--help` flags for specific commands to understand their usage and options. ```bash garage help garage bucket allow --help ``` -------------------------------- ### Listing Admin Tokens Source: https://garagehq.deuxfleurs.fr/documentation/reference-manual/admin-api Example output of the command to list existing administration tokens. ```APIDOC ## garage admin-token list ### Description Lists all existing administration tokens, including their ID, creation date, name, expiration, and scope. ### Output Example ``` ID Created Name Expiration Scope - - metrics_token (from daemon configuration) never Metrics 8ed1830b10a276ff57061950 2025-06-15 my-token 2025-07-15 15:12:44.117 +02:00 ListBuckets, ... (8) ``` ``` -------------------------------- ### duck CLI Basic Commands Source: https://garagehq.deuxfleurs.fr/documentation/connect/cli Examples of using the duck CLI to list buckets, list objects, download, upload, and delete objects in Garage. ```bash # List buckets duck --list garage:/ # List objects in a bucket duck --list garage:/my-files/ # Download an object duck --download garage:/my-files/an-object.txt /tmp/object.txt # Upload an object duck --upload /tmp/object.txt garage:/my-files/another-object.txt # Delete an object duck --delete garage:/my-files/an-object.txt ``` -------------------------------- ### Configure Rclone for Development Source: https://garagehq.deuxfleurs.fr/documentation/development/scripts Sets up Rclone to work with the development cluster. Examples demonstrate listing remote directories and copying files. ```bash source ./script/dev-env-rclone.sh # some examples rclone lsd garage: rclone copy /proc/cpuinfo garage:eprouvette/cpuinfo.txt ``` -------------------------------- ### List and Inspect Buckets Source: https://garagehq.deuxfleurs.fr/documentation Use `bucket list` to see all existing buckets and `bucket info` to get details about a specific bucket. ```bash garage bucket list garage bucket info nextcloud-bucket ``` -------------------------------- ### Verify s3_media_upload Tool Availability Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Ensure the `s3_media_upload` tool is in your PATH after installation. ```bash PATH=$HOME/.local/bin/:$PATH command -v s3_media_upload ``` -------------------------------- ### Create and Allow S3 Bucket for pict-rs Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Use Garage CLI commands to create a new S3 bucket and grant read/write access to a specific key. This is the initial setup for pict-rs. ```bash garage key new --name pictrs-key garage bucket create pictrs-data garage bucket allow pictrs-data --read --write --key pictrs-key ``` -------------------------------- ### Minio SDK for S3 Source: https://garagehq.deuxfleurs.fr/documentation/build/python This section explains how to install and use the Minio SDK to interact with S3-compatible storage within Garage. It covers client instantiation and common S3 operations like listing buckets and putting/getting objects. ```APIDOC ## Using Minio SDK ### Installation ``` pip3 install minio ``` ### Client Instantiation ```python import minio client = minio.Minio( "your.domain.tld", "GKyourapikey", "abcd[...]1234", # Force the region, this is specific to garage region="garage", ) ``` ### Common S3 Operations ```python # List buckets print(client.list_buckets()) # Put an object containing 'content' to /path in bucket named 'bucket': content = b"content" client.put_object( "bucket", "path", io.BytesIO(content), len(content), ) # Read the object back and check contents data = client.get_object("bucket", "path").read() assert data == content ``` For further documentation, see the Minio SDK Reference. ``` -------------------------------- ### Initialize and Use Garage Admin API Client Source: https://garagehq.deuxfleurs.fr/documentation/build/javascript Initialize the ApiClient with the server address and set the authentication token. This example demonstrates fetching nodes using the NodesApi. ```javascript const garage = require('garage_administration_api_v1garage_v0_9_0'); const api = new garage.ApiClient("http://127.0.0.1:3903/v1"); api.authentications['bearerAuth'].accessToken = "s3cr3t"; const [node, layout, key, bucket] = [ new garage.NodesApi(api), new garage.LayoutApi(api), new garage.KeyApi(api), new garage.BucketApi(api), ]; node.getNodes().then((data) => { console.log(`nodes: ${Object.values(data.knownNodes).map(n => n.hostname)}`) }, (error) => { console.error(error); }); ``` -------------------------------- ### Configure S3cmd for Development Source: https://garagehq.deuxfleurs.fr/documentation/development/scripts Sources the environment for s3cmd to manage the development cluster's S3 buckets. Examples show listing buckets and uploading files. ```bash source ./script/dev-env-s3cmd.sh # some examples s3cmd ls s3cmd put /proc/cpuinfo s3://eprouvette/cpuinfo.txt ``` -------------------------------- ### Administration SDK - Nodes API Source: https://garagehq.deuxfleurs.fr/documentation/build/golang Example demonstrating how to interact with the Nodes API to retrieve node information, stage layout changes, and apply them, as well as get cluster health status. ```go package main import ( "context" "fmt" "os" "strings" garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang" ) func main() { // Initialization configuration := garage.NewConfiguration() configuration.Host = "127.0.0.1:3903" client := garage.NewAPIClient(configuration) ctx := context.WithValue(context.Background(), garage.ContextAccessToken, "s3cr3t") // Nodes fmt.Println("--- nodes ---") nodes, _, _ := client.NodesApi.GetNodes(ctx).Execute() fmt.Fprintf(os.Stdout, "First hostname: %v\n", nodes.KnownNodes[0].Hostname) capa := int64(1000000000) change := []garage.NodeRoleChange{ garage.NodeRoleChange{NodeRoleUpdate: &garage.NodeRoleUpdate { Id: *nodes.KnownNodes[0].Id, Zone: "dc1", Capacity: *garage.NewNullableInt64(&capa), Tags: []string{ "fast", "amd64" }, }}, } staged, _, _ := client.LayoutApi.AddLayout(ctx).NodeRoleChange(change).Execute() msg, _, _ := client.LayoutApi.ApplyLayout(ctx).LayoutVersion(*garage.NewLayoutVersion(staged.Version + 1)).Execute() fmt.Printf(strings.Join(msg.Message, "\n")) // Layout configured health, _, _ := client.NodesApi.GetHealth(ctx).Execute() fmt.Printf("Status: %s, nodes: %v/%v, storage: %v/%v, partitions: %v/%v\n", health.Status, health.ConnectedNodes, health.KnownNodes, health.StorageNodesOk, health.StorageNodes, health.PartitionsAllOk, health.Partitions) } ``` -------------------------------- ### Create and Configure Garage Buckets for Nix Source: https://garagehq.deuxfleurs.fr/documentation/connect/repositories Set up Garage Cloud Storage buckets and keys for Nix. This involves creating a key, creating a bucket, granting permissions, and enabling website access. ```bash garage key create nix-key garage bucket create nix.example.com garage bucket allow nix.example.com --read --write --key nix-key garage bucket website nix.example.com --allow ``` -------------------------------- ### Install awscli Source: https://garagehq.deuxfleurs.fr/documentation Install the awscli tool using pip if Python is available on your system. This command installs the package for the current user. ```bash python -m pip install --user awscli ``` -------------------------------- ### Create Garage Bucket and Key for Mastodon Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Set up a Garage key and a bucket for Mastodon media storage. Ensure the key has read and write permissions for the bucket. ```bash garage key create mastodon-key garage bucket create mastodon-data garage bucket allow mastodon-data --read --write --key mastodon-key ``` -------------------------------- ### Build Project with Nix Source: https://garagehq.deuxfleurs.fr/documentation/development/devenv Build the project using Nix. This command initiates the Nix build process. ```bash nix-build ``` -------------------------------- ### Configure Initial Access Credentials Source: https://garagehq.deuxfleurs.fr/documentation Sets environment variables to automatically create a default access key, secret key, and storage bucket upon Garage startup. Use your own keys and bucket names if preferred. ```shell export GARAGE_DEFAULT_ACCESS_KEY="GK$(openssl rand -hex 16)" export GARAGE_DEFAULT_SECRET_KEY="$(openssl rand -hex 32)" export GARAGE_DEFAULT_BUCKET="default-bucket" ``` -------------------------------- ### Create Gitea Key and Bucket Source: https://garagehq.deuxfleurs.fr/documentation/connect/repositories Use these commands to create a Garage key and bucket for Gitea. Ensure the key has read and write permissions for the bucket. ```bash garage key create gitea-key garage bucket create gitea garage bucket allow gitea --read --write --key gitea-key ``` -------------------------------- ### Check Rust Distribution Installation Source: https://garagehq.deuxfleurs.fr/documentation/development/devenv Verify that your Rust toolchain (rustc, cargo, rustfmt, clippy) is installed correctly. ```bash rustc --version cargo --version rustfmt --version clippy-driver --version ``` -------------------------------- ### Install Rust and Cargo on Debian Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/from-source Installs the necessary Rust compiler and Cargo package manager on Debian-based systems using apt-get. ```bash sudo apt-get update sudo apt-get install -y rustc cargo ``` -------------------------------- ### Initialize Garage Admin SDK Client Source: https://garagehq.deuxfleurs.fr/documentation/build/python Configure and initialize the Garage Admin SDK client with the host and access token. Import necessary APIs and models. ```python import garage_admin_sdk from garage_admin_sdk.apis import * from garage_admin_sdk.models import * configuration = garage_admin_sdk.Configuration( host = "http://localhost:3903/v1", access_token = "s3cr3t" ) # Init APIs api = garage_admin_sdk.ApiClient(configuration) nodes, layout, keys, buckets = NodesApi(api), LayoutApi(api), KeyApi(api), BucketApi(api) ``` -------------------------------- ### Install Garage with conda-forge Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/binary-packages Install the Garage package globally using pixi, a tool for managing applications and environments, from the conda-forge channel. ```bash pixi global install garage ``` -------------------------------- ### Install ejabberd mod_s3_upload Module Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Install the necessary module for ejabberd to enable S3 uploads. This is the first step in integrating ejabberd with Garage. ```bash ejabberdctl module_install mod_s3_upload ``` -------------------------------- ### Launch Garage Server (Single Node) Source: https://garagehq.deuxfleurs.fr/documentation Use this command to launch a single-node Garage server with a default bucket. Omit flags for manual configuration. ```bash garage server --single-node --default-bucket ``` -------------------------------- ### Alternative Nix Copy Commands Source: https://garagehq.deuxfleurs.fr/documentation/development/miscellaneous-notes Demonstrates alternative methods for using `nix copy`, including copying specific Nix derivations or store paths directly. ```bash # alternative ways to use nix copy nix copy nixpkgs.garage --to ... nix copy /nix/store/3rbb9qsc2w6xl5xccz5ncfhy33nzv3dp-crate-garage-0.3.0 --to ... ``` -------------------------------- ### Start a Data Store Scrub Source: https://garagehq.deuxfleurs.fr/documentation/operations/durability-repairs Manually initiate a scrub operation to verify data block integrity. Scrubs are automatically scheduled but can be started on demand. ```bash garage repair scrub start ``` -------------------------------- ### Create Garage Key and Bucket Source: https://garagehq.deuxfleurs.fr/documentation/connect/backup Use the Garage CLI to create a new access key and a bucket for storing backups. Ensure the key has read and write permissions for the bucket. ```bash garage key create my-plakar-key garage bucket create plakar-backups garage bucket allow plakar-backups --read --write --key my-plakar-key ``` -------------------------------- ### Test Garage with Minio Client (Insecure) Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/reverse-proxy Demonstrates how to list buckets using the Minio client with the `--insecure` flag, which is necessary when using self-signed certificates. ```bash mc ls --insecure garage/ ``` -------------------------------- ### Install External Storage App via occ Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Installs the 'files_external' application using the Nextcloud occ command-line tool. Ensure you have CLI access to your Nextcloud instance. ```bash php occ app:install files_external ``` -------------------------------- ### Pleroma S3 Migration Error Example Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps This is an example of a potential error encountered during Pleroma's internal S3 migration tool, specifically when trying to stream a directory as a file. ```elixir ** (EXIT from #PID<0.98.0>) an exception was raised: ** (File.Error) could not stream "/var/lib/pleroma/uploads/09/f8": illegal operation on a directory (elixir 1.17.3) lib/file/stream.ex:100: anonymous fn/3 in Enumerable.File.Stream.reduce/3 (elixir 1.17.3) lib/stream.ex:1675: anonymous fn/5 in Stream.resource/3 (elixir 1.17.3) lib/stream.ex:1891: Enumerable.Stream.do_each/4 (elixir 1.17.3) lib/task/supervised.ex:370: Task.Supervised.stream_reduce/7 (elixir 1.17.3) lib/enum.ex:4423: Enum.map/2 (ex_aws_s3 2.5.8) lib/ex_aws/s3/upload.ex:141: ExAws.Operation.ExAws.S3.Upload.perform/2 (pleroma 2.10.0) lib/pleroma/uploaders/s3.ex:60: Pleroma.Uploaders.S3.put_file/1 (pleroma 2.10.0) lib/pleroma/uploaders/uploader.ex:49: Pleroma.Uploaders.Uploader.put_file/2 ``` -------------------------------- ### Install Garage on Alpine Linux Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/binary-packages Use this command to install the Garage package on Alpine Linux. Note that this package is built without certain features like Consul discovery and OpenTelemetry exporter. ```bash apk add garage ``` -------------------------------- ### Create and Configure Garage Bucket for ejabberd Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Create a new Garage key and bucket, then grant permissions for ejabberd to read and write. Enable website hosting for the bucket. ```bash garage key new --name ejabberd ``` ```bash garage bucket create objects.xmpp-server.fr ``` ```bash garage bucket allow objects.xmpp-server.fr --read --write --key ejabberd ``` ```bash garage bucket website --allow objects.xmpp-server.fr ``` -------------------------------- ### Example values.override.yaml for Microk8s Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/kubernetes An example of a 'values.override.yaml' file for deploying Garage in a Microk8s cluster. It includes configurations for replication factor, deployment replicas, persistence storage, and S3 API ingress with TLS. ```yaml garage: # Use only 2 replicas per object replicationFactor: 2 # Start 4 instances (StatefulSets) of garage deployment: replicaCount: 4 # Override default storage class and size persistence: meta: storageClass: "openebs-hostpath" size: 100Mi data: storageClass: "openebs-hostpath" size: 1Gi ingress: s3: api: enabled: true className: "public" annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" nginx.ingress.kubernetes.io/proxy-body-size: 500m hosts: - host: s3-api.my-domain.com paths: - path: / pathType: Prefix tls: - secretName: garage-ingress-cert hosts: - s3-api.my-domain.com ``` -------------------------------- ### Get Garage Metrics via HTTP Source: https://garagehq.deuxfleurs.fr/documentation/reference-manual/admin-api Fetch internal Garage metrics in Prometheus format by making a GET request to the `/metrics` endpoint. The output contains detailed performance and operational data. ```bash $ curl -i http://localhost:3903/metrics HTTP/1.1 200 OK content-type: text/plain; version=0.0.4 content-length: 12145 date: Tue, 08 Aug 2023 07:25:05 GMT # HELP api_admin_error_counter Number of API calls to the various Admin API endpoints that resulted in errors # TYPE api_admin_error_counter counter api_admin_error_counter{api_endpoint="CheckWebsiteEnabled",status_code="400"} 1 api_admin_error_counter{api_endpoint="CheckWebsiteEnabled",status_code="404"} 3 # HELP api_admin_request_counter Number of API calls to the various Admin API endpoints # TYPE api_admin_request_counter counter api_admin_request_counter{api_endpoint="CheckWebsiteEnabled"} 7 api_admin_request_counter{api_endpoint="Health"} 3 # HELP api_admin_request_duration Duration of API calls to the various Admin API endpoints ... ``` -------------------------------- ### Get Garage Health Status via HTTP Source: https://garagehq.deuxfleurs.fr/documentation/reference-manual/admin-api Check the operational status of the Garage cluster by sending a GET request to the `/health` endpoint. It returns a 200 OK status if the cluster can serve requests, otherwise a 503 Service Unavailable. ```bash $ curl -i http://localhost:3903/health HTTP/1.1 200 OK content-type: text/plain content-length: 102 date: Tue, 08 Aug 2023 07:22:38 GMT Garage is fully operational Consult the full health check API endpoint at /v2/GetClusterHealth for more details ``` -------------------------------- ### Ente Credentials Configuration (credentials.yaml) Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Prepare the `credentials.yaml` file for Ente, specifying database connection details and S3 storage configuration. This includes settings for local Minio instances, Garage endpoint, and bucket names. Ensure placeholders like ``, ``, ``, ``, ``, and `` are replaced with actual values. ```yaml db: host: postgres port: 5432 name: user: password: s3: # Override the primary and secondary hot storage. The commented out values # are the defaults. # hot_storage: primary: b2-eu-cen # secondary: wasabi-eu-central-2-v3 # If true, enable some workarounds to allow us to use a local minio instance # for object storage. # # 1. Disable SSL. # 2. Use "path" style S3 URLs (see `use_path_style_urls` below). # 3. Directly download the file during replication instead of going via the # Cloudflare worker. # 4. Do not specify storage classes when uploading objects (since minio does # not support them, specifically it doesn't support GLACIER). are_local_buckets: true # To use "path" style S3 URLs instead of DNS-based bucket access # default to true if you set "are_local_buckets: true" # use_path_style_urls: true b2-eu-cen: # Don't change this key, it is hardcoded key: secret: endpoint: garage:3900 # publicly accessible endpoint of your garage instance region: garage bucket: use_path_style: true # you can specify secondary locations, names are hardcoded as well # wasabi-eu-central-2-v3: # scw-eu-fr-v3: # and you can also specify a bucket to be used for embeddings, preview etc.. # default to the first bucket # derived-storage: wasabi-eu-central-2-derived ``` -------------------------------- ### Initialize sftpgo Provider Source: https://garagehq.deuxfleurs.fr/documentation/connect/cli Initialize the sftpgo provider, which defaults to using an SQLite database for configuration. ```bash sftpgo initprovider ``` -------------------------------- ### Build K2V CLI Utility from Source Source: https://garagehq.deuxfleurs.fr/documentation/reference-manual/k2v Clone the Garage repository and build the K2V CLI utility using Cargo. The CLI is self-documented. ```bash git clone https://git.deuxfleurs.fr/Deuxfleurs/garage.git cd garage/src/k2v-client cargo build --features cli --bin k2v-cli ``` -------------------------------- ### Start sftpgo Daemon Source: https://garagehq.deuxfleurs.fr/documentation/connect/cli Launch the sftpgo daemon. It will listen on HTTP port 8080 and SSH port 2022 by default. ```bash sftpgo serve ``` -------------------------------- ### Create Garage Buckets for Peertube Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Create two buckets in Garage: one for normal videos and another for webtorrent videos. These buckets will store the media content served by Peertube. ```bash garage bucket create peertube-videos garage bucket create peertube-playlists ``` -------------------------------- ### Creating a User-Defined Admin Token Source: https://garagehq.deuxfleurs.fr/documentation/reference-manual/admin-api Example CLI command to create a new administration token with specified expiration and scope. ```APIDOC ## garage admin-token create ### Description Creates a new user-defined administration token. Tokens can be scoped to specific permissions and have an expiration date. ### Command ```bash $ garage admin-token create --expires-in 30d \ --scope ListBuckets,GetBucketInfo,ListKeys,GetKeyInfo,CreateBucket,CreateKey,AllowBucketKey,DenyBucketKey \ my-token ``` ### Output Example ``` This is your secret bearer token, it will not be shown again by Garage: 8ed1830b10a276ff57061950.kOSIpxWK9zSGbTO9Xadpv3YndSFWma0_snXcYHaORXk ==== ADMINISTRATION TOKEN INFORMATION ==== Token ID: 8ed1830b10a276ff57061950 Token name: my-token Created: 2025-06-15 15:12:44.160 +02:00 Validity: valid Expiration: 2025-07-15 15:12:44.117 +02:00 Scope: ListBuckets GetBucketInfo ListKeys GetKeyInfo CreateBucket CreateKey AllowBucketKey DenyBucketKey ``` ### Notes - The secret bearer token is shown only once. Ensure it is saved securely. - The token ID prefix is saved in clear and used for identification. ``` -------------------------------- ### List and Inspect Buckets Source: https://garagehq.deuxfleurs.fr/documentation/quick-start Verify bucket creation by listing all buckets or inspecting the details of a specific bucket. This helps confirm that the bucket exists and is accessible. ```bash garage bucket list garage bucket info nextcloud-bucket ``` -------------------------------- ### Schedule Matrix Cache GC with Crontab Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Add the matrix-cache-gc script to your crontab to run it periodically, for example, every 10 minutes. ```bash crontab -e */10 * * * * $HOME/.local/bin/matrix-cache-gc ``` -------------------------------- ### Configure Initial Access Credentials for Garage Source: https://garagehq.deuxfleurs.fr/documentation/quick-start Exports environment variables to automatically create a default access key, secret key, and storage bucket upon Garage startup. This is a convenient way to set up initial credentials for testing or simple deployments. ```bash export GARAGE_DEFAULT_ACCESS_KEY="GK$(openssl rand -hex 16)" export GARAGE_DEFAULT_SECRET_KEY="$(openssl rand -hex 32)" export GARAGE_DEFAULT_BUCKET="default-bucket" ``` -------------------------------- ### Create Test Bucket and Key Source: https://garagehq.deuxfleurs.fr/documentation/development/scripts Creates an 'eprouvette' bucket and a key with read/write permissions. The key is stored in `/tmp/garage.s3` for use with other tools. ```bash ./script/dev-bucket.sh ``` -------------------------------- ### Get Node Identifier Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/real-world Run this command on a Garage node to retrieve its unique identifier and network address. This is essential for connecting nodes. ```bash Mercury$ garage node id 563e1ac825ee3323aa441e72c26d1030d6d4414aeb3dd25287c531e7fc2bc95d@[fc00:1::1]:3901 Venus$ garage node id 86f0f26ae4afbd59aaf9cfb059eefac844951efd5b8caeec0d53f4ed6c85f332@[fc00:1::2]:3901 ``` -------------------------------- ### Get Next Scheduled Scrub Time Source: https://garagehq.deuxfleurs.fr/documentation/operations/durability-repairs View the estimated time for the next automatically scheduled data store scrub operation. ```bash garage worker get ``` -------------------------------- ### Configure Bucket for Website Access via CLI Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/exposing-websites Use this command to publicly expose a bucket on the default web endpoint. Ensure you have the necessary permissions. ```bash garage bucket website --allow my-website ``` -------------------------------- ### Accessing an Admin API Endpoint Source: https://garagehq.deuxfleurs.fr/documentation/reference-manual/admin-api Example of how to make a request to an admin API endpoint using curl, including the necessary Authorization header. ```APIDOC ## GET /v2/GetClusterStatus ### Description Retrieves the current status of the cluster. ### Method GET ### Endpoint /v2/GetClusterStatus ### Parameters #### Query Parameters None #### Request Body None ### Request Example ```bash curl -H 'Authorization: Bearer s3cr3t' http://localhost:3903/v2/GetClusterStatus | jq ``` ### Response #### Success Response (200) - **status** (string) - The current status of the cluster. #### Response Example ```json { "status": "running" } ``` ``` -------------------------------- ### Create and Allow Garage Bucket for Nextcloud Source: https://garagehq.deuxfleurs.fr/documentation/connect/apps Create a bucket for Nextcloud and grant read/write permissions to the previously created key. ```bash garage bucket create nextcloud garage bucket allow nextcloud --read --write --key nextcloud-key ``` -------------------------------- ### Create and Publish Garage Docker Container Source: https://garagehq.deuxfleurs.fr/documentation/development/release-process Build and publish a Docker container for Garage. Configure Docker authentication, platform, container name, and tag before executing 'to_docker' in a Nix shell. ```bash export DOCKER_AUTH='{ "auths": { "https://index.docker.io/v1/": { "auth": "xxxx" }}}" export DOCKER_PLATFORM='linux/amd64' # check GOARCH and GOOS from golang.org export CONTAINER_NAME='me/amd64_garage' export CONTAINER_TAG='handcrafted-1.0.0' nix-shell --run to_docker ```