> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nolongerevil.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-Hosted Troubleshooting

> Solutions to common issues when self-hosting No Longer Evil

## Installation Issues

<AccordionGroup>
  <Accordion title="Docker containers won't start" icon="docker">
    **Symptoms**: `docker ps` shows no running containers

    **Solutions**:

    1. **Check Docker is running**:
       ```bash theme={null}
       sudo systemctl status docker  # Linux
       # or check Docker Desktop is running on macOS
       ```

    2. **View container logs**:
       ```bash theme={null}
       docker logs nolongerevil-server
       ```

    3. **Check for port conflicts**:
       ```bash theme={null}
       sudo lsof -i :8000  # Check if port 8000 is in use
       sudo lsof -i :8082  # Check if port 8082 is in use
       ```

    4. **Restart Docker**:
       ```bash theme={null}
       sudo systemctl restart docker  # Linux
       # or restart Docker Desktop on macOS
       ```
  </Accordion>

  <Accordion title="Build dependencies failed to install" icon="exclamation-triangle">
    **Ubuntu/Debian**:

    ```bash theme={null}
    sudo apt-get update
    sudo apt-get install --fix-missing build-essential libusb-1.0-0-dev gcc pkg-config
    ```

    **macOS**:

    ```bash theme={null}
    # Make sure Homebrew is up to date
    brew update
    brew doctor
    brew install libusb pkg-config
    ```
  </Accordion>
</AccordionGroup>

***

## Thermostat Flashing Issues

