Skip to content

Commit a31dd33

Browse files
committed
feat: Allow each individual mount config and serve config entry to override its own env vars
1 parent 413388a commit a31dd33

File tree

9 files changed

+95
-13
lines changed

9 files changed

+95
-13
lines changed

compose.yaml

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
services:
22
rclone-manager:
3-
image: ipromknight/rclone-manager:latest
43
container_name: rclone-manager
54
restart: unless-stopped
65
stop_signal: SIGTERM
@@ -22,15 +21,18 @@ services:
2221
environment:
2322
# General
2423
RCLONE_BUFFER_SIZE: 0
25-
RCLONE_BWLIMIT: 100M
24+
RCLONE_BWLIMIT: off
2625
RCLONE_BIND: 0.0.0.0
27-
RCLONE_LOG_LEVEL: INFO
26+
RCLONE_LOG_LEVEL: Info
2827
RCLONE_CACHE_DIR: /caches/rclone
2928
RCLONE_DIR_CACHE_TIME: 10s
3029
RCLONE_TIMEOUT: 10m
3130
RCLONE_UMASK: 002
3231
RCLONE_UID: 1000
3332
RCLONE_GID: 1000
33+
RCLONE_LINKS: true
34+
RCLONE_MULTI_THREAD_STREAMS: 1
35+
RCLONE_TRANSFERS: 1
3436
RCLONE_ALLOW_NON_EMPTY: "true"
3537
RCLONE_ALLOW_OTHER: "true"
3638
RCLONE_CONFIG: /data/rclone.conf
@@ -42,12 +44,9 @@ services:
4244
RCLONE_RC_WEB_GUI_NO_OPEN_BROWSER: "true"
4345

4446
# VFS DEFAULTS
45-
RCLONE_VFS_MIN_FREE_SPACE: off
46-
RCLONE_VFS_CACHE_MAX_AGE: 24h
47-
RCLONE_VFS_MAX_CACHE_SIZE: 100G
4847
RCLONE_VFS_CACHE_MODE: writes
49-
RCLONE_VFS_READ_CHUNK_LIMIT: 64M
50-
RCLONE_VFS_READ_CHUNK_SIZE: 5M
48+
RCLONE_VFS_READ_CHUNK_SIZE: 10M
49+
RCLONE_VFS_READ_CHUNK_SIZE_LIMIT: 10M
5150

5251
# MOUNT DEFAULTS
5352
RCLONE_NO_TRAVERSE: "true"

config.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,28 @@
11
mounts:
22
- backendName: "AllDebrid"
33
mountPoint: "/mnt/rclone/alldebrid"
4+
environment:
5+
RCLONE_BWLIMIT: off
6+
RCLONE_READ_ONLY: true
7+
RCLONE_VFS_READ_CHUNK_SIZE: 16M
8+
RCLONE_VFS_READ_CHUNK_SIZE_LIMIT: 32M
49

510
serves:
611
- backendName: "AllDebrid"
712
protocol: "webdav"
813
addr: "0.0.0.0:8080"
14+
environment:
15+
RCLONE_BUFFER_SIZE: 0
16+
RCLONE_BWLIMIT: 300M
17+
RCLONE_COPY_LINKS: true
18+
RCLONE_LINKS: false
19+
RCLONE_MAX_HEADER_SIZE: 8192
20+
RCLONE_VFS_READ_CHUNK_SIZE: 16M
21+
RCLONE_VFS_READ_CHUNK_SIZE_LIMIT: 32M
22+
RCLONE_STATS: 60s
23+
RCLONE_VFS_CACHE_MODE: writes
24+
RCLONE_CUTOFF_MODE: cautious
25+
RCLONE_MULTI_THREAD_STREAMS: 0
26+
RCLONE_DIR_CACHE_TIME: 10s
27+
RCLONE_NO_MODTIME: true
28+
RCLONE_READ_ONLY: true

