This commit is contained in:
2026-02-13 17:30:39 +01:00
parent 20e90ec240
commit 9dfb1a9755
6 changed files with 84 additions and 13 deletions

10
.env
View File

@@ -3,7 +3,7 @@
# ===========================================
# S3 Configuration (Server)
S3_ENABLED=true
S3_ENABLED=false
S3_ENDPOINT=localhost:9000
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=minioadmin
@@ -22,8 +22,10 @@ PORT=8080
# Client Configuration
# ===========================================
CLIENT_ID=client1
API_KEY=fcf730b6d95236ecd3c9fc2d92d7b6b2bb061514961aec041d6c7a7192f592e4
# NOTE: Use the RAW API key here, not the hashed version!
# The server stores the hash in clients.json, client sends raw key
API_KEY=secret123
SERVER_URL=http://localhost:8080
LOCAL_DATASET=zfs/data
LOCAL_DATASET=volume/test
COMPRESS=true
STORAGE_TYPE=s3
STORAGE_TYPE=s3

View File

@@ -31,16 +31,20 @@ func main() {
localBackend := server.NewLocalBackend(cfg.BaseDataset)
// Create metadata directory if needed
dir := cfg.MetadataFile
if idx := len(dir) - 1; idx > 0 {
// Create metadata directory if needed (only if path contains a directory)
if idx := len(cfg.MetadataFile) - 1; idx > 0 {
dir := cfg.MetadataFile
foundSlash := false
for i := len(dir) - 1; i >= 0; i-- {
if dir[i] == '/' {
dir = dir[:i]
foundSlash = true
break
}
}
os.MkdirAll(dir, 0755)
if foundSlash && dir != "" {
os.MkdirAll(dir, 0755)
}
}
srv := server.New(cfg.ConfigFile, cfg.MetadataFile, s3Backend, localBackend)

View File

@@ -134,9 +134,11 @@ func (c *Client) streamToS3(snapshot *zfs.Dataset, uploadURL, storageKey string)
gzWriter := gzip.NewWriter(pw)
go func() {
defer pw.Close()
defer gzWriter.Close()
// Copy zfs output to gzip writer
io.Copy(gzWriter, zfsOut)
// Close gzip writer first to flush footer, then close pipe
gzWriter.Close()
pw.Close()
}()
reader = pr

View File

@@ -222,9 +222,11 @@ func (c *Client) streamIncrementalToS3(snapshot *zfs.Dataset, base, uploadURL, s
gzWriter := gzip.NewWriter(pw)
go func() {
defer pw.Close()
defer gzWriter.Close()
// Copy zfs output to gzip writer
io.Copy(gzWriter, zfsOut)
// Close gzip writer first to flush footer, then close pipe
gzWriter.Close()
pw.Close()
}()
reader = pr

View File

@@ -346,9 +346,11 @@ func (s *Server) HandleUploadStream(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
// Upload to S3
// When using chunked transfer (io.Pipe), ContentLength is -1
// MinIO requires -1 for unknown size to use streaming upload
size := r.ContentLength
if size < 0 {
size = 0
size = -1 // Use streaming upload for unknown size
}
if err := s.s3Backend.Upload(ctx, storageKey, r.Body, size); err != nil {

View File

@@ -93,6 +93,8 @@ COMPRESS=true
STORAGE_TYPE=s3
```
> **Important**: The `API_KEY` in the client `.env` file must be the **raw (unhashed)** key. The server stores the SHA-256 hash in `clients.json`, and the client sends the raw key which the server then hashes for comparison. For example, if `clients.json` has `api_key: "fcf730b6d95236ecd3c9fc2d92d7b6b2bb061514961aec041d6c7a7192f592e4"` (hash of "secret123"), the client `.env` should have `API_KEY=secret123`.
### Restore Tool Configuration
```env
@@ -265,6 +267,63 @@ S3_BUCKET=zfs-snapshots
S3_USE_SSL=false
```
#### Setting Up MinIO Locally
**Option A: Using Docker (Recommended)**
```bash
# Create a directory for MinIO data
mkdir -p ~/minio-data
# Run MinIO container
docker run -d \
--name minio \
-p 9000:9000 \
-p 9001:9001 \
-v ~/minio-data:/data \
-e MINIO_ROOT_USER=minioadmin \
-e MINIO_ROOT_PASSWORD=minioadmin \
minio/minio server /data --console-address ":9001"
```
**Option B: Using Binary**
```bash
# Download MinIO
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
sudo mv minio /usr/local/bin/
# Create data directory
mkdir -p ~/minio-data
# Start MinIO
MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=minioadmin \
minio server ~/minio-data --console-address ":9001"
```
**Create the Bucket**
After starting MinIO, create the bucket using the MinIO Client (mc) or web console:
```bash
# Install MinIO Client (mc)
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/bin/
# Configure alias to local MinIO
mc alias set local http://localhost:9000 minioadmin minioadmin
# Create bucket
mc mb local/zfs
# Verify bucket was created
mc ls local
```
Alternatively, access the MinIO Web Console at http://localhost:9001 and create the bucket through the UI (login: `minioadmin` / `minioadmin`).
### Backblaze B2
```env