Skip to content

Commit

Permalink
Add support for setcap from build command (#129)
Browse files Browse the repository at this point in the history
  • Loading branch information
francislavoie authored Feb 6, 2023
1 parent e0ed12b commit 661655c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 15 deletions.
19 changes: 13 additions & 6 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ builds:
- s390x
- ppc64le
goarm:
- 5
- 6
- 7
- "5"
- "6"
- "7"
ignore:
- goos: darwin
goarch: arm
Expand All @@ -54,7 +54,7 @@ builds:
goarch: s390x
- goos: freebsd
goarch: arm
goarm: 5
goarm: "5"
flags:
- -trimpath
ldflags:
Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
46 changes: 38 additions & 8 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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...))
Expand All @@ -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
Expand Down

0 comments on commit 661655c

Please sign in to comment.