dozzle icon indicating copy to clipboard operation
dozzle copied to clipboard

🚧 Deprecation of remote host in favor of agents

Open amir20 opened this issue 1 year ago • 35 comments

Hello!

I am in the process of releasing a very big feature for Dozzle which will introduce agents. Agents can run remotely on a set of hosts or in swarm mode. Agents use a secured connection that only Dozzle UI and agents can connect.

Agents are much safer than exposing Docker socket. They are also more efficient since each agent does the majority of the work.

I have currently updated documentation at https://dozzle.dev/guide/remote-hosts to be deprecated.

If you have any reasons to keep remote hosts in Dozzle then use this issue to provide feedback. I'd like to hear of use cases that wouldn't be possible with agent.

Thanks!

amir20 avatar Jul 05 '24 20:07 amir20

Someone pointed out on reddit that they might want to control permissions to docker.sock and that now there is no way. Hmmm....not sure if I have a solution with that.

amir20 avatar Jul 07 '24 01:07 amir20

Is this why there's degraded functionality here where some metrics are unavailable?

image

agneevX avatar Jul 07 '24 09:07 agneevX

The way I see it is that I already have a wireguard tunnel for secure communications between docker-socket-proxy and Dozzle. I also use this for Portainer docker host control.

So now, I'll need to deploy Dozzle to all machines??

agneevX avatar Jul 07 '24 09:07 agneevX

Is this why there's degraded functionality here where some metrics are unavailable?

No, changes to functionality that I know of...

The way I see it is that I already have a wireguard tunnel for secure communications between docker-socket-proxy and Dozzle. I also use this for Portainer docker host control

Interesting, I didn't know Portainer supports this. Perhaps, I can keep the socket proxy support but remove TLS. Not sure yet.

Let's see what others think @agneevX. If very few people need remote host then it makes it hard for me to support it because it takes me significant amount of time to support all different options. I rather trim to what is most used and safest. For now, no change.....

amir20 avatar Jul 07 '24 14:07 amir20

If you have any reasons to keep remote hosts in Dozzle then use this issue to provide feedback. I'd like to hear of use cases that wouldn't be possible with agent.

When possible, I like to avoid giving the entire Docker socket directly to a container, but instead give it access to a socket-proxy with limited permissions. Using DOZZLE_REMOTE_HOST I can do that. If that goes away, then I need to give Dozzle the entire socket, which I would prefer not to do.

If I understand the new agent feature correctly, to somewhat imitate what I'm doing now (Dozzle + a sibling socket-proxy container to provide limitations), I would have to spin up Dozzle and an agent Dozzle next to it. But I would have to give the agent Dozzle full socket access, which defeats the purpose of what I was trying to limit.

jathek avatar Jul 08 '24 04:07 jathek

I have been using tecnativa/docker-socket-proxy giving only CONTAINERS and IMAGES permission but made the switch to agent today, and all is good. Thanks for your work, your dozzle has been evolving constantly, happy to see this. 🥇

C8opmBM avatar Jul 08 '24 09:07 C8opmBM

No, changes to functionality that I know of...

In that screenshot, I was referring to the unavailability of CPU and RAM info.

agneevX avatar Jul 08 '24 10:07 agneevX

Does that mean that a docker-socket-proxy is not supported anymore?

Should it currently still work? I am getting an error:

dozzle          | head
dozzle          | Usage: dozzle [--addr ADDR] [--base BASE] [--hostname HOSTNAME] [--level LEVEL] [--auth-provider AUTH-PROVIDER] [--auth-header-user AUTH-HEADER-USER] [--auth-header-email AUTH-HEADER-EMAIL] [--auth-header-name AUTH-HEADER-NAME] [--enable-actions] [--filter FILTER] [--remote-host REMOTE-HOST] [--remote-agent REMOTE-AGENT] [--no-analytics] [--mode MODE] <command> [<args>]
dozzle          | error: unknown argument --remote-host dockersocket:2375

