iainbullock / tesla-http-proxy-docker

Apache License 2.0
25 stars 7 forks source link

Nginx Proxy Manager setup #40

Closed xPand4B closed 2 months ago

xPand4B commented 2 months ago

It would be very cool and usefull to have a guide/version of this container for a setup using the Nginx Proxy Manager.

Exposing the service to some port and e.g. having a new env var "SERVER_TYPE" with values like "local" and "NPM" could be the activator for this. This way it should be possible to just use this web server instead of booting up another one just for this client.

Any suggestions?

tux43 commented 2 months ago

I've just been writing up a guide

Any feedback is very welcome.!

mekaneck commented 2 months ago

I'm running this using NPM only without spinning up a separate NGINX server. I can try to write up a guide over the weekend. The key is to place the com.tesla.3p.public-key.pem file into your NPM's data folder under a subfolder called tesla-http-proxy and then when you add a proxy host in the GUI you add this to the "advanced" tab:

location /.well-known/appspecific/com.tesla.3p.public-key.pem {
        root /data/tesla_http_proxy;
        try_files /com.tesla.3p.public-key.pem =404;
}
mekaneck commented 2 months ago

Here is my docker-compose, note I use ${DOCKER_DATA_DIR} and ${TZ} variables for my directory path and timezone, respectively. Also note I use an external network as per the recommended practices so I don't have to publish ports on my host and instead I use the expose argument (ref: NPM documentation). (expose may not even be necessary, it's possible it could be eliminated entirely, I haven't tried.)

version: '3.0'

networks:
  default:
    external: true
    name: same_external_network_as_NPM_container

services:
  tesla_http_proxy:
    container_name: tesla_http_proxy
    image: "iainbullock/tesla_http_proxy:latest"

    environment:
      - TZ=${TZ}

    stdin_open: true
    tty: true         

    entrypoint: "/app/run.sh"
    working_dir: /app

    volumes:
      - ${DOCKER_DATA_DIR}/tesla_http_proxy:/data
      # Webserver root for the $DOMAIN virtual server. Change the path according to your webserver setup. Path must exist or this container won't start
      - ${DOCKER_DATA_DIR}/nginx-proxy-manager/data/tesla_http_proxy:/share/nginx
      # Path to tesla_http_proxy directory inside /config on Home Assistant instance. Change according to your HA setup. Path must exist or this container won't start
      - ${DOCKER_DATA_DIR}/homeassistant/config/tesla_http_proxy:/share/home-assistant
    expose:
      - 443
      - 8099

    restart: unless-stopped  

Also here is my NPM docker-compose, notice that it is set up on two external networks. One matches the network that is use in every container I want to proxy with NPM: same_external_network_as_NPM_container The other gives NPM an address on my real network.


version: '3.8'

networks:
  default:
    external: true
    name: same_external_network_as_NPM_container
  home_network_vlan_1:
    external: true
    name: home_network_vlan_1

services:      
  nginx:
    container_name: nginx
    image: jc21/nginx-proxy-manager
    restart: unless-stopped
    expose:
      - 81
      - 80
      - 443
    volumes:
      - ${DOCKER_DATA_DIR}/nginx-proxy-manager/data:/data
      - ${DOCKER_DATA_DIR}/nginx-proxy-manager/letsencrypt:/etc/letsencrypt
      - ${DOCKER_DATA_DIR}/nginx/snippets:/snippets:ro
    environment:
      TZ: ${TZ}
    mac_address: xx:xx:xx:xx:xx:xx
    networks:
      home_network_vlan_1:
        ipv4_address: 192.168.1.xx
      default:

And if you don't have that external network already created, you need to first create it with a command like docker network create -d macvlan -o parent=eth0 --subnet=192.168.1.0/24 --gateway=192.168.1.1 --ip-range=192.168.1.1/32 home_network_vlan_1

The other external network is easier to create, and as referenced in the NPM documentation is docker network create same_external_network_as_NPM_container

Now, back to the Tesla Proxy instructions:

First you can set up a new proxy host on NPM. Assuming your top level domain is example.com you can fill in the NPM proxy host details like this:

Go to the SSL tab:

Go to the "Advanced" tab, and enter the following:

Then follow the instructions in the regular setup guide. When you get the .pem file to copy, you copy it to your NPM's data folder under a subfolder called tesla_http_proxy (or whatever matches the path after root in the text you entered on the "Advanced" tab of your proxy host). After you shut down the flask server, you'll need to go back into your NPM proxy host settings and change the "Forward Port" that we set earlier from 8099 to 443 and also change the scheme from http to https.

I did all this with the initial release of the docker file, so the steps have changed a little and I think I've updated what needs updating. But if you run into issues let me know. Sorry it's not a complete guide, it just has the unique points for NPM.

andjo commented 2 months ago

Just managed to get this setup with the above instructions from @mekaneck. 😍 The only snag was that I needed to use http scheme for the 8099 port, and then switch to https for 443.

