Add support for setcap from build command (#129)

This commit is contained in:
Francis Lavoie 2023-02-06 13:26:33 -05:00 committed by GitHub
parent e0ed12b135
commit 661655cf05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 15 deletions

View file

@ -34,9 +34,9 @@ builds:
- s390x
- ppc64le
goarm:
- 5
- 6
- 7
- "5"
- "6"
- "7"
ignore:
- goos: darwin
goarch: arm
@ -54,7 +54,7 @@ builds:
goarch: s390x
- goos: freebsd
goarch: arm
goarm: 5
goarm: "5"
flags:
- -trimpath
ldflags:
@ -64,8 +64,15 @@ archives:
- format_overrides:
- goos: windows
format: zip
replacements:
darwin: mac
name_template: >-
{{ .ProjectName }}_
{{- .Version }}_
{{- if eq .Os "darwin" }}mac{{ else }}{{ .Os }}{{ end }}_
{{- .Arch }}
{{- with .Arm }}v{{ . }}{{ end }}
{{- with .Mips }}_{{ . }}{{ end }}
{{- if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}
checksum:
algorithm: sha512

View file

@ -167,7 +167,7 @@ Because the subcommands and flags are constrained to benefit rapid plugin protot
- `CADDY_VERSION` sets the version of Caddy to build.
- `XCADDY_RACE_DETECTOR=1` enables the Go race detector in the build.
- `XCADDY_DEBUG=1` enables the DWARF debug information in the build.
- `XCADDY_SETCAP=1` will run `sudo setcap cap_net_bind_service=+ep` on the temporary binary before running it when in dev mode.
- `XCADDY_SETCAP=1` will run `sudo setcap cap_net_bind_service=+ep` on the resulting binary. By default, the `sudo` command will be used if it is found; set `XCADDY_SUDO=0` to avoid using `sudo` if necessary.
- `XCADDY_SKIP_BUILD=1` causes xcaddy to not compile the program, it is used in conjunction with build tools such as [GoReleaser](https://goreleaser.com). Implies `XCADDY_SKIP_CLEANUP=1`.
- `XCADDY_SKIP_CLEANUP=1` causes xcaddy to leave build artifacts on disk after exiting.
- `XCADDY_WHICH_GO` sets the go command to use when for example more then 1 version of go is installed.

View file

@ -144,6 +144,12 @@ func runBuild(ctx context.Context, args []string) error {
log.Fatalf("[FATAL] %v", err)
}
// if requested, run setcap to allow binding to low ports
err = setcapIfRequested(output)
if err != nil {
return err
}
// prove the build is working by printing the version
if runtime.GOOS == os.Getenv("GOOS") && runtime.GOARCH == os.Getenv("GOARCH") {
if !filepath.IsAbs(output) {
@ -223,14 +229,10 @@ func runDev(ctx context.Context, args []string) error {
return err
}
if os.Getenv("XCADDY_SETCAP") == "1" {
cmd = exec.Command("sudo", "setcap", "cap_net_bind_service=+ep", binOutput)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Printf("[INFO] Setting capabilities (requires admin privileges): %v", cmd.Args)
if err = cmd.Run(); err != nil {
return err
}
// if requested, run setcap to allow binding to low ports
err = setcapIfRequested(binOutput)
if err != nil {
return err
}
log.Printf("[INFO] Running %v\n\n", append([]string{binOutput}, args...))
@ -257,6 +259,34 @@ func runDev(ctx context.Context, args []string) error {
return cmd.Wait()
}
func setcapIfRequested(output string) error {
if os.Getenv("XCADDY_SETCAP") != "1" {
return nil
}
args := []string{"setcap", "cap_net_bind_service=+ep", output}
// check if sudo isn't available, or we were instructed not to use it
_, sudoNotFound := exec.LookPath("sudo")
skipSudo := sudoNotFound != nil || os.Getenv("XCADDY_SUDO") == "0"
var cmd *exec.Cmd
if skipSudo {
cmd = exec.Command(args[0], args[1:]...)
} else {
cmd = exec.Command("sudo", args...)
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Printf("[INFO] Setting capabilities (requires admin privileges): %v", cmd.Args)
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to setcap on the binary: %v", err)
}
return nil
}
type module struct {
Path string // module path
Version string // module version