This article shows my take on DHCP server lease script, which creates and deletes static DNS records automatically, based on creation and deletion of DHCP leases. Although, bunch of such scripts is already available, I wanted to have the features I liked merged into one universal script.


  • 2020-07-23 Fixed decision on usage of DNS domain and made according section less complex. Thanks to Wojtek and Gavin who pointed this out.


  • Creates static DNS records according to assigned DHCP lease.
  • Deletes static DNS records according to unassigned DHCP lease.
  • Deletes all related static DNS records, when new DNS record is being created to prevent duplicates. This can be done by IP and by hostname.
  • DNS records hostname can use additional domain name or use short hostname – or both.
  • Hostname for DNS record can be set from:
    • Variable set from the lease ( $”lease-hostname” ) – quick solution, which uses hostname passed from client
    • Hostname from the lease ( “host-name” attribute ) – a bit more CPU intensive solution, which searches leases for related hostname, but is also more compatible, if previous option is not available
    • Comment of the static lease ( “comment” attribute ) – secure solution, which uses hostname from comment of related static DHCP lease
  • Supports separated deployment on multiple instances of DHCP server within one MikroTik device.


To use the script, just copy-paste it into DHCP Server lease script field ( IP -> DHCP Server -> DHCP (tab) -> DHCP server instance -> Script (tab) -> Lease Script ) or into console editor using “/ip dhcp-server edit default lease-script” or by other means:

# When "1" all DNS entries with IP address of DHCP lease are removed
:local dnsRemoveAllByIp "1"
# When "1" all DNS entries with hostname of DHCP lease are removed
:local dnsRemoveAllByName "1"
# When "1" addition and removal of DNS entries is always done also for non-FQDN hostname
:local dnsAlwaysNonfqdn "1"
# DNS domain to add after DHCP client hostname
:local dnsDomain "dynamic.example.local"
# DNS TTL to set for DNS entries
:local dnsTtl "00:15:00"
# Source of DHCP client hostname, can be "lease-hostname" or any other lease attribute, like "host-name" or "comment"
:local leaseClientHostnameSource "lease-hostname"

