mirror of
https://github.com/Noooste/garage-ui.git
synced 2026-08-31 09:18:29 +00:00
feat: update README to simplify descriptions and enhance clarity; improve quick start instructions
Signed-off-by: Noste <83548733+Noooste@users.noreply.github.com>
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 248 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 364 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 289 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 344 KiB |
@@ -1,6 +1,6 @@
|
|||||||
# Garage UI
|
# Garage UI
|
||||||
|
|
||||||
A modern, full-stack web interface for managing [Garage](https://garagehq.deuxfleurs.fr/) distributed object storage systems. Built with React, TypeScript, Go, and Fiber for production-ready S3-compatible storage management.
|
A web interface for managing [Garage](https://garagehq.deuxfleurs.fr/) object storage clusters.
|
||||||
|
|
||||||
[](https://github.com/Noooste/garage-ui/actions/workflows/build.yml)
|
[](https://github.com/Noooste/garage-ui/actions/workflows/build.yml)
|
||||||
[](https://github.com/Noooste/garage-ui/actions/workflows/release.yml)
|
[](https://github.com/Noooste/garage-ui/actions/workflows/release.yml)
|
||||||
@@ -9,665 +9,188 @@ A modern, full-stack web interface for managing [Garage](https://garagehq.deuxfl
|
|||||||
[](https://nodejs.org/)
|
[](https://nodejs.org/)
|
||||||
[](https://artifacthub.io/packages/search?repo=garage-ui)
|
[](https://artifacthub.io/packages/search?repo=garage-ui)
|
||||||
|
|
||||||
Garage UI provides a comprehensive dashboard for managing your Garage S3 storage cluster, featuring bucket management, object operations, user access control, and real-time cluster monitoring—all through an intuitive web interface.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><img src=".github/assets/dashboard.png" alt="Dashboard" /></td>
|
||||||
|
<td><img src=".github/assets/buckets.png" alt="Buckets" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src=".github/assets/cluster.png" alt="Cluster" /></td>
|
||||||
|
<td><img src=".github/assets/access-control.png" alt="Access Control" /></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Bucket Management** - Create, configure, and delete S3 buckets with visual controls
|
- Bucket and object management
|
||||||
- **Object Operations** - Upload, download, and manage objects with drag-and-drop support
|
- User access control
|
||||||
- **User & Access Control** - Manage access keys, permissions, and user credentials
|
- Cluster monitoring
|
||||||
- **Cluster Monitoring** - Real-time cluster health metrics, node status, and performance statistics
|
- Multiple authentication options (none/basic/OIDC)
|
||||||
- **Multi-Auth Support** - Flexible authentication with None, Basic Auth, and OIDC/OAuth2 modes
|
- Drag-and-drop file uploads
|
||||||
- **Modern UI/UX** - Responsive React interface with dark mode, built on Tailwind CSS and shadcn/ui
|
|
||||||
- **Production Ready** - Docker/Kubernetes deployment, health checks, and Prometheus metrics
|
|
||||||
- **API-First Design** - RESTful API with Swagger/OpenAPI documentation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- **Garage S3** storage cluster running (v2.0.0+)
|
- Docker & Docker Compose
|
||||||
- **Docker** & Docker Compose (recommended) OR
|
- Garage S3 cluster (v2.1.0+) or use the included setup
|
||||||
- **Go** 1.25+ and **Node.js** 25+ (for development)
|
|
||||||
|
|
||||||
### Using Docker Compose (Recommended)
|
### 1. Clone & Setup
|
||||||
|
|
||||||
1. **Clone the repository:**
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/Noooste/garage-ui.git
|
git clone https://github.com/Noooste/garage-ui.git
|
||||||
cd garage-ui
|
cd garage-ui
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Configure the application:**
|
### 2. Start Garage
|
||||||
|
|
||||||
|
If you don't have Garage running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d garage
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# Initialize cluster
|
||||||
|
docker-compose exec garage garage layout assign -z dc1 -c 1G $(docker-compose exec garage garage node id -q)
|
||||||
|
docker-compose exec garage garage layout apply --version 1
|
||||||
|
|
||||||
|
# Create admin key
|
||||||
|
docker-compose exec garage garage key create admin-key
|
||||||
|
```
|
||||||
|
|
||||||
|
Save the access key and secret key from the output.
|
||||||
|
|
||||||
|
### 3. Configure
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp config.yaml.example config.yaml
|
cp config.yaml.example config.yaml
|
||||||
# Edit config.yaml with your Garage endpoints and credentials
|
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Start the services:**
|
Edit `config.yaml` with your Garage endpoints and admin token (from `garage.toml`).
|
||||||
|
|
||||||
|
### 4. Start UI
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose up -d
|
docker-compose up -d garage-ui
|
||||||
```
|
```
|
||||||
|
|
||||||
4. **Access the UI:**
|
Access at http://localhost:8080
|
||||||
|
|
||||||
Open your browser to [http://localhost:8080](http://localhost:8080)
|
|
||||||
|
|
||||||
> The Docker Compose setup includes both Garage and Garage UI services for quick local development.
|
|
||||||
|
|
||||||
### Using Docker
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run -d \
|
|
||||||
-p 8080:8080 \
|
|
||||||
-v $(pwd)/config.yaml:/app/config.yaml \
|
|
||||||
-e GARAGE_UI_GARAGE_ENDPOINT=http://your-garage:3900 \
|
|
||||||
-e GARAGE_UI_GARAGE_ADMIN_ENDPOINT=http://your-garage:3903 \
|
|
||||||
noooste/garage-ui:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### Docker Deployment
|
|
||||||
|
|
||||||
**Pull the latest image:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker pull noooste/garage-ui:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
The Docker image is multi-platform, supporting `linux/amd64` and `linux/arm64`.
|
|
||||||
|
|
||||||
### Kubernetes Deployment with Helm
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Add the Helm repository (if available)
|
|
||||||
helm repo add garage-ui https://helm.noste.dev/
|
|
||||||
|
|
||||||
# Install the chart
|
|
||||||
helm install garage-ui garage-ui/garage-ui \
|
|
||||||
--set garage.endpoint=http://garage:3900 \
|
|
||||||
--set garage.adminEndpoint=http://garage:3903 \
|
|
||||||
--set garage.adminToken=your-admin-token
|
|
||||||
```
|
|
||||||
|
|
||||||
Or use the local Helm chart:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm install garage-ui ./helm/garage-ui -f custom-values.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
### Building from Source
|
|
||||||
|
|
||||||
**Backend:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd backend
|
|
||||||
go mod download
|
|
||||||
swag init # Generate API docs
|
|
||||||
go build -o garage-ui .
|
|
||||||
```
|
|
||||||
|
|
||||||
**Frontend:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd frontend
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
**Run:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# From project root
|
|
||||||
./backend/garage-ui --config config.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Garage UI can be configured via YAML file or environment variables.
|
Minimum required config:
|
||||||
|
|
||||||
### Configuration File
|
|
||||||
|
|
||||||
Create a `config.yaml` based on the provided example:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# Server configuration
|
|
||||||
server:
|
server:
|
||||||
host: "0.0.0.0"
|
|
||||||
port: 8080
|
port: 8080
|
||||||
environment: "production"
|
|
||||||
|
|
||||||
# Garage S3 Configuration
|
|
||||||
garage:
|
garage:
|
||||||
endpoint: "garage:3900"
|
endpoint: "http://garage:3900"
|
||||||
region: "eu-west-1" # Ensure to match Garage region from garage.toml
|
|
||||||
admin_endpoint: "http://garage:3903"
|
admin_endpoint: "http://garage:3903"
|
||||||
admin_token: "your-admin-token-here"
|
admin_token: "your-admin-token"
|
||||||
|
region: "garage"
|
||||||
# Authentication Configuration
|
|
||||||
# You can enable one or both authentication methods
|
|
||||||
auth:
|
|
||||||
# Admin authentication (username/password)
|
|
||||||
admin:
|
|
||||||
enabled: false # Set to true to enable admin login
|
|
||||||
username: "admin"
|
|
||||||
password: "secure-password"
|
|
||||||
|
|
||||||
# OIDC authentication (Keycloak, Auth0, etc.)
|
|
||||||
oidc:
|
|
||||||
enabled: false # Set to true to enable OIDC login
|
|
||||||
provider_name: "Keycloak"
|
|
||||||
client_id: "garage-ui"
|
|
||||||
client_secret: "your-client-secret"
|
|
||||||
issuer_url: "https://auth.example.com/realms/master"
|
|
||||||
auth_url: "https://auth.example.com/realms/master/protocol/openid-connect/auth"
|
|
||||||
token_url: "https://auth.example.com/realms/master/protocol/openid-connect/token"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
See [`config.yaml.example`](config.yaml.example) for all available options.
|
Enable authentication (optional):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
auth:
|
||||||
|
admin:
|
||||||
|
enabled: true
|
||||||
|
username: "admin"
|
||||||
|
password: "your-password"
|
||||||
|
```
|
||||||
|
|
||||||
|
See [config.yaml.example](config.yaml.example) for all options.
|
||||||
|
|
||||||
### Environment Variables
|
### Environment Variables
|
||||||
|
|
||||||
All configuration can be set via environment variables with the prefix `GARAGE_UI_`:
|
Override any config value with `GARAGE_UI_` prefix:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
GARAGE_UI_SERVER_PORT=8080
|
GARAGE_UI_SERVER_PORT=8080
|
||||||
GARAGE_UI_GARAGE_ENDPOINT=http://garage:3900
|
GARAGE_UI_GARAGE_ENDPOINT=http://garage:3900
|
||||||
GARAGE_UI_GARAGE_ADMIN_ENDPOINT=http://garage:3903
|
|
||||||
GARAGE_UI_GARAGE_ADMIN_TOKEN=your-token
|
GARAGE_UI_GARAGE_ADMIN_TOKEN=your-token
|
||||||
GARAGE_UI_AUTH_ADMIN_ENABLED=true
|
|
||||||
GARAGE_UI_AUTH_ADMIN_USERNAME=admin
|
|
||||||
GARAGE_UI_AUTH_ADMIN_PASSWORD=password
|
|
||||||
GARAGE_UI_AUTH_OIDC_ENABLED=false
|
|
||||||
GARAGE_UI_LOGGING_LEVEL=info
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Configuration Priority:** Environment variables override YAML file settings.
|
## Deployment
|
||||||
|
|
||||||
---
|
### Docker
|
||||||
|
|
||||||
## Project Structure
|
```bash
|
||||||
|
docker run -d -p 8080:8080 \
|
||||||
```
|
-v $(pwd)/config.yaml:/app/config.yaml \
|
||||||
garage-ui/
|
noooste/garage-ui:latest
|
||||||
├── backend/ # Go backend (Fiber framework)
|
|
||||||
│ ├── internal/
|
|
||||||
│ │ ├── auth/ # Authentication services (JWT, OIDC)
|
|
||||||
│ │ ├── config/ # Configuration loading
|
|
||||||
│ │ ├── handlers/ # HTTP request handlers
|
|
||||||
│ │ ├── middleware/ # CORS, auth middleware
|
|
||||||
│ │ ├── models/ # Data models and types
|
|
||||||
│ │ ├── routes/ # API route definitions
|
|
||||||
│ │ └── services/ # Business logic (S3, Garage Admin)
|
|
||||||
│ ├── pkg/ # Shared packages
|
|
||||||
│ ├── main.go # Application entry point
|
|
||||||
│ └── go.mod # Go dependencies
|
|
||||||
│
|
|
||||||
├── frontend/ # React + TypeScript frontend
|
|
||||||
│ ├── src/
|
|
||||||
│ │ ├── components/ # Reusable UI components
|
|
||||||
│ │ │ ├── buckets/ # Bucket-specific components
|
|
||||||
│ │ │ ├── charts/ # Data visualization
|
|
||||||
│ │ │ ├── layout/ # App layout and navigation
|
|
||||||
│ │ │ └── ui/ # shadcn/ui component library
|
|
||||||
│ │ ├── hooks/ # Custom React hooks
|
|
||||||
│ │ ├── lib/ # API client and utilities
|
|
||||||
│ │ ├── pages/ # Page components (Dashboard, Buckets, etc.)
|
|
||||||
│ │ ├── types/ # TypeScript type definitions
|
|
||||||
│ │ └── App.tsx # Main application component
|
|
||||||
│ ├── package.json # Node dependencies
|
|
||||||
│ └── vite.config.ts # Vite build configuration
|
|
||||||
│
|
|
||||||
├── helm/ # Kubernetes Helm chart
|
|
||||||
│ └── garage-ui/
|
|
||||||
│ ├── Chart.yaml # Chart metadata
|
|
||||||
│ ├── values.yaml # Default values
|
|
||||||
│ └── templates/ # K8s resource templates
|
|
||||||
│
|
|
||||||
├── .github/workflows/ # CI/CD pipelines
|
|
||||||
│ ├── build.yml # Docker build and push
|
|
||||||
│ └── release.yml # Helm chart releases
|
|
||||||
│
|
|
||||||
├── Dockerfile # Multi-stage build
|
|
||||||
├── docker-compose.yml # Local development stack
|
|
||||||
└── config.yaml.example # Configuration template
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Key Directories:**
|
### Kubernetes
|
||||||
|
|
||||||
- **`backend/internal/handlers/`** - REST API endpoints for buckets, objects, users, cluster, and monitoring
|
```bash
|
||||||
- **`frontend/src/pages/`** - Main application views (Dashboard, Buckets, Cluster, Access Control)
|
helm repo add garage-ui https://helm.noste.dev/
|
||||||
- **`backend/internal/services/`** - Core business logic interfacing with Garage Admin API and S3
|
helm install garage-ui garage-ui/garage-ui \
|
||||||
- **`frontend/src/lib/api.ts`** - Axios-based API client with automatic error handling
|
--set garage.endpoint=http://garage:3900 \
|
||||||
|
--set garage.adminEndpoint=http://garage:3903 \
|
||||||
---
|
--set garage.adminToken=your-token
|
||||||
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
### Local Development Setup
|
Backend (Go 1.25+):
|
||||||
|
|
||||||
**1. Start Garage (using Docker Compose):**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose up garage -d
|
|
||||||
```
|
|
||||||
|
|
||||||
**2. Run the backend:**
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd backend
|
cd backend
|
||||||
go run main.go --config ../config.yaml
|
go run main.go --config ../config.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
The backend will start on `http://localhost:8080` with hot-reload (use [air](https://github.com/cosmtrek/air) for auto-reload).
|
Frontend (Node.js 25+):
|
||||||
|
|
||||||
**3. Run the frontend:**
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd frontend
|
cd frontend
|
||||||
npm install
|
npm install
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
The frontend dev server starts on `http://localhost:3000` with API proxy to backend.
|
API docs: http://localhost:8080/api/v1/
|
||||||
|
|
||||||
### Available Scripts
|
## Garage Configuration
|
||||||
|
|
||||||
**Backend:**
|
Garage UI requires these settings in your `garage.toml`:
|
||||||
|
|
||||||
```bash
|
```toml
|
||||||
go run main.go # Start server
|
# Admin API (required for Garage UI)
|
||||||
go test ./... # Run tests
|
[admin]
|
||||||
swag init # Regenerate API docs
|
api_bind_addr = "0.0.0.0:3903" # Default: 127.0.0.1:3903
|
||||||
go build -o garage-ui . # Build binary
|
admin_token = "your-admin-token" # Generate with: openssl rand -base64 32
|
||||||
|
|
||||||
|
# S3 API
|
||||||
|
[s3_api]
|
||||||
|
s3_region = "garage" # Default: "garage"
|
||||||
|
api_bind_addr = "[::]:3900" # Default: 127.0.0.1:3900
|
||||||
```
|
```
|
||||||
|
|
||||||
**Frontend:**
|
**Important:** The `admin_token` and `s3_region` in `garage.toml` must match your Garage UI `config.yaml`.
|
||||||
|
|
||||||
```bash
|
For complete Garage configuration, see the [official documentation](https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/).
|
||||||
npm run dev # Development server (Vite)
|
|
||||||
npm run build # Production build
|
|
||||||
npm run lint # ESLint checks
|
|
||||||
npm run preview # Preview production build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Backend tests
|
|
||||||
cd backend && go test ./internal/...
|
|
||||||
|
|
||||||
# Frontend tests (if available)
|
|
||||||
cd frontend && npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
### Building Docker Image
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker build -t garage-ui:dev .
|
|
||||||
```
|
|
||||||
|
|
||||||
The Dockerfile uses a multi-stage build:
|
|
||||||
1. **Frontend build** - Node.js Alpine to compile React app
|
|
||||||
2. **Backend build** - Go Alpine to compile binary
|
|
||||||
3. **Runtime** - Minimal Alpine with ca-certificates
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API Documentation
|
|
||||||
|
|
||||||
Once the backend is running, access the Swagger UI documentation at:
|
|
||||||
|
|
||||||
**http://localhost:8080/api/v1/**
|
|
||||||
|
|
||||||
### API Endpoints Overview
|
|
||||||
|
|
||||||
| Endpoint | Method | Description |
|
|
||||||
|----------|--------|-------------|
|
|
||||||
| `/health` | GET | Health check endpoint |
|
|
||||||
| `/api/v1/buckets` | GET | List all buckets |
|
|
||||||
| `/api/v1/buckets` | POST | Create a new bucket |
|
|
||||||
| `/api/v1/buckets/{name}` | GET | Get bucket details |
|
|
||||||
| `/api/v1/buckets/{name}` | DELETE | Delete a bucket |
|
|
||||||
| `/api/v1/buckets/{name}/objects` | GET | List objects in bucket |
|
|
||||||
| `/api/v1/objects/upload` | POST | Upload object to bucket |
|
|
||||||
| `/api/v1/objects/download` | GET | Download object |
|
|
||||||
| `/api/v1/objects/delete` | DELETE | Delete object |
|
|
||||||
| `/api/v1/users` | GET | List access keys |
|
|
||||||
| `/api/v1/users` | POST | Create access key |
|
|
||||||
| `/api/v1/users/{id}` | DELETE | Delete access key |
|
|
||||||
| `/api/v1/cluster/status` | GET | Cluster node status |
|
|
||||||
| `/api/v1/cluster/health` | GET | Cluster health metrics |
|
|
||||||
| `/api/v1/cluster/statistics` | GET | Storage statistics |
|
|
||||||
| `/api/v1/metrics` | GET | Prometheus metrics |
|
|
||||||
|
|
||||||
**Authentication:** Bearer token in `Authorization` header when using OIDC or session-based auth.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Authentication
|
|
||||||
|
|
||||||
Garage UI supports flexible authentication with the ability to enable one or both methods simultaneously:
|
|
||||||
|
|
||||||
### No Authentication
|
|
||||||
|
|
||||||
If neither admin nor OIDC authentication is enabled, the application runs without authentication - suitable for private networks or development.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
auth:
|
|
||||||
admin:
|
|
||||||
enabled: false
|
|
||||||
oidc:
|
|
||||||
enabled: false
|
|
||||||
```
|
|
||||||
|
|
||||||
### Admin Authentication
|
|
||||||
|
|
||||||
Simple username/password authentication using JWT tokens.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
auth:
|
|
||||||
admin:
|
|
||||||
enabled: true
|
|
||||||
username: "admin"
|
|
||||||
password: "your-secure-password"
|
|
||||||
oidc:
|
|
||||||
enabled: false
|
|
||||||
```
|
|
||||||
|
|
||||||
### OIDC (OpenID Connect) Authentication
|
|
||||||
|
|
||||||
Enterprise-grade authentication with providers like Keycloak, Auth0, Okta, etc.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
auth:
|
|
||||||
admin:
|
|
||||||
enabled: false
|
|
||||||
oidc:
|
|
||||||
enabled: true
|
|
||||||
provider_name: "Keycloak"
|
|
||||||
client_id: "garage-ui"
|
|
||||||
client_secret: "your-client-secret"
|
|
||||||
issuer_url: "https://auth.example.com/realms/master"
|
|
||||||
auth_url: "https://auth.example.com/realms/master/protocol/openid-connect/auth"
|
|
||||||
token_url: "https://auth.example.com/realms/master/protocol/openid-connect/token"
|
|
||||||
userinfo_url: "https://auth.example.com/realms/master/protocol/openid-connect/userinfo"
|
|
||||||
session_max_age: 86400 # 24 hours
|
|
||||||
cookie_secure: true # Enable in production with HTTPS
|
|
||||||
```
|
|
||||||
|
|
||||||
### Both Authentication Methods
|
|
||||||
|
|
||||||
You can enable both admin and OIDC authentication simultaneously. Users will be presented with both options on the login page:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
auth:
|
|
||||||
admin:
|
|
||||||
enabled: true
|
|
||||||
username: "admin"
|
|
||||||
password: "your-secure-password"
|
|
||||||
oidc:
|
|
||||||
enabled: true
|
|
||||||
provider_name: "Keycloak"
|
|
||||||
client_id: "garage-ui"
|
|
||||||
client_secret: "your-client-secret"
|
|
||||||
issuer_url: "https://auth.example.com/realms/master"
|
|
||||||
auth_url: "https://auth.example.com/realms/master/protocol/openid-connect/auth"
|
|
||||||
token_url: "https://auth.example.com/realms/master/protocol/openid-connect/token"
|
|
||||||
userinfo_url: "https://auth.example.com/realms/master/protocol/openid-connect/userinfo"
|
|
||||||
session_max_age: 86400
|
|
||||||
cookie_secure: true
|
|
||||||
```
|
|
||||||
|
|
||||||
**Role-Based Access (Optional):**
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
auth:
|
|
||||||
oidc:
|
|
||||||
role_attribute_path: "resource_access.garage-ui.roles"
|
|
||||||
admin_role: "admin"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Deployment Best Practices
|
|
||||||
|
|
||||||
### Production Considerations
|
|
||||||
|
|
||||||
1. **Use HTTPS** - Always enable TLS in production:
|
|
||||||
```yaml
|
|
||||||
auth:
|
|
||||||
oidc:
|
|
||||||
cookie_secure: true
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Set Strong Admin Token** - Generate a secure token for Garage Admin API:
|
|
||||||
```bash
|
|
||||||
openssl rand -base64 32
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Configure CORS** - Restrict allowed origins:
|
|
||||||
```yaml
|
|
||||||
cors:
|
|
||||||
allowed_origins:
|
|
||||||
- "https://garage-ui.yourdomain.com"
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Enable Monitoring** - Expose metrics endpoint for Prometheus:
|
|
||||||
```yaml
|
|
||||||
# Metrics available at /api/v1/metrics
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Resource Limits** - Set appropriate CPU/memory limits in Kubernetes/Docker
|
|
||||||
|
|
||||||
### Health Checks
|
|
||||||
|
|
||||||
The application provides a health check endpoint:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl http://localhost:8080/health
|
|
||||||
# Response: {"status":"ok","version":"0.1.0"}
|
|
||||||
```
|
|
||||||
|
|
||||||
Docker health check is configured automatically (every 30s).
|
|
||||||
|
|
||||||
### Kubernetes Deployment
|
|
||||||
|
|
||||||
The Helm chart includes:
|
|
||||||
|
|
||||||
- **Deployment** with configurable replicas
|
|
||||||
- **Service** (ClusterIP/LoadBalancer)
|
|
||||||
- **Ingress** with TLS support
|
|
||||||
- **ConfigMap** for configuration
|
|
||||||
- **NetworkPolicy** for security
|
|
||||||
- **ServiceMonitor** for Prometheus (optional)
|
|
||||||
|
|
||||||
Example custom values:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# custom-values.yaml
|
|
||||||
replicaCount: 2
|
|
||||||
|
|
||||||
image:
|
|
||||||
repository: noooste/garage-ui
|
|
||||||
tag: latest
|
|
||||||
|
|
||||||
garage:
|
|
||||||
endpoint: "http://garage.storage.svc.cluster.local:3900"
|
|
||||||
adminEndpoint: "http://garage.storage.svc.cluster.local:3903"
|
|
||||||
adminToken: "your-secure-token"
|
|
||||||
|
|
||||||
ingress:
|
|
||||||
enabled: true
|
|
||||||
className: nginx
|
|
||||||
hosts:
|
|
||||||
- host: garage-ui.example.com
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
tls:
|
|
||||||
- secretName: garage-ui-tls
|
|
||||||
hosts:
|
|
||||||
- garage-ui.example.com
|
|
||||||
|
|
||||||
config:
|
|
||||||
auth:
|
|
||||||
admin:
|
|
||||||
enabled: false
|
|
||||||
oidc:
|
|
||||||
enabled: true
|
|
||||||
client_id: garage-ui
|
|
||||||
client_secret: secret
|
|
||||||
issuer_url: https://auth.example.com/realms/master
|
|
||||||
```
|
|
||||||
|
|
||||||
Install with:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm install garage-ui ./helm/garage-ui -f custom-values.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Technology Stack
|
|
||||||
|
|
||||||
### Backend
|
|
||||||
|
|
||||||
- **[Go](https://go.dev/)** 1.25+ - High-performance backend runtime
|
|
||||||
- **[Fiber v3](https://gofiber.io/)** - Express-inspired web framework
|
|
||||||
- **[Viper](https://github.com/spf13/viper)** - Configuration management
|
|
||||||
- **[Minio Go SDK](https://github.com/minio/minio-go)** - S3 client library
|
|
||||||
- **[go-oidc](https://github.com/coreos/go-oidc)** - OpenID Connect support
|
|
||||||
- **[Zerolog](https://github.com/rs/zerolog)** - Structured logging
|
|
||||||
- **[Swagger/Swag](https://github.com/swaggo/swag)** - API documentation
|
|
||||||
|
|
||||||
### Frontend
|
|
||||||
|
|
||||||
- **[React](https://react.dev/)** 19 - UI framework
|
|
||||||
- **[TypeScript](https://www.typescriptlang.org/)** 5.9+ - Type safety
|
|
||||||
- **[Vite](https://vitejs.dev/)** 7 - Build tool and dev server
|
|
||||||
- **[React Router](https://reactrouter.com/)** 7 - Client-side routing
|
|
||||||
- **[TanStack Query](https://tanstack.com/query)** - Server state management
|
|
||||||
- **[Zustand](https://github.com/pmndrs/zustand)** - Client state management
|
|
||||||
- **[React Hook Form](https://react-hook-form.com/)** + [Zod](https://zod.dev/) - Form validation
|
|
||||||
- **[Tailwind CSS](https://tailwindcss.com/)** 4 - Utility-first styling
|
|
||||||
- **[shadcn/ui](https://ui.shadcn.com/)** - Component library
|
|
||||||
- **[Lucide Icons](https://lucide.dev/)** - Icon library
|
|
||||||
- **[Recharts](https://recharts.org/)** - Data visualization
|
|
||||||
- **[Axios](https://axios-http.com/)** - HTTP client
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Contributions are welcome! Whether it's bug reports, feature requests, or code contributions, your input helps improve Garage UI.
|
|
||||||
|
|
||||||
### How to Contribute
|
|
||||||
|
|
||||||
1. **Fork the repository**
|
|
||||||
2. **Create a feature branch** (`git checkout -b feature/amazing-feature`)
|
|
||||||
3. **Make your changes**
|
|
||||||
4. **Commit your changes** (`git commit -m 'Add amazing feature'`)
|
|
||||||
5. **Push to the branch** (`git push origin feature/amazing-feature`)
|
|
||||||
6. **Open a Pull Request**
|
|
||||||
|
|
||||||
### Development Guidelines
|
|
||||||
|
|
||||||
- Follow existing code style (use `gofmt` for Go, ESLint for TypeScript)
|
|
||||||
- Add tests for new features when possible
|
|
||||||
- Update documentation for API changes
|
|
||||||
- Keep commits atomic and descriptive
|
|
||||||
- Ensure all tests pass before submitting PR
|
|
||||||
|
|
||||||
### Reporting Issues
|
|
||||||
|
|
||||||
Please open an issue on GitHub with:
|
|
||||||
- Clear description of the problem
|
|
||||||
- Steps to reproduce
|
|
||||||
- Expected vs actual behavior
|
|
||||||
- Environment details (OS, Docker version, etc.)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Common Issues
|
**Connection failed:**
|
||||||
|
```bash
|
||||||
**Issue: "Failed to connect to Garage Admin API"**
|
curl http://localhost:3903/status -H "Authorization: Bearer your-token"
|
||||||
|
```
|
||||||
- **Solution:** Verify `garage.admin_endpoint` and `garage.admin_token` in config.yaml
|
|
||||||
- Check Garage Admin API is accessible: `curl http://garage:3903/status -H "Authorization: Bearer your-token"`
|
|
||||||
|
|
||||||
**Issue: "CORS errors in browser console"**
|
|
||||||
|
|
||||||
- **Solution:** Configure CORS in config.yaml to allow frontend origin:
|
|
||||||
```yaml
|
|
||||||
cors:
|
|
||||||
allowed_origins:
|
|
||||||
- "http://localhost:3000" # For dev
|
|
||||||
```
|
|
||||||
|
|
||||||
**Issue: "401 Unauthorized with OIDC"**
|
|
||||||
|
|
||||||
- **Solution:** Verify OIDC configuration, especially `issuer_url`, `client_id`, and `client_secret`
|
|
||||||
- Check provider configuration allows the redirect URL: `http://your-app/auth/callback`
|
|
||||||
|
|
||||||
**Issue: "Objects not appearing after upload"**
|
|
||||||
|
|
||||||
- **Solution:** Check S3 endpoint connectivity and bucket permissions
|
|
||||||
- Verify Garage bucket exists: `garage bucket list`
|
|
||||||
|
|
||||||
### Debug Mode
|
|
||||||
|
|
||||||
Enable debug logging for troubleshooting:
|
|
||||||
|
|
||||||
|
**Enable debug logs:**
|
||||||
```yaml
|
```yaml
|
||||||
logging:
|
logging:
|
||||||
level: "debug"
|
level: "debug"
|
||||||
format: "json"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Or via environment variable:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
GARAGE_UI_LOGGING_LEVEL=debug
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details.
|
MIT - see [LICENSE](LICENSE)
|
||||||
|
|
||||||
---
|
## Links
|
||||||
|
|
||||||
## Acknowledgments
|
- [Issues](https://github.com/Noooste/garage-ui/issues)
|
||||||
|
- [Contributing](CONTRIBUTING.md)
|
||||||
- [Garage](https://garagehq.deuxfleurs.fr/) - The lightweight, geo-distributed S3 storage system
|
- [Garage Docs](https://garagehq.deuxfleurs.fr/documentation/)
|
||||||
- [shadcn/ui](https://ui.shadcn.com/) - Beautiful, accessible React components
|
|
||||||
- [Fiber](https://gofiber.io/) - Fast and lightweight Go web framework
|
|
||||||
- All open-source contributors who made this project possible
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
- **Documentation:** [GitHub Wiki](https://github.com/Noooste/garage-ui/wiki) (coming soon)
|
|
||||||
- **Issues:** [GitHub Issues](https://github.com/Noooste/garage-ui/issues)
|
|
||||||
- **Discussions:** [GitHub Discussions](https://github.com/Noooste/garage-ui/discussions)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Made with ❤️ for the Garage community**
|
|
||||||
|
|||||||
Reference in New Issue
Block a user