Remote Access using a FritzBox & the AVM myFritz DDNS Service

Note: Typically you would use Wireguard VPN for remote access. This is easier, more secure and recommended. But with VPN you cannot use Alexa actionable notifications for example. Or if you don’t want to spin up VPN everytime before you access HA remotely then you need HTTPS access to it.

There are many community sources on how to do this with the duckdns add-on and I used it too. But I found duckdns unreliable. I had issues with it lately. But Fritzbox owners have another choice: MyFritz DDNS. I wanted to give it a try and see if it’s more reliable.

I have it running now for 9 months or so and didn’t have any problem so far. So I wrote down the steps on how I configured it for the benefit of those who want to try this out as well.

Prerequisites:
You do NOT have a full blown internet connection with a DS-Lite stack. DS-Lite does not provide you with a public IPv4 address. It is often provided by Vodafone Cable and 1&1.

Your installed HA system supports add-ons. You know how to install & configure add-ons and how to edit the configuration.yaml and automations.yaml files. You also know how to add blueprints to HA. You have a myFritz account and configured your Fritzbox to use it. You know how to configure port forwarding in your router and port 80 is available for port forwarding. You enabled “Advanced Mode” in your user profile. Otherwise not all HA config options are visible.

I. DDNS:

  1. login to your fritzbox and take a note of your myFritz address (xxxxxxxxx.myfritz.net). You will find this under Internet → MyFritz Account.
  2. If you don’t need it then disable HTTPS Remote Internet Access to your router. Internet → Freigaben → Fritzbox-Dienste
  3. Test if you can ping your router using the myFritz address: ping xxxxxxxxx.myfritz.net
  4. Optional but recommended: ping your domain from outside your network (e.g. use a smartphone and an app that allows you to ping, e.g. the Fing app on Android)
  5. If ping succeeds then myFritz DDNS is working.

II. Certificates:

  1. Install the Let’s Encrypt add-on in Home Assistant
  2. Configure the add-on: Use http for the challenge setting. The YAML based config should look like this:
  domains:
    - xxxxxxxxx.myfritz.net
  email: your-email@address
  keyfile: myfritzprivkey.pem
  certfile: myfritzfullchain.pem
  challenge: http
  dns: {}
  1. Leave the http challenge port at 80 or use a different one. I used 8001 because 80 is already used in my system.
  2. Important: configure port forwarding in your router so that the external port 80 points to port 80 (or whatever port you set in the previous step) on the home assistant host’s internal IP address. Note that it has to be port 80 externally!
  3. Start Let’s Encrypt.
  4. Check the log file to see if cert generation was successful. If so the certification files with your myFritz domain (xxxxxxxxx.myfritz.net) are now in your /ssl folder.
    These are valid for 90 days only. Note that the add-on will stop running after the certificates are created. If you run it again it will check whether or not the certs are still valid and if not it
    will generate new ones and then stop again.
  5. Later we will add a blueprint to HA to automatically run let’s encrypt to update the certs if needed.
  6. Note that port 80 is open on your router but there is no service running behind it. Only if the Let’s Encrypt add-on runs it uses this port for a short period of time and then stops.
    I’m not a security expert but as far as I understand an open port that is not used by any app is not a problem. Correct me if I am wrong.
    Anyway, there is a way to open the port only while the add-on is running.
    You can do this by installing the AVM FritzBox Tools integration which will expose one switch for every configured port forward (e.g. switch.fb7590_port_forward_letsencrypt).
    This switch allows you to enable/disable port forwarding for the let’s encrypt add-on.
    It can be used in an automation to turn port forwarding on, run the add-on and then turn port forwarding off again.