Now I'm back in business with Home Assistant + Tesla Custom Integration in a Proxmox VM (HAOS), with Tesla HTTP Proxy Docker and NPM managed by Portainer in a separate VM.

In this environment I had to copy selfsigned.pem manually to Home Assistant.

tux43 commented 2 months ago

I’ve tried to document all of it - happy for feedback.

https://www.smartmotion.life/2024/04/23/tesla-custom-integration-with-home-assistant-on-docker/

mekaneck commented 2 months ago

Thanks for the feedback @andjo I've updated my previous post with those changes.

@tux43 - this discussion is specific to NGINX Proxy Manager, which is a an implementation of NGINX that uses a GUI and therefore has some restrictions on what customization is possible compared to the vanilla NGINX. Your guide appears to pertain to vanilla NGINX.

Chacsam commented 2 months ago

Just managed to get this setup with the above instructions from @mekaneck. 😍 The only snag was that I needed to use http scheme for the 8099 port, and then switch to https for 443.

Now I'm back in business with Home Assistant + Tesla Custom Integration in a Proxmox VM (HAOS), with Tesla HTTP Proxy Docker and NPM managed by Portainer in a separate VM.

In this environment I had to copy selfsigned.pem manually to Home Assistant.

Hi,

Do I get it right that you installed the Tesla HTTP Proxy Docker on the same VM as your NPM (while Home assistant is on another one)? I am trying to make something similar based on a config where my NPM Docker and my Home Assistant Docker run on 2 different servers.

Looking at @mekaneck's code it seems to me that they are all on one single host with a common ${DOCKER_DATA_DIR}/.

Not sure how I should set it up... (I am not an expert indeed)

andjo commented 2 months ago

You got it right @Chacsam.

The only problem with HA in an other location is the bind mount that is trying to point to a location in the HA configuration directory. I created a dummy directory for that, and after the selfsigned.pem was generated, I copied that file to the HA installation at /config/tesla_http_proxy/selfsigned.pem and pointed to that when doing the setup in HA.

My volumes looks like this:

    volumes:
      - /opt/tesla-http-proxy:/data
      - /opt/proxy-manager/data/tesla-http-proxy:/share/nginx
      - /opt/tesla-http-proxy-homeassistant/config/tesla_http_proxy:/share/home-assistant # for selfsigned.pem, only used during setup
iainbullock commented 2 months ago

@tux43 Many thanks for creating the blog. I will refer to it in the Readme

iainbullock commented 2 months ago

@Chacsam @xPand4B @mekaneck Just catching up on this Issue. Can I close this one yet?

Chacsam commented 2 months ago

Sorry guys, but I am still not there yet.

So, my setup is as follow:

I have successfully run the following docker compose on 210 (NPM)

version: '3.0'

networks:
  default:
    external: true
    name: npm_proxy_default

services:
  tesla_http_proxy:
    container_name: tesla_http_proxy
    image: "iainbullock/tesla_http_proxy:latest"

    environment:
      - TZ='Europe/Amsterdam'

    stdin_open: true
    tty: true         

    entrypoint: "/app/run.sh"
    working_dir: /app

    volumes:
      - /home/apps/tesla_http_proxy:/data
      - /home/apps/npm_proxy/data/tesla_http_proxy:/share/nginx
      - /home/apps/ha_proxy/config/tesla_http_proxy:/share/home-assistant
    expose:
      - 443
      - 8099

    restart: unless-stopped

My NPM setup looks like this:

I have changed the config.sh file as per instruction.

Rerun the docker container and can find the pem files (on my 210 NPM device):

