Convert Figma logo to code with AI

tianon logogosu

Simple Go-based setuid+setgid+setgroups+exec

4,685
312
4,685
3

Top Related Projects

68,457

The Moby Project - a collaborative project for the container ecosystem to assemble container-based systems

9,777

A tiny but valid `init` for containers

A minimal init system for Linux containers

A minimal Ubuntu base image modified for Docker-friendliness

2,591

Quick Overview

Gosu is a lightweight tool designed to run commands as a specific user, primarily used in Docker containers. It simplifies the process of switching between root and non-root users, addressing common permission issues in containerized environments.

Pros

  • Simple and lightweight, with minimal dependencies
  • Improves security by allowing easy user switching in containers
  • Faster and more efficient than alternatives like su or sudo
  • Actively maintained and widely used in the Docker community

Cons

  • Limited functionality compared to more comprehensive user management tools
  • Primarily designed for use in Docker containers, may not be suitable for all environments
  • Requires root privileges to run, which may not be ideal in some security-sensitive scenarios
  • Limited documentation and examples for advanced use cases

Code Examples

  1. Basic usage to run a command as a specific user:
gosu username command
  1. Running a shell as a specific user:
gosu username sh -c 'echo "Hello, $(whoami)!"'
  1. Using gosu in a Dockerfile:
FROM debian:buster-slim
RUN apt-get update && apt-get install -y gosu
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
  1. Example entrypoint script using gosu:
#!/bin/bash
set -e

if [ "$1" = 'redis-server' ]; then
    chown -R redis .
    exec gosu redis "$@"
fi

exec "$@"

Getting Started

To use gosu in your Docker container:

  1. Install gosu in your Dockerfile:

    RUN apt-get update && apt-get install -y gosu
    
  2. Use gosu in your entrypoint script or directly in your Dockerfile:

    gosu user_name command_to_run
    
  3. Make sure to set appropriate permissions for the gosu binary:

    RUN chmod +s /usr/sbin/gosu
    

Remember to always use gosu with caution and follow security best practices when switching users in your containers.

Competitor Comparisons

68,457

The Moby Project - a collaborative project for the container ecosystem to assemble container-based systems

Pros of Moby

  • Comprehensive container platform with a wide range of features
  • Large and active community, extensive documentation
  • Supports multiple architectures and operating systems

Cons of Moby

  • More complex and resource-intensive
  • Steeper learning curve for beginners
  • Requires more setup and configuration

Code Comparison

Gosu (simple privilege dropping):

if err := gosu.Run(uid, gid, cmd, args...); err != nil {
    log.Fatal(err)
}

Moby (running a container):

resp, err := cli.ContainerCreate(ctx, &container.Config{
    Image: "alpine",
    Cmd:   []string{"echo", "hello world"},
}, nil, nil, nil, "")
if err != nil {
    panic(err)
}

Summary

Gosu is a lightweight tool focused on running commands with different privileges, while Moby is a comprehensive container platform. Gosu is simpler and easier to use for specific tasks, whereas Moby offers a full suite of container management features but with increased complexity. Choose Gosu for simple privilege dropping in containers, and Moby for building, shipping, and running containerized applications at scale.

9,777

A tiny but valid `init` for containers

Pros of Tini

  • Acts as a lightweight init system, handling zombie processes and signal forwarding
  • Provides a more complete solution for container process management
  • Supports custom entrypoints and can run as PID 1

Cons of Tini

  • Slightly larger binary size compared to Gosu
  • May introduce additional complexity for simple use cases
  • Requires explicit installation and configuration in Dockerfiles

Code Comparison

Tini usage in Dockerfile:

FROM debian:stretch
RUN apt-get update && apt-get install -y tini
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["your-app-command"]

Gosu usage in Dockerfile:

FROM debian:stretch
RUN apt-get update && apt-get install -y gosu
COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]

Tini focuses on process management and signal handling, while Gosu primarily addresses user switching and permission issues. Tini is better suited for complex container environments requiring proper init system functionality, whereas Gosu excels in scenarios where simple user switching is the main concern. The choice between the two depends on the specific requirements of your containerized application.

A minimal init system for Linux containers

Pros of dumb-init

  • Handles signal forwarding and reaping of zombie processes
  • Lightweight and simple to use
  • Can be used as an init system for containers

Cons of dumb-init

  • Limited functionality compared to gosu
  • Does not provide user-switching capabilities
  • May require additional configuration for complex use cases

Code Comparison

dumb-init usage:

FROM debian:stretch-slim
RUN apt-get update && apt-get install -y dumb-init
ENTRYPOINT ["dumb-init", "--"]
CMD ["my-app", "my-app-args"]

gosu usage:

FROM debian:stretch-slim
RUN apt-get update && apt-get install -y gosu
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
CMD ["my-app", "my-app-args"]

Summary

dumb-init focuses on process management and signal handling, making it ideal for simple containerized applications. gosu, on the other hand, specializes in user-switching capabilities, which can be crucial for security and permissions management in more complex scenarios. While dumb-init is easier to implement, gosu offers more flexibility in terms of user management within containers.

A minimal Ubuntu base image modified for Docker-friendliness

Pros of baseimage-docker

  • Provides a complete, init-system-enabled base image for Docker containers
  • Includes useful tools and services pre-installed (e.g., SSH, cron, syslog)
  • Offers better process management and zombie reaping

Cons of baseimage-docker

  • Larger image size due to additional components
  • More complex setup and configuration
  • Potential security concerns with unnecessary services

Code Comparison

baseimage-docker:

