diff --git a/deploy/install-mtproxy.sh b/deploy/install-mtproxy.sh index 141ec08..948ee1b 100755 --- a/deploy/install-mtproxy.sh +++ b/deploy/install-mtproxy.sh @@ -48,6 +48,15 @@ if [[ ! -x "$source_directory/objs/bin/mtproto-proxy" ]] || rm -rf "$temporary" fi +# install.sh runs with umask 077, so make's output keeps owner-only +# permissions; the unprivileged mtproxy service user must be able to +# traverse the tree and execute the binary. Normalize permissions +# unconditionally: when the guard above skipped a rebuild (a previous +# failed run may already have left /opt/MTProxy with a root-owned +# 0700 binary), the tree is reused as-is and still needs this fix. +chown -R root:root "$source_directory" +chmod -R a+rX "$source_directory" + install -d -o root -g mtproxy -m 0750 /etc/mtproxy secret_temp="$(mktemp /etc/mtproxy/proxy-secret.XXXXXX)" config_temp="$(mktemp /etc/mtproxy/proxy-multi.conf.XXXXXX)" diff --git a/internal/config/config_test.go b/internal/config/config_test.go index d977312..213ab18 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -234,6 +234,12 @@ func TestLoadAcceptsSystemdCredentialReadPermissions(t *testing.T) { if err := os.WriteFile(profiles, []byte(content), 0444); err != nil { t.Fatal(err) } + // Force the intended mode: install.sh runs tests under umask 077, + // which would otherwise strip the group/other read bits and make the + // "outside a credential directory" assertion below vacuously pass. + if err := os.Chmod(profiles, 0444); err != nil { + t.Fatal(err) + } t.Setenv("CREDENTIALS_DIRECTORY", credentials) server := `{"public_hostname":"proxy.example.com","public_dir":"public","profiles_file":"credentials/profiles.json"}` path := filepath.Join(directory, "config.json")