When I follow the instructions and "enter the URL of your FQDN into a web browser." I just get a 502 Bad Gateway, openresty Error. (calling directly the http://192.168.1.210:8099 page gives a ERR_CONNECTION_TIMED_OUT)

The logs of the docker container seems ok, finishes with:

Found existing keypair
Starting temporary Python app for authentication flow. Delete /data/access_token to force regeneration in the future
[07:06:36] main:INFO: *** Starting Flask server... ***
[07:06:36] werkzeug:INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:8099
 * Running on http://172.19.0.5:8099
[07:06:36] werkzeug:INFO: Press CTRL+C to quit

Where did I miss?

iainbullock commented 2 months ago

Sorry for delay in response. I'm not familiar with the NPM method, however I make the following comments / suggestions:

Chacsam commented 2 months ago

Sorry for delay in response. I'm not familiar with the NPM method, however I make the following comments / suggestions:

  • The Flask server is not receiving a connection as there are no logs after [07:06:36] werkzeug:INFO: Press CTRL+C to quit
  • The 502 Bad Gateway error happens when you connect to the FQDN but no service is listening, which aligns withthe above observation
  • Your Custom NGinx config has the location block for the public key, but not the redirect to the Flask server. You also need a location block like this: location / { proxy_pass http://192.168.0.3:8099; # Change to hostname or IP of your Docker host }

Hi,

Thanks for the response. In my understanding, the base NPM feature acts as the location / block. I did gave your suggestion a try, adapting the "Custom Nginx Configuration" as below, but it didn't change anything.

    location / {
        proxy_pass http://192.168.1.210:8099; 
    }

    # static public key for Tesla
    location /.well-known/appspecific/com.tesla.3p.public-key.pem {
        root /usr/share/nginx/tesla_http_proxy;
        try_files /com.tesla.3p.public-key.pem =404;
    }

I have another container running on my "210" device which is can be accessed via a NPM config, so that's not a problem either

iainbullock commented 2 months ago

You don't get any more proxy logs either? Anything in NGinx logs?

Looks like something is blocking the connection.

How about connecting to the container directly http://172.19.0.5:8099 from a browser (not a permanent solution as the IP address may change)

Chacsam commented 2 months ago

You don't get any more proxy logs either? Anything in NGinx logs?

Looks like something is blocking the connection.

How about connecting to the container directly http://172.19.0.5:8099 from a browser (not a permanent solution as the IP address may change)

Connecting to the container directly from a browser gives ERR_CONNECTION_TIMED_OUT

NGINX error logs gives

2024/05/03 10:59:36 [error] 311#311: *14649 connect() failed (111: Connection refused) while connecting to upstream, client: [--MY PC LOCAL IP--], server: [---MY_FQDN---], request: "GET / HTTP/2.0", upstream: "http://192.168.1.210:8099/", host: "[---MY_FQDN---]", referrer: "http://192.168.1.210:81/"
2024/05/03 10:59:36 [error] 311#311: *14649 connect() failed (111: Connection refused) while connecting to upstream, client: [--MY PC LOCAL IP--], server: [---MY_FQDN---], request: "GET /favicon.ico HTTP/2.0", upstream: "http://192.168.1.210:8099/favicon.ico", host: "[---MY_FQDN---]", referrer: "https://[---MY_FQDN---]/"
2024/05/03 11:04:25 [error] 338#338: *15130 connect() failed (111: Connection refused) while connecting to upstream, client: [--MY PC LOCAL IP--], server: [---MY_FQDN---], request: "GET / HTTP/2.0", upstream: "http://192.168.1.210:8099/", host: "[---MY_FQDN---]", referrer: "http://192.168.1.210:81/"
2024/05/03 11:04:25 [error] 338#338: *15130 connect() failed (111: Connection refused) while connecting to upstream, client: [--MY PC LOCAL IP--], server: [---MY_FQDN---], request: "GET /favicon.ico HTTP/2.0", upstream: "http://192.168.1.210:8099/favicon.ico", host: "[---MY_FQDN---]", referrer: "https://[---MY_FQDN---]/"
2024/05/03 11:11:05 [error] 337#337: *15628 connect() failed (111: Connection refused) while connecting to upstream, client: [--MY PC LOCAL IP--], server: [---MY_FQDN---], request: "GET / HTTP/2.0", upstream: "http://192.168.1.210:8099/", host: "[---MY_FQDN---]", referrer: "http://192.168.1.210:81/"
2024/05/03 11:11:05 [error] 337#337: *15628 connect() failed (111: Connection refused) while connecting to upstream, client: [--MY PC LOCAL IP--], server: [---MY_FQDN---], request: "GET /favicon.ico HTTP/2.0", upstream: "http://192.168.1.210:8099/favicon.ico", host: "[---MY_FQDN---]", referrer: "https://[---MY_FQDN---]/"
2024/05/03 11:23:10 [error] 389#389: *16311 connect() failed (111: Connection refused) while connecting to upstream, client: [--MY PC LOCAL IP--], server: [---MY_FQDN---], request: "GET / HTTP/2.0", upstream: "http://192.168.1.210:8099/", host: "[---MY_FQDN---]"
2024/05/03 11:23:10 [error] 389#389: *16311 connect() failed (111: Connection refused) while connecting to upstream, client: [--MY PC LOCAL IP--], server: [---MY_FQDN---], request: "GET /favicon.ico HTTP/2.0", upstream: "http://192.168.1.210:8099/favicon.ico", host: "[---MY_FQDN---]", referrer: "https://[---MY_FQDN---]/"
2024/05/03 11:41:11 [error] 389#389: *16658 connect() failed (111: Connection refused) while connecting to upstream, client: [--MY PC LOCAL IP--], server: [---MY_FQDN---], request: "GET / HTTP/2.0", upstream: "http://192.168.1.210:8099/", host: "[---MY_FQDN---]"
2024/05/03 11:41:11 [error] 389#389: *16658 connect() failed (111: Connection refused) while connecting to upstream, client: [--MY PC LOCAL IP--], server: [---MY_FQDN---], request: "GET /favicon.ico HTTP/2.0", upstream: "http://192.168.1.210:8099/favicon.ico", host: "[---MY_FQDN---]", referrer: "https://[---MY_FQDN---]/"
iainbullock commented 2 months ago

Umm, not sure.

Is the Flask Server still running, what are the latest logs from the container?

Do you still have this: [07:06:36] main:INFO: Starting Flask server... [07:06:36] werkzeug:INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.

Maybe try to connect from inside the container itself. Get a command line using

docker exec -it bash # you can get using docker ps

then execute wget http://127.0.0.1:8099

see if that connects

Chacsam commented 2 months ago

First, thanks a lot for looking with me.

I restarted the container to have a clean start.

Container logs still stops with:

Configuration Options are:
CLIENT_ID=379680272824-xxxx-xxxx-xxxxxxxxb006
CLIENT_SECRET=Not Shown
DOMAIN=txxxx.vxxxx.be
PROXY_HOST=Proxy
REGION=Europe, Middle East, Africa
Found existing keypair
Starting temporary Python app for authentication flow. Delete /data/access_token to force regeneration in the future
[10:06:17] main:INFO: *** Starting Flask server... ***
[10:06:17] werkzeug:INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:8099
 * Running on http://172.19.0.5:8099
[10:06:17] werkzeug:INFO: Press CTRL+C to quit

The wget within the docker downloads an index.html that looks correct

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <style>
        body {
            font-family: sans-serif;
            text-align: center;
        }

        div.content {
            width: 100%;
            padding: 10px;
        }

        button {
            padding: 10px;
            font-size: 14px;
            width: 300px;
        }
    </style>
</head>

<body>
    <h2>Tesla HTTP Proxy setup</h2>
    <hr>
    <div class="content">
        <a href="https://auth.tesla.com/oauth2/v3/authorize?&client_id=379680272824-xxxx-xxxx-xxxxxxxxb006&locale=en-US&prompt=login&redirect_uri=https://[--MY FQDN--]/cal
            target="_blank"><button type="button">1. Generate OAuth token</button></a>
    </div>

    <div class="content">
        <a href="https://[--MY FQDN--]/.well-known/appspecific/com.tesla.3p.public-key.pem" target="_blank"><button
                type="button">2. Test public key endpoint</button></a>
    </div>
    <div class="content">
        <a href="register-partner-account"><button type="button">3. Register Partner account<br />
                (Make sure test 2 works first)</button></a>
    </div>
    <div class="content">
        <a href="https://tesla.com/_ak/[--MY FQDN--]" target="_blank"><button type="button">4. Enrol private key into your
                vehicle</button></a>
    </div>
    <div class="content">
        <a href="shutdown"><button type="button">5. Shutdown Flask server</button></a>
    </div>
</body>

</html>
iainbullock commented 2 months ago

No problem!

Can you now connect by running the same command on the docker host, e.g.

wget http://192.168.1.210:8099

Or wget http://172.19.0.5:8099

If not something in the npm setup is blocking the connection

Chacsam commented 2 months ago

Getting there...

wget http://172.19.0.5:8099/ works

wget http://192.168.1.210:8099 gives

Connecting to 192.168.1.210:8099 (192.168.1.210:8099)
wget: can't connect to remote host (192.168.1.210): Connection refused
iainbullock commented 2 months ago

Yes there is a clue.

I'm not familiar with how npm maps ports between host and container. Have a look at documentation for this and inspect these lines in docker-compose.yml: expose:

Which is different than standard docker compose

Chacsam commented 2 months ago

I have tried a few things, like declaring ports the standard way in my docker-compose (with our without forced network declaration), but always the same result. Also adding the tesla_http_proxy service in my main NPM docker-compose didn't help. :-( Will therefore need to keep looking

One attemp: could it come from a wrong docker host name in the config.sh file? I am not sure about "PROXY_HOST=Proxy", but Proxy is what I have found in portainer. (it's the name I gave the CT when creating it in Proxmox)

iainbullock commented 2 months ago

The PROXY_HOST in config.sh is used to sign selfsigned.pem. It doesn't explain why you can't make a connection to the Flask Server from outside the container

Things you could try is:

Chacsam commented 2 months ago

NPM is on port 443, that one I can hardly change. I don't see anything on port 8099.

Network_mode on host gives (a normal error)

Starting Tesla HTTP Proxy

Do not listen on a network interface without adding client authentication. Unauthorized clients may
be used to create excessive traffic from your IP address to Tesla's servers, which Tesla may respond
to by rate limiting or blocking your connections.
2024-05-04T09:04:46Z [debug] Creating proxy
2024-05-04T09:04:46Z [info ] Listening on 0.0.0.0:443
2024-05-04T09:04:46Z [error] Server stopped: listen tcp 0.0.0.0:443: bind: address already in use
iainbullock commented 2 months ago

Ok so port 443 is already used on the host. The container uses 443 internally for the proxy, but the standard docker compose remaps it to 4430 on the host. When you tried earlier to 'declare ports the standard way in my docker-compose' did you remap 443 to 4430 or to 443?

Chacsam commented 2 months ago

to 443, shall I remap to 4430?

iainbullock commented 2 months ago

Yes please try that to avoid clash with the host

Chacsam commented 2 months ago

You mean this, right?

services:
  tesla_http_proxy:
    container_name: tesla_http_proxy
    image: "iainbullock/tesla_http_proxy:latest"
    network_mode: host
    ports:
      - '8089:8089' 
      - '4430:4430'

I still have the same bind error

Starting Tesla HTTP Proxy

Do not listen on a network interface without adding client authentication. Unauthorized clients may
be used to create excessive traffic from your IP address to Tesla's servers, which Tesla may respond
to by rate limiting or blocking your connections.
2024-05-04T09:31:20Z [debug] Creating proxy
2024-05-04T09:31:20Z [info ] Listening on 0.0.0.0:443
2024-05-04T09:31:20Z [error] Server stopped: listen tcp 0.0.0.0:443: bind: address already in use
iainbullock commented 2 months ago

Sorry I should have said change back to bridge mode as host mode won't work, and remap as follows:

network_mode: bridge
ports:
  - 8089:8089
  - 4430:443
Chacsam commented 2 months ago

Still no luck.

I did clean everything up for a fresh start,

Container runs Docker ps says:

CONTAINER ID   IMAGE                                 COMMAND                  CREATED             STATUS                PORTS                                                                                            NAMES
8f9d014a6184   iainbullock/tesla_http_proxy:latest   "/app/run.sh"            11 minutes ago      Up 9 minutes          0.0.0.0:8089->8089/tcp, :::8089->8089/tcp, 0.0.0.0:4430->443/tcp, :::4430->443/tcp               tesla_http_proxy
0f3c4efd45cd   jc21/nginx-proxy-manager:latest       "/init"                  About an hour ago   Up About an hour      0.0.0.0:80-81->80-81/tcp, :::80-81->80-81/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp             NPMproxy
...

Log says:

Setting up GnuPG and password-store
gpg: keybox '/data/gnugpg/pubring.kbx' created
gpg: /data/gnugpg/trustdb.gpg: trustdb created
gpg: directory '/data/gnugpg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/data/gnugpg/openpgp-revocs.d/xxxxxxxx.rev'
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2027-05-04
/data/gnugpg/pubring.kbx
------------------------
pub   ed25519 2024-05-04 [SC] [expires: 2027-05-04]
      xxxxxxxxxx
uid           [ultimate] myself
sub   cv25519 2024-05-04 [E]

created directory: '/data/password-store/'
Password store initialized for myself
Generating keypair
-----BEGIN PUBLIC KEY-----
xxxx+ORZ36DQNxxxxxxxxxxCABw1j6
xxxxxxxxx//xxxx==
-----END PUBLIC KEY-----
SSL certificate does not exist
Generating self-signed SSL certificate
-----
Starting temporary Python app for authentication flow. Delete /data/access_token to force regeneration in the future
[09:58:23] main:INFO: *** Starting Flask server... ***
[09:58:23] werkzeug:INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:8099
 * Running on http://172.17.0.4:8099
[09:58:23] werkzeug:INFO: Press CTRL+C to quit

But still the same http 502 error and no access from within container

8f9d014a6184:/app# wget http://192.168.11.210:8089
Connecting to 192.168.11.210:8089 (192.168.11.210:8089)
wget: error getting response: Connection reset by peer

I also fully turned off the firewall on Proxmox at datacenter level to test a few minutes, but that didn't change anything

iainbullock commented 2 months ago

I've run out of ideas to be honest. Not using Proxmox or NPM makes difficult for me to offer other suggestions. There is something blocking connections between the host and the container. If you do manage to figure it out please update here

Chacsam commented 2 months ago

I figured so, am a bit getting desperate as well. Again, thanks for trying all this time. I will update here if I find light

Chacsam commented 2 months ago

No solution, but additional information for anyone who would have a clue. I have created the docker in a brand new proxmox CT with only Docker and Portainer on it.

I made a quick and dirty setup on host network:

version: '3.0'

services:
  tesla_http_proxy:
    container_name: tesla_http_proxy
    image: "iainbullock/tesla_http_proxy:latest"
    network_mode: host

    environment:
      - TZ='Europe/Amsterdam'

    stdin_open: true
    tty: true         

    entrypoint: "/app/run.sh"
    working_dir: /app

    volumes:
      - /root/proxy_app/tesla_http:/data
      - /root/proxy_app/nginx_share:/share/nginx
      - /root/proxy_app/ha_config:/share/home-assistant

    restart: unless-stopped

I can access the tesla_http_proxy page from the host on which NPM is running:

wget http://192.168.11.225:8099
--2024-05-04 13:53:42--  http://192.168.11.225:8099/
Connecting to 192.168.11.225:8099... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1704 (1.7K) [text/html]
Saving to: 'index.html'

Which is nicely registered in the log of tesla_http_proxy [11:53:42] werkzeug:INFO: 192.168.11.210 - - [04/May/2024 11:53:42] "GET / HTTP/1.1" 200 -

But I cannot access it from my Desktop browser, neither on http://192.168.11.225:8099 nor via NPM proxy I am getting a ERR_CONNECTION_TIMED_OUT from the browser and a 504 gateway timeout via NPM

If I disable the Proxmox Firewall at Datacenter level (there is no firewall activated at CT level) the timeout becomes ERR_CONNECTION_REFUSED (ie a 502 via NPM)

mekaneck commented 2 months ago

@Chacsam maybe you better start at the basics: what docker network settings to you use for NPM, and what docker network settings do you use for containers that you successfully have proxied with NPM?

Chacsam commented 2 months ago

@Chacsam maybe you better start at the basics: what docker network settings to you use for NPM, and what docker network settings do you use for containers that you successfully have proxied with NPM?

Hi @mekaneck My NPM manages a dozen of proxy hosts successfully forwarding traffic to my Synology NAS or different Proxmox CT's or VM's with applications such as Nextcloud, Home Assistant, Grocy,, Immich... This is really the first one I cannot get connected. So I believe the basics are right, but any suggestion is welcome

mekaneck commented 2 months ago

@Chacsam Yes I figured as much. Can you share how those are set up so that I can make some suggestions for setting up this container?

Chacsam commented 2 months ago

@mekaneck My base setup has been described above: https://github.com/iainbullock/tesla-http-proxy-docker/issues/40#issuecomment-2088042547

My NPM docker-compose looks like this

services:
  app:
    container_name: NPMproxy
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      # These ports are in format <host-port>:<container-port>
      - '80:80' # Public HTTP Port
      - '443:443' # Public HTTPS Port
      - '81:81' # Admin Web Port
    environment:
      # Mysql/Maria connection parameters:
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "xxxxxfx"
      DB_MYSQL_PASSWORD: "xxxxxxx"
      DB_MYSQL_NAME: "xxxxxxxx"
      TZ: "Europe/Amsterdam"
    volumes:
      - /home/frederic/npm_proxy/data:/data
      - /home/frederic/npm_proxy/letsencrypt:/etc/letsencrypt

NPM is running on the npm_proxy_default network.

mekaneck commented 2 months ago

so if you have your container setup in comment #40, your forward hostname/IP setting in NPM should be tesla_http_proxy instead of 192.168.1.210

Chacsam commented 2 months ago

so if you have your container setup in comment #40, your forward hostname/IP setting in NPM should be tesla_http_proxy instead of 192.168.1.210

Thank you! That did the trick. I have been able to configure the http proxy.

Now, a small issue in Home Assistant, where the setup of the car was claimed as succesful, but it keeps reinitializing as it fails to configure.

The log doesn't help me much. Only that certificate seems to come from some Turkish corporation, does it sound right?

2024-05-06 08:28:29.577 DEBUG (MainThread) [custom_components.tesla_custom] Trusting CA: {'subject': ((('countryName', 'TR'),), (('localityName', 'Gebze - Kocaeli'),), (('organizationName', 'Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK'),), (('organizationalUnitName', 'Kamu Sertifikasyon Merkezi - Kamu SM'),), (('commonName', 'TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1'),)), 'issuer': ((('countryName', 'TR'),), (('localityName', 'Gebze - Kocaeli'),), (('organizationName', 'Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK'),), (('organizationalUnitName', 'Kamu Sertifikasyon Merkezi - Kamu SM'),), (('commonName', 'TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1'),)), 'version': 3, 'serialNumber': '01', 'notBefore': 'Nov 25 08:25:55 2013 GMT', 'notAfter': 'Oct 25 08:25:55 2043 GMT'}
2024-05-06 08:28:29.593 DEBUG (MainThread) [teslajsonpy.controller] 552 endpoints loaded
2024-05-06 08:28:29.593 DEBUG (MainThread) [teslajsonpy.connection] Token expiration in -19850 days, 15:31:31
2024-05-06 08:28:29.593 DEBUG (MainThread) [teslajsonpy.connection] Oauth expiration detected
2024-05-06 08:28:29.593 DEBUG (MainThread) [teslajsonpy.connection] Refreshing access token with refresh_token
2024-05-06 08:28:30.048 DEBUG (MainThread) [teslajsonpy.connection] Saved new auth info {'access_token': 'eXXXrA', 'refresh_token': 'EU_xxx6', 'expires_in': 1715012909}
2024-05-06 08:28:30.048 DEBUG (MainThread) [teslajsonpy.connection] Successfully refreshed oauth
2024-05-06 08:28:30.049 DEBUG (MainThread) [teslajsonpy.connection] get: https://proxy:4430/api/1/products {}
2024-05-06 08:28:31.723 DEBUG (MainThread) [teslajsonpy.connection] Token expiration in 7:59:59
2024-05-06 08:28:31.724 DEBUG (MainThread) [teslajsonpy.connection] get: https://proxy:4430/api/1/products {}
2024-05-06 08:28:34.138 DEBUG (MainThread) [teslajsonpy.connection] Token expiration in 7:59:56
2024-05-06 08:28:34.138 DEBUG (MainThread) [teslajsonpy.connection] get: https://proxy:4430/api/1/products {}
2024-05-06 08:28:39.123 DEBUG (MainThread) [teslajsonpy.connection] Token expiration in 7:59:51
2024-05-06 08:28:39.123 DEBUG (MainThread) [teslajsonpy.connection] get: https://proxy:4430/api/1/products {}
2024-05-06 08:28:44.594 DEBUG (MainThread) [teslajsonpy.connection] Token expiration in 7:59:46
2024-05-06 08:28:44.595 DEBUG (MainThread) [teslajsonpy.connection] get: https://proxy:4430/api/1/products {}
iainbullock commented 2 months ago

Not sure about the Turkish Certificate Authority - that's coming from the https://github.com/alandtse/tesla custom component. I don't recall what I got at this stage.

Is the HA custom component failing to intialise? Do you get a dialog box with error message on HA? Can you advise what parameters you enterred into setup dialog box for the custom component?

If you haven't done already it might be worth testing the proxy from the command line on your host, e.g. (assuming I got the paths right for your setup):

cd /root/proxy_app/tesla_http export TESLA_AUTH_TOKEN='cat access_token' curl --cacert cert.pem --header "Authorization: Bearer $TESLA_AUTH_TOKEN" "https://url_of_your_proxy:4430/api/1/vehicles"

The access_token has probably expired, but at least it will test the connection to the proxy

Chacsam commented 2 months ago

Thanks for the trick.

It seems indeed I cannot get te right hots_name for my proxy server (I tried various option, the host name of the host on which NPM and the tesla proxy are running is "Proxy" according to portainer)

curl --cacert cert.pem --header "Authorization: Bearer $TESLA_AUTH_TOKEN" "https://Proxy:4430/api/1/vehicles"
curl: (7) Failed to connect to Proxy port 4430 after 1 ms: Connection refused

curl --cacert cert.pem --header "Authorization: Bearer $TESLA_AUTH_TOKEN" "https://tesla_http_proxy:4430/api/1/vehicles"
curl: (7) Failed to connect to tesla_http_proxy port 4430 after 24 ms: Connection refused

curl --cacert cert.pem --header "Authorization: Bearer $TESLA_AUTH_TOKEN" "https://proxy:4430/api/1/vehicles"
curl: (7) Failed to connect to proxy port 4430 after 0 ms: Connection refused
iainbullock commented 2 months ago

The host name should be the hostname of your docker host (although in your case I believe that's the NPM host). Sorry if I caused confusion in my last post.

What is the IP address of your docker / NPM host? We can do a reverse lookup to see if your DNS has a hostname for it. e.g. in my case the docker host is 192.168.21.5, so I run this to do a reverse lookup:

nslookup 192.168.21.5

which gives:

5.21.168.192.in-addr.arpa name = macmini.home.

Authoritative answers can be found from:

I can then check the forward lookup works:

nslookup macmini.home

which gives:

Server: 127.0.0.53 Address: 127.0.0.53#53

Non-authoritative answer: Name: macmini.home Address: 192.168.21.5

I therefore use https://macmini.home:4430 as the URL for curl

Lets get this working for you before proceeding further!

Chacsam commented 2 months ago

No confusion at all, I am the one with a strange problem. (and it's clearly somewhere on my network)

I tried the nslookup (I am learning a lot here), and got first an internal redirect to the FQDN of my dashboard coming from my pihole setup. So, to avoid any disturbance, I shut down the pihole container, changed my dns on my router back to google dns and tried again.

From the NPM host itself (192.168.11.210):

nslookup 192.168.11.210
** server can't find 210.11.168.192.in-addr.arpa: NXDOMAIN

From my windows desktop:

nslookup 192.168.11.210
Serveur :   dns.google
Address:  8.8.8.8
*** dns.google can't find 192.168.11.210 : Non-existent domain

From within the tesla_http_proxy docker container:

nslookup 192.168.11.210
Server:         127.0.0.11
Address:        127.0.0.11:53

** server can't find 210.11.168.192.in-addr.arpa: NXDOMAIN

A nslookup on devices outside my Proxmox environment works, so I guess there is something there... A ping on these IP's does give response. I temporarly turned off firewall on Proxmox, that didn't help either

iainbullock commented 2 months ago

You need to create a hostname / IP address mapping for your docker / NPM host on your network. Let's call it proxy.home We therefore need proxy.home to resolve to 192.168.11.210

There are various ways of doing this. For a home network there is often an option on your router to map local hostnames to IP addresses (might be called static DNS).

I note that your network clients are using google (8.8.8.8) directly for DNS rather than your router providing DNS. That's not a problem but probably means that any static DNS entries you create on your router won't resolve on your network.

Another approach is to use /etc/hosts on the docker NPM host. Just add a line at the bottom of the file like this:

192.168.11.210 proxy.home

Then test using nslookup again:

nslookup proxy.home

If that resolves to 192.168.11.210, then that's good

Then try the curl again using https://proxy.home:4430 as the URL

I'm traveling again so might be slow to respond

Chacsam commented 2 months ago

okay... so, I guess there is something linked to Proxmox DNS management as it adds the following in /etc/hosts (host name in proxmox is proxy.l11)

# --- BEGIN PVE ---
192.168.11.210 proxy.l11 proxy
# --- END PVE ---

but...

nslookup proxy.l11 
Server:         192.168.11.1
Address:        192.168.11.1#53

** server can't find proxy.l11: NXDOMAIN

So I added the redirect on proxy.home in my (pihole) dns server (as the /etc/hosts method didn't seem to work)

nslookup proxy.home
Server:         192.168.11.1
Address:        192.168.11.1#53

Name:   proxy.home
Address: 192.168.11.210

looking good, also

nslookup 192.168.11.210
210.11.168.192.in-addr.arpa     name = proxy.home.

But the curl didn't work

# curl --cacert cert.pem --header "Authorization: Bearer $TESLA_AUTH_TOKEN" "https://proxy.home:4430/api/1/vehicles"
curl: (7) Failed to connect to proxy.home port 4430 after 3 ms: Connection refused
# curl --cacert cert.pem --header "Authorization: Bearer $TESLA_AUTH_TOKEN" "https://proxy.l11:4430/api/1/vehicles"
curl: (7) Failed to connect to proxy.l11 port 4430 after 0 ms: Connection refused

Don't know if this (on 443) helps:

# curl --cacert cert.pem --header "Authorization: Bearer $TESLA_AUTH_TOKEN" "https://proxy.home:443/api/1/vehicles"
curl: (35) error:0A000458:SSL routines::tlsv1 unrecognized name
# curl --cacert cert.pem --header "Authorization: Bearer $TESLA_AUTH_TOKEN" "https://proxy.l11:443/api/1/vehicles"
curl: (35) error:0A000458:SSL routines::tlsv1 unrecognized name
iainbullock commented 2 months ago

I think you've fixed the DNS issues so that's good.

Which port do you have mapped on your docker / NPM host to port 443 on the proxy container? The standard setup is having port 4430 mapped to 443. This is specified in docker-compose.yml.

Port 443 on the host would normally be for a webserver of some type e.g. nginx (and so might respond with SSL routines::tlsv1 unrecognized name)

I assume you resolved the connection issue you were having to port 8099 that you reported previously? Maybe you need to do the same fix for port 4430?

Chacsam commented 2 months ago

[Edit: At some point, while I was noting the issues, it started working (Home Assistant kept trying to reinitialize in the background, so I'll pout a summary of changes I made as it might help someone]

OK, learnings from my configuration.

Source problem seemed to be in DNS management, so

As per @mekaneck advise, I did forward hostname/IP setting in NPM to tesla_http_proxy instead of the 192.168.11.210 IP, which solved connection issues.

My final docker compose is a mix of @menaleck's initial share, combined with a bridge of the ports.

version: '3.0'

networks:
  default:
    external: true
    name: npm_proxy_default

services:
  tesla_http_proxy:
    container_name: tesla_http_proxy
    image: "iainbullock/tesla_http_proxy:latest"

    ports:           # change to initial docker-compose  
      - "8099:8099"  # change to initial docker-compose
      - "4430:443"   # change to initial docker-compose

#     expose:        # commented out from initial docker-compose
#       - 443          # commented out from initial docker-compose
#       - 8099        # commented out from initial docker-compose

    environment:
      - TZ='Europe/Amsterdam'

    stdin_open: true
    tty: true         

    entrypoint: "/app/run.sh"
    working_dir: /app

    volumes:
      - /home/app/tesla_http_proxy:/data
      - /home/app/npm_proxy/data/tesla_http_proxy:/share/nginx
      - /home/app/ha_proxy/config/tesla_http_proxy:/share/home-assistant

    restart: unless-stopped

My config.sh looks like this

#!/bin/ash
# Enter values for your particular configuration here
CLIENT_ID='xxx'
CLIENT_SECRET='xxx'
DOMAIN='teslaapi.xxxxxxx.com' # Public FQDN 
PROXY_HOST='proxy.home' # Local hostname (not IP) of this docker host
REGION='Europe, Middle East, Africa' # Change to match your region
# Change this to OPTIONS_COMPLETE=1 when ready to run
OPTIONS_COMPLETE=1

I followed the 5-step instructions in the app.

Then, based on @andjo's method, I copied manually the selfsigned.pem file created in /home/app/ha_proxy/config/tesla_http_proxy on my NPM host to my home assisstant host in /config/tesla_http_proxy/

And I set it up in Home Assistant with following parameters:

For some reason, it tried to initialize several times during a few minutes before working, but now it's up and running.

Thank you @mekaneck and @andjo for the initial tips; A big thank you to @iainbullock for his patience and guidance these last days

iainbullock commented 2 months ago

@Chacsam well done for perseverence! You got there in the end, and probably learnt a lot in the process.