Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve documentation on non-root container usage #194

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,3 @@ issues:
path: _test\.go$
text: "unused-parameter"
exclude-use-default: false

service:
golangci-lint-version: 1.43.x
7 changes: 5 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ RUN \
cd app && go build -o /build/reproxy -ldflags "-X main.revision=${version} -s -w"


FROM ghcr.io/umputun/baseimage/app:v1.12.0 as base
FROM ghcr.io/umputun/baseimage/app:latest as base

FROM scratch

# enables automatic changelog generation by tools like Dependabot
LABEL org.opencontainers.image.source="https://github.com/umputun/reproxy"
ENV REPROXY_IN_DOCKER=1

Expand All @@ -31,5 +33,6 @@ COPY --from=base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=base /etc/passwd /etc/passwd
COPY --from=base /etc/group /etc/group

# user is implicitly set to `root`, learn how to use non-root user here: https://reproxy.io/#container-security
WORKDIR /srv
ENTRYPOINT ["/srv/reproxy"]
ENTRYPOINT ["/srv/reproxy"]
48 changes: 47 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,12 +339,58 @@ _See [examples/plugin](https://github.com/umputun/reproxy/tree/master/examples/p

## Container security

By default, the reproxy container runs under the root user to simplify the initial setup and access the docker's socket. This is needed to allow the docker provider discovery of the running containers. However, if such a discovery is not required or the docker provider not in use, it is recommended to change the user to some less-privileged one. It can be done on the docker-compose level and on docker level with `user` option.
By default, the reproxy container runs under the root user to simplify the initial setup and access the docker's socket. This is needed to allow the docker provider discovery of the running containers. However, if such a discovery is not required or the docker provider not in use, it is recommended to change the user to some less-privileged one. It can be done on the docker-compose level and on docker level with `user` option, see the section below for details.

Sometimes, even with inside-the-docker routing, it makes sense to disable the docker provider and setup rules with either static or file provider. All the containers running within a compose sharing the same network and accessible via local DNS. User can have a rule like this to avoid docker discovery: `- STATIC_RULES=*,/api/email/(.*),http://email-sender:8080/$$1`. This rule expects `email-sender` container defined inside the same compose. Please note: users can achieve the same result by using the docker network even if the destination service was defined in a different compose file. This way reproxy configuration can stay separate from the actual services.

There is nothing except reproxy binary inside the reproxy container, as it builds on top of an empty (scratch) image.

### How to set up non-root user with docker access and use it with reproxy container
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is too much instruction for the task, which is not really related to the Reproxy itself but rather to the general question "how do I map host uid/gid to container". It is also not a universal recipe, as it won't work on some flavors of Linux (Alpine, for example) and it's not sure if it will work on macOS.

In addition, I think this is not the only way to run the Reproxy container under a non-root account. It is possible to map the uid/gid from any existing user to app inside the container.

My suggestion is to leave only the part describing what user already exists in the container and add a general statement like "you may need to set up uid/gid mapping at the Docker level and ensure the user has permission to access the Docker socket, in case the Docker provider is used". A link to the Docker documentation explaining uid mapping would also be helpful.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a better suggestion, extend that section with an explanation on how to map the existing UID/GID without adding a new user to the host machine. One of our other projects may have a similar solution already, though I can't recall which one. Additionally, the details after the basic information on existing UID/GID should be collapsed by default, as users who need this information likely already know how to achieve the mapping, while the rest of the users may not understand the purpose of these details.


User with UID `1001` with groups `1001` and `999` is pre-created within the container and could be used for running reproxy. The prerequisite for this is to grant the user permissions to access the docker socket:

1. Check which user/group IDs are already in use on the host machine. In case any of the groups `999` and `1001` are not in use, safest option is to create them on the host machine, otherwise you need to decide if you are okay with granting the existing group permissions to write to docker socket.
```shell
# check groups which you can use within container
getent group 999
getent group 1001
# check user which you can use within container
getent passwd 1001
# empty output means that there is no such group or user, and output will show you which group or user already exist
```
2. In case groups are not in use, create one of them on the host machine. For example, to create group `1001`:
```shell
sudo groupadd -g 1001 reproxy
# here is group info after adding:
# getent group 1001
# reproxy:x:1001:
```
In case user is not in use, create it as well with no login shell and no home directory:
```shell
sudo useradd -u 1001 -g 1001 -s /sbin/nologin -M reproxy
# here is user info after adding:
# getent passwd 1001
# reproxy:x:1001:1001::/nonexistent:/usr/sbin/nologin
```
3. Grant permissions to the group (`1001` in that example, `999` can be used as well) or user to the docker socket:
```shell
# in case you created user
sudo usermod -aG docker reproxy
# in case you created only the group
sudo setfacl -m group:reproxy:rw /var/run/docker.sock
```

After setup is done, you can run reproxy container with the user `1001`:

```yaml
services:
reproxy:
user: 1001
image: umputun/reproxy:latest
# <...>
# see examples/ssl/docker-compose.yml for the full file example
```

## Options

Each option can be provided in two forms: command line or environment key:value pair. Some command line options have a short form, like `-l localhost:8080` and all of them have the long form, i.e `--listen=localhost:8080`. The environment key (name) [listed](#all-application-options) for each option as a suffix, i.e. `[$LISTEN]`.
Expand Down
Loading