for my little compose experiment:

services:
  dozzle:
    container_name: dozzle
    image: amir20/dozzle:latest
    networks:
      - dockersocket
      - proxy
    restart: unless-stopped
    security_opt:
      - no-new-privileges: true
    user: 10020:0
    command:
      - --remote-host dockersocket: 2375
    labels:
      - traefik.enable=true
      - traefik.http.routers.dozzle.rule=Host(`dozzle.example.com`)
      - traefik.http.routers.dozzle.service=api@internal
      - traefik.http.routers.dozzle.middlewares=dozzleauth
      - traefik.http.middlewares.dozzleauth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/

  dockersocket:
    image: nginx:alpine-slim
    hostname: dockersocket
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - dockersocket
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    configs:
      - source: nginx
        target: /etc/nginx/nginx.conf
    expose:
      - 2375

networks:
  proxy:
    name: proxy
    external: true
  dockersocket:
    name: dockersocket

configs:
  nginx:
    content: |
      user root;
      events { worker_connections 1024; }
      http {
        server {
          listen 2375;
          location ~ ^/v1\.24/(events|containers|services|version|networks|tasks) {
            if ($$request_method != GET) { return 405; }
            proxy_pass http://unix:/var/run/docker.sock;
            proxy_set_header Host $$host;
            proxy_set_header X-Real-IP $$remote_addr;
            proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $$scheme;
            proxy_read_timeout 3600s;
          }
          location / { return 405; }
        }
      }

It would be great if a TCP connection to a docker socket is still possible.

bluepuma77 avatar Jul 10 '24 13:07 bluepuma77

Just wanted to chime in that I'd also be losing the ability to use socket-proxy with Dozzle, seems a shame to lose that feature in favor of another I wouldn't use.

epd5 avatar Jul 10 '24 13:07 epd5

I'm also using a socket proxy (this one from LinuxServer) and restricting permissions to the proxy's clients.

I like the Agent mode; it seems cool, but I would prefer a model where it coexists with the remote host option.

Also, I hope that the Agent mode eventually allows the same granular access permission as some of these proxies. The current implementation makes me feel pretty insecure, and I wouldn't want to use it.

tenfourty avatar Jul 10 '24 14:07 tenfourty

@EoinD123

Just wanted to chime in that I'd also be losing the ability to use socket-proxy with Dozzle, seems a shame to lose that feature in favor of another I wouldn't use.

Can you share about your use case as why you wouldn't use it? Socket-proxy is not very secure without TLS so I am trying to understand if the only use case is limiting permissions.

@bluepuma77 I haven't removed any functionality. So it should work. I have never used your setup though. Documentation with socket proxy should still work at https://dozzle.dev/guide/remote-hosts. You are using your own setup so I am not sure.

amir20 avatar Jul 10 '24 15:07 amir20

@tenfourty I think the majority of people want to limit permissions which is why they use socket proxy? Is that so? I think a better solution would be to map docker.socket to another such as docker-readonly.socket by setting up a proxy. My gripe with socket-proxy is that is actually opens up docker to be able to read anything, even within the network could be a security threat.

Based on feedback, I think one thing is for sure. Removing the TLS support for remote hosts seems to be OK. I am just trying to remove features that rarely get used.

I hope that the Agent mode eventually allows the same granular access permission as some of these proxies

What would you imagine that looking like? Agents are already read only because the GRPC only supports reading logs, events, and stats. So I would be interested to know how you would feel comfortable knowing that agents only return data.

I would be happy if we could collaborate on a model with agent that makes people comfortable with agents. The remote hosts are not safe:

  • socket proxy doesn't use TLS. Agents have a secure mTLS communication
  • socket proxy needs to be setup correctly and I get too many pings about that. Agents just work out of the box.
  • Agents distribute the load on the host whereas remote host set up brings the computation on the UI.

Personally, I wish there was a solution that remaps socket file to another file that limits non-get requests.

amir20 avatar Jul 10 '24 15:07 amir20

