diff --git a/cmd/zfs-server/main.go b/cmd/zfs-server/main.go index f391ff8..75881c0 100644 --- a/cmd/zfs-server/main.go +++ b/cmd/zfs-server/main.go @@ -42,11 +42,13 @@ func main() { srv.RegisterRoutes(mux) // Create HTTP server with timeouts for security and reliability + // Note: ReadTimeout is set high to allow streaming uploads where data + // may come in bursts (zfs send can pause between chunks) httpServer := &http.Server{ Addr: ":" + cfg.Port, Handler: mux, - ReadTimeout: 30 * time.Second, // Prevent slowloris attacks - WriteTimeout: 30 * time.Minute, // Allow large file uploads + ReadTimeout: 30 * time.Minute, // Allow streaming uploads with pauses + WriteTimeout: 30 * time.Minute, // Allow large file downloads IdleTimeout: 120 * time.Second, // Close idle connections } diff --git a/internal/server/storage.go b/internal/server/storage.go index c8ca1e7..06c3b1c 100644 --- a/internal/server/storage.go +++ b/internal/server/storage.go @@ -5,7 +5,9 @@ import ( "fmt" "io" "log" + "net/http" "os/exec" + "time" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" @@ -29,9 +31,23 @@ type S3Backend struct { // NewS3Backend creates a new S3 storage backend func NewS3Backend(endpoint, accessKey, secretKey, bucketName string, useSSL bool) (*S3Backend, error) { + // Create custom HTTP transport with extended timeouts for large file uploads + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + // Extended timeouts for streaming large ZFS snapshots + ResponseHeaderTimeout: 5 * time.Minute, + ExpectContinueTimeout: 30 * time.Second, + IdleConnTimeout: 90 * time.Second, + // Connection pooling + MaxIdleConns: 10, + MaxIdleConnsPerHost: 10, + DisableCompression: false, + } + client, err := minio.New(endpoint, &minio.Options{ - Creds: credentials.NewStaticV4(accessKey, secretKey, ""), - Secure: useSSL, + Creds: credentials.NewStaticV4(accessKey, secretKey, ""), + Secure: useSSL, + Transport: transport, }) if err != nil { return nil, fmt.Errorf("failed to create S3 client: %v", err)