src/internal/config/config.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@ import (
88

99
type Config struct {
1010
Serves []struct {
11-
BackendName string `yaml:"backendName"`
12-
Protocol string `yaml:"protocol"`
13-
Addr string `yaml:"addr"`
11+
BackendName string `yaml:"backendName"`
12+
Protocol string `yaml:"protocol"`
13+
Addr string `yaml:"addr"`
14+
Environment map[string]string `yaml:"environment,omitempty"`
1415
} `yaml:"serves"`
1516

1617
Mounts []struct {
17-
BackendName string `yaml:"backendName"`
18-
MountPoint string `yaml:"mountPoint"`
18+
BackendName string `yaml:"backendName"`
19+
MountPoint string `yaml:"mountPoint"`
20+
Environment map[string]string `yaml:"environment,omitempty"`
1921
} `yaml:"mounts"`
2022
}
2123

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package environment
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"strings"
7+
)
8+
9+
func PrepareEnvironment(envVars map[string]string) []string {
10+
if envVars == nil {
11+
return os.Environ()
12+
}
13+
14+
envMap := make(map[string]string)
15+
16+
for _, env := range os.Environ() {
17+
parts := splitEnv(env)
18+
envMap[parts[0]] = parts[1]
19+
}
20+
21+
for key, value := range envVars {
22+
envMap[key] = value
23+
}
24+
25+
return mapToSlice(envMap)
26+
}
27+
28+
func splitEnv(env string) []string {
29+
parts := make([]string, 2)
30+
idx := strings.Index(env, "=")
31+
if idx != -1 {
32+
parts[0] = env[:idx]
33+
parts[1] = env[idx+1:]
34+
} else {
35+
parts[0] = env
36+
parts[1] = ""
37+
}
38+
return parts
39+
}
40+
41+
func mapToSlice(envMap map[string]string) []string {
42+
var env []string
43+
for k, v := range envMap {
44+
env = append(env, fmt.Sprintf("%s=%s", k, v))
45+
}
46+
return env
47+
}

src/internal/mount_manager/helpers.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os/exec"
88
"rclone-manager/internal/config"
99
"rclone-manager/internal/constants"
10+
"rclone-manager/internal/environment"
1011
"syscall"
1112
)
1213

@@ -34,6 +35,9 @@ func createMountCommand(instance *MountedEndpoint) *exec.Cmd {
3435
cmd.Stdout = os.Stdout
3536
cmd.Stderr = os.Stderr
3637
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
38+
39+
cmd.Env = environment.PrepareEnvironment(instance.EnvVars)
40+
3741
return cmd
3842
}
3943

@@ -81,6 +85,7 @@ func setupMountsFromConfig(conf *config.Config, logger zerolog.Logger) {
8185
instance := &MountedEndpoint{
8286
BackendName: mount.BackendName,
8387
MountPoint: mount.MountPoint,
88+
EnvVars: mount.Environment,
8489
}
8590
if existing, ok := getMountedEndpoint(mount.BackendName); ok {
8691
if existing.MountPoint != instance.MountPoint {

src/internal/mount_manager/mount.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ var (
1515
type MountedEndpoint struct {
1616
BackendName string
1717
MountPoint string
18+
EnvVars map[string]string
1819
}
1920

2021
func InitializeMounts(conf *config.Config, logger zerolog.Logger, processLock *sync.Mutex) {
@@ -31,6 +32,7 @@ func InitializeMounts(conf *config.Config, logger zerolog.Logger, processLock *s
3132
instance := &MountedEndpoint{
3233
BackendName: mount.BackendName,
3334
MountPoint: mount.MountPoint,
35+
EnvVars: mount.Environment,
3436
}
3537
StartMountWithRetries(instance, logger)
3638
}

src/internal/serve_manager/helpers.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os/exec"
88
"rclone-manager/internal/config"
99
"rclone-manager/internal/constants"
10+
"rclone-manager/internal/environment"
1011
)
1112

1213
func getServeInstance(key string) (*ServeProcess, bool) {
@@ -25,6 +26,8 @@ func createServeCommand(instance *ServeProcess) *exec.Cmd {
2526
cmd.Stdout = os.Stdout
2627
cmd.Stderr = os.Stderr
2728

29+
cmd.Env = environment.PrepareEnvironment(instance.EnvVars)
30+
2831
return cmd
2932
}
3033

@@ -42,6 +45,7 @@ func setupServesFromConfig(conf *config.Config, logger zerolog.Logger) {
4245
Backend: serve.BackendName,
4346
Protocol: serve.Protocol,
4447
Addr: serve.Addr,
48+
EnvVars: serve.Environment,
4549
}
4650
if existing, ok := getServeInstance(serve.BackendName); ok {
4751
if existing.Protocol != serve.Protocol || existing.Addr != serve.Addr {

src/internal/serve_manager/monitor.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func MonitorServeProcesses(logger zerolog.Logger) {
4242
Backend: serveProcess.Backend,
4343
Protocol: serveProcess.Protocol,
4444
Addr: serveProcess.Addr,
45+
EnvVars: serveProcess.EnvVars,
4546
}
4647

4748
newProcess := StartServeWithRetries(newServe, logger)

src/internal/serve_manager/serve.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type ServeProcess struct {
1717
Addr string
1818
StartedAt time.Time
1919
GracePeriod time.Duration
20+
EnvVars map[string]string
2021
}
2122

2223
var (
@@ -38,6 +39,7 @@ func InitializeServeEndpoints(conf *config.Config, logger zerolog.Logger, proces
3839
Backend: serve.BackendName,
3940
Protocol: serve.Protocol,
4041
Addr: serve.Addr,
42+
EnvVars: serve.Environment,
4143
}
4244
StartServeWithRetries(instance, logger)
4345
}

0 commit comments

Comments
 (0)