Add ability to select compression algo by downloading location with file extension.

- Also update README.md with more useful examples.
This commit is contained in:
eleksir
2026-04-04 11:47:39 +03:00
parent afffc99a8a
commit 8beba095d0
9 changed files with 91 additions and 41 deletions

View File

@@ -198,7 +198,8 @@ Config is JSON (HJSON with comments supported). Default path depends on OS:
| compression_level | `9` | Gzip level (1-9) |
| exclude_patterns | `[]` | Regex patterns to exclude from backup |
| filename_prefix | `backup` | Prefix for backup filename in Content-Disposition header |
| compression_algorithm | `gzip` | Compression algorithm: gzip, pgzip, bzip2, zstd, lz4 or xz |
| default_compression | `gzip` | Default compression algorithm: gzip, pgzip, bzip2, zstd, lz4 or xz |
| compression_algorithm | `gzip` | Alias for default_compression (deprecated) |
## Architecture & Key Patterns

View File

@@ -28,10 +28,22 @@ If you running FreeBSD, use the rc.d script `contrib/backer.freebsd` and place i
Build, install and configure backer. On your backup storage server you can do
```bash
curl -u username:password https://your_server:8086/archive -o "backup-$(date +%Y%m%d-%H%M%S).tar.gz"
wget --quiet --no-check-certificate --content-disposition --http-user=username --http-password=password https://your_server:8086/archive
```
The filename and extension depend on your `filename_prefix` and `compression_algorithm` settings.
The filename and extension depend on your `filename_prefix` and `default_compression` settings.
You can also override compression by specifying the archive extension in the URL:
```bash
wget --quiet --no-check-certificate --content-disposition --http-user=username --http-password=password https://your_server:8086/archive.xz
wget --quiet --no-check-certificate --content-disposition --http-user=username --http-password=password https://your_server:8086/archive.gz # Uses pgzip
wget --quiet --no-check-certificate --content-disposition --http-user=username --http-password=password https://your_server:8086/archive.bz2
wget --quiet --no-check-certificate --content-disposition --http-user=username --http-password=password https://your_server:8086/archive.zst
wget --quiet --no-check-certificate --content-disposition --http-user=username --http-password=password https://your_server:8086/archive.lz4
```
Note: `/archive.tar.gz` always uses pgzip (parallel gzip) for better performance.
Of course, something can go wrong, so you must check http status code after downloading backup.
@@ -56,7 +68,8 @@ All options described in example config.
| compression_level | 9 | Compression level. | 1 (fastest) to 9 (best compression). |
| exclude_patterns | [] | Regex patterns to exclude from backup. | E.g., `[".*\\.tmp$", "/node_modules/"]`. |
| filename_prefix | "backup" | Prefix for backup filename. | E.g., "mybackup" produces `mybackup-20260325-092341.tar.gz`. |
| compression_algorithm | "gzip" | Compression algorithm. | Options: gzip, pgzip, bzip2, zstd, lz4, xz. |
| default_compression | "gzip" | Default compression algorithm. | Options: gzip, pgzip, bzip2, zstd, lz4, xz. |
| compression_algorithm | "gzip" | Alias for default_compression. | You should use default_compression instead. |
## Compression algorithms

View File

@@ -7,6 +7,7 @@ pidfile="/run/$SVCNAME/$SVCNAME.pid"
depend() {
need net
use dns
}
start_pre() {

View File

@@ -26,27 +26,30 @@
/* Where to store logs. */
"log": "/var/log/backer.log",
/* Verbosity of logs */
/* Verbosity of logs. */
"loglevel": "info",
/* Diretories to backup */
"directories": [
"/path/to/directory1",
"/path/to/directory2"
],
/* Backup streaming timeout in minutes. */
"backup_timeout": 60,
/* Gzip compression level (1-9, where 9 is best compression). */
"compression_level": 9,
/* Regex patterns to exclude from backup. */
"exclude_patterns": [],
/* Prefix for backup filename in Content-Disposition header. */
"filename_prefix": "backup",
/* Compression algorithm: gzip, pgzip, bzip2, zstd, lz4 or xz. */
"compression_algorithm": "gzip"
/* Compression algorithm alias (deprecated: use default_compression). */
"compression_algorithm": "gzip",
/* Default compression algorithm: gzip, pgzip, bzip2, zstd, lz4 or xz. */
"default_compression": "gzip",
/* Regex patterns to exclude from backup. */
"exclude_patterns": [],
/* Directories to backup. */
"directories": [
"/path/to/directory1",
"/path/to/directory2"
]
}

