Can I route on remote_ip? or if remote_ip -eq

1. Caddy version (caddy version):

v2.2.1

2. How I run Caddy:

a. System environment:

Running in Docker on a Raspberry Pi 3

uname -a
Linux a209985abe23 4.19.97-v7+ #1294 SMP Thu Jan 30 13:15:58 GMT 2020 armv7l Linux

b. Command:

Ran via docker-compose

docker-compose up

c. Service/unit/compose file:

docker-compose.yml

version: '3.4'

services:
  caddy:
    image: caddyauth
    container_name: caddyv2
    volumes:
      - ${HOME}/New-Docker/Caddy/Data:/data 
      - ${HOME}/New-Docker/Caddy/Caddyfile:/etc/caddy/Caddyfile  
      - ${HOME}/New-Docker/Caddy/Config:/config 
      - ${HOME}/New-Docker/Caddy/Config/assets/templates/basic:/assets/templates/basic
      - ${HOME}/New-Docker/Caddy/Site:/var/www
    ports:
      - "80:80"
      - "443:443"
    networks:
      web:
       ipv4_address: 172.22.0.3
    restart: always

  ddclient:
    image: linuxserver/ddclient
    container_name: ddclient
    environment:
      - PUID=1001
      - PGID=1002
      - TZ=Europe/London
    networks:
      web:
    volumes:
      - ${HOME}/New-Docker/Ddclient:/config
    restart: always

  homeassistant:
    container_name: homeassistant
    restart: always
    image: homeassistant/home-assistant
    volumes:
      - ${HOME}/New-Docker/Homeassistant:/config
      - /etc/localtime:/etc/localtime:ro
      - ${HOME}/New-Docker/Shared:/shared
    ports:
      - "8123:8123"
    privileged: true
    environment:
      - PUID=1001
      - PGID=1002
      - TZ=Europe/London
    networks:
      web:
       ipv4_address: 172.22.0.4

networks:
  web:
   driver: bridge
   ipam:
    config:
     - subnet: 172.22.0.0/24

docker file for Caddy

FROM caddy:builder AS builder

RUN caddy-builder \
    github.com/greenpau/caddy-auth-portal

FROM caddy:latest

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

d. My complete Caddyfile or JSON config:

{
    email myemail@gmail.com
    acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}


test.domain.xyz {
    encode gzip
    route /auth* {
        auth_portal {
	    path /auth
            backends {
                google_oauth2_backend {
                    method oauth2
                    realm google
                    provider google
                    client_id ***.apps.googleusercontent.com
                    client_secret ***
                    scopes email
                    user myemail@gmail.com add role auth_user
                }
            }
            jwt {
                token_name access_token
                token_secret ***
                token_issuer ***
            }
            ui {
                theme basic
                login_template "/assets/templates/basic/login.template"
                portal_template "/assets/templates/basic/portal.template"
                logo_url "https://caddyserver.com/resources/images/caddy-circle-lock.svg"
                logo_description "Caddy"
                links {
                    "Home Assistant" /homeassistant
                }
            }
        }
    }

    
    route /for_jwt_only {
        jwt {
            primary yes
            trusted_tokens {
                static_secret {
                    token_name access_token
                    token_secret ***
                    token_issuer ***
                }
            }
            allow role auth_user
        }
    }

route /homeassistant*  {	
		jwt
	uri strip_prefix /homeassistant
		reverse_proxy homeassistant:8123 
	}
 
    route /sso/oauth2/google* {
        jwt {
            auth_url /auth/oauth2/google
        }
        respond * "google oauth2 sso" 200
    }

    route {
        redir https://{hostport}/auth 302
    }
}

3. The problem I’m having:

Been trying to set up a raspberry pi running docker with a Caddy front end so I can run some resources from home but access from the web. I have a domain, have ddclient updating my public IP, and I can access the domain. I am using the Oath2 Plugin and using the google oath backend, this also works I have managed to restrict pages to my user account etc so all of the part I thought was going to be the hard bit is done.
My issue is I am trying to keep in under one domain and use /service to access what I want but this is causing issues, my first service I am trying is home assistant also running in docker as files show. I strip the /homeassistant and proxy it onto the container running home assistant, this is where the problem occurs. It sends a redirect to /onboarding.html, which caddy receives as test.domain.xyz/onboarding.html and therefore hits the catch all redirect back to /auth as the request has no /homeassistant in it to get routed back to homeassistant correctly.
I feel I need a:

 if {remoteip} eq {homeassistantIP} rewrite somethinghere

but that doesn’t appear to exist.

