docker
docker copied to clipboard
Add support for Client push app
It would be great to add support for the notify_push app which is available for Nextcloud 21.
Judging from the documentation of the app https://github.com/nextcloud/notify_push#push-server and previous discussions in this repository, I guess having the notify_push server process run in the same container as Nextcloud server is not desired and a similar approach as for the Cron service should be followed.
The docker way is not to put the rust service also in the same container.
For example, you use for redis and mariadb/postgres also a separate container and the db is not included in the nextcloud container.
The notify_push container must just share the same data directory /var/www/html:/path/to/nextcloud/:ro when ExecStart = /path/to/push/binary/notify_push /path/to/nextcloud/config/config.php is your docker command.
Here is an example configuration for docker-compose to run the daemon in a separate container:
notify_push:
container_name: notify_push
image: nextcloud/fpm-alpine
restart: always
networks:
nextcloud-net:
environment:
- PORT=7867
- NEXTCLOUD_URL=https://example.com/nextcloud/
volumes:
- /data/nextcloud:/var/www/html/nextcloud/data:ro
entrypoint: /var/www/html/nextcloud/custom_apps/notify_push/bin/x86_64/notify_push /var/www/html/nextcloud/config/config.php
After that I just followed the configuration manual here https://github.com/nextcloud/notify_push#configuration (but skipped the steps regarding systemd service)
Thanks for the docker-compose files. I run this behind a traefik2 instance, and somehow I am stuck at
docker-compose exec --user www-data app php occ notify_push:setup https://nextcloud-domain/push
which says 🗴 push server is not receiving redis messages. Has anyone got this working with traefik?
I've just set it up with traefik2 as well, though in Kubernetes. Here's the middleware and ingressroute I ended up using;
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: nextcloud-push-strip
namespace: nextcloud
spec:
stripPrefix:
prefixes:
- /push
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: nextcloud
namespace: nextcloud
spec:
routes:
- kind: Rule
match: Host(`cloud.example.com`) && PathPrefix(`/push`)
middlewares:
- name: nextcloud-push-strip
namespace: nextcloud
services:
- kind: Service
name: nextcloud-push
namespace: nextcloud
port: 80
- kind: Rule
match: Host(`cloud.example.com`)
services:
- kind: Service
name: nextcloud
namespace: nextcloud
port: 8080
tls:
domains:
- main: cloud.example.com
secretName: nextcloud-tls
The important path is to strip the /push prefix from the requests you pass along to the push daemon.
Thanks for the docker-compose files. I run this behind a traefik2 instance, and somehow I am stuck at
docker-compose exec --user www-data app php occ notify_push:setup https://nextcloud-domain/pushwhich says
🗴 push server is not receiving redis messages. Has anyone got this working with traefik?
I had this in the beginning, but adding NEXTCLOUD_URL=https://example.com/nextcloud/ as environment variable (notice the trailing slash) fixed it for me.
Thanks for the hints, but I still cannot figure out the correct config for notify_push. 🙈 This is what I have (and what works for the traefik-nextcloud connection):
Edit: I removed the broken configuration, see below for the working one.
docker-compose exec --user www-data app php occ notify_push:setup https://nextcloud.domain.com/push now says 🗴 can't connect to push server: cURL error 28: Operation timed out after 30001 milliseconds with 0 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://nextcloud.domain.com/push/test/cookie
Any hint is highly appreciated again. And once it works, I am happy to provide a PR to document how to do it.
@raimund-schluessler Do you get the same if you run this command?
docker-compose exec --user www-data app php occ notify_push:setup http://notify_push
@mikey242 This gets me a bit further:
✓ redis is configured
🗴 using unencrypted https for push server is strongly discouraged
✓ push server is receiving redis messages
✓ push server can load mount info from database
✓ push server can connect to the Nextcloud server
🗴 push server is not a trusted proxy, please add '84.146.29.183' to the list of trusted proxies or configure any existing reverse proxy to forward the 'x-forwarded-for' send by the push server.
I guess traefik is not forwarding the requests correctly, so https://nextcloud.domain.com/push does not work properly.
You probably have to add your notify_push container to the same network as your proxy otherwise traefik can forward /push to your container:
notify_push:
image: nextcloud:latest
restart: always
networks:
- nextcloud
- proxy
...
@raimund-schluessler Well that's exactly where I am with this, though I also had it working with https://nextcloud.domain.com/push. Looks like this issue is being discussed here
You probably have to add your notify_push container to the same network as your proxy otherwise traefik can forward
/pushto your container:
I guess that's indeed one part of the puzzle. But when adding the network, I now get 502 Bad Gateway for https://nextcloud.domain.com/push
You probably have to add your notify_push container to the same network as your proxy otherwise traefik can forward
/pushto your container:I guess that's indeed one part of the puzzle. But when adding the network, I now get
502 Bad Gatewayforhttps://nextcloud.domain.com/push
Ok, this seemed to be a docker networking issue. After removing and recreating the proxy network I can now use the full domain and docker-compose exec --user www-data app php occ notify_push:setup https://nextcloud.domain.com/push brings me to the same issue @mikey242 has:
✓ redis is configured
✓ push server is receiving redis messages
✓ push server can load mount info from database
✓ push server can connect to the Nextcloud server
🗴 push server is not a trusted proxy, please add '84.146.29.183' to the list of trusted proxies or configure any existing reverse proxy to forward the 'x-forwarded-for' send by the push server.
✓ redis is configured ✓ push server is receiving redis messages ✓ push server can load mount info from database ✓ push server can connect to the Nextcloud server 🗴 push server is not a trusted proxy, please add '84.146.29.183' to the list of trusted proxies or configure any existing reverse proxy to forward the 'x-forwarded-for' send by the push server.
In my case my reverse proxy had the setting real_ip_header X-Real-IP. Setting it to real_ip_header X-Forwarded-For solved that issue (I'm using a double reverse-proxy setup, so YMMV).
I know it's not the "docker way" but I added notify_push into the same container as the Nextcloud instance itself: https://github.com/Starbix/dockerimages/tree/master/nextcloud It's still under development, but might be useful to some.
I have the same issue as @raimund-schluessler and @mikey242.
✓ redis is configured
✓ push server is receiving redis messages
✓ push server can load mount info from database
✓ push server can connect to the Nextcloud server
🗴 push server is not a trusted proxy, please add '172.24.0.1' to the list of trusted proxies or configure any existing reverse proxy to forward the 'x-forwarded-for' send by the push server.
I thought this was the IP address of my proxy, and the first version of my comment reflected that, but after digging around further and giving the proxy a static address, it appears that I'm getting the gateway address of a different Docker network than the one the proxy is on.
I think I've got the correct stuff in my nginx config:
location /push/ {
// nextcloud_notify_push is the name of the push server.
proxy_pass http://nextcloud_notify_push:7867/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
For traefik, to get push server is not a trusted proxy to pass, I had to add this snippet under my entrypoint to traefik.yml:
entryPoints:
https:
address: :443
forwardedHeaders:
trustedIPs:
- "172.16.0.0/12"
When all possible scenarios and best practices will be figured out, will the final instructions be added to the docs or examples folder?
I got it working by using @benwaffle advice as a hint (https://doc.traefik.io/traefik/routing/entrypoints/#forwarded-headers).
traefik.toml
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.forwardedHeaders]
trustedIPs = [
"127.0.0.1/32",
"192.168.0.1/32"
]
notify_push part of docker-compose.yml
....
notify_push:
image: docker.io/icewind1991/notify_push:0.1.3 # image by notify_push developer
restart: unless-stopped
command: ["./notify_push", "config.php"]
volumes:
- ./app/config.php:/config.php:ro
depends_on:
- db
- cache
expose:
- "7867/tcp"
networks:
- backend # db, redis, nextcloud
- web # traefik connection
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.nc-strip-push.stripprefix.prefixes=/push"
- "traefik.http.routers.nc-push.middlewares=nc-strip-push"
- "traefik.http.routers.nc-push.entrypoints=https"
- "traefik.http.routers.nc-push.rule=Host(`nc.domain.tld`) && Path(`/push`)"
- "traefik.http.routers.nc-push.tls=true"
- "traefik.http.routers.nc-push.tls.certresolver=letsencrypt"
- "traefik.http.routers.nc-push.service=nc-push"
- "traefik.http.services.nc-push.loadbalancer.server.port=7867"
....
setup command:
docker-compose exec -u www-data nextcloud sh
./occ app:install notify_push
./occ notify_push:setup http://notify_push
The output should be:
✓ redis is configured
🗴 using unencrypted https for push server is strongly discouraged
✓ push server is receiving redis messages
✓ push server can load mount info from database
✓ push server can connect to the Nextcloud server
✓ push server is a trusted proxy
✓ push server is running the same version as the app
For traefik, to get
push server is not a trusted proxyto pass, I had to add this snippet under my entrypoint to traefik.yml:
@benwaffle Thanks for the hint, I got it "working". The forwardedHeaders key is the culprit, but I had to add insecure = true instead of the trustedIPs. The notify_push configuration now runs through. But I think it's not a good idea to run it like this, because, well, it's insecure. For some reason my notify_push server sees the public IP and not the IP of the proxy network, so I guess that's the reason why adding the trustedIPs doesn't work.
I have to admit, that I don't understand why notify_push complains about the public IP and not the traefik proxy networks IP. Here is the full configuration I got so far, maybe someone has an idea.
Edit: I removed the broken configuration, see below for the working one.
@raimund-schluessler
So if you add entryPoints.https.forwardedHeaders.insecure=true it worked right?
The app seems to run something similar to
curl -H 'x-forwarded-for: 1.2.3.4' https://example.com/index.php/apps/notify_push/test/remote
and expects 1.2.3.4 as the answer (which works if our proxy does not modify the contents of x-forwarded-for). By default traefik will replace the contents of x-forwarded-for with the actual source IP (which is correct behaviour?). If we add entryPoints.https.forwardedHeaders.insecure=true, traefik will leave the header x-forwarded-for: 1.2.3.4 unchanged and the selftest is successful.
So add entryPoints.https.forwardedHeaders.insecure=true, restart traefik and then run the setup:
./occ notify_push:setup https://exmaple.com/push
✓ redis is configured
✓ push server is receiving redis messages
✓ push server can load mount info from database
✓ push server can connect to the Nextcloud server
✓ push server is a trusted proxy
✓ push server is running the same version as the app
configuration saved
Now check the log of notify_push, you should see that clients connect to the websocket:
notify_push | [2021-02-24 22:27:41.476686 +00:00] INFO [notify_push::connection] src/connection.rs:64: new websocket authenticated as XXXXXXXX
Now that the configuration is saved, we can remove entryPoints.https.forwardedHeaders.insecure=true again and clients should still be able to connect to the push service. (Verifiy it by checking the notify_push logs again)
Now that the configuration is saved, we can remove
entryPoints.https.forwardedHeaders.insecure=trueagain and clients should still be able to connect to the push service. (Verifiy it by checking the notify_push logs again)
Won't this fail after the docker container is recreated or the machine is rebooted?
I'm using caddy as reverse_proxy and nextcloud:fpm-alpine, so I could not connect to the nextcloud container directly, as this is not speaking HTTP. First I had the problem with not having my changing public ip address (DynDNS) within trusted proxies.
The simplest solution was for me to add the extra_hosts key to the push container, mapping my public domain name to the private ip address of the host (e.g. 192.168.12.34). I suppose this solution should also work for other installations.
nextcloud_push:
container_name: nextcloud_push
image: nextcloud:fpm-alpine
restart: always
links:
- mariadb
- redis
extra_hosts:
- ${DOMAIN_NEXTCLOUD}:<PRIVATE_IP_ADDRESS_OF_HOST>
entrypoint: /var/www/html/apps/notify_push/bin/armv7/notify_push /var/www/html/config/config.php
volumes:
- nccontent:/var/www/html:ro
- ${DATA_DIR}/nextcloud/config:/var/www/html/config
- ${DATA_DIR}/nextcloud/data:/var/www/html/data
# Caddyfile
{$DOMAIN_NEXTCLOUD} {
root * /var/www/html
file_server
handle_path /push/* {
rewrite * {path}
reverse_proxy nextcloud_push:7867
}
...
}
The simplest solution was for me to add the
extra_hostkey to the push container mapping my public domain name to the private ip address of the host (e.g.192.168.12.34). I suppose this solution should also work for other installations.
I think this is very similar to adding NEXTCLOUD_URL=http://app (with app as the name of the nextcloud container) as environment variable to the notify_push container as proposed in https://github.com/nextcloud/notify_push/issues/11#issuecomment-785183282. But this lead to a 🗴 push server can't connect to the Nextcloud server for me 😕
@raimund-schluessler exactly, I'd the same problem but mapping the ip solved it.
I finally got it working without any insecure hack, see https://github.com/nextcloud/notify_push/issues/11#issuecomment-786154882 for the trick.
I will put the complete traefik - nextcloud configuration here after cleaning it up.
Found an even simpler config (for at least my caddy reverse proxy deployment) without
- (additional)
trusted_proxiesin nextcloud config - (additional)
trusted_domainsin nextcloud_config NEXTCLOUD_URLenvironment variable at push container- insecure header config at the reverse proxy
- local ip address of the host
Instead you could just link to the reverse proxy container and alias it like your external domain.
nextcloud_push:
container_name: nextcloud_push
image: nextcloud:fpm-alpine
restart: always
links:
- mariadb
- redis
- caddy:${DOMAIN_NEXTCLOUD}
entrypoint: /var/www/html/apps/notify_push/bin/armv7/notify_push /var/www/html/config/config.php
volumes:
- nccontent:/var/www/html:ro
- ${DATA_DIR}/nextcloud/config:/var/www/html/config
- ${DATA_DIR}/nextcloud/data:/var/www/html/data
Additionally you could also use HTTPS as you're using the external domain name. So everything has a green check mark.
$ docker exec -itu82 nextcloud_push ./occ notify:setup https://nextcloud.example.com/push
✓ redis is configured
✓ push server is receiving redis messages
✓ push server can load mount info from database
✓ push server can connect to the Nextcloud server
✓ push server is a trusted proxy
✓ push server is running the same version as the app
configuration saved
Possible is maybe also this for the reverse proxy, but I don't use separated networks currently:
services:
reverse_proxy:
...
networks:
web:
backend:
aliases:
- nextcloud.example.com
Here is my configuration with traefik2.
docker-compose.yml for traefik
version: '3.7'
networks:
proxy:
name: traefik_proxy
ipam:
config:
- subnet: 172.33.0.0/16
services:
traefik:
image: "traefik:latest"
container_name: "traefik"
ports:
- "80:80"
- "443:443"
- "8080:8080"
networks:
- proxy
volumes:
- "./config/traefik.toml:/etc/traefik/traefik.toml:ro"
- "./config/dynamic.toml:/etc/traefik/dynamic.toml:ro"
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
traefik.toml
[api]
insecure = false
dashboard = true
[providers]
[providers.docker]
exposedbydefault = false
network = "traefik_proxy"
[providers.file]
filename = "/etc/traefik/dynamic.toml"
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
[entryPoints.websecure]
address = ":443"
[certificatesResolvers]
[certificatesResolvers.letsencrypt]
[certificatesResolvers.letsencrypt.acme]
tlschallenge = true
email = "[email protected]"
storage = "./letsencrypt/acme.json"
[certificatesResolvers.letsencrypt.acme.httpchallenge]
entrypoint = "web"
dynamik.toml (just for the sake of completeness, necessary for a propper TLS configuration)
[tls.options]
[tls.options.default]
minVersion = "VersionTLS12"
sniStrict = true
cipherSuites = [
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
]
[tls.options.mintls13]
minVersion = "VersionTLS13"
docker-compose.yml for nextcloud
version: '3.7'
networks:
nextcloud:
ipam:
config:
- subnet: 172.22.0.0/16 # necessary for the notify_push <-> nextcloud traffic
proxy:
external:
name: traefik_proxy
services:
db:
image: mariadb
restart: always
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
volumes:
- "./db:/var/lib/mysql"
networks:
- nextcloud
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_PASSWORD=passwordpassword
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
redis:
image: redis:latest
restart: always
networks:
- nextcloud
volumes:
- "./redis:/var/lib/redis"
notify_push:
image: nextcloud:latest
restart: always
networks:
- nextcloud
- proxy
depends_on:
- db
- redis
- app
volumes:
- "./nextcloud:/var/www/html"
- "./apps:/var/www/html/custom_apps"
- "./config:/var/www/html/config"
- "./data:/var/www/html/data"
environment:
- PORT=7867
- NEXTCLOUD_URL=http://app # don't go through the proxy to contact the nextcloud server
entrypoint: /var/www/html/custom_apps/notify_push/bin/x86_64/notify_push /var/www/html/config/config.php
labels:
- traefik.enable=true
- traefik.protocol=http
- traefik.docker.network=traefik_proxy
- traefik.port=7867
- traefik.http.services.nextcloud_push.loadbalancer.server.port=7867
- traefik.http.routers.nextcloud_push.priority=2
- traefik.http.routers.nextcloud_push.middlewares=nextcloud_strip_push
- traefik.http.routers.nextcloud_push.tls=true
- traefik.http.routers.nextcloud_push.entryPoints=websecure
- traefik.http.routers.nextcloud_push.tls.certresolver=letsencrypt
# necessary for the notify_push app to work:
- traefik.http.routers.nextcloud_push.rule=Host(`nextcloud.domain.com`) && PathPrefix(`/push`)
- traefik.http.middlewares.nextcloud_strip_push.stripprefix.prefixes=/push
app:
image: nextcloud:latest
restart: always
networks:
- nextcloud
- proxy
depends_on:
- db
- redis
volumes:
- "./nextcloud:/var/www/html"
- "./apps:/var/www/html/custom_apps"
- "./config:/var/www/html/config"
- "./data:/var/www/html/data"
environment:
- REDIS_HOST=redis
- MYSQL_PASSWORD=passwordpassword
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_HOST=db
- OVERWRITEPROTOCOL=https
- TRUSTED_PROXIES=172.33.0.0/16 172.22.0.0/16 # make sure this is reflected in your nextcloud config.php
- NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.domain.com app # make sure this is reflected in your nextcloud config.php
labels:
- traefik.enable=true
- traefik.protocol=http
- traefik.docker.network=traefik_proxy
- traefik.port=80
- traefik.http.services.nextcloud.loadbalancer.server.port=80
- traefik.http.routers.nextcloud.priority=1
- traefik.http.routers.nextcloud.middlewares=nextcloud,nextcloud_redirect
- traefik.http.routers.nextcloud.tls=true
- traefik.http.routers.nextcloud.entryPoints=websecure
- traefik.http.routers.nextcloud.tls.certresolver=letsencrypt
- traefik.http.routers.nextcloud.rule=Host(`nextcloud.domain.com`)
- traefik.http.middlewares.nextcloud.headers.contentSecurityPolicy=frame-ancestors 'self' domain.com *.domain.com
- traefik.http.middlewares.nextcloud.headers.stsSeconds=155520011
- traefik.http.middlewares.nextcloud.headers.stsIncludeSubdomains=true
- traefik.http.middlewares.nextcloud.headers.stsPreload=true
- traefik.http.middlewares.nextcloud_redirect.redirectregex.regex=/.well-known/(card|cal)dav
- traefik.http.middlewares.nextcloud_redirect.redirectregex.replacement=/remote.php/dav/
cron:
image: nextcloud:latest
restart: always
networks:
- nextcloud
depends_on:
- db
- redis
volumes:
- "./nextcloud:/var/www/html"
- "./apps:/var/www/html/custom_apps"
- "./config:/var/www/html/config"
- "./data:/var/www/html/data"
entrypoint: /cron.sh
With this you can also use
docker-compose exec --user www-data app php occ notify_push:setup https://nextcloud.domain.com/push
and get all green checkmarks 😉
@nextcloud/docker If it is wanted, I can provide a PR with this.
- traefik.port=80 - traefik.http.services.nextcloud_push.loadbalancer.server.port=80
Nice work @raimund-schluessler!
But the push service port is wrong. The service runs at 7867. With port 80, i got a bad gateway error from Traefik.
My Traefik labels are:
- "traefik.enable=true"
- "traefik.http.routers.nextcloud-push.entrypoints=https"
- "traefik.http.routers.nextcloud-push.rule=Host(`nextcloud.domain.tld`) && PathPrefix(`/push`)"
[...]
- "traefik.http.routers.nextcloud-push.priority=2"
- "traefik.http.routers.nextcloud-push.middlewares=nextcloud-strip-push"
- "traefik.http.services.nextcloud-push.loadbalancer.server.scheme=http"
- "traefik.http.services.nextcloud-push.loadbalancer.server.port=7867"
- "traefik.http.middlewares.nextcloud-strip-push.stripprefix.prefixes=/push"
After fixing a push server is not a trusted proxy error now works!
But the push service port is wrong. The service runs at 7867. With port 80, i got a bad gateway error from Traefik.
I don't know, for me it works like this.
But the push service port is wrong. The service runs at 7867. With port 80, i got a bad gateway error from Traefik.
I don't know, for me it works like this.
Default port changed in v0.1.4 - https://github.com/nextcloud/notify_push/releases/tag/v0.1.4
But the push service port is wrong. The service runs at 7867. With port 80, i got a bad gateway error from Traefik.
I don't know, for me it works like this.
Default port changed in v0.1.4 - https://github.com/nextcloud/notify_push/releases/tag/v0.1.4
Ah, yes. That explains it. The update to v0.1.4 indeed broke the configuration. Thanks for the hints @foorschtbar @TBK. I updated the configuration above to account for the changed default port.