Darn lol, I was using the TLS implementation for a remote host and setup some PKI for it. More than happy to give the agents a whirl though, I guess my only gripe would be having another container running on the remote host to support it, but that is a very small gripe. There are also some plus sides to this approach as you mention above.

I was starting to look into proxying the docker socket and providing access more granularly for the container on the 'master' host, same as most above. I saw #3088 today and didn't realise that the :ro didn't apply to sockets which prompted some investigation into proxying the docker socket as that seemed like the best approach.

dj3520-git avatar Jul 10 '24 16:07 dj3520-git

@dj3520-git you must be one of three rare people? 😂 Setting up TLS with Docker is so hard that most people just don't do it. I have had so many issues opened asking how to do it that I just gave up and said use socket proxy.

More than happy to give the agents a whirl though, I guess my only gripe would be having another container running on the remote host to support it

Please do give agents a try. The agent is actually pretty light. A big advantage is that each agent does it's own processing making it lighter on the UI. There is also support for swarm mode.

Just so that everybody understand why I am pushing back on this, the majority of issues that come through are something like "hey, I setup TLS or socket proxy and it doesn't work". After a bunch of investigation, I find that they misconfigured it or some thing beyond Dozzle. Even after all of this, they have exposed Docker API to their whole network. I can't imagine anybody would prefer this knowing the risks. So my goal with agents is to have some thing super easy to setup without needing to support external dependencies that I have no control over. I just don't have a lot time to support every single use case. Having agents, makes it easier to see here is a docker-compose.yml file and it should just work without anything extra work. https://github.com/amir20/dozzle/issues/3066#issuecomment-2220532261 is an example that is beyond me investigating.

This project is taking considerable amount of time from me 💁🏼. But it sounds like people just want control permissions to Dozzle. I wonder if there is any other ways to do this. I could use some help from the community. I don't think setting up an HTTP proxy just for the sake of controlling permission is the right solution.

I saw https://github.com/amir20/dozzle/issues/3088 today and didn't realise that the :ro didn't apply to sockets which prompted some investigation into proxying the docker socket as that seemed like the best approach.

That's right. I don't why anybody ever thought :ro is means the socket is read only.

As said earlier, the right approach would be to have docker.socket proxied through another socket file. I am sure something like this exists.

amir20 avatar Jul 10 '24 17:07 amir20

For me, while Dozzle agents are useful, and I will implement one shortly, they don't give me the same security to the main Dozzle instance that using a socket-proxy does. Limiting access to the docker socket by Dozzle is important to me b/c I access Dozzle via reverse proxy. I have Authelia as a single sign-on authentication protecting it, but I like having the extra just-in-case security roadblock.

jathek avatar Jul 10 '24 20:07 jathek

@EoinD123

Just wanted to chime in that I'd also be losing the ability to use socket-proxy with Dozzle, seems a shame to lose that feature in favor of another I wouldn't use.

Can you share about your use case as why you wouldn't use it? Socket-proxy is not very secure without TLS so I am trying to understand if the only use case is limiting permissions.

Sure! Very interesting reading the thread, a lot I dont know about the workings of docker. I'm running a hobbyist stack of ~50 containers, about 6 of them require socket access, so I run socket-proxy & the rest of them on their own internal only network. Having said that I kinda assumed anyway if some of them share another icc enabled network maybe it defeats the purpose.

epd5 avatar Jul 10 '24 21:07 epd5

Hey folks! Let me try to summarize.

Based on the feedback, people want to have a way to control the permissions for Dozzle. All fair. I did some research and Docker doesn't seem to have a solution. Seems like socket-proxy is the best solution. It's not great solution and I can't find anything better. Side project anyone? 🤔

Therefore, until there is a better choice to control docker.sockets's permission. I don't think it would make sense to remove this functionality to use socket-proxy.

Now speaking of the TLS support which requires someone to setup TLS in Docker and expose over HTTP I think makes less sense to support. It is much more work to setup and agents could just replace that with a safer choice. But as long I don't get issues to debug why it didn't work then no worries.