<AccordionGroup>
  <Accordion title="Device won't enter DFU mode (Gen 2)" icon="usb">
    **Try these steps in order**:

    1. **Back plate sequence first** — Attach to wall mount, wait 2–3 seconds, then remove. The back plate contact arms DFU mode.
    2. **Connect USB immediately after removing from back plate** — Use a data-capable cable (not charge-only)
    3. **Charge battery** — Ensure >50% battery
    4. **Reboot** — Hold display for 10-15 seconds

    See [DFU Mode Troubleshooting](/hosted/troubleshooting#dfu-mode-issues) for more details
  </Accordion>

  <Accordion title="Gen 1 contact bridging not working" icon="screwdriver-wrench">
    **Common issues**:

    * Contacts not held long enough - Keep bridging until USB connects
    * Wrong contacts bridged - Double-check the image in the guide
    * Battery disconnected - Device won't boot without battery
    * Screen still on - Make sure screen is off before bridging

    **Solution**: Try multiple times, ensuring:

    * Battery is connected
    * Screen is off
    * Installer is waiting
    * Bridge contacts, THEN connect USB while holding bridge
  </Accordion>

  <Accordion title="Installer doesn't detect device" icon="computer">
    **Linux**:

    1. **Check USB permissions** — run the installer app with sudo:
       ```bash theme={null}
       sudo ./NoLongerEvil-*.AppImage
       ```

    2. **Add udev rules** for a permanent fix:
       ```bash theme={null}
       echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="0451", MODE="0666"' | sudo tee /etc/udev/rules.d/99-omap.rules
       sudo udevadm control --reload-rules
       ```

    **macOS**:

    * Grant USB permissions in System Preferences → Security & Privacy

    **Both**:

    * Try different USB cable (must be data-capable)
    * Try different USB port

    **Back plate sequence reminder**: Attach to back plate (2–3 sec) → remove → plug USB. This must be repeated for each flash attempt. If you plugged USB without the back plate step, the device booted normally instead of entering DFU mode.
  </Accordion>
</AccordionGroup>

***

## Server Connection Issues

<Note>
  The NLE server is a standalone service, separate from the firmware flashing tool.
  It runs as a Docker container using the image `ghcr.io/codykociemba/nolongerevil-selfhosted:latest`,
  as a Python service, or as a Home Assistant add-on. See the [self-hosted installation guide](/self-hosted/installation)
  for server setup instructions.
</Note>

<Warning>
  **Home Assistant Add-on users:** The add-on's external device port is **9543** (not 8000).
  The thermostat must be configured to reach `http://[HA-IP]:9543`.

  If your thermostat isn't connecting: verify `api_origin` in the add-on's Configuration tab
  is set to an IP address, not `homeassistant.local`.

  The control dashboard (port 8082) is only accessible via the HA sidebar (Ingress) by default.
  To expose it directly, go to Settings → Add-ons → No Longer Evil → Configuration → Network
  and assign a host port to container port 8082.
</Warning>

<AccordionGroup>
  <Accordion title="Thermostat can't connect to server" icon="plug-circle-xmark">
    **Check**:

    1. **API server is running**:
       ```bash theme={null}
       docker ps | grep nolongerevil
       curl http://localhost:8082/health  # Should respond
       ```

    2. **Firewall allows connections**:
       ```bash theme={null}
       sudo ufw allow 8000  # Linux
       sudo ufw allow 8082
       ```

    3. **Port forwarding configured** (if remote access):
       * Check router settings
       * Verify ports 8000 and 8082 are forwarded to your server

    4. **DNS resolves correctly** (if using domain):
       ```bash theme={null}
       nslookup your-domain.com
       ```

    5. **Thermostat can reach server**:
       * Check WiFi connection on thermostat
       * Verify thermostat is on same network (for local-only setup)
  </Accordion>

  <Accordion title="Thermostat not connecting to self-hosted server" icon="network-wired">
    **Symptoms**: Thermostat shows No Longer Evil firmware but connects to cloud, or shows "No Server"

    **Method 1 — NLEAPI (easier, web-based):**

    The thermostat exposes a configuration API at port 8080. Navigate to:

    ```
    http://[THERMOSTAT-IP]:8080/cgi-bin/api/settings
    ```

    Find `cloudregisterurl` in the settings and update it to your server's `/entry` endpoint:

    * Standalone Docker: `http://[SERVER-IP]:8000/entry`
    * HA Add-on: `http://[HA-IP]:9543/entry`

    You can find the exact URL by querying your server's info endpoint:

    ```
    http://[SERVER-IP]:[PORT]/info
    ```

    > **Password protection:** If the thermostat has been powered on for more than 30 minutes,
    > the NLEAPI is protected by a password. To find the password, SSH into the thermostat and
    > read `/etc/nestlabs/apikey.txt`:
    >
    > ```bash theme={null}
    > ssh root@[THERMOSTAT-IP]   # default password: nolongerevil
    > cat /etc/nestlabs/apikey.txt
    > ```
    >
    > Use this value as the password when the NLEAPI prompts for authentication.

    After saving, reboot the thermostat.

    ***

    **Method 2 — SSH / direct file edit (fallback):**

    ```bash theme={null}
    ssh root@[THERMOSTAT-IP]
    # Default password: nolongerevil
    vi /etc/nestlabs/client.config
    ```

    Find the `cloudregisterurl` entry and update the value to your server's `/entry` endpoint
    (same values as Method 1 above).

    Save with `:wq`, then reboot:

    ```bash theme={null}
    reboot
    ```

    After reboot: Settings (gear icon) → Nest App → Get Entry Key (only needed if `REQUIRE_DEVICE_PAIRING=true`).
  </Accordion>

  <Accordion title="SSL/TLS certificate errors" icon="shield-xmark">
    **Self-signed certificates**:
    If using self-signed certs, browsers will warn. You can:

    * Use Let's Encrypt for free valid certificates
    * Accept the browser warning (not recommended for production)

    **Let's Encrypt setup**:

    ```bash theme={null}
    sudo apt-get install certbot
    sudo certbot certonly --standalone -d your-domain.com
    ```

    Then configure `CERT_DIR` in your Docker environment to point to the certificates in `/etc/letsencrypt/live/your-domain.com/`
  </Accordion>
</AccordionGroup>

***

## Docker Issues

<AccordionGroup>
  <Accordion title="Containers keep restarting" icon="rotate">
    **View logs to see why**:

    ```bash theme={null}
    docker logs nolongerevil-server
    ```

    **Common causes**:

    * Port already in use
    * Missing environment variables
    * Insufficient resources (RAM/CPU)
    * Database connection failed

    **Check resource usage**:

    ```bash theme={null}
    docker stats
    ```
  </Accordion>

  <Accordion title="Can't access containers from host" icon="network-wired">
    **Check port mappings**:

    ```bash theme={null}
    docker ps
    ```

    Look for `0.0.0.0:8000->8000/tcp` and `0.0.0.0:8082->8082/tcp`

    **If ports aren't mapped**, recreate containers with proper port mapping:

    ```bash theme={null}
    docker run -p 8000:8000 -p 8082:8082 ...
    ```
  </Accordion>

  <Accordion title="Out of disk space" icon="hard-drive">
    **Check Docker disk usage**:

    ```bash theme={null}
    docker system df
    ```

    **Clean up unused resources**:

    ```bash theme={null}
    docker system prune -a
    docker volume prune
    ```

    **Warning**: This will remove all stopped containers and unused images
  </Accordion>
</AccordionGroup>

***

## Network & Remote Access

<AccordionGroup>
  <Accordion title="Can't access server remotely" icon="globe">
    **Check these in order**:

    1. **Port forwarding configured**:
       * Log into your router
       * Forward ports 8000, 8082 to your server's local IP
       * Verify forwards are active

    2. **Firewall allows traffic**:
       ```bash theme={null}
       sudo ufw status
       sudo ufw allow 8000
       sudo ufw allow 8082
       ```

    3. **Public IP correct**:
       ```bash theme={null}
       curl ifconfig.me  # Shows your public IP
       ```

    4. **Dynamic DNS working** (if using DDNS):
       * Verify DNS record points to current IP
       * Check DDNS client is running and updating

    5. **ISP not blocking ports**:
       * Some ISPs block common ports
       * Try alternative ports or contact ISP
  </Accordion>

  <Accordion title="HTTPS not working" icon="lock">
    **Check certificate**:

    ```bash theme={null}
    sudo certbot certificates
    ```

    **Renew if expired**:

    ```bash theme={null}
    sudo certbot renew
    ```

    **Test HTTPS endpoint**:

    ```bash theme={null}
    curl -k https://your-domain.com  # -k skips cert validation
    ```

    **Common issues**:

    * Certificate not installed correctly
    * Server not configured for HTTPS (`CERT_DIR` env var not set)
    * Port 8000 not open
    * Domain doesn't match certificate
  </Accordion>
</AccordionGroup>

***

## Performance Issues

<AccordionGroup>
  <Accordion title="Server running slow" icon="gauge-high">
    **Check resource usage**:

    ```bash theme={null}
    top
    docker stats
    df -h  # Check disk space
    ```

    **Solutions**:

    * Allocate more resources to Docker
    * Enable `DEBUG_LOGGING=false` to reduce log overhead
    * Use faster storage (SSD vs HDD)
  </Accordion>

  <Accordion title="High memory usage" icon="memory">
    **Check which container is using memory**:

    ```bash theme={null}
    docker stats
    ```

    **Restart container to free memory**:

    ```bash theme={null}
    docker restart nolongerevil-server
    ```
  </Accordion>
</AccordionGroup>

***

## Still Having Issues?

<CardGroup cols={2}>
  <Card title="Join Discord" icon="discord" href="https://discord.gg/AffeGaJ5XS">
    Ask the self-hosting community for help
  </Card>

  <Card title="GitHub Issues" icon="github" href="https://github.com/codykociemba/NoLongerEvil-Thermostat/issues">
    Report bugs or check existing issues
  </Card>

  <Card title="Check Logs" icon="file-lines">
    Always check Docker logs first:

    ```
    docker logs nolongerevil-server
    ```
  </Card>

  <Card title="Hosted Service" icon="cloud" href="/hosted/overview">
    Consider using the hosted service if self-hosting is too complex
  </Card>
</CardGroup>
