diff --git a/README.md b/README.md
index f737c4e..cd8b76e 100644
--- a/README.md
+++ b/README.md
@@ -2,50 +2,64 @@ dyndns.pl
 =========
 
 Perl CGI-BIN script to handle Dynamic DNS updates through HTTP (e.g. from a
-router), updating DNS records through secure DNS update statements.
+router), updating DNS records through secure DNS update statements to run your
+own Dynamic DNS Service.
 
-**Version 1.0**, latest version, documentation and bugtracker available on my
+**Version 1.1**, latest version, documentation and bugtracker available on my
 [GitLab instance](https://gitlab.lindenaar.net/scripts/dyndns)
 
-Copyright (c) 2013 - 2015 Frederik Lindenaar. free for distribution under the
+Copyright (c) 2013 - 2019 Frederik Lindenaar. free for distribution under the
 GNU License, see [below](#license)
 
 
 Introduction
 ------------
-This script provides a simple interface to allow Dynamic DNS updates for DNS
-zones. It is intended to be used for routers and (aDSL) modems to register their
-IP address by simply opening a URL (this is supported by many modern devices)
-but can also be used by end-users (either directly by using a client). Please
-bear in mind that this script suits my setup and still might have glitches, but
-so far turned out to be a quite stable solution for my needs and I use it in a
-production setup. In case you have any comments / questions or issues, please
-raise them through my
-[GitLab instance](https://gitlab.lindenaar.net/scripts/dyndns) so that all
-users benefit.
-
-Setup
------
+`dyndns.pl` provides a simple interface to allow Dynamic DNS updates for DNS
+zones through HTTP requests. It is intended  for routers and (aDSL) modems to
+register their IP address by simply opening a URL (this is supported by most
+modern devices) but can also be used by end-users (either directly by using a
+client). The script itself uses DNS' `nsupdate` calls to perform the update.
+With this script you can integrate devices not supporting `nsupdate` and
+environments where the master DNS server is not publicly available. The script
+suits my setup/and needs and still might have glitches, but turned out to be a
+very stable solution the last 6 years on both Linux as well as MacOS.
+
+Please [see below](#integration) on how to setup the client side including:
+  * [Cisco Routers](#cisco_integration)
+  * [AVM Fritz!Box routers](#fritzbox_integration)
+  * [Synology DSM](#synology_integration) (NAS)
+
+In case you have any comments / questions or issues, please raise them through
+my [GitLab instance](https://gitlab.lindenaar.net/scripts/dyndns) so that other
+users can benefit and respond. Please also use this to submit setup instructions
+for other devices you have set up for inclusion in this document.
+
+
+Setup of the server side
+========================
 This script is to be executed as CGI-BIN script by a web server. As it is
-written in Perl, it requires that installed (which is pretty standard nowadays
-on all *nix platforms). This description covers the installation on Apache 2.4,
-which should be similar for other web servers, with ISC Bind v9. For performance
-reasons consider using the Apache mod_perl module for highly a volatile domain.
+written in Perl, it requires that installed (which is pretty standard on \*nix
+platforms). This description covers the installation on Apache 2.4 and should be
+similar for other web servers, with ISC Bind v9. For performance reasons
+consider using the Apache mod_perl module for highly a volatile domain.
 
+
+<a name=installation>Installation</a>
+-------------------------------------
 The setup of this solution consists of the following steps:
 
   1. Ensure that the Perl modules CGI and Net::DNS are installed.
-     * on Debian/Ubunto linux this can be done by:
+     * on Debian/Ubuntu linux this can be done by:
 
-       ~~~~
+       ```
        sudo apt-get install libcgi-pm-perl libnet-dns-perl
-       ~~~~
+       ```
 
-     * or if you have cpan installed:
+     * or directly from CPAN (assuming that is installed):
 
-       ~~~
+       ```
        cpan CGI Net::DNS
-       ~~~
+       ```
 
   2. Install the file `dyndns.pl` either in your cgi-bin directory or in a
      separate folder
@@ -60,22 +74,27 @@ The setup of this solution consists of the following steps:
      server's cgi-bin directory) add the following line to your Apache virtual
      host configuration (replacing `[INSTALL_DIR]` with the install directory):
 
-          ScriptAlias /dyndns   [INSTALL_DIR]/dyndns.pl
+     ```
+     ScriptAlias /dyndns   [INSTALL_DIR]/dyndns.pl
+     ```
 
      in case you have installed the script in a non-standard folder, you will
      also need the following to make this work on Apache 2.4 (again replacing
      `[INSTALL_DIR]` with the install directory):
 
-     ~~~
+     ```
      <Directory [INSTALL_DIR]/>
            AllowOverride None
            Options +ExecCGI -MultiViews -Indexes
            Require all granted
      </Directory>
-     ~~~
+     ```
 
      reload apache with `/etc/init.d/apache reload` to make the script
-     available at <http://myserver.mydomain.tld/dyndns>
+     available at <http://myserver.mydomain.tld/dyndns>.
+
+     It is also possible to run as a virtual host, [see below](#VirtualHost) for
+     an example of that.
 
   5. To setup your Bind nameserver, either update `named.conf` direcly or create
      a separate file (e.g. `named.dyndns.conf` in the Bind configuration
@@ -83,7 +102,7 @@ The setup of this solution consists of the following steps:
      (e.g. `include "named.dyndns.conf";`). For a basic dynamic DNS setup a
      configuration like below is required:
 
-     ~~~
+     ```
      // Define the keys for DynDNS
      key "dyndns.mydomain.tld" {
          algorithm hmac-md5; secret "QdDJC7QVYmsCxgWoSAUmBg==";
@@ -106,13 +125,13 @@ The setup of this solution consists of the following steps:
                  grant siteuser name site.dyndns.mydomain.tld ANY;
           };
      };
-     ~~~
+     ```
 
      The above defines a domain zone file `dyndns/db.dyndns.mydomain.tld` with
      two signer/keys. *siteuser* only can update `site.dyndns.mydomain.tld`
      while *dyndns.mydomain.tld* can update all entries in the domain (intended
      for expiry). If you intend to use expiry or want to be able to retrieve a
-     list of all entries, comment out the `allow-transfer` statement and update
+     list of all entries, uncomment the `allow-transfer` statement and update
      the IP adres to that of your web server.
 
      To seed these entries with fresh keys), use the following
@@ -120,23 +139,23 @@ The setup of this solution consists of the following steps:
 
        * to generate a new key *dyndns.mydomain.tld*:
 
-         ~~~
+         ```
          ddns-confgen -a hmac-md5 -k dyndns.mydomain.tld -z dyndns.mydomain.tld
-         ~~~
+         ```
 
        * generate the required configuration for *siteuser* (or any new user):
 
-         ~~~
+         ```
          ddns-confgen -a hmac-md5 -k siteuser -s site.dyndns.mydomain.tld
-         ~~~
+         ```
 
   6. Generate an initial zone file like the one below for the dyndns domain in
      the location specified in the config file above.
 
-     ~~~
+     ```
      $TTL 3600       ; 1 hour
      @               IN  SOA auth.dns.mydomain.tld. hostmaster.mydomain.tld. (
-                         2015051401 ; serial
+                         2019000001 ; serial
                          43200      ; refresh (12 hours)
                           3600      ; retry (1 hour)
                          86400      ; expire (24 hours)
@@ -145,7 +164,7 @@ The setup of this solution consists of the following steps:
                      TXT   "Dynamic DNS zone for mydomain.tld"
 
      site            A       1.2.3.4
-     ~~~
+     ```
 
      Please note that Bind will rewrite this file and you need to be careful
      with it. Entries do not need to exist initially, as long as the signer/key
@@ -168,38 +187,111 @@ The setup of this solution consists of the following steps:
 
      * <http://myserver.mydomain.tld/dyndns/list?domain=dyndns.mydomain.tld>
        to list the entries in the domain (requires zone transfer rights!)
-     * <http://myserver.mydomain.tld/dyndns/update?host=site.dyndns.mydomain.tld&user=siteuser&key=......>
+     * <http://myserver.mydomain.tld/dyndns/update?host=site.dyndns.mydomain.tld&user=siteuser&secret=......>
        to add/update a site and
-     * <http://myserver.mydomain.tld/dyndns/delete?host=site.dyndns.mydomain.tld&user=siteuser&key=......>
+     * <http://myserver.mydomain.tld/dyndns/delete?host=site.dyndns.mydomain.tld&user=siteuser&secret=......>
        to delete (clear) it.
 
 Please read the section below as well on the configuration and different modes
 (operations) available.
 
+
 <a name=configuration>Configuration</a>
 ---------------------------------------
-
 At the top of the script is a "Configuration" section, which contains the
-configurable options of the scripts.
+configurable options of the scripts. As of version 1.1 the script also supports
+a [configuration file](#config_file) so that modifying the script is no longer
+required.
+
 
 Parameter        | Description
-:----------------+:-------------------------------------------------------------
+:----------------|:-------------------------------------------------------------
+`$ConfigFile`    | Enable/disable config file support, [see below](config_file)
 `$DNSServer`     | IP address of the DNS Server to send DNS update requests to
-`$ExpandCNAMEs`  | Max. CNAME lookups for `$host` (0 to disable), see below
+`@DNSDomain`     | How to determine the host's domain name, [see below](#conf_dnszone)
+`$DomainListKey` | Secret required to use the list mode, set to '' to always enable and to 'off' to disable this mode
+`$ExpandCNAMEs`  | Max. CNAME lookups for `$host` (0 to disable), [see below](#conf_cname)
 `$AllowDebugKey` | Output debug log after result when `debug` parameter equals this value. Set to '' to always enable and to 'off' to disable debugging
-`$AuthMode`      | Defines how to authenticate DNS update requests, see below
+`$AuthMode`      | Defines how to authenticate DNS update requests, [see below](#conf_auth)
 `$StaticSigner`  | Static signer ID to be used for AuthMode `static` or `both`
 `$StaticKey`     | Static signing key to be used for AuthMode `static` or `both`
-`$RequireRR`     | Require an existing DNS record of this type to allow updates.
-`$ExpireAfter`   | Expire time for registrations in minutes, hours, weeks or seconds. Format is number optionally followed by m, h, w, s (seconds is default).
+`$RequireRR`     | Require an existing DNS record of this type to allow updates
+`$ExpireAfter`   | Expire time for registrations in minutes, hours, weeks or seconds. Format is number optionally followed by m, h, w, s (seconds is default)
 `@ReplaceRR`     | List of DNS Record types to remove (clear) as part of update.
 `$UpdateTXT`     | Add host TXT record during update with this text followed by a timestamp. Used for expiry (so don't change!), leave empty to not add this
-`$DeleteTXT`     | Set TXT record upon deletion with this text and a timestamp. 
-
-Please note that the values must be correctly quoted, etc. not to break the script.
-
-
-#### CNAME Support
+`$DeleteTXT`     | Set TXT record upon deletion with this text and a timestamp.
+`$RecordTTL`     | TTL for created records in minutes, hours, weeks or seconds. Format is number optionally followed by m, h, w, s (seconds is default)
+
+Please note: when changing the script all values must be correctly quoted, etc.
+not to break the script. Therefore as of version 1.1 a config file is supported
+(preferred), [see below](config_file).
+
+
+#### <a name=config_file>Configuration File</a>
+The script can read its settings from a config located in the same directory as
+the script and with the extension `.cfg` (ignoring a `.pl` extension) so the
+default config file would be `dyndns.cfg`. The behavior of how to support the
+config file is configured through the variable `$ConfigFile` and can be one of:
+  * `optional` - config file is read if it exists, this is the default
+  * `required` - config file is read and must exist (or the script will fail)
+  * `ignore` - config file is ignored and not read, configuration in the script
+
+The general format of the config file is `keyword = value`, see the table below
+for a mapping of the parameters to keywords. For lists (variables starting with
+a `@`) the value is comma-separated. The config file supports comments, ignores
+empty lines, starting/trailing spaces and everything following a `#`. Refer to
+`dyndns.cfg.dist` for an example config file. Please note that the script will
+fail if it encounters an error or unknown keyword in the config file.
+
+Parameter         | Config Setting     | Default value
+:-----------------|:-------------------|:------------------------------
+`$AllowDebugKey`  | `allow_debug_key`  | `off` (debugging disabled)
+`$AuthMode`       | `auth_mode`        | `remote` ([see below](#conf_auth))
+`$DeleteTXT`      | `delete_txt`       | `DynDNS cleared on`
+`$DNSServer`      | `dns_server`       | `192.168.1.1`
+`@DNSDomain`      | `dns_domain`       | `?, !, 0` ([see below](#conf_dnszone))
+`$DomainListKey`  | `domain_list_key`  | `off` (domain list disabled)
+`$ExpandCNAMEs`   | `expand_cnames`    | `1` (1 level, [see below](#conf_cname))
+`$ExpireAfter`    | `expire_after`     | `1w` (1 week, [see below](#expire))
+`$RecordTTL`      | `record_ttl`       | `1h` (1 hour)
+`$RequireRR`      | `require_rr`       |
+`@ReplaceRR`      | `replace_rr`       | `A, AAAA, TXT`
+`$StaticKey`      | `static_key`       |
+`$StaticSigner`   | `static_signer`    |
+`$UpdateTXT`      | `update_txt`       | `Last DynDNS update on`
+
+Please note that since `$ConfigFile` determines config file support, it cannot
+be configured in the file. By default the config file is optional not to break
+existing configurations.
+
+
+#### <a name=conf_dnszone>DNS Zone (Domain Name) Selection</a>
+In order to send the right update request to the DNS server, the correct DNS
+zone to update must be determined based on the request's hostname. Most of the
+time an update for `hostname.subdomain.mydomain.tld` is an update of `hostname`
+the DNS zone `subdomain.mydomain.tld` and then the defaults are sufficient.
+However, in some scenarios (e.g. one of my use cases) an update should be sent
+for hostname `hostname.subdomain` in the zone `mydomain.tld` instead. The DNS
+server cannot figure this out itself (at least ISC's Bind9 can not) so it is
+implemented here.
+
+The array `@DNSDomain` contains a list of values matched against the hostname
+to determine the DNS zone to update and can contain:
+
+Value            | match hostname ending with
+:----------------|:-------------------------------------------------------
+`"?"`            | the domain name from parameter `domain`
+`"!"`            | server name the HTTP(S) request was sent to
+`0`              | domain from hostname (strip of everythin till first `.`)
+positive number  | last # parts from hostname
+negative number  | last # parts of server name the HTTP(S) request was sent to
+any other string | use value specified
+
+The first parameter matching the hostname's end will be used. The default is
+`( '?', '!', 0 )`, which should be OK in most cases.
+
+
+#### <a name=conf_cname>CNAME Support</a>
 The script supports using separate subdomain (e.g. dyndns.mydomain.tld) for
 dynamic DNS and CNAMEs to entries in that subdomain from another zone (e.g.
 mydomain.tld). The advantage of such a setup is that only one zone (SOA file)
@@ -212,17 +304,18 @@ the host provided is a CNAME and if so, performs the request for the actual
 hostname instead of the provided one. The value of `$ExpandCNAMEs` determines
 the maximum number of CNAME lookups supported (so nesting is allowed and this
 limits the level of nesting to prevent loops).
+
 To disable lookups for CNAME expansion, set `$ExpandCNAMEs` to 0.
 
 
-#### Authentication Modes
+#### <a name=conf_auth>Authentication Modes</a>
 For signing DNS update requests sent to the DNS server the script supports 3
 ways to obtain the signer and key:
 
 AuthMode | Description
-:--------+:---------------------------------------------------------------------
+:--------|:---------------------------------------------------------------------
 *static* | use only static authentication information from `$StaticSigner` and`$StaticKey` (and ignore authentication information provided in the request)
-*remote* | use only authentication information provided in the request 
+*remote* | use only authentication information provided in the request
 *both*   | use authentication information provided in the request (fields `user` and `secret`) when provided, otherwise use static values from `$StaticSigner` and `$StaticKey`. Please note that this is checked per parameter
 
 
@@ -230,51 +323,59 @@ Supported Operations
 --------------------
 The script can perform the following operations (modes):
 
-Mode   | Description              | Required Parameters | Optional Parameters
-:------+:-------------------------+:--------------------+:----------------------
-list   | Show DDNS domain entries | `domain`__**__      |
-view   | Show DDNS hostname entry | `host`              |
-update | Update/add a DDNS host   | `host` + auth.__*__ | `ipv4addr`, `ipv6addr`
-delete | Remove DDNS registration | `host` + auth.__*__ |
-expire | Expire registrations     | `domain`__**__ + auth.__*__
+Mode   | Description            | Required Parameters | Optional Parameters
+:------|:-----------------------|:--------------------|:----------------------
+list   | List zone __***__      | `secret` __***__    | `domain`__**__
+view   | Show host's DNS entry  | `host`              |
+update | Update/add a DDNS host | `host` + auth.__*__ | `ipv4addr`, `ipv6addr`
+delete | Remove registration    | `host` + auth.__*__ |
+expire | Expire registrations   | `domain`__**__ + auth.__*__
 
-__*__   Modes that change registrations require authentication, depending on the
-        value of `$AuthMode` the parameters `user` and `secret` may be required
+__*__   modes that change DNS require authentication, depending on the value of
+        `$AuthMode` the parameters `user` and `secret` may be required
         (`$AuthMode` *remote*) required or optional (`$AuthMode` *both*)
 
 __**__  in case `domain` is omitted, it will be determined using the `host`
-        parameter, if provided
-
-
-#### Parameters
-The script supports the following parameters (please see the table above for which is needed for what mode):
-
-Parameter | Description
-:---------+:--------------------------------------------------------------------
-`mode`    | the action to perform (if not provided as part of the path name)
-`domain`  | domain for list/expire request, determined from `host` if ommitted
-`host`    | hostname to act on, expand CNAMEs max. `$ExpandCNAMEs` levels deep
-`ip`      | alias / shortcut for `ipv4addr`
-`ipv4addr`| The IPv4 address to register for the host (update mode only) __*__
-`ipv6addr`| The IPv6 address to register for the host (update mode only) __*__
-`user`    | signer of the DNS Update, used for `AuthMode` *remote* and *both*
-`key`     | key to sign the DNS Update, used for `AuthMode` *remote* and *both*
-`debug`   | debug key, show debug information if this equals `$AllowDebugKey`
-
-__*__   in update mode, if `ipv4addr` or `ipv6addr` is not provided with the
+        parameter, if provided, or by using the virtualhost the script runs on
+        based on the `@DNSDomain` setting
+
+__***__ list mode is only available when `$DomainListKey` is not set to `off`,
+        in case `$DomainListKey` is not empty, `secret` is required and must
+        equal the key in `$DomainListKey`
+
+
+#### <a name=req_params>Request Parameters</a>
+The script supports (requires) the following parameters (please see the table
+above for which is needed for what mode):
+
+Parameter  | Description
+:----------|:-------------------------------------------------------------------
+`mode`     | the action to perform (if not provided as part of the path name)
+`domain`   | domain for list/expire request, determined from `host` if ommitted
+`host`     | hostname to act on, expand CNAMEs max. `$ExpandCNAMEs` levels deep
+`ip`       | alias / shortcut for `ipv4addr`
+`ipv4addr` | The IPv4 address to register for the host (update mode only) __*__
+`ipv6`     | alias / shortcut for `ipv6addr`
+`ipv6addr` | The IPv6 address to register for the host (update mode only) __*__
+`user`     | signer of the DNS Update, used for `AuthMode` *remote* and *both*
+`secret`   | key to sign the DNS Update, used for `AuthMode` *remote* and *both*, also used as `$DomainListKey` for list mode.
+`debug`    | debug key, show debug information if this equals `$AllowDebugKey`
+
+__*__   in update mode, if `ipv4addr` or `ipv6addr` is set to `auto` in the
         request, the CGI variable `$REMOTE_ADDR` (the client address), its value
-        will be used instead as IPv4/IPv6 address.
+        will be used instead as IPv4/IPv6 address. __Please Note__ that if both
+        are omitted existing addresses will be removed!
 
 
-#### <a name="invoking">Invoking the script</a>
+#### <a name=invoking>Invoking the script</a>
 The script is implemented using the perl CGI module so for testing purposes it
 can be called from the command line with parameters as arguments, i.e.
 
     ./dyndns.pl mode=expire domain=mydomain.tld debug=....
 
-Which is quite handy for debugging purposes. Please note that the Perl CGI
-library sets `$REMOTE_ADDR` to 127.0.0.1 and that the output will always be
-the HTML-based result.
+Which is quite handy for debugging. Please note that the Perl CGI library sets
+`$REMOTE_ADDR` to 127.0.0.1, the server name in this case will be `localhost`
+and that the output is the HTML result.
 
 The standard way to use the script is to place it in the cgi-bin folder your
 server, which allows it to be called as:
@@ -295,14 +396,54 @@ When combining the setup would become:
 
     http://myserver.mydomain.tld/dyndns/list?domain=mydomain.tld&debug=...
 
+If using a dedicated virtual host [see below](#VirtualHost) it becomes:
+
+    http://myserver.mydomain.tld/list?domain=mydomain.tld&debug=...
+
 Which is how I use it.
 
 
+### <a name=expire>Expiring Records</a>
+The script can expire registrations after a while. For this, it must add a TXT
+record containing the date of the last change (on by default) and when requested
+it will remove any entry older than the value configured in `$ExpireAfter`.
+
+Please note that:
+  * as this is dependent on the value of a TXT record, it may fail if these
+    records are updated through another method.
+  * there is no security implemented (other than the value of `$ExpireAfter`)
+
+To initiate the expiry, the script must be called with two parameters:
+  1. `mode` should be set to `expire`
+  2. `domain` must be set to the DNS Zone (domain) to run against.
+
+Both can be setup easily in cron with entries like:
+
+~~~
+# Samples to run the expiry every hour
+
+# Cron fields definition:
+#.---------------- minute (0 - 59)
+#| .------------- hour (0 - 23)
+#| |  .---------- day of month (1 - 31)
+#| |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
+#| |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
+#| |  |  |  |
+#* *  *  *  * user-name command to be executed
+
+# Directly run the script, does not require specific permissions
+15 *  *  *  * www-data  [INSTALL_DIR]/dyndns.pl mode=expire domain=mydomain.tld
+
+# example using curl
+15 *  *  *  * www-data  curl https://myserver.mydomain.tld/expire?domain=mydomain.tld > /dev/null
+~~~
+
+
 Name Server Setup Requirements
 ------------------------------
 As the script is only translating requests, depends heavily on the setup of the
 nameserver. The DNS server (obviously) needs to allow DNS updates. In addition
-to the setup described above, please note that: 
+to the setup described above, please note that:
 
   * For the modes list and expire to work, the script needs to perform a DNS
     zone transfer (AXFR). This must be allowed for the host running the script.
@@ -314,22 +455,191 @@ to the setup described above, please note that:
     used Perl Net::DNS library). The keys setup in the nameservers must
     therefore be of the same time or authentication won't work.
 
-The solution scales reasonable well, although adding the keys to the nameserver
-configuration is still manual in my setup (but since it does not happen that
-often, it's no hassle). This setup has been tested against ISC Bind version 9.
-
+This setup has been tested against ISC Bind version 9 and scales pretty well.
+Adding the keys to the nameserver configuration is still manual in my setup but
+bit difficult script, if needed.
+
+
+<a name=VirtualHost>Configure as Virtual Host</a>
+-------------------------------------------------
+Running dyndns.pl on a Virtual Host is possible using `mod_rewrite`. This is how
+I use it as it allows the URLs to become even more simple, e.g.:
+
+  * to update: `https://dyndns.mydomain.tld/update/hostname.mydomain.tld?secret=...`
+  * to delete: `https://dyndns.mydomain.tld/delete/hostname.mydomain.tld?secret=...`
+  * to view:   `https://dyndns.mydomain.tld/view/hostname.mydomain.tld`
+  * to list:   `https://dyndns.mydomain.tld/list/mydomain.tld?secret=...`
+  * to expire: `https://dyndns.mydomain.tld/expire/mydomain.tld`
+
+An example Apache 2.4 config is shown below (please replace `[INSTALL_DIR]` with
+the install directory and obviously replace the server name as well):
+
+~~~
+<VirtualHost *:80 *:443>
+  ServerName dyndns.mydomain.tld
+
+  # Enable URL Rewriting
+  RewriteEngine On
 
-<a name="license">License</a>
------------------------------
-This script, documentation and configration examples are free software: you can
+  # Enforce HTTPS access
+  RewriteCond %{HTTPS} off
+  RewriteRule /         https://%{HTTP_HOST}%{REQUEST_URI}      [R]
+
+  # re-route everything to the dyndns script
+  RewriteRule (.*)      /dyndns/$1                              [PT]
+
+  ScriptAlias /dyndns           [INSTALL_DIR]/dyndns.pl
+
+  <Directory [INSTALL_DIR]>
+        AllowOverride None
+        Options +ExecCGI -MultiViews
+        Require all granted
+  </Directory>
+
+</VirtualHost>
+~~~
+
+
+<a name=integration>Integration with devices</a>
+================================================
+Integration on routers and other devices is straigtforward, provided do support
+DDNS registrations using a custom URL. The Basic format for the registration
+URL to register is:
+
+~~~
+https://SERVER/cgi-bin/dyndns/update?host=HOSTNAME&ip=IPADDRESS&secret=KEY`
+~~~
+
+Check the [list of parameters supported](req_params) for all available options,
+the above URL contains the absolute minimum where:
+
+Parameter   | Value
+:-----------|:---------------------------------------------------------------
+`SERVER`    | is the host the script is installed on
+`HOSTNAME`  | is the client's hostname as configured in the DNS server
+`SECRET`    | is the secret key as configured in the DNS server
+`IPADDRESS` | is the ipv4 address (often dynamic, can also be set to `auto`)
+
+Depending on how you have configured the URL of the script to be, the path
+(`/cgi-bin/dyndns/` may need to be altered as per your setup).
+
+Please note that:
+  * The generated secret may contain a `+`, which must be encoded correctly in
+    the request or it will fail. I found that not all clients (e.g. a Fritz!Box)
+    do this correctly, make sure that your secrets either don't contain a `+`
+    or encode it manually (replace any `+` with `%2B` in that case).
+  * In case the IP address of the device is behind NAT and you want to have the
+    public address register, use the `auto` value for parameters `ip`/`ipv4addr`
+    and `ipv6`/`ipv6addr` to have the script auto-detect it (though that this
+    can only be used for either an IPv4 or an IPv6 address and will only work
+    for devices registering using that protocol!)
+  * Some devices have a preference to connect over IPv6 (e.g. Cisco routers).
+    This can be used to register the IPv4 and IPv6 addresses together by passing
+    the IPv4 address as parameter en setting the IPv6 parameter to `auto`.
+  * Some devices (e.g. a Fritz!Box) support a separate URL for IPv4 and IPv6
+    registrations. Unfortunately this script cannot handle this yet and will
+    unregister a previous registration when the second request comes in. Please
+    raise a ticket if you have such a situation to work on a solution together.
+
+To check whether the client's registration was successful (and correct) visit:
+
+~~~
+https://SERVER/cgi-bin/dyndns/view?host
+~~~
+
+
+<a name=cisco_integration>Cisco Routers</a>
+-------------------------------------------
+For Cisco routers add the following config:
+
+```
+ip ddns update method DYNDNS
+ HTTP
+  add https://SERVER/cgi-bin/dyndns/update?host=<h>&ip=<a>&secret=SECRET
+  remove https://SERVER/cgi-bin/dyndns/delete?host=<h>&secret=SECRET
+ interval maximum 0 1 0 0
+```
+
+replacing `SERVER` for the host the script is installed on and `SECRET`
+for a DNS key authorized to update the record. The cisco router will replace <a>
+and <h> with the IPv4 address and hostname.
+
+To setup interface `Dialer0` to register as `hostname.dyndns.mydomain.tld` add:
+
+```
+interface Dialer0
+ ip ddns update hostname hostname.dyndns.mydomain.tld
+ ip ddns update DYNDNS
+```
+
+Which instructs to register using the address of Dialer0 as soon as that is up
+or changes (this also works for non-dialer devices).
+
+Please note that before entering the `?` as part of the URL, a `CTRL`-`V` is
+required to prevent the Cisco CLI to list the available command parameters.
+
+
+<a name=fritzbox_integration>AVM Fritz!Box routers</a>
+------------------------------------------------------
+To setup DynDNS on a Fritz!Box perform the following steps:
+  * Login to your Fritz!Box as an admin user
+  * Open the 'Internet' menu an go through the 'External Access' page
+  * Open the 'DynDNS' tab
+  * Enable the 'Use DynDNS' checkbox
+  * Select DynDNS Provider: 'User-defined'
+  * Enter the following data (replacing `YOURDOMAIN` with your DynDNS domain
+    and `SERVER` with your server name - check the rest of the URL as well!)
+    - Update URL: `https://SERVER/cgi-bin/dyndns/update?host=<domain>&ip=<ipaddr>&secret=<pass>`
+    - Domain name: hostname setup in DNS
+    - Username/Email: put here something, not used unless you add it to the URL
+    - Password: secret key setup in DNS
+  * Click 'Apply' to store and activate the DDNS registrations
+
+Check [this page](https://service.avm.de/help/en/FRITZ-Box-7581/017p2/hilfe_dyndns)
+for the available parameters that can be substituted in the URL.
+
+The status of the DynDNS registrations can be seen in the 'Internet' menu on the
+'Online Monitor' page.
+
+To stop DynDNS registrations, uncheck 'Use DynDNS' from the same screen.
+
+
+<a name=synology_integration>Synology DSM (NAS)</a>
+---------------------------------------------------
+To setup DynDNS on a Synology NAS (DSM 6 or later) perform the following steps:
+  * Login to your Synology NAS DSM as an admin user
+  * Open the Control Panel and go to 'External Access'
+  * Click 'Customize' to add a new DDNS provider
+  * Enter the following data (replacing `YOURDOMAIN` with your DynDNS domain
+    and `SERVER` with your server name - check the rest of the URL as well!)
+    - Service Provider: `YOURDOMAIN`
+    - Query URL `https://SERVER/cgi-bin/dyndns/update?host=__HOSTNAME__&ip=__MYIP__&secret=__PASSWORD__`
+  * Click Save to store the custom DDNS provider
+  * Click Add to register the DDNS registration and enter:
+    - Service Provider: select the name you have just added (`*YOURDOMAIN`)
+    - Hostname: hostname setup in DNS
+    - Username/Email: put here something, not used unless you add it to the URL
+    - Password/Key: secret key setup in DNS
+  * Click 'OK' to store and activate the DDNS registrations
+
+After a while the screen should display that the status is Normal and when the
+last update occurred.
+
+To stop DDNS registrations, 'Delete' the registration from the same screen.
+
+
+<a name=license>License</a>
+=============================
+This script, documentation and configuration examples are free software: you can
 redistribute and/or modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation, either version 3 of the License,
 or (at your option) any later version.
 
-This script, documenatation and configuration examples are distributed in the
+This script, documentation and configuration examples are distributed in the
 hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.
 
 You should have received a copy of the GNU General Public License along with
 this program.  If not, download it from <http://www.gnu.org/licenses/>.
+