henrygd/beszel · warning

no SELinux tools available (semanage/restorecon or chcon)

Error message

no SELinux tools available (semanage/restorecon or chcon)

What it means

HandleSELinuxContext first tries persistent SELinux relabeling via semanage/restorecon, then falls back to chcon. If none of these tools can be found on PATH (exec.LookPath fails for chcon as the last fallback), it returns this error. It indicates an SELinux system (or one the function treats as such) with no available tooling to apply a bin_t context.

Source

Thrown at internal/ghupdate/selinux.go:36

		return nil
	}

	ColorPrint(ColorYellow, "SELinux is enabled; applying context…")

	// Try persistent context via semanage+restorecon
	if success := trySemanageRestorecon(path); success {
		return nil
	}

	// Fallback to temporary context via chcon
	if chconPath, err := exec.LookPath("chcon"); err == nil {
		if err := exec.Command(chconPath, "-t", "bin_t", path).Run(); err != nil {
			return fmt.Errorf("chcon failed: %w", err)
		}
		return nil
	}

	return fmt.Errorf("no SELinux tools available (semanage/restorecon or chcon)")
}

// trySemanageRestorecon attempts to set persistent SELinux context using semanage and restorecon.
// Returns true if successful, false otherwise.
func trySemanageRestorecon(path string) bool {
	semanagePath, err := exec.LookPath("semanage")
	if err != nil {
		return false
	}

	restoreconPath, err := exec.LookPath("restorecon")
	if err != nil {
		return false
	}

	// Try to add the fcontext rule; if it already exists, try to modify it
	if err := exec.Command(semanagePath, "fcontext", "-a", "-t", "bin_t", path).Run(); err != nil {
		// Rule may already exist, try modify instead

View on GitHub (pinned to b38fb7dafa)

Solutions

  1. Install SELinux userland tools: `dnf install policycoreutils-python-utils` (semanage/restorecon) or at minimum `yum install policycoreutils` (chcon).
  2. Ensure PATH includes /usr/sbin and /sbin when running from systemd/cron, since SELinux tools often live there.
  3. If the host does not use SELinux, guard the call so HandleSELinuxContext is skipped (e.g. check /sys/fs/selinux exists) — this error is expected on non-SELinux systems.
  4. Relabel manually after update: `sudo chcon -t bin_t /path/to/binary`.

Example fix

// before: minimal container without SELinux tools
// error: no SELinux tools available (semanage/restorecon or chcon)

// after: install tooling or skip when SELinux is absent
if _, err := os.Stat("/sys/fs/selinux"); err == nil {
    if err := HandleSELinuxContext(binPath); err != nil { log.Warn(err) }
}
Defensive patterns

Strategy: fallback

Validate before calling

func selinuxManaged() bool {
    if _, err := os.Stat("/sys/fs/selinux"); err != nil { return false }
    for _, t := range []string{"semanage", "restorecon", "chcon"} {
        if _, err := exec.LookPath(t); err == nil { return true }
    }
    return false
}
// call HandleSELinuxContext only if selinuxManaged()

Type guard

func hasAnySELinuxTool() bool {
    for _, t := range []string{"semanage", "restorecon", "chcon"} {
        if p, _ := exec.LookPath(t); p != "" { return true }
    }
    return false
}

Try / catch

err := HandleSELinuxContext(binPath)
if err != nil && strings.Contains(err.Error(), "no SELinux tools available") {
    log.Info("SELinux tooling absent; skipping context fix")
    return nil
}

Prevention

When it happens

Trigger: Calling HandleSELinuxContext on a host where neither semanage, restorecon, nor chcon is installed or on PATH. Tests TestHandleSELinuxContext_NoSELinux and TestHandleSELinuxContext_InvalidPath exercise this path.

Common situations: Minimal/scratch container images or distroless systems without SELinux userland; running from an environment with a stripped PATH (cron, systemd unit with minimal Environment); SELinux utilities simply never installed on the host.

Related errors


AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31). Data as JSON: /api/errors/f318312507e357c6. Report an issue: GitHub.