All that said, I am not planning to make any changes. So don't freak out. I'll keep this issue open for a while. I am sure at some point there will be features that will be easier implemented (like swarm mode) in agents. Overtime, I hope the use of agents would grow. For example, performance and memory is already faster in agents because everything use protobuf which requires less parsing. Where using socket proxy has everything passed around as JSON increasing CPU considerably on the UI.

I do plan to add retry when agents fail which is a common request. I can do this with agents now but I won't plan to do it with remote-hosts.

amir20 avatar Jul 11 '24 00:07 amir20

DOZZLE_REMOTE_HOST=tcp://dockersocket:2375 works for me, shows a deprecation message.

But --remote-host tcp://dockersocket:2375 does not work:

error: unknown argument --remote-host tcp://dockersocket:2375

Doozle works with this (very simplified) inline docker-socket-proxy solution:

services:
  dockersocket:
    image: nginx:alpine-slim
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    configs:
      - source: nginx
        target: /etc/nginx/nginx.conf

configs:
  nginx:
    content: |
      user root;
      events { worker_connections 1024; }
      http {
        server {
          listen 2375;
          location ~ ^/v1\.(24|46)/(info|events|containers|services|version|networks|tasks) {
          if ($$request_method !~ ^(GET|HEAD)$$) { return 405; }
            proxy_pass http://unix:/var/run/docker.sock;
            proxy_set_header Host $$host;
            proxy_set_header X-Real-IP $$remote_addr;
            proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $$scheme;
            proxy_read_timeout 3600s;
          }
          location /_ping {
          if ($$request_method !~ ^(GET|HEAD)$$) { return 405; }
            proxy_pass http://unix:/var/run/docker.sock;
          }
          location / { return 405; }
        }
      }

The advantage of the docker-socket-proxy is that I do not need a high trust level with the application using it. Sadly Docker does not enable restricting the socket to GET only.

With the docker-socket-proxy I can ensure that containers with access will not be wreaking havoc. I don't need high trust in the code, that a contributor might be smuggling in bad code, that someone highjacks the build pipeline or someone finds a bug to hack into the container. Effects should be minimised that way, security increased. And by not trusting another random proxy solution (but a bigger corporate brand), I only increase the attack surface minimally.

So thanks a lot for providing dozzle and for keeping the remote host 👍

bluepuma77 avatar Jul 11 '24 08:07 bluepuma77

Based on the feedback, people want to have a way to control the permissions for Dozzle. All fair. I did some research and Docker doesn't seem to have a solution. Seems like socket-proxy is the best solution. It's not great solution and I can't find anything better. Side project anyone? 🤔

Therefore, until there is a better choice to control docker.sockets's permission. I don't think it would make sense to remove this functionality to use socket-proxy.

Thanks, @amir20. This sounds like a pragmatic way forward. I use my Docker socket proxy for other containers to securely access my Docker socket, not just Dozzle, so I found it easier to set up one container for all my services that need it.

I don't expose my proxy directly to my LAN, it's only available to a few containers via a docker network on the same host (of course still a risk) but I think it's low given it exposes a read-only API.

tenfourty avatar Jul 11 '24 10:07 tenfourty

@amir20 Thank you for keeping the TLS side of things for now and for all your hard work with Dozzle. I completely understand if the support burden gets too large; as you say, agents are a simpler way of achieving the same thing with a copy and paste compose file (and I will be having a good look at this as soon as I can). Thank you also for the kind words regarding Docker and TLS! I guess the hardest part is the PKI, but once that is sorted so long as you read the documentation here and for Docker (both are really good) it all just slotted together nicely for me.

@bluepuma77 That looks like a very eloquent solution for proxying the docker socket for other containers to use https://github.com/amir20/dozzle/issues/3066#issuecomment-2222375239, thank you for sharing! I agree it's a notch above spinning up someone else's container and I like your choice of nginx too, nice work. 👍

