doas
Doas is a lightweight command-line utility in Unix-like operating systems that enables a user to execute commands as another user, typically the superuser (root), after authentication via password or other configured methods.[1] Originally developed for OpenBSD, doas provides a simpler and more minimalistic alternative to the widely used sudo tool, with a smaller codebase that enhances auditability and reduces potential security vulnerabilities.[2] Introduced in OpenBSD 5.8 in October 2015 by developer Ted Unangst, it addresses concerns over sudo's complexity by offering straightforward syntax and configuration while maintaining essential privilege escalation functionality.[1][3] The utility operates by parsing rules defined in a configuration file, usually/etc/doas.conf, which specifies permissions such as allowing certain users to run commands as root or others without repeated authentication.[4] Key features include support for non-interactive modes, environment variable inheritance (like DISPLAY and TERM for graphical applications), and options to persist authentication or check configuration validity without execution.[1] Unlike sudo, doas does not preserve the entire user environment by default, instead setting variables like HOME and SHELL to those of the target user to promote security through isolation.[1] It has been praised for its efficiency in resource-constrained environments and is configurable to deny or permit actions based on user, group, or command specifics.[5]
Since its inception, doas has gained adoption beyond OpenBSD through community ports and packages, becoming available in major Linux distributions such as Arch Linux (via the opendoas package), Debian, Gentoo, and Ubuntu, as well as in FreeBSD and other BSD variants.[6][7][8] These implementations maintain compatibility with the original while adapting to diverse system architectures, including support for illumos, NetBSD, and even macOS in some forks.[2] Doas's design philosophy emphasizes proactive security and simplicity, aligning with OpenBSD's broader focus on correctness and minimalism in system tools.[3]
History and Development
Origins and Motivation
In Unix-like systems, privilege escalation has long been facilitated by tools such as su and sudo, with the latter originating in 1980 at the State University of New York at Buffalo as a means to execute commands as another user, typically root, under configurable permissions. Over decades, sudo accumulated extensive features including detailed logging, plugin support, scripting capabilities, and environmental controls, resulting in a codebase significantly larger and more complex than necessary for basic use cases.[9] Within the OpenBSD project, which prioritizes code correctness, minimalism, and proactive security auditing, sudo's growth into a multifaceted utility raised concerns about its maintenance burden and attack surface; developers like Theo de Raadt and Todd Miller highlighted that its size—approximately five times that of typical setuid binaries—meant excessive code executed in privileged contexts, potentially amplifying vulnerabilities.[10] Ted Unangst, a longtime OpenBSD contributor, developed doas as a direct response to these issues, driven by his own frustrations with sudo's default configuration, particularly its "safe environment" mode that unpredictably altered variables and disrupted routine tasks like package additions or port compilations.[10] He aimed to provide a streamlined alternative that embodied OpenBSD's core tenets of simplicity and security, avoiding the feature creep that had encumbered sudo.[10] Initial proposals and discussions emerged in the OpenBSD community around mid-2015, reflecting broader desires to prune bloated dependencies from the base system while preserving sudo for advanced needs via the ports collection.[10] Unangst's design goals centered on a focused, single-purpose tool for switching to root privileges, deliberately omitting extraneous elements such as humorous insults, complex scripting interfaces, or built-in logging to minimize the codebase and enhance auditability.[10]Release and Initial Implementation
doas was initially developed by Ted Unangst ([email protected]) as a lightweight alternative to sudo, with the codebase imported into the OpenBSD source tree on July 16, 2015.[11][12] The implementation, written primarily in C, featured a simple parser generated by yacc and totaled approximately 800 lines of code across its core files (doas.c, env.c, parse.y, and doas.h).[13] This compact design emphasized minimalism, contrasting sharply with sudo's extensive footprint exceeding 200,000 lines.[14] Following its import, doas underwent testing in OpenBSD snapshots, the daily development builds available between releases, allowing early feedback from developers before stabilization.[15] It was released as a standard utility in OpenBSD 5.8 on October 18, 2015, becoming the default tool for privilege escalation and replacing sudo in the base system.[1] The project adopted the ISC license, a permissive open-source license commonly used in OpenBSD for its brevity and compatibility with BSD traditions.[16] Documentation accompanied the rollout, including the doas(1) man page detailing usage and the doas.conf(5) man page specifying configuration syntax, both integrated into the official OpenBSD manual set from the initial release.[1][4] Contributions from other OpenBSD developers refined the code during the pre-release period, focusing on security audits and portability within the base system.[11] This integration aligned with OpenBSD's emphasis on secure-by-default utilities, as outlined in its development philosophy.Functionality
Purpose and Design Principles
doas is a lightweight utility designed to execute commands with elevated privileges, typically as the root user, by allowing configurable permissions for specified users or groups. Its primary purpose is to serve as a streamlined alternative to sudo, enabling secure and controlled privilege escalation in Unix-like systems, particularly those prioritizing security and minimalism, such as OpenBSD.[1][10] The design of doas adheres to principles of minimalism and simplicity to enhance security and usability. It eschews complex features like built-in logging, scripting capabilities, or command aliases, instead relying on a straightforward configuration file for access control and the system's native authentication mechanisms—such as password prompts via /etc/login.conf—for verification. This approach results in a significantly smaller codebase compared to sudo, which reduces the potential attack surface by limiting the amount of privileged code executed.[1][17][10] By focusing on essential functionality, doas offers advantages including faster execution times and lower resource consumption, making it suitable for environments where efficiency and reduced complexity are paramount. Its configuration-driven model supports fine-grained permissions without unnecessary overhead, thereby minimizing vulnerabilities associated with feature bloat in more comprehensive tools.[10][17] doas targets use cases in security-oriented system administration, such as in BSD variants, where administrators require non-interactive or targeted privilege granting for routine tasks like package management or service configuration, without the need for elaborate policy enforcement.[1][10]Basic Usage Mechanics
Thedoas utility executes a specified command as another user, with the basic syntax given by doas [-Lns] [-a style] [-C config] [-u user] command [arg ...].[1] The command argument is mandatory unless the -C, -L, or -s options are used, and it allows the user to run programs with elevated privileges after authentication.[1] By default, without the -u option, doas targets the root user for execution.[1]
At runtime, doas forks a new process to execute the command with the privileges of the target user, preserving the invoking user's current working directory.[1] It constructs a new environment for the subprocess, setting variables such as HOME, LOGNAME, PATH, SHELL, and USER to values appropriate for the target user, while inheriting DISPLAY and TERM from the parent process; the DOAS_USER variable is also set to identify the invoking user.[1] Unless otherwise configured, doas prompts the invoking user for their password to authenticate the request before proceeding, and the process exits upon command completion.[1]
For error handling, doas provides clear diagnostic messages, such as indications of permission denials, configuration parsing failures, authentication errors, or issues with command location or executability.[1] It returns an exit status of 0 upon successful execution and a non-zero status greater than 0 for any failure, allowing scripts and calling processes to detect and respond to errors programmatically.[1]
Configuration
Syntax and Directives
The configuration file for doas is located at/etc/doas.conf and is parsed line-by-line, with comments introduced by the # character and extending to the end of the line.[4]
The core syntax of rules in doas.conf follows the format permit | deny [options] identity [as target] [cmd command [args ...]], where permit allows execution and deny blocks it (though deny is rarely used as unmatched rules default to denial).[4] Here, identity specifies the user or group (prefixed with :) initiating the command, target optionally designates the user to run as (defaulting to any user, including root, if unspecified), and cmd restricts execution to a specific command path with optional arguments.[4] Commands must use absolute paths for precision, and wildcards are not supported in command specifications.[4]
Key options, or flags, modify rule behavior: nopass exempts the rule from requiring a password prompt, persist caches successful authentication credentials for the duration of the session to avoid repeated prompts, and keepenv preserves specified environment variables during execution.[4] The target clause explicitly sets the execution user, overriding defaults.[4]
Rules are evaluated in the order they appear in the file, with the last matching rule determining the outcome; if no rule matches, access is denied, making rule ordering critical for precedence.[4]
Practical Examples
Practical examples of doas configuration demonstrate how administrators can tailor permissions for specific users, groups, and commands in real-world scenarios, such as system monitoring, service management, and user privilege delegation. These configurations are defined in the/etc/doas.conf file, where rules follow a structured syntax to control access without unnecessary overhead. The following annotated examples illustrate common use cases, drawing from established documentation to ensure secure and targeted privilege escalation.[4]
One straightforward application allows a designated user to execute a monitoring tool as root without requiring a password prompt, enhancing efficiency for routine diagnostics. For instance, the rule permit nopass user1 as [root](/page/Root) cmd /usr/sbin/procmap enables user1 to run the /usr/sbin/procmap command—useful for process mapping—directly as root, bypassing authentication each time. This setup is ideal for trusted administrative tasks where repeated access is needed but security risks are minimized by limiting to a single command.[4]
For broader administrative access, group-based rules simplify management across multiple users. The configuration permit :wheel as root grants all members of the wheel group full root privileges for any command, allowing them to perform system-wide operations like package installation or file edits without individual rule definitions. This is commonly used in environments where wheel membership already signifies elevated trust, such as development teams handling server maintenance.[4]
In service-oriented setups, particularly on systems with systemd, caching authentication can streamline repeated interactions. The rule permit persist :admins cmd /usr/bin/systemctl permits members of the admins group to manage services via systemctl (e.g., starting or stopping daemons) with a password prompt only on the first use per session, after which access persists until a timeout of 5 minutes (in the OpenBSD implementation). This reduces interruptions during maintenance windows while restricting actions to service control.[6]
To support specialized tasks like running scripts in a restricted context, environment preservation ensures compatibility. The example permit keepenv user2 as [nobody](/page/Nobody) allows user2 to execute commands as the nobody user—a low-privilege account for untrusted processes—while retaining key environment variables from the original session, preventing issues with paths or locales. This is particularly useful for web server operations or sandboxed applications where full environment reset could break functionality.[4]
Best practices for doas configurations emphasize precision and verification to maintain security. Always specify exact commands with absolute paths rather than broad permissions to limit exposure, and test rules using non-root accounts via syntax checks like doas -C /etc/doas.conf before deployment. Additionally, set file permissions to 0400 owned by root to prevent unauthorized modifications.[4][6]
Security Model
Permissions and Authentication
Doas enforces access control through a rule-based permissions model defined in the configuration file/etc/doas.conf. Rules specify permit or deny directives that match the invoking user's identity (username or group) against the target user and command to be executed, with the last matching rule taking precedence; if no rule matches, access is denied by default.[4] This model evaluates permissions before command execution, allowing fine-grained control such as restricting specific commands or arguments for designated users or groups.[4]
Authentication in doas integrates with the host system's mechanisms, such as the BSD authentication framework on OpenBSD or Pluggable Authentication Modules (PAM) on other BSD variants like FreeBSD.[18] By default, doas prompts for the target user's password upon invocation unless a rule includes the nopass option, which permits execution without authentication; doas-specific methods can be configured via an auth-doas entry in /etc/login.conf on OpenBSD to select alternative styles like one-time passwords.[18] For non-root targets, specified via the -u option or as target in rules, authentication similarly verifies the target user's credentials.[18]
The persist option in rules enables caching of successful authentication for subsequent invocations within the same session, avoiding repeated prompts; this persists for a default timeout of 5 minutes, after which re-authentication is required.[19] Users can manually clear the cache using doas -L to invalidate persisted credentials before the timeout.[18] In portable implementations, persist behavior may vary due to platform-specific kernel APIs, but it remains configurable per rule.[8]
Doas includes basic logging of successful command executions to the system logger (syslogd) by default, but lacks built-in facilities for denial logging; tracking of denied attempts relies on external system audit tools such as auditd.[4] The nolog option in rules can disable even this syslog recording for specific permissions.[4] Configuration changes in /etc/doas.conf take effect immediately upon the next invocation, as doas parses the file each time without requiring a restart or reload; the -C option allows syntax validation beforehand.[18]
Key Differences from Sudo
doas emphasizes simplicity and minimalism in its design, lacking many advanced features found in sudo such as command aliases, configurable timeouts, email alerts for usage, and support for plugins or LDAP integration. This reduction in functionality streamlines privilege escalation for basic needs but may limit its suitability for environments requiring granular policy enforcement or auditing beyond syslog logging.[20][4] The configuration file for doas, /etc/doas.conf, employs a straightforward syntax with rules in the form of "permit|deny [options] identity [as target] [cmd command]", without support for includes, regular expressions, or complex runas specifications present in sudoers. This design facilitates easier auditing and maintenance due to its linear evaluation (last matching rule applies) and default deny policy, though it offers less flexibility for intricate access controls.[4][20] In terms of performance, doas presents a smaller footprint, with its source code consisting of a single file of approximately 2,500 lines compared to sudo's multi-file codebase exceeding 200,000 lines, resulting in lower overhead for privilege escalation and reduced resource consumption during execution.[21][22] Security-wise, doas mitigates risks associated with feature bloat by omitting capabilities like session recording or extensive environment manipulation, which have contributed to numerous vulnerabilities in sudo, including over 50 CVEs since 2000 related to privilege escalation and buffer overflows. While doas forgoes some auditing features, its kernel-tied authentication (using process ID checks) and minimal attack surface—evidenced by only one known CVE in non-OpenBSD ports—enhance overall configurability and auditability for simpler setups.[23][24][20] Migrating from sudoers to doas.conf typically involves manual simplification, as automated tools are unavailable; administrators must translate permissive rules into doas's basic permit/deny structure, often discarding advanced sudo options like timeouts or aliases that have no direct equivalent.[25][26]Availability and Ports
Native Implementations
Doas is natively integrated into the base system of several BSD variants, providing a lightweight alternative to sudo for privilege escalation without requiring additional package installation. In OpenBSD, doas has been the default utility since version 5.8, released in October 2015, where it fully replaces sudo in the base installation while sudo remains available as an optional package.[27][1] This integration ensures doas is immediately usable out-of-the-box, with configuration handled through /etc/doas.conf, emphasizing OpenBSD's commitment to simplicity and security in core utilities. DragonFly BSD includes support for doas starting from version 5.4, released in December 2018, available via the DPorts package system as security/doas for executing commands with elevated privileges.[28] The utility is configured via /etc/doas.conf, aligning with DragonFly's focus on performance-oriented features while adopting doas for its minimal footprint compared to more feature-heavy alternatives. Official manual pages document its usage, confirming compatibility without reliance on external sources.[29] FreeBSD provides doas via the ports collection under security/doas beginning with earlier versions, including dedicated man pages and example configurations to facilitate adoption. Available since 2016, this allows users to install and leverage doas (e.g.,pkg install doas) for system management, reflecting FreeBSD's emphasis on providing versatile, secure tools through its ports system.[30][31] The utility's presence in the ports collection streamlines administrative tasks across FreeBSD environments.
In NetBSD, doas is natively supported through integration with the pkgsrc package collection under security/doas, available in recent releases such as NetBSD 9.0 and later, though not part of the minimal base system install. This setup enables straightforward installation via pkgin install doas or source building from pkgsrc, ensuring compatibility with NetBSD's portable packaging ecosystem while maintaining the utility's original OpenBSD semantics.[32]
For illumos-based systems, doas finds native support in distributions like SmartOS, where it is available through the pkgsrc framework with configurations adapted to Solaris-compatible paths such as /etc/doas.conf. This integration allows doas to function within SmartOS's lightweight, RAM-based hypervisor environment, providing privilege escalation for zone management and other administrative operations without conflicting with illumos's SVR4 heritage.[33]
Third-Party Ports and Packages
OpenDoas serves as the primary portable implementation of doas, a community-maintained fork of the OpenBSD original written in portable C to support non-BSD systems.[34] This port enables doas functionality on Linux distributions and other Unix-like operating systems by adapting the core logic for different authentication backends, such as PAM on Linux.[34] Linux Distributions Several major Linux distributions package OpenDoas or compatible variants, facilitating easy integration as a sudo alternative.- In Arch Linux, opendoas is available in the official extra repository, installable via
pacman -S opendoas.[35] - Debian and its derivatives provide opendoas in the main repository, with the
doaspackage acting as a transitional symlink; installation usesapt install opendoas.[36] - Alpine Linux includes doas directly in its edge/main repository and has positioned it as the recommended sudo replacement since version 3.16, due to its minimal footprint; install with
apk add doas.[37][38] - Gentoo offers it as the app-admin/doas ebuild in the main portage tree, emergeable with
emerge app-admin/doas.[39] - NixOS integrates doas natively, enabled by setting
security.doas.enable = truein configuration.nix, with the package available in nixpkgs.[40]
chmod 4755 /usr/local/bin/doas) ensures proper operation.[2]
It is also packaged in MacPorts as doas, installable via sudo port install doas, providing seamless integration with macOS security contexts like SIP.[41]
While not in the core Homebrew formulae, community taps or manual installation via Homebrew's brew install --HEAD from the repository source are possible for users preferring that manager.[34]
Other Systems and Forks
Maintained forks extend doas to additional platforms, including FreeBSD, where it is available as a security port (pkg install doas) derived from OpenBSD contributions, offering full compatibility with FreeBSD's authentication.[31]
Portable versions have been adapted for niche systems like Haiku and SerenityOS through community efforts, focusing on core privilege escalation without full PAM support.[2]
Building from source across these ports typically requires a C compiler and, on Linux, libpam-dev (e.g., libpam0g-dev on Debian for PAM-enabled builds).[34]
Current Adoption (2025)
By 2025, third-party doas ports enjoy widespread use in resource-constrained environments, particularly minimal Linux distributions like Alpine, where it replaces heavier alternatives for better security and performance.[6]
Ongoing maintenance, including security patches addressing issues like CVE-2023-28339, ensures cross-platform reliability, with active development on repositories like Duncaen/OpenDoas.[42][34]