TOTP iOS mobile app notifications - solution (partial) to no push notifications | Nextcloud in Docker, behind proxy

Hi all,

recently I found out that there is built-in mechanism to authorize login with mobile app. This however didn’t exactly work for my setup which is:

  • Server: Nextcloud docker container behind Caddy proxy
  • Mobile: iPhone 15 Pro

I found it quite hard to find the solution for given case, but finally managed, thus I want to leave some short guide to (maybe) help someone with similar setup.

Issue

2FA is enabled in Nextcloud, but when trying to use mobile app to authorize there is no push notification.

Solution

It seems that using notify_push app helps to solve the issue of getting instant app notifications.

Installing notify_push app to Nextcloud docker container

Prerequisites

Functional Nextcloud iOS mobile app.

I assume that you have following Nextcloud in Docker instance running:

  • Reverse Proxy + Nextcloud + DB + Redis

exact implementation will differ based on exact images used for these, but the general solution should be quite the same.

In my case I’m using following component images:

  • Reverse Proxy: caddy:latest
  • Nextcloud: nextcloud:31.0.8
  • DB: mariadb:11.4
  • Redis: redis:alpine

This is how the docker compose looks like for my system (simplified):

  1. Caddy container
services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile  # Caddy config
      - caddy_data:/data  # SSL cert storage
      - caddy_config:/config  # Config storage
    networks:
      - proxy_network  # Shared network

networks:
  proxy_network:
    external: true  # Use the shared proxy network

volumes:
  caddy_data:
  caddy_config:
  1. Nextcloud + DB + Redis
networks:
  proxy_network:
    external: true  # Use the shared proxy network

services:
  db:
    image: mariadb:11.4
    container_name: nextcloud_db
    restart: always
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    volumes:
      - db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=xxxxxxxxxxxxx <- very secure pswd
      # and the rest of the secrets 
    networks:
      - proxy_network  # Shared network with Caddy

  app:
    image: nextcloud:31.0.8
    container_name: nextcloud_app
    restart: always
    volumes:
      - nextcloud:/var/www/html
      - config:/var/www/html/config
    environment:
      - MYSQL_PASSWORD= ...
      # and the rest of the secrets
      - TRUSTED_PROXIES= here go proxies
    expose:
      - "80"  # Expose port instead of binding it
    networks:
      - proxy_network  # Shared network with Caddy
    depends_on:
      - db
      - redis

  redis:
    image: redis:alpine
    container_name: nextcloud_redis
    restart: always
    command: redis-server
    networks:
      - proxy_network

volumes:
  data:
  config:
  db:
  nextcloud:

Step by step

  1. Add nextcloud notify_push container
  notify_push:
    container_name: nextcloud_notify
    image: nextcloud:31.0.8 # Should be the same as nextcloud instance
    restart: always
    expose:
      - "7867"
    environment:
      - NEXTCLOUD_URL=http://nextcloud_app/ # Point to local nextcloud_app container
    volumes:
      - nextcloud:/var/www/html:z
      - config:/var/www/html/config:ro
    entrypoint: /var/www/html/custom_apps/notify_push/bin/x86_64/notify_push /var/www/html/config/config.php
    depends_on:
      - db
      - app
      - redis
    networks:
      - proxy_network
  1. Disable apache (from the inside of nextcloud) from rewriting the IP:
app:
    image: nextcloud:31.0.8
    container_name: nextcloud_app
    restart: always
    volumes:
      - nextcloud:/var/www/html
      - config:/var/www/html/config
    environment:
      - MYSQL_PASSWORD= ...
      # and the rest of the secrets
      - TRUSTED_PROXIES= here go proxies
      ## Add
      - APACHE_DISABLE_REWRITE_IP=1 
    expose:
      - "80"  # Expose port instead of binding it
    networks:
      - proxy_network  # Shared network with Caddy
    depends_on:
      - db
      - redis
  1. Modify Caddyfile
my.great.nextcloud.server {
	handle_path /my_nextcloud_root_path/* {
		reverse_proxy nextcloud_app
	}
    
    ## Add
	handle_path /push/* {
        # Add port to solve potential HTTP502: Bad gateway issue
		reverse_proxy nextcloud_notify:7867
	}
}
  1. Install notify_push app in Nextcloud

  2. Run OCC app setup command - this also performs initial check if the configuration is ok

x@xoxo:~$ docker exec -it nextcloud_app php occ notify_push:setup https://my.great.nextcloud.server/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

Test the TOTP app notifications

Enable the TOTP in your profile and use mobile app.

You should now get the mobile app notification to authorize login!

The only downside I see right now is that after clicking the notification banner you’re not automatically redirected to the tab to accept the request, but you need to do this one additional click to open the notifications inside the app…

I hope this will save some time for others.