dj3520-git avatar Jul 11 '24 13:07 dj3520-git

@bluepuma77 created #3095. I am pretty sure you have a typo some where as it works for me.

amir20 avatar Jul 11 '24 15:07 amir20

@tenfourty

Thanks, @amir20. This sounds like a pragmatic way forward. I use my Docker socket proxy for other containers to securely access my Docker socket, not just Dozzle, so I found it easier to set up one container for all my services that need it.

That's a fair point. I didn't realize how many other applications require docker.socket.

amir20 avatar Jul 11 '24 15:07 amir20

I'm not able to get agents to work in my kubernetes (k8s) environment. I'm using docker with containerd=/run/containerd/containerd.sock with tls certs, hence docker.socket is not available. In my scenario all docker communication is done over a tls connection to the containerd.sock. How do I get the agent to talk to containerd.sock using tls certs?

dhop90 avatar Jul 12 '24 19:07 dhop90

I love the addition of the agent, makes it very simple to connect my various LXC containers running docker to 1 central dozzle instance. There seems to be a limit of 7 agent connections. I can add more, but only 7 show on the UI. Is this something that will change in future releases? It'd also be great to have some sort of sort order to the agent connections.

MRobi1 avatar Jul 13 '24 12:07 MRobi1

@MRobi1 there is no limits to the number of agents that can be configured. You maybe running to this issue. https://github.com/amir20/dozzle/issues/3072. Make sure to look at the logs. I added a section in FAQ about this. https://dozzle.dev/guide/faq#i-am-seeing-duplicate-hosts-error-in-the-logs-how-do-i-fix-it

You can create a new issue if it's something else. ❤️

amir20 avatar Jul 13 '24 14:07 amir20

Yup, duplicate hosts was my issue since I typically deploy my LXC containers using a template that I built.

That does bring up a few additional things:

  • I'd recommend linking to that section through the agent docs so it's more obvious
  • I'd also recommend adding "restart: unless-stopped" to the docker compose and equivalent for the docker run commands when deploying the agent so they'll start again on reboot
  • If Dozzle is started before the agent, it doesn't appear to connect without restarting dozzle. This means dozzle will need to be the absolute last thing started or require a manual reboot every time. Is there a way to implement something when the agent starts it will initiate a reconnect to dozzle? Or in dozzle have it attempt reconnects every X minutes on agents that did not connect on initial startup?

MRobi1 avatar Jul 13 '24 15:07 MRobi1

I'd recommend linking to that section through the agent docs so it's more obvious I'd also recommend adding "restart: unless-stopped" to the docker compose and equivalent for the docker run commands when deploying the agent so they'll start again on reboot

If you have time send PRs! I am out of the office for a while.

If Dozzle is started before the agent, it doesn't appear to connect without restarting dozzle. This means dozzle will need to be the absolute last thing started or require a manual reboot every time. Is there a way to implement something when the agent starts it will initiate a reconnect to dozzle? Or in dozzle have it attempt reconnects every X minutes on agents that did not connect on initial startup?

That's on the roadmap and tracked at https://github.com/amir20/dozzle/issues/3094

amir20 avatar Jul 13 '24 15:07 amir20

Added 64e8ec48 for a quick warning on duplicate hosts.

amir20 avatar Jul 13 '24 21:07 amir20

@dhop90 Looks like agents work in k8s and I have updated the other bug.

amir20 avatar Jul 13 '24 21:07 amir20

Just wanted to say that after testing the agent I've migrated to it from remote host TLS on the production setup and everything's working great, thanks for the awesome feature! I will still likely experiment with the inline nginx solution at some stage (posted in https://github.com/amir20/dozzle/issues/3066#issuecomment-2222375239), so it would be good to keep the remote host feature. Though, as I have no other containers that require access right now, I will be using the agent for the foreseeable future.

dj3520-git avatar Jul 26 '24 09:07 dj3520-git