ItsEcholot / ContainerNursery

Puts Docker Containers to sleep and wakes them back up when they're needed
MIT License
95 stars 6 forks source link

Configure Nextcloud to allow ContainerNursery #3

Closed C4ArtZ closed 3 years ago

C4ArtZ commented 3 years ago

Container immediately crashes after copying conf.yml.example to conf.yml with the following error:

node:internal/process/promises:246

          triggerUncaughtException(err, true /* fromPromise */);

          ^

Error: connect ENOENT /var/run/docker.sock

    at PipeConnectWrap.afterConnect [as oncomplete] (node:net:1146:16) {

  errno: -2,

  code: 'ENOENT',

  syscall: 'connect',

  address: '/var/run/docker.sock'

}

Tried with latest (1.0.2), 1.0.1 and dev with and without mounting the config directory as docker volume.

ItsEcholot commented 3 years ago

Did you mount your Docker socket into the container with -v /var/run/docker.sock:/var/run/docker.sock? This is necessary so that ContainerNursery can actually get the status of your containers and issue the start & stop commands.

C4ArtZ commented 3 years ago

I didn't think of that. Nursery can now start and stop the container but the redirect doesn't seem to work. I get stuck on the loading screen. I tried with nextcloud and a clean nginx container.


{"level":30,"time":1631269181856,"pid":1,"hostname":"645a36df01f4","msg":"(Re)loading hosts, clearing all existing hosts first"},
{"level":30,"time":1631269181857,"pid":1,"hostname":"645a36df01f4","host":"cloud.c4artz.de","container":"nginx","proxy":{"host":"localhost","port":180},"timeoutSeconds":15,"msg":"Added proxy host"},
{"level":30,"time":1631269181872,"pid":1,"hostname":"645a36df01f4","port":80,"msg":"Proxy listening"},
{"level":30,"time":1631269181876,"pid":1,"hostname":"645a36df01f4","port":8080,"host":"127.0.0.1","msg":"Proxy placeholder server listening"},
{"level":30,"time":1631269196897,"pid":1,"hostname":"645a36df01f4","container":"nginx","msg":"Stopping container"},
{"level":30,"time":1631269201282,"pid":1,"hostname":"645a36df01f4","container":"nginx","msg":"Starting container"}
ItsEcholot commented 3 years ago

What is your config.yml File looking like? And how is your routing? Are you using another reverse proxy in front of ContainerNursery? If so how‘s the config of that reverse proxy?

C4ArtZ commented 3 years ago

The chain is as follows: cloud.c4artz.de -> Cloudflare DNS -> Cloudflare Argo tunnel -> Container Nursery -> nextcloud / nginx container

Container Nursery config

proxyHosts:
  - domain: cloud.c4artz.de
    containerName: nginx
    proxyHost: localhost
    proxyPort: 180
    timeoutSeconds: 15

cloudflared config

tunnel: <tunnelid>
credentials-file: /home/c4artz/.cloudflared/<tunnelid>.json

ingress:
  - hostname: cloud.c4artz.de
    service: http://localhost:80
  - service: http_status:404
ItsEcholot commented 3 years ago

I haven't tested this with Cloudflare Argo so I have no idea if this is the root of your issue. Could you examine the browser traffic when calling the app/loading screen? Is the loading screen making requests to check if the container finished starting? What are the headers and response looking like?

Besides the point of this issue I really recommend putting another reverse proxy like NginxProxyManager or something similar in front of ContainerNursery. Both for security and for terminating SSL. I'm pretty sure ContainerNursery can't handle SSL connections.

My chain (tested successfully): Domain -> DNS -> NginxProxyManager -> ContainerNursery -> Container

C4ArtZ commented 3 years ago

I haven't uses the Nginx Proxy Manager before but I will try to set it up today or tomorrow.

Chrome Dev Tools shows requests every ~100ms. I'm guessing these are the checks you meant.