4. Error messages and/or full log output:

This is the redirect stream.

Summary
URL: https://test.domain.xyz/homeassistant
URL: https://test.domain.xyz/onboarding.html
URL: https://test.domain.xyz/auth
URL: https://test.domain.xyz/auth/portal
Status: 200

5. What I already tried:

If I go to test.domain.xyz/homeassistant/onboarding.html it works, kind of, I get the page but non of the resources load up as they are also missing the /homeassistant/ before the required file

Tried assorts over the last few days I have lost track:
Tried changing the default route before the redirect

try_files https://{hostport}/homeassistant/{uri}
try_files https://{hostport}/homeassistant/{path}

tried a rewrite with ifs I understand that was in Caddyv1 but cannot get it to work in Caddyv1

  rewrite {
    if {remoteip} is 172.22.0.4 
    to https://{hostport}/homeassisant/{path}
  }

amongst other things, like trying to see if I can route on remote port, tried to maniple headers to see if that helped, tried not stripping the /homeassistant but that just returns a 404 which makes sense.

trying to not just cave and use multiple domains, but to me it looks like that might be the only way, and figure out the OAuth to see if I can SSO across the domains or something

Theres loads of words here, hopefully it makes sense what I am trying to do and my issue.

6. Links to relevant resources:

Yep! That’s what request matchers are for:

Looks more like this:

@isLocal remote_ip 172.22.0.4
rewrite @isLocal /homeassistant/{path}

But I’m not totally certain I understand what you’re trying to achieve with the rewrite. The remote IP will be the IP address of the browser making the request, not the IP address of the server that responded to the previous request. I think with the above, the rewrite will just never apply.

Homeassistant must have configuration that lets you change its base path, so that it doesn’t make the redirects happen to the root. See this article:

I have clearly miss understood what remote_ip was, I thought it would be the ip of the service so that’s my bad, thanks for clearing that up.

It does indeed sound like a subfolder problem, although I had already tried the “base_url” thing, and headers. However maybe I was implementing them incorrectly, I shall go and try them again to see if I was making a silly mistake.

1 Like

Been trying all sorts to get this to work, annoyingy the homeassistant base_url equivalent doesn’t accept paths in it so I couldn’t set that, they have no intention of changing this as looking thru issue tracker it looks like its been requested many times.

Soooo I have been trying to figure out a way around this and feel like I have a solution but either I’m missing the point or uri strip_prefix isn’t quite working as intended so thought id pop back to ask.

I have added the following parts into my caddyfile

@hass path_regexp ^(/homeassistant[,%20\s]{0,4})/(.*)$
route @hass {
                jwt
                header {
                     location /homeassistant
               }
        uri strip_prefix /homeassistant,
        reverse_proxy homeassistant:8123
}

Adding a location header is allowing the request that comes back to have extra in the path, however it comes back with a ,%20 in it as well due to how the location field is used.

/homeassistant,%20/onboard.html

my plan was to then using the regex to match the path, then strip the homeassistant,%20 from the path and pass the rest along. My theory sounded fine in my head but it was failing so I went at it step by step and using {debug} to track what was going on.

path requested /homeassistant,

uri strip_prefix /homeassistant,

this works the /homeassistant, get stripped (comma is meant to be removed)
however as soon as I do this
path requested /homeassistant,%

uri strip_prefix /homeassistant,%

this does not get stripped. Just adding the % means it does not get stripped.

Is there something about the strip_prefix that means it doesn’t handle % character?I had a look at the .json that is built from the caddyfile and there is a % in the json so I don’t think its in that conversion.

any thoughts?
Thanks

What the heck, that doesn’t make sense. Why is there a , and %20 (a space, URL encoded)? Sounds like a homeassistant misconfiguration.

Are you configuring these options?

Yer I have tried those settings but they don’t allow paths. So I cannot set my.domain.com/homeassistant only my.domain.com and they are refusing to add that functionality in as its been asked before.

The ,%20 i’m guessing is because i’m setting the location: /homeassistant header…although now I see what you mean homeassistant shouldn’t take the comma separated list from location without formatting correctly. Maybe I’ll take that up with them and see what they say.

Still doesn’t explain why uri strip_prefix won’t strip a % though, or at least wouldn’t for me

This is starting to be more hassle than I wanted, but I’m at a point where I refuse to be beaten now :smiley: I’ll head over to homeassistant and see what they say about the header stuff

It would be much easier to use a subdomain, as I said before. Why not do that?

This topic was automatically closed after 30 days. New replies are no longer allowed.