:local leaseComment "dhcp-lease-script_$leaseServerName_$leaseClientHostnameSource"
:local leaseClientHostname
:if ($leaseClientHostnameSource = "lease-hostname") do={
  :set leaseClientHostname $"lease-hostname"
} else={
  :set leaseClientHostname ([:pick \
    [/ip dhcp-server lease print as-value where server="$leaseServerName" address="$leaseActIP" mac-address="$leaseActMAC"] \
:local leaseClientHostnames "$leaseClientHostname"
:if ([:len [$dnsDomain]] > 0) do={
  :if ($dnsAlwaysNonfqdn = "1") do={
    :set leaseClientHostnames "$leaseClientHostname.$dnsDomain,$leaseClientHostname"
  } else={
    :set leaseClientHostnames "$leaseClientHostname.$dnsDomain"
:if ($dnsRemoveAllByIp = "1") do={
  /ip dns static remove [/ip dns static find comment="$leaseComment" and address="$leaseActIP"]
:foreach h in=[:toarray value="$leaseClientHostnames"] do={
  :if ($dnsRemoveAllByName = "1") do={
    /ip dns static remove [/ip dns static find comment="$leaseComment" and name="$h"]
  /ip dns static remove [/ip dns static find comment="$leaseComment" and address="$leaseActIP" and name="$h"]
  :if ($leaseBound = "1") do={
    :delay 1
    /ip dns static add comment="$leaseComment" address="$leaseActIP" name="$h" ttl="$dnsTtl"

Other Scripts

As mentioned, there are also other scripts with similar functionality – each with a bit different implementation. Maybe some other script will fit your needs better if this one did not, so here are some that I stumbled upon:


Gavin · June 3, 2020 at 03:03

There’s a bug in this script. If you set dnsAlwaysNonfqdn to 0, then the dns entry that’s added is never a FQDN

    Pessoft · June 5, 2020 at 23:10

    Hi Gavin,

    Variable dnsAlwaysNonfqdn is used only if dnsDomain variable is also set. In such case, if dnsAlwaysNonfqdn is 0 then script adds DNS only entry with additional dnsDomain suffix. If dnsAlwaysNonfqdn is 1 then script adds DNS entry with dnsDomain suffix and also without it. What entry it really is, depends on the source of the name. If source of the name is lease-hostname, then it comes from the client itself and client decides if it send FQDN or non-FQDN hostname. Main use case of dnsAlwaysNonfqdn is that you have some hosts which send non-FQDN hostnames to DHCP and you want to register in DNS both entries – with and without DNS suffix – so they are reachable by short and also full hostname.

    Pessoft · June 23, 2020 at 00:16

    And there was a bug indeed. Thank you.

Tim · July 12, 2020 at 23:34

Thanks for the script! Where is $leaseBound set? Is this a ‘magic’ variable set for DHCP scripts?

    Pessoft · July 15, 2020 at 20:37

    Hi Tim, yes, you are right. Variables $leaseBound, $leaseServerName, $leaseActMAC, $leaseActIP, $lease-hostname and $lease-options are global variables that are pre-set with lease related information by RouterOS when lease script is called. It is easy to distinguish what each variable contains by variable name, but you can also find more specific information in lease-script property on Mikrotik Wiki.

Tom · July 14, 2020 at 03:45

Hi, Thank you for the great script! I notice some of the other dhcp to dns scripts have some kind of character checker… Does yours do that? Is it important? Thanks again!

    Pessoft · August 3, 2020 at 21:07

    Hi Tom, my script does not have a character checker. But it is a good point and I will consider that. Reason for it is that any input which is not under your control must be sanitized to prevent getting unexpected input, which could cause unintended activity. If DNS entries are created based on what client sends as hostname ( which is also default behavior of my script ), then someone can exploit it and send some unexpected input to the script. This can be prevented by mentioned character checker or by using trusted source ( like fixed hostnames in lease comments for example ).

Geeom · July 17, 2020 at 15:50

Is the script working on rOS 6.47(.1)?

I pasted the script “as is” but no entry appear in DNS Static window upon renewing client DHCP lease.

    Pessoft · September 22, 2020 at 23:37

    Hi, I did not test the script specifically on this version, but it was running on versions before and after 6.47(.1), so it should work your version too. Script is triggered on creation and deletion of DHCP lease.

Tim · August 2, 2020 at 11:04

What is the :delay 1 for in the end of the script?

The script works intermittently for me, and I fail to see why it sometimes does or doesn’t. One cause could be is that I use dns-based Adblock which heavily uses static dns entries and makes queries slow (~5s), such that the 1s delay might not be enough to do whatever it’s supposed to do.

    Pessoft · August 3, 2020 at 20:58

    It sometimes happened to me when disconnection of the client was followed by immediate re-connection of the client, script was executed twice ( as it should ), but disconnection related script execution somehow occurred after connection related script execution and this resulted in deleted DNS entries. I’ve therefore added a 1 second delay to make sure that connection run always wins.

ilium007 · September 12, 2020 at 03:52

Didn’t work on routerOS 7beta2

ilium007 · September 12, 2020 at 04:01

Just realised the script does not work for DHCP leases that are static assigned.

ilium007 · September 12, 2020 at 10:03

My bad – script works fine on routerOS 7beta2. Thanks!

    Pessoft · September 12, 2020 at 17:22

    Hi. Thank you too for feedback from 7beta2 😉

Alex22 · September 14, 2020 at 23:09

Thanks for this script; Seems to work on 6.47.3 but only for new/changed Leases. A migration path for existing systems would be fine 😉 Can i trigger the script for all existing leases?


    Pessoft · September 22, 2020 at 23:33

    Hello Alex, this script is intended to by used for new DHCP leases and it is being triggered by creation and deletion of DHCP leases. If there is some existing solution, which needs to be migrated, it must be done separately.

Leave a Reply

Your email address will not be published. Required fields are marked *