FROM phusion/baseimage:latest
RUN /etc/my_init.d/00_regen_ssh_host_keys.sh
CMD ["/sbin/my_init"]

gosu:

FROM debian:buster-slim
RUN apt-get update && apt-get install -y gosu
COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]

Key Differences

  • gosu focuses on running processes with a specific user and group ID
  • baseimage-docker provides a more comprehensive environment for containerized applications
  • gosu is lightweight and single-purpose, while baseimage-docker offers a full-featured base image

Use Cases

  • gosu: Ideal for simple containers requiring user switching
  • baseimage-docker: Suitable for complex applications needing multiple services and better process management
2,591

Pros of nsenter

  • Provides more advanced namespace manipulation capabilities
  • Allows entering existing namespaces, not just creating new ones
  • Useful for debugging and inspecting running containers

Cons of nsenter

  • More complex to use and understand
  • Requires root privileges or special capabilities
  • Less focused on the specific use case of running commands as a different user

Code Comparison

nsenter:

int main(int argc, char *argv[])
{
    int c;
    while ((c = getopt_long(argc, argv, "+a:m:u:i:n:p:t:F:Z:r:w:S:G:", longopts, NULL)) != -1) {
        switch (c) {
        case 'a':

gosu:

func main() {
    if len(os.Args) <= 2 {
        usage()
    }

    user := os.Args[1]

Summary

nsenter is a more powerful tool for namespace manipulation, while gosu focuses specifically on running commands as a different user. nsenter offers greater flexibility but requires more expertise, whereas gosu provides a simpler solution for a common use case in containerized environments. The code snippets highlight the difference in complexity, with nsenter handling multiple options and gosu focusing on a straightforward user switch.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

gosu

This is a simple tool grown out of the simple fact that su and sudo have very strange and often annoying TTY and signal-forwarding behavior. They're also somewhat complex to setup and use (especially in the case of sudo), which allows for a great deal of expressivity, but falls flat if all you need is "run this specific application as this specific user and get out of the pipeline".

The core of how gosu works is stolen directly from how Docker/libcontainer itself starts an application inside a container (and in fact, is using the /etc/passwd processing code directly from libcontainer's codebase).

$ gosu
Usage: ./gosu user-spec command [args]
   eg: ./gosu tianon bash
       ./gosu nobody:root bash -c 'whoami && id'
       ./gosu 1000:1 id

./gosu version: 1.1 (go1.3.1 on linux/amd64; gc)

Once the user/group is processed, we switch to that user, then we exec the specified process and gosu itself is no longer resident or involved in the process lifecycle at all. This avoids all the issues of signal passing and TTY, and punts them to the process invoking gosu and the process being invoked by gosu, where they belong.

Warning

The core use case for gosu is to step down from root to a non-privileged user during container startup (specifically in the ENTRYPOINT, usually).

Uses of gosu beyond that could very well suffer from vulnerabilities such as CVE-2016-2779 (from which the Docker use case naturally shields us); see tianon/gosu#37 for some discussion around this point.

Installation

High-level steps:

  1. download gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }') as gosu
  2. download gosu-$(dpkg --print-architecture | awk -F- '{ print $NF }').asc as gosu.asc
  3. fetch my public key (to verify your download): gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
  4. gpg --batch --verify gosu.asc gosu
  5. chmod +x gosu

For explicit Dockerfile instructions, see INSTALL.md.

Why?

$ docker run -it --rm ubuntu:trusty su -c 'exec ps aux'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  46636  2688 ?        Ss+  02:22   0:00 su -c exec ps a
root         6  0.0  0.0  15576  2220 ?        Rs   02:22   0:00 ps aux
$ docker run -it --rm ubuntu:trusty sudo ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  3.0  0.0  46020  3144 ?        Ss+  02:22   0:00 sudo ps aux
root         7  0.0  0.0  15576  2172 ?        R+   02:22   0:00 ps aux
$ docker run -it --rm -v $PWD/gosu-amd64:/usr/local/bin/gosu:ro ubuntu:trusty gosu root ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   7140   768 ?        Rs+  02:22   0:00 ps aux

Additionally, due to the fact that gosu is using Docker's own code for processing these user:group, it has exact 1:1 parity with Docker's own --user flag.

If you're curious about the edge cases that gosu handles, see Dockerfile.test-alpine for the "test suite" (and the associated test.sh script that wraps this up for testing arbitrary binaries).

(Note that sudo has different goals from this project, and it is not intended to be a sudo replacement; for example, see this Stack Overflow answer for a short explanation of why sudo does fork+exec instead of just exec.)

Alternatives

chroot

With the --userspec flag, chroot can provide similar benefits/behavior:

$ docker run -it --rm ubuntu:trusty chroot --userspec=nobody / ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
nobody       1  5.0  0.0   7136   756 ?        Rs+  17:04   0:00 ps aux

setpriv

Available in newer util-linux (>= 2.32.1-0.2, in Debian; https://manpages.debian.org/buster/util-linux/setpriv.1.en.html):

$ docker run -it --rm buildpack-deps:buster-scm setpriv --reuid=nobody --regid=nogroup --init-groups ps faux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
nobody       1  5.0  0.0   9592  1252 pts/0    RNs+ 23:21   0:00 ps faux

su-exec

In the Alpine Linux ecosystem, su-exec is a minimal re-write of gosu in C, making for a much smaller binary, and is available in the main Alpine package repository. However, as of version 0.2 it has a pretty severe parser bug that hasn't been in a release for many years (and which the buggy behavior is that typos lead to running code as root unexpectedly 😬).

Others

I'm not terribly familiar with them, but a few other alternatives I'm aware of include:

  • chpst (part of runit)