diff --git a/app/Models/Service.php b/app/Models/Service.php index 2f8a64464..2cea4c805 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -712,6 +712,84 @@ public function extraFields() $fields->put('MinIO', $data->toArray()); break; + case $image->contains('garage'): + $data = collect([]); + $s3_api_url = $this->environment_variables()->where('key', 'GARAGE_S3_API_URL')->first(); + $web_url = $this->environment_variables()->where('key', 'GARAGE_WEB_URL')->first(); + $admin_url = $this->environment_variables()->where('key', 'GARAGE_ADMIN_URL')->first(); + $admin_token = $this->environment_variables()->where('key', 'GARAGE_ADMIN_TOKEN')->first(); + if (is_null($admin_token)) { + $admin_token = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GARAGE')->first(); + } + $rpc_secret = $this->environment_variables()->where('key', 'GARAGE_RPC_SECRET')->first(); + if (is_null($rpc_secret)) { + $rpc_secret = $this->environment_variables()->where('key', 'SERVICE_HEX_32_RPCSECRET')->first(); + } + $metrics_token = $this->environment_variables()->where('key', 'GARAGE_METRICS_TOKEN')->first(); + if (is_null($metrics_token)) { + $metrics_token = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GARAGEMETRICS')->first(); + } + + if ($s3_api_url) { + $data = $data->merge([ + 'S3 API URL' => [ + 'key' => data_get($s3_api_url, 'key'), + 'value' => data_get($s3_api_url, 'value'), + 'rules' => 'required|url', + ], + ]); + } + if ($web_url) { + $data = $data->merge([ + 'Web URL' => [ + 'key' => data_get($web_url, 'key'), + 'value' => data_get($web_url, 'value'), + 'rules' => 'required|url', + ], + ]); + } + if ($admin_url) { + $data = $data->merge([ + 'Admin URL' => [ + 'key' => data_get($admin_url, 'key'), + 'value' => data_get($admin_url, 'value'), + 'rules' => 'required|url', + ], + ]); + } + if ($admin_token) { + $data = $data->merge([ + 'Admin Token' => [ + 'key' => data_get($admin_token, 'key'), + 'value' => data_get($admin_token, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + } + if ($rpc_secret) { + $data = $data->merge([ + 'RPC Secret' => [ + 'key' => data_get($rpc_secret, 'key'), + 'value' => data_get($rpc_secret, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + } + if ($metrics_token) { + $data = $data->merge([ + 'Metrics Token' => [ + 'key' => data_get($metrics_token, 'key'), + 'value' => data_get($metrics_token, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + } + + $fields->put('Garage', $data->toArray()); + break; case $image->contains('weblate'): $data = collect([]); $admin_email = $this->environment_variables()->where('key', 'WEBLATE_ADMIN_EMAIL')->first(); diff --git a/bootstrap/helpers/constants.php b/bootstrap/helpers/constants.php index 9196f9fb8..114c4bb98 100644 --- a/bootstrap/helpers/constants.php +++ b/bootstrap/helpers/constants.php @@ -58,6 +58,7 @@ 'ghcr.io/coollabsio/minio', 'coollabsio/minio', 'svhd/logto', + 'dxflrs/garage', ]; // Based on /etc/os-release diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 759d345b0..a0f810480 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -312,6 +312,36 @@ function generateServiceSpecificFqdns(ServiceApplication|Application $resource) $LOGTO_ADMIN_ENDPOINT->value.':3002', ]); break; + case $type?->contains('garage'): + $GARAGE_S3_API_URL = $variables->where('key', 'GARAGE_S3_API_URL')->first(); + $GARAGE_WEB_URL = $variables->where('key', 'GARAGE_WEB_URL')->first(); + $GARAGE_ADMIN_URL = $variables->where('key', 'GARAGE_ADMIN_URL')->first(); + + if (is_null($GARAGE_S3_API_URL) || is_null($GARAGE_WEB_URL) || is_null($GARAGE_ADMIN_URL)) { + return collect([]); + } + + if (str($GARAGE_S3_API_URL->value ?? '')->isEmpty()) { + $GARAGE_S3_API_URL->update([ + 'value' => generateUrl(server: $server, random: 's3-'.$uuid, forceHttps: true), + ]); + } + if (str($GARAGE_WEB_URL->value ?? '')->isEmpty()) { + $GARAGE_WEB_URL->update([ + 'value' => generateUrl(server: $server, random: 'web-'.$uuid, forceHttps: true), + ]); + } + if (str($GARAGE_ADMIN_URL->value ?? '')->isEmpty()) { + $GARAGE_ADMIN_URL->update([ + 'value' => generateUrl(server: $server, random: 'admin-'.$uuid, forceHttps: true), + ]); + } + $payload = collect([ + $GARAGE_S3_API_URL->value.':3900', + $GARAGE_WEB_URL->value.':3902', + $GARAGE_ADMIN_URL->value.':3903', + ]); + break; } return $payload; diff --git a/public/svgs/garage.svg b/public/svgs/garage.svg new file mode 100644 index 000000000..18aedeaaf --- /dev/null +++ b/public/svgs/garage.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/compose/garage.yaml b/templates/compose/garage.yaml new file mode 100644 index 000000000..865a9c89a --- /dev/null +++ b/templates/compose/garage.yaml @@ -0,0 +1,60 @@ +# ignore: true +# documentation: https://garagehq.deuxfleurs.fr/documentation/ +# slogan: Garage is an S3-compatible distributed object storage service designed for self-hosting. +# category: storage +# tags: object, storage, server, s3, api, distributed +# logo: svgs/garage.svg +# port: 3900 + +services: + garage: + image: dxflrs/garage:v2.1.0 + environment: + - GARAGE_S3_API_URL=$GARAGE_S3_API_URL + - GARAGE_WEB_URL=$GARAGE_WEB_URL + - GARAGE_ADMIN_URL=$GARAGE_ADMIN_URL + - GARAGE_RPC_SECRET=${SERVICE_HEX_32_RPCSECRET} + - GARAGE_ADMIN_TOKEN=$SERVICE_PASSWORD_GARAGE + - GARAGE_METRICS_TOKEN=$SERVICE_PASSWORD_GARAGEMETRICS + - GARAGE_ALLOW_WORLD_READABLE_SECRETS=true + - RUST_LOG=${RUST_LOG:-garage=info} + volumes: + - garage-meta:/var/lib/garage/meta + - garage-data:/var/lib/garage/data + - type: bind + source: ./garage.toml + target: /etc/garage.toml + content: | + metadata_dir = "/var/lib/garage/meta" + data_dir = "/var/lib/garage/data" + db_engine = "lmdb" + + replication_factor = 1 + consistency_mode = "consistent" + + compression_level = 1 + block_size = "1M" + + [rpc] + bind_addr = "[::]:3901" + rpc_secret_file = "env:GARAGE_RPC_SECRET" + bootstrap_peers = [] + + [s3_api] + s3_region = "garage" + api_bind_addr = "[::]:3900" + root_domain = ".s3.garage.localhost" + + [s3_web] + bind_addr = "[::]:3902" + root_domain = ".web.garage.localhost" + + [admin] + api_bind_addr = "[::]:3903" + admin_token_file = "env:GARAGE_ADMIN_TOKEN" + metrics_token_file = "env:GARAGE_METRICS_TOKEN" + healthcheck: + test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:3903/health"] + interval: 10s + timeout: 5s + retries: 5