III. Reverse Proxy
This is not strictly required but I recommend it because when the certificates change you only need to restart the proxy and not Home Assistant itself. Big benefit.
The remaining steps assume that nginx is installed. Otherwise the HA configuration (step V) would be different and additional changes in your router would be required (DNS-Rebind).

  1. Install the nginx add-on. (called NGINX Home Assistant SSL proxy)
  2. Configure it. Use your myFritz domain and the certs we generated with the Let’s Encrypt add-on. The YAML version should look like this:
  domain: xxxxxxxxx.myfritz.net
  hsts: max-age=31536000; includeSubDomains
  certfile: myfritzfullchain.pem
  keyfile: myfritzprivkey.pem
  cloudflare: false
  customize:
    active: false
    default: nginx_proxy_default*.conf
    servers: nginx_proxy/*.conf
  1. Use standard nginx SSL port 443 (or change it if required)
  2. Start the add-on

IV. Port Forwarding to Nginx (Home Assistant)

  1. In the fritzbox add an additional port forward for the nginx add-on. I use 8123 (external) and forward it to the nginx SSL port 443 (see III.3).

V. Configure Home Assistant

  1. Add the following to your configuration.yaml. Note that you need to use the IP address range excatly as shown. Thes are the IP addresses that HAOS uses for the add-ons.
  http:
    use_x_forwarded_for: true
    trusted_proxies: 
      - 172.30.33.0/24
    ip_ban_enabled: true
    login_attempts_threshold: 5
  1. Add your myFritz domain to the Home Assistant URL in Setup → System → Network
  2. Restart HA

VI. Optional but highly recommended: Use 2FA for your HA users !

  1. In HA click your user name and enable Multi-Factor-Authentication. Use TOTP and an authenticator app like Authy for example.
  2. Do this for every HA user

Now you should be able to connect securely to Home Assistant from the Internet using this URL: https://xxxxxxxxx.myfritz.net:8123.
You need a user name, password and an additional time-based one-time password to login (if you enabled 2FA and you should!). Note that on your internal network you can still use http://your_internal_ip:8123 (http not https!)

VII. Finally we should add an automation to update the Let’s Encrypt certs if required and restart HA and/or nginx to pick up the new certificates For that you can use this great blueprint from TJ-developer:
https://community.home-assistant.io/t/blueprint-for-automatic-renewal-of-a-lets-encrypt-certificate/300533 This blueprint only allows you to restart HA. The modified version of this blueprint done by “mdeweerd” allows you to restart HA and/or nginx. I used this one and configured it to only restart nginx.

Note that these blueprints do not enable/disable port forwarding in your router as explained in II.8. You would need to add that to the blueprint if you believe this is required.

6 Likes

Hello, I have also made HA accessible via MyFRITZ! Unfortunately without https so far. The instructions for encryption are exactly what I have been looking for.

Super, many thanks

Thanks for letting me know that you find this useful. Übrigens, niemehrarbeiten als User name gefällt mir. :sweat_smile:

1 Like

I’m trying to follow this, but am getting the following error:

I can’t find a setting to allow this Certificate?

Some questions:
In the fritz.box I made these 2 port forwardings which create 4 entries:


Is this correct?

For nginx, also MariaDB must be installed (!) which I found out later.

In Step V.1, is the IP fix?

In Step V.2, in which format did you put the myFritz domain? I put ‘https://xxxxxx.myfritz.net:8123’. Is that correct?

Did the let’s encrypt add-on generate the certificates correctly?

You only need 2:
TCP external 8123 to internal port used for III.3 (default 443)
TCP external 80 to internal port used for II.3 (default 80)

No, if you use the add-on it includes everything you need. My instructions are valid for the nginx add-on. If you don’t use it your installation instructions are different and not covered above.

Yes

Yes

Yes I believe the certificates are correct:

The letsencrypt settings:

domains:
  - xxxxx.myfritz.net
email: [email protected]
keyfile: myfritzprivkey.pem
certfile: myfritzfullchain.pem
challenge: http
dns: {}

Here is the ssl folder where the certificates are stored:
grafik

The 2 bottom port forwards seem to be from the IPv6. I deleted those in the fritz.box.

These are the settings now:

The nginx add-on asks for the MariaDB in the description. It gave me an error when I installed it withou? https://github.com/hassio-addons/addon-nginx-proxy-manager/blob/43aa9f96a4283f3ef74055be8f4a1ddd1ee818e1/proxy-manager/DOCS.md Under installation 1)

It still does not work unfortunately.

I found my mistake!

I installed the Nginx Proxy Manager
What is needed is the NGINX Home Assistant SSL proxy!

grafik

It works now! Thanks for the help!

Looks like you are using a different nginx add-on :grimacing:. I was not aware that there are at least 2 add-ons. Mine does not ask for a MariaDB installation and it looks like this:

1 Like

I added the name of the add-on to my instructions to avoid confusions in the future.
Thanks.

1 Like

HI
what device or name you did use for the port forwarding in the FRITZ!Box?
I did try the myfritz Domain, the external address of my router which forwards the HAOS as well the public IP of the F!B. None did work.

THX Markus

Guess I got it. Your installation has setting the HAOS behind the F!B on a LAN Port of it.
If so, unfortunately my HAOS and my F!B are not on the same subnet or better said not even connected in any LAN/WLAN way.

That is correct.

ok thx…so I need to find another solution for my setting

I have been accessing HA remotely through the fritz!box DDNS service for many years. But using HTTP: not HTTPS:. I have also tried many times over the years to get HTTPS: access working, but never succeeded. I’m trying again, I think I’m close, but no cigar!

Did the port forwarding as shown by @SpaceGlider (very helpful, thank you!). The certificates have been generated and show in the ssl folder. I have set the HA URL.

When I try to remote access HA now using HTTP: I get a warning (from HA nginx) that it should be HTTPS: (as expected), when I try to remote access HA using HTTPS: I get an error from the browser that the site can’t be reached.

Any suggestions?

Question for clarification: in the instructions, does ‘xxxxxxxxx.myfritz.net’ stand for ‘devicename.myfritzaddress.myfritz.net’ or simply for ‘myfritzaddress.myfritz.net’? In other words, should it include the device name?

The text under VI.2 makes me believe is should include the device name, but the NGINX log shows an error when I do, and only when I do:

It stands for myfritzaddress.myfritz.net, should be something like pwxy8m398lcziyzo.myfritz.net and don’t forget to add the port in your browser if you don’t use the default port 443: https://pwxy8m398lcziyzo.myfritz.net:8123

EDIT:
Here is my router’s port forwards to nginx:

Thank you very much! Got it working now.

The port forwarding was ok. But for the HTTP: access I had (have) the device name included in the address, for the HTTPS: it only works if I do not include the device name. I’m sure that make sense, … somehow …

Hey,

first of all I want to mention that I am not that knowledgable with all of the port forwarding etc. Therefore I tried to follow the instructions but got stuck in step V.2
My problem is, that I seem to not be able to add the myFritz domain to the settings, since it claims that the settings are done in the configuration.yaml.
(Displayed message: “Editor deaktiviert, da die Konfiguration in configuration.yaml gespeichert ist.”)

I had a look at the configuration file but at least in my opinion there is nothing that should conflict with the external access settings? Only settings I had in there were the proposed ones in V.1?

Do you have any idea what might cause this issue?

Greetings
Jan

Hi Jan,
my network configuration looks like this. Of course you have to replace xxxxxxxxxx with your host ID. If this does not help you to solve this problem then please post the content of your configuration.yaml file. And yes, you need to add the lines from V.1 into your config file. Make sure the indentations are exactly as shown.

Hey @starob,

thanks for your help. This window is exactly, where It says that it is configured by configuration.yaml.

This is the current content of the file:

homeassistant: 
  name: Home 
  #latitude: xx.xxxx
  #longitude: xx.xxxx 
  unit_system: metric
  time_zone: Europe/Berlin
  packages: !include_dir_named packages
  
  
#Für Externen Zugriff über Fritz DDNS Service
#see: https://community.home-assistant.io/t/remote-access-using-a-fritzbox-the-avm-myfritz-ddns-service/611990
http:
  use_x_forwarded_for: true
  trusted_proxies: 
    - 172.30.33.0/24
  ip_ban_enabled: true
  login_attempts_threshold: 5
  
#logger:
#  default: info
#  logs:  
#    homeassistant.components.zha: debug
#    zigpy: debug

# Loads default set of integrations. Do not remove.
default_config:

# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes
 
panel_custom:
  - name: ha_integ
    sidebar_title: Integrations
    sidebar_icon: mdi:chip
    js_url: /api/hassio/app/entrypoint.js
    url_path: 'config/integrations'
    embed_iframe: true
    require_admin: true
    config:
      ingress: core_configurator  
  - name: ha_auto
    sidebar_title: Automations
    sidebar_icon: mdi:cog-outline
    js_url: /api/hassio/app/entrypoint.js
    url_path: 'config/automation'
    embed_iframe: true
    require_admin: true
    config:
      ingress: core_configurator  
  - name: ha_file_editor
    sidebar_title: File Editor
    sidebar_icon: mdi:file
    js_url: /api/hassio/app/entrypoint.js
    url_path: 'hassio/ingress/core_configurator'
    embed_iframe: true
    require_admin: true
    config:
      ingress: core_configurator   
  - name: ha_esphome
    sidebar_title: ESPHome
    sidebar_icon: mdi:car-esp
    js_url: /api/hassio/app/entrypoint.js
    url_path: 'hassio/ingress/5c53de3b_esphome'
    embed_iframe: true
    require_admin: true
    config:
      ingress: core_configurator   
  - name: ha_addons
    sidebar_title: Addons
    sidebar_icon: mdi:plus
    js_url: /api/hassio/app/entrypoint.js
    url_path: 'hassio/dashboard'
    embed_iframe: true
    require_admin: true
    config:
      ingress: core_configurator 


# Text to speech
tts:
  - platform: google_translate
  
#Rest_commands
rest_command:
    example_request:
        url: "http://example.com/"
        
    luigi_dock:
        url: "http://192.168.188.72/Dock?"
        
    luigi_clean:
        url: "http://192.168.188.72/Clean?"
        
    music_on_rest:
        url: "http://192.168.188.24/SocketAOn"
        
    music_off_rest:
        url: "http://192.168.188.24/SocketAOff"
        
    tv_on_rest:
        url: "http://192.168.188.24/SocketBOn"
        
    tv_off_rest:
        url: "http://192.168.188.24/SocketBOff"
        
    screens_on_rest:
        url: "http://192.168.188.24/SocketCOn"
        
    screens_off_rest:
        url: "http://192.168.188.24/SocketCOff"
        
    hdmi_splitter_on_rest:
        url: "http://192.168.188.24/SocketDOn"
        
    hdmi_splitter_off_rest:
        url: "http://192.168.188.24/SocketDOff"
        
    socket_a2_on_rest:
        url: "http://192.168.188.24/SocketA2On"
        
    socket_a2_off_rest:
        url: "http://192.168.188.24/SocketA2Off"
        
    socket_b2_on_rest:
        url: "http://192.168.188.24/SocketB2On"
        
    socket_b2_off_rest:
        url: "http://192.168.188.24/SocketB2Off"
        
    printer_on_rest:
        url: "http://192.168.188.24/SocketC2On"
        
    printer_off_rest:
        url: "http://192.168.188.24/SocketC2Off"
        
    socket_d2_on_rest:
        url: "http://192.168.188.24/SocketD2On"
        
    socket_d2_off_rest:
        url: "http://192.168.188.24/SocketD2Off"
        

device_tracker:
  - platform: ping
    hosts:
      ping_a40_jan: 192.168.188.21
      ping_iphone_salo: 192.168.188.23

spotcast:
  sp_dc: !secret sp_dc
  sp_key: !secret sp_key
  country: SE #optional, added in 3.6.24
  
  
#Additional Helper-Variables, that are NOT switchable in the UI
var:
  salo_long_gone:
    friendly_name: 'Salo_away'
    initial_value: false
    icon: mdi:bug
  jan_long_gone:
    friendly_name: 'Jan_away'
    initial_value: false
    icon: mdi:bug
    
#Additional Helper-Variables, that ARE switchable in the UI
input_boolean:
  #Disable some automations when guests are staying over for the night
  guest_sleepover_mode:
    name: Guest Sleepover Mode
    icon: mdi:party-popper
    initial: off
    
  #Change some automations when we are both on holidays
  holiday_mode:
    name: Holiday Mode
    icon: mdi:airplane
    initial: off
    
  #Try to find out if somebody was in the bathroom
  bathroom_occupied:
    name: Bathroom occupied
    icon: mdi:toilet
    initial: off
    
  #See If the window message has already been sent
  window_open_message_cooldown:
    name: Window Message Cooldown
    icon: mdi:curtain
    initial: off
    
  #Luigi has not cleaned for x days
  luigi_cleaning_overdue:
    name: Luigi Cleaning Overdue
    icon: mdi:robot-vacuum
    initial: off
    
  #Shutters of Window kitchen east wants to close
  shutters_kitchen_east_closing:
    name: Shutters Kitchen East closing
    icon: mdi:window-shutter-alert
    initial: off
    
  #Shutters of Window kitchen south wants to close 
  shutters_kitchen_south_closing:
    name: Shutters Kitchen South closing
    icon: mdi:window-shutter-alert
    initial: off
    
  #Shutters of Window living room wants to close
  shutters_livingroom_closing:
    name: Shutters Livingroom closing
    icon: mdi:window-shutter-alert
    initial: off
    
  #Shutters of Window bedroom wants to close
  shutters_bedroom_closing:
    name: Shutters Bedroom closing
    icon: mdi:window-shutter-alert
    initial: off
    
    
# This gets the max temp of the day
#sensor:
#  - platform: template
#      max_temp_today:
#        value_template: >
#          {% set tomorrow = (as_timestamp(now().date() + timedelta(days=1)) | timestamp_utc).replace(' ', 'T') ~ '+00:00' %}
#          {% set today = state_attr('weather.home_hourly', 'forecast')| selectattr('datetime', 'lt', tomorrow) | map(attribute='temperature') | list %}
#          {{ today | max }}
#        unit_of_measurement: "°C"
#        friendly_name: "Max Temp Today"

    
#THERMOSTATGRUPPEN
climate:
  - platform: climate_group
    name: 'Thermostate Wohnküche'
    temperature_unit: C  # default to celsius, 'C' or 'F'
    entities:
    - climate.thermostat_kuche
    - climate.thermostat_wohnzimmer
  - platform: climate_group
    name: 'Thermostate Alle'
    temperature_unit: C  # default to celsius, 'C' or 'F'
    entities:
    - climate.thermostat_kuche
    - climate.thermostat_wohnzimmer
    - climate.thermostat_bad
    - climate.thermostat_arbeitszimmer
    - climate.thermostat_schlafzimmer
    
#Helligkeitssensor ohne externe Hardware
sensor:
  - platform: illuminance
    # Name of new sensor entity
    name: Home Outdoor Illuminance
    # Existing entity that provides current weather conditions
    #entity_id: weather.home
    #entity_id: weather.forecast_apf85_u
    entity_id: sensor.openweathermap_cloud_coverage

    
zha:
  zigpy_config:
    #TO UPDATE THE IKEA 5btnremote TO THE NEWEST VERSION!
    ota:
      #otau_directory: /config/zigpy_ota
      ikea_provider: true
      ikea_update_url: http://fw.ota.homesmart.ikea.net/feed/version_info.json
      inovelli_provider: false
      ledvance_provider: false
      salus_provider: false
      sonoff_provider: false
      thirdreality_provider: false
  #CUSTOM QUIRK TO MAKE THE NEW CHANGES OF IKEA 5btnremote WITH VERSION 24.4.5 WORKING!!!
  #Custom quirk was released end of January 2023 - as of march first 2023 not yet integrated - might delete later??
  #Test for this: test if the automations with left and right of 5btnremote is working or not...
  custom_quirks_path: /config/zha_new_quirks/ 
  #EDIT 24.10.2023 --> Added another quirk file for the tuya thermostats

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

Do you find anything that I would need to have commented out?

Jan

I don’t see anything that might cause this. But you have packages configured:

Maybe some of those are causing this. Can you check those for potential problems?

Hey,

just for tests I commented out the line with the packages. But the message still remains. What exactly am I looking for that might overwrite the UI-control? I mean what yaml-command? Maybe I can search for that ones in particular.