Spring Boot REST application with JWT security, static page hosting, MySQL persistence, and Tesla Fleet API command endpoints.
- Hosts static HTML from
src/main/resources/staticonhttp://localhost:8081/. - Exposes a Tesla public key file for domain verification.
- Connects to a local MySQL database from either the IDE or Docker.
- Stores Tesla token, client, and vehicle data in MySQL.
- Calls Tesla Fleet API directly for vehicle lookup and wake-up.
- Calls the configured Tesla proxy for vehicle commands.
- Java 21
- Spring Boot 4.0.6
- Spring Security
- Spring Data JPA
- MySQL 8
- Flyway migrations
- Jakarta Validation
- Lombok
- Maven
- Docker
Start MySQL on your machine first. The default database config is:
DB_HOST=localhost
DB_PORT=3306
DB_NAME=tesla
DB_USERNAME=root
DB_PASSWORD=root
JWT_PUBLIC_KEY_PATH=C:\path\to\jwt-public-key.pem
JWT_AUDIENCES=auth-clientsBuild and run:
mvn clean package -DskipTests
mvn spring-boot:runOpen:
http://localhost:8081/
When the app runs in Docker, localhost points to the container, not your laptop. The Docker image uses host.docker.internal by default so the container can reach MySQL running on your host machine.
Build:
docker build -t tesla-dashboard-services .Run:
docker run -d --name tesla-dashboard-services -p 8081:8081 tesla-dashboard-services:latestRun with explicit database settings:
docker run -d --name tesla-dashboard-services -p 8081:8081 ^
-e DB_HOST=host.docker.internal ^
-e DB_PORT=3306 ^
-e DB_NAME=tesla ^
-e DB_USERNAME=root ^
-e DB_PASSWORD=root ^
-e TESLA_PROXY_BASE=https://host.docker.internal:4443 ^
-e JWT_PUBLIC_KEY_PATH=/keys/jwt-public-key.pem ^
-v C:\path\to\keys:/keys:ro ^
tesla-dashboard-services:latestOn Linux, add the host gateway mapping:
docker run -d --name tesla-dashboard-services ^
--add-host=host.docker.internal:host-gateway ^
-p 8081:8081 tesla-dashboard-services:latestApplication settings are in src/main/resources/application.properties. Runtime values can be overridden with environment variables.
| Property | Environment Variable | Default |
|---|---|---|
server.port |
SERVER_PORT if added manually |
8081 |
spring.datasource.url |
DB_HOST, DB_PORT, DB_NAME |
jdbc:mysql://localhost:3306/tesla |
spring.datasource.username |
DB_USERNAME |
root |
spring.datasource.password |
DB_PASSWORD |
root |
tesla.fleet-api-base |
TESLA_FLEET_API_BASE |
https://fleet-api.prd.na.vn.cloud.tesla.com |
tesla.proxy-base |
TESLA_PROXY_BASE |
https://127.0.0.1:4443 |
tesla.auth-token-url |
TESLA_AUTH_TOKEN_URL |
https://auth.tesla.com/oauth2/v3/token |
tesla.vehicle-id-or-vin |
TESLA_VEHICLE_ID_OR_VIN |
empty |
tesla.default-token-id |
TESLA_DEFAULT_TOKEN_ID |
1 |
tesla.token-refresh-skew-minutes |
TESLA_TOKEN_REFRESH_SKEW_MINUTES |
2 |
app.jwt.public-key-path |
JWT_PUBLIC_KEY_PATH |
empty |
app.jwt.public-key-base64 |
JWT_PUBLIC_KEY_BASE64 |
empty |
app.jwt.audiences |
JWT_AUDIENCES or JWT_AUDIENCE |
auth-clients |
The Tesla URLs are not hardcoded in service code. TeslaService reads them through TeslaProperties.
| URL | Description |
|---|---|
GET / |
Static home page from static/index.html |
GET /api/hello |
Simple application health-style response |
GET /.well-known/appspecific/com.tesla.3p.public-key.pem |
Tesla public key file |
GET /api/.well-known/appspecific/com.tesla.3p.public-key.pem |
API-prefixed Tesla public key file |
GET /api/tesla/vehicles |
Fetches vehicles from Tesla Fleet API |
GET /api/tesla/status |
Reads combined lock and charging status |
GET /api/tesla/status/lock |
Reads whether the vehicle is locked or unlocked |
GET /api/tesla/status/charging |
Reads whether the vehicle is charging |
POST /api/tesla/wake |
Wakes the configured vehicle |
POST /api/tesla/flash-lights |
Flashes vehicle lights |
POST /api/tesla/honk |
Honks horn |
POST /api/tesla/lock |
Locks doors |
POST /api/tesla/unlock |
Unlocks doors |
POST /api/tesla/climate/start |
Starts climate |
POST /api/tesla/climate/stop |
Stops climate |
POST /api/tesla/trunk/open |
Opens rear trunk |
POST /api/tesla/frunk/open |
Opens front trunk |
POST /api/tesla/start/charging |
Starts charging |
POST /api/tesla/stop/charging |
Stops charging |
POST /api/tesla/cmd?command=<tesla_command> |
Sends a custom command |
This project uses Cloudflare Tunnel for the public domain, not ngrok.
Create or route the DNS name to your Cloudflare tunnel:
cloudflared tunnel route dns test vinodbalakumar.comStart the Cloudflare tunnel so the public domain points to the local Spring Boot app on port 8081:
cloudflared tunnel run testThe public Cloudflare URL should route to:
http://localhost:8081
Keep the Tesla HTTP proxy running separately on 127.0.0.1:4443:
.\tesla-http-proxy.exe `
-key-file config\private-key.pem `
-cert localhost-cert.pem `
-tls-key localhost-key.pem `
-host 127.0.0.1 `
-port 4443 `
-verboseCloudflare should expose the Spring Boot app on port 8081. Do not point Cloudflare to the Tesla proxy TLS port 4443; that proxy is only used internally by TeslaService when sending signed vehicle commands.
If http://localhost:8081 does not open:
docker ps --filter "name=tesla-dashboard-services"
docker logs --tail 100 tesla-dashboard-servicesIf Docker cannot connect to MySQL:
- Make sure MySQL is running on the host.
- Make sure the
tesladatabase exists. - Make sure the configured MySQL user can connect over TCP.
- In Docker, use
DB_HOST=host.docker.internal, notlocalhost.
If Docker cannot connect to the Tesla HTTP proxy:
- In Docker, use
TESLA_PROXY_BASE=https://host.docker.internal:4443, nothttps://127.0.0.1:4443. - Confirm the proxy is running on the host with
Get-NetTCPConnection -LocalPort 4443. - From inside the container,
127.0.0.1is the container itself, not your Windows host.
If the Tesla public key fails:
- Confirm the file exists at
src/main/resources/static/.well-known/appspecific/com.tesla.3p.public-key.pem. - Rebuild the Docker image after changing static files.
- Test
http://localhost:8081/.well-known/appspecific/com.tesla.3p.public-key.pem.
If Cloudflare domain requests do not reach the app:
- Confirm the app is running on
http://localhost:8081. - Confirm
cloudflared tunnel run testis still running. - Confirm the DNS route exists for
vinodbalakumar.com. - Confirm Cloudflare routes to port
8081, not proxy port4443. - Check app logs with
docker logs --tail 100 tesla-dashboard-services.
Use this before deploying:
mvn clean package -DskipTests
docker build -t tesla-dashboard-services .
docker run -d --name tesla-dashboard-services -p 8081:8081 tesla-dashboard-services:latestSmoke test:
curl -H "Authorization: Bearer <super-admin-token>" http://localhost:8081/
curl -H "Authorization: Bearer <super-admin-token>" http://localhost:8081/api/hello
curl -H "Authorization: Bearer <super-admin-token>" http://localhost:8081/.well-known/appspecific/com.tesla.3p.public-key.pem