I have uploaded the har file to a repo if you want to have a look at it.

containernursery_network_log

ItsEcholot commented 3 years ago

I took a quick glance at your requests and they look good. So the problem seems to be that ContainerNursery doesn't recognise your container as „ready“. It checks this by issuing a HEAD http request and waits till code 200 or 300-399 is returned.

Would you mind trying with another container? Like the handbrake one that I used in the example?

It could be that your container is returning a different code instead of 200 or 3xx. With the container running (manually) could you try accessing it on path / using http (not https) with Postman or a similar tool so we can check what response code it returns?

ItsEcholot commented 3 years ago

This could actually be the same bug as fixed in PR #6, please try the latest container version.

C4ArtZ commented 3 years ago

So I've set up the Nginx Proxy Manager and pulled the latest Container Nursery version.

The chain is now like you mentioned above.

I tested it with my nextcloud and nginx containers. Nextcloud still doesn't reload but nginx does. How does CN handle other codes like 400? Nextcloud uses trusted domains to allow access. It could be that Nextcloud returns 400 because CN is not configured as trusted domain. I tried setting CNs hostname and IP as trusted domains but that didn't help.

The requests from postman return 200 OK when the domain / IP is set as trusted domains. X-Powered-By contains PHP/8.0.10.

Can I somehow see what response CN is getting?

ItsEcholot commented 3 years ago

How does CN handle other codes like 400?

Other response codes are handled as "container not ready". Thus ContainerNursery doesn't change it's proxy target to the container until it receives 200 or 3xx response. This is to ensure the started container is actually really ready to accept our new request.

It seems to me you have a Nextcloud configuration issue since it returns 400.

Can I somehow see what response CN is getting?

Yes the newest update allows setting the log level using an environment variable like so: CN_LOG_LEVEL=debug. After enabling debug log level you should see Checked if container is ready log messages that contain more information like the received status and headers.

C4ArtZ commented 3 years ago

Yeah CN get's a 400. I will try to configure Nextcloud to allow CN. Any ideas? I've added CNs hostname and the IP adress inside the docker network but still get a 400. I'm kind of unsure about "host": "localhost". Seems to me like CN is asking itself on port 8080....

DEBUG [2021-09-11 09:56:45.064 +0000]: Checked if container is ready

    container: "nextcloud"

    status: 400

    headers: {}

DEBUG [2021-09-11 09:56:45.247 +0000]: Proxied request

    host: "cloud.c4artz.de"

    target: {

      "host": "localhost",

      "port": 8080

    }

    headers: {

      "x-container-nursery-container-name": "nextcloud"

    }

DEBUG [2021-09-11 09:56:45.249 +0000]: Resetting connection timeout

    container: "nextcloud"

    timeoutSeconds: 15

Edit: Here is my current CN config:

proxyHosts:
  - domain: cloud.c4artz.de
    containerName: nextcloud
    proxyHost: nextcloud
    proxyPort: 80
    timeoutSeconds: 15
ItsEcholot commented 3 years ago

Yeah CN get's a 400. I will try to configure Nextcloud to allow CN. Any ideas? I've added CNs hostname and the IP adress inside the docker network but still get a 400.

I'm sorry but I have no experience with Nextcloud. Maybe you could check if the Nextcloud logs contain more information about what was blocked and why?

I'm kind of unsure about "host": "localhost". Seems to me like CN is asking itself on port 8080....

No this simply means the traffic is being proxied to CNs internal Webserver (which runs and listens only on localhost and port 8080) which is used to render and serve the loading page.

C4ArtZ commented 3 years ago

I got it to work. Don't know why I didn't realize this sooner. I had to set the nextcloud container as a trusted domain. Makes sense, because that's how CN accesses it. Thank you for your help!

The Nextcloud config should look like this (nexcloud is the hostname of the container):

  'trusted_domains' =>
  array (
    0 => 'nextcloud',
  ),