IP Address in Environment Variable in Snippet

1. Caddy version (caddy version):

v2.2.1

2. How I run Caddy:

As a systemd service on raspbian. Caddyfile in /etc/caddy/.

a. System environment:

Raspbian 7

b. Command:

caddy run / caddy adapt / caddy reload

c. Service/unit/compose file:

N/A(?)

d. My complete Caddyfile or JSON config:

#snippet to detefine logging
(logging) {
        log {
                output file /var/log/access.log
        }
}

#snippet to determine whether hosts are inside or outside LAN.
(ip_match) {
        @lan_hosts {
                remote_ip 10.10.1.1/24 {$VPNIP}
        }

        @not_lan_hosts {
                not {
                        remote_ip 10.10.1.1/24 {$VPNIP}
                }
        }
}

#snippet to deny access to hosts from outside LAN
(access_denied) {
        respond @not_lan_hosts "Access Denied" 403 {
                close
        }
}

########################################################################

pve.rmwhite.us {
        import logging
        import ip_match
        import access_denied

        reverse_proxy @lan_hosts {
                to 10.10.1.50:8006

                transport http {
                        tls_insecure_skip_verify
                }
        }
}

3. The problem I’m having:

I am working from home connected to a VPN. My desktop gets a different IP address every day, but I still need to use my local services. I would like to be able to update my primary computer’s VPN IP via a script. I am attempting to assign this VPN IP to an environment variable ($VPNIP) so I can simply update that variable, caddy reload, and have access to my local services.

The allow and deny blocks are entered as snippets in the beginning of my caddyfile.

4. Error messages and/or full log output:

If I enter the environment variable in the form {$VPNIP}, running “caddy adapt” just shows that caddy is ignoring the environment variable. That is to say, if I had:

remote_IP 10.10.1.1/24 {$VPNIP}

the caddyfile is parsed as:

[{“remote_ip”:{“ranges”:[“10.10.1.1/24,”]}}]

which ignores the environment variable, but caddy will run.

If I use the format {env.VPNIP}, I get the same output as above from caddy adapt, but caddy reload provides the error:

reload: sending configuration to instance: caddy responded with error: HTTP 400: {“error”:"loading config: loading new config: loading http app module: provision http: server srv0: setting up route handlers: route 0: loading handler modules: position 0: loading module ‘subroute’: provision http.handlers.subroute: setting up subroutes: route 0: loading matcher modules: module name ‘not’: provision http.matchers.not: loading matcher sets: module name ‘remote_ip’: provision http.matchers.remote_ip: invalid IP address: "}

and caddy will not run.

5. What I already tried:

I tried both of the environment variable formats I’ve found in the documentation.

6. Links to relevant resources:

Welcome!

You have a comma at the end of your value, which is invalid.

Chances are your env variable is not set. Use caddy environ to confirm (make sure to run it as your service though).

Also please use ``` on the lines before and after your config to use code formatting. It looks all messed up right now, hard to read.

Hi Matt,

Thanks for your help.

I have confirmed that my environment variable is set using caddy environ

I’m not sure why the comma was in there, but when I change my remote_ip line to:

remote_ip 10.10.1.1/24 {$VPNIP}

The output of caddy adapt is still:

“match”:[{“remote_ip”:{“ranges”:[“10.10.1.1/24”]}}]

as if the environment variable does not exist or is not in the file.

To be clear, the reverse proxy works well when I’m not connected to the vpn.

I recommend you use the caddy fmt command to clean up the whitespace of your config as well :smile:

Anyways, works for me, so it must be an issue with your environment variable.

$ cat Caddyfile
foo.com

@test remote_ip 1.1.1.1 {$VPNIP}
respond @test "Foo" 200

$ VPNIP="2.2.2.2" caddy adapt --pretty
2020/11/03 04:18:02.809	INFO	using adjacent Caddyfile
{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "listen": [
            ":443"
          ],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "foo.com"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "body": "Foo",
                          "handler": "static_response",
                          "status_code": 200
                        }
                      ],
                      "match": [
                        {
                          "remote_ip": {
                            "ranges": [
                              "1.1.1.1",
                              "2.2.2.2"
                            ]
                          }
                        }
                      ]
                    }
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    }
  }
}

Thanks for your help, francislavoie!

What I’ve found is that I need to use the syntax you use, where the environment variable is set in the same line as the caddy adapt or caddy run command.

I had assumed I could simply set a system environment variable and it would update automatically, which seems was obviously incorrect (and overly optimistic).

For those who stumble upon this in the future, my solution was to run the following:

$VPNIP=‘10.10.1.x’
VPNIP=$VPNIP caddy reload

I don’t know if this is the best way to do it, but now I’m able to write a short script to update the VPN IP of my computer while I’m working.

Well, environment variables are per-user, per-shell. Basically it’s set in your current “context”. So if you set it for your current user and not the caddy user, then Caddy won’t find out about it.

You can use sudo systemctl edit caddy to modify the service file, and you can add Environment= lines to set variables for that context. Maybe that’s what’s right for you.

https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html

Thanks, francislavoie, you’ve taught me about Caddy and Linux at the same time. I was setting the environment variable for the local user instead of the caddy user.

It seems that, in the context I want to use it, it is simpler to set the environment variable with the caddy run command.

In any case, I was able to write a simple .bat file to update my VPN IP address using plink, which is an extension of putty:

::Pull public IP address of local windows machine
for /f "delims=" %%i in ('curl "http://myexternalip.com/raw"') do set VPNIP=%%i

::SSH into Caddy server and set VPN ip address in Caddy.
plink.exe -ssh username@10.10.1.9 -i putty_private_key.ppk VPNIP=%VPNIP% caddy reload --config /etc/caddy/Caddyfile

Thanks again for all the help!

1 Like

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