View File

@@ -50,8 +50,8 @@ const (
// defaultFilenamePrefix is the default prefix for backup filenames.
defaultFilenamePrefix = "backup"
// defaultCompressionAlgorithm is the default compression algorithm.
defaultCompressionAlgorithm = "gzip"
// defaultDefaultCompression is the default compression algorithm.
defaultDefaultCompression = "gzip"
)
/* vim: setlocal ft=go noet ai ts=4 sw=4 sts=4: */

View File

@@ -135,15 +135,20 @@ func LoadConfig(path string) error {
log.Warnf("Config option filename_prefix is not set, fallback to %s", C.FilenamePrefix)
}
// CompressionAlgorithm: default and validate.
if C.CompressionAlgorithm == "" {
C.CompressionAlgorithm = defaultCompressionAlgorithm
log.Warnf("Config option compression_algorithm is not set, fallback to %s", C.CompressionAlgorithm)
// DefaultCompression: default and validate. If compression_algorithm is set (deprecated), use it as fallback.
if C.DefaultCompression == "" {
if C.CompressionAlgorithm != "" {
C.DefaultCompression = C.CompressionAlgorithm
} else {
C.DefaultCompression = defaultDefaultCompression
}
}
if C.CompressionAlgorithm != "gzip" && C.CompressionAlgorithm != "bzip2" && C.CompressionAlgorithm != "zstd" && C.CompressionAlgorithm != "lz4" && C.CompressionAlgorithm != "xz" && C.CompressionAlgorithm != "pgzip" {
return fmt.Errorf("Config option compression_algorithm must be gzip, bzip2, zstd, lz4, xz or pgzip, got %s", C.CompressionAlgorithm)
switch C.DefaultCompression {
case "gzip", "pgzip", "bzip2", "xz", "lz4", "zstd":
log.Infof("Using %s as defailt compression algorithm", C.DefaultCompression)
default:
return fmt.Errorf("Config option default_compression must be gzip, bzip2, zstd, lz4, xz or pgzip, got %s", C.DefaultCompression)
}
// Compile exclude patterns.

View File

@@ -227,8 +227,8 @@ func TestLoadConfigDefaultValues(t *testing.T) {
t.Errorf("C.FilenamePrefix should default to backup, got %s", C.FilenamePrefix)
}
if C.CompressionAlgorithm != "gzip" {
t.Errorf("C.CompressionAlgorithm should default to gzip, got %s", C.CompressionAlgorithm)
if C.DefaultCompression != "gzip" {
t.Errorf("C.DefaultCompression should default to gzip, got %s", C.DefaultCompression)
}
}
@@ -248,8 +248,8 @@ func TestLoadConfigCompressionAlgorithmBzip2(t *testing.T) {
t.Errorf("Expected no error, got %v", err)
}
if C.CompressionAlgorithm != "bzip2" {
t.Errorf("C.CompressionAlgorithm should be bzip2, got %s", C.CompressionAlgorithm)
if C.DefaultCompression != "bzip2" {
t.Errorf("C.DefaultCompression should be bzip2, got %s", C.DefaultCompression)
}
}
@@ -269,8 +269,8 @@ func TestLoadConfigCompressionAlgorithmZstd(t *testing.T) {
t.Errorf("Expected no error, got %v", err)
}
if C.CompressionAlgorithm != "zstd" {
t.Errorf("C.CompressionAlgorithm should be zstd, got %s", C.CompressionAlgorithm)
if C.DefaultCompression != "zstd" {
t.Errorf("C.DefaultCompression should be zstd, got %s", C.DefaultCompression)
}
}
@@ -290,8 +290,8 @@ func TestLoadConfigCompressionAlgorithmLz4(t *testing.T) {
t.Errorf("Expected no error, got %v", err)
}
if C.CompressionAlgorithm != "lz4" {
t.Errorf("C.CompressionAlgorithm should be lz4, got %s", C.CompressionAlgorithm)
if C.DefaultCompression != "lz4" {
t.Errorf("C.DefaultCompression should be lz4, got %s", C.DefaultCompression)
}
}
@@ -311,8 +311,8 @@ func TestLoadConfigCompressionAlgorithmXz(t *testing.T) {
t.Errorf("Expected no error, got %v", err)
}
if C.CompressionAlgorithm != "xz" {
t.Errorf("C.CompressionAlgorithm should be xz, got %s", C.CompressionAlgorithm)
if C.DefaultCompression != "xz" {
t.Errorf("C.DefaultCompression should be xz, got %s", C.DefaultCompression)
}
}
@@ -332,8 +332,8 @@ func TestLoadConfigCompressionAlgorithmPgzip(t *testing.T) {
t.Errorf("Expected no error, got %v", err)
}
if C.CompressionAlgorithm != "pgzip" {
t.Errorf("C.CompressionAlgorithm should be pgzip, got %s", C.CompressionAlgorithm)
if C.DefaultCompression != "pgzip" {
t.Errorf("C.DefaultCompression should be pgzip, got %s", C.DefaultCompression)
}
}

View File

@@ -7,6 +7,7 @@ import (
"io"
"net"
"net/http"
"path"
"strings"
"time"
@@ -76,9 +77,14 @@ func NewServer(configPath string) (*http.Server, error) {
var (
archive io.ReadCloser
extension string
algorithm string
)
switch C.CompressionAlgorithm {
requestedExt := strings.TrimPrefix(path.Ext(r.URL.Path), ".")
algorithm = getCompressionAlgorithm(requestedExt)
switch algorithm {
case "bzip2":
archive = CreateTarBzip2Stream(ctx, files)
extension = "tar.bz2"
@@ -207,4 +213,24 @@ func getClientIP(r *http.Request) string {
return host
}
// getCompressionAlgorithm determines which compression algorithm to use based on the requested extension.
// If the extension is recognized, it returns the corresponding algorithm; otherwise, it returns the default.
// For .tar.gz extension, pgzip is always used for parallel compression.
func getCompressionAlgorithm(requestedExt string) string {
switch requestedExt {
case "tar.bz2":
return "bzip2"
case "tar.zst":
return "zstd"
case "tar.lz4":
return "lz4"
case "tar.xz":
return "xz"
case "tar.gz":
return "pgzip"
default:
return C.DefaultCompression
}
}
/* vim: setlocal ft=go noet ai ts=4 sw=4 sts=4: */

View File

@@ -18,7 +18,8 @@ type (
CompressionLevel int `json:"compression_level"` // Compression level (1-9, default 9).
ExcludePatterns []string `json:"exclude_patterns"` // Regex patterns to exclude from backup.
FilenamePrefix string `json:"filename_prefix"` // Prefix for backup filename (default: "backup").
CompressionAlgorithm string `json:"compression_algorithm"` // Compression algorithm: gzip, pgzip, bzip2, zstd, lz4 or xz.
CompressionAlgorithm string `json:"compression_algorithm"` // Compression algorithm alias (deprecated: use default_compression).
DefaultCompression string `json:"default_compression"` // Default compression algorithm: gzip, pgzip, bzip2, zstd, lz4 or xz.
}
)