diff --git a/docs/user/site.rst b/docs/user/site.rst
index b066f8c2f507d8d0414c86f120111928cf480f66..bfceb83e5696f5bdfcf6dd16548f420d9e4a1f1a 100644
--- a/docs/user/site.rst
+++ b/docs/user/site.rst
@@ -370,6 +370,10 @@ config_mode \: optional
     Additional configuration for the configuration web interface. All values are
     optional.
 
+    When no hostname is specified, a default hostname based on the *hostname_prefix*
+    and the node's primary MAC address is assigned. Manually setting a hostname
+    can be enforced by setting *hostname.optional* to *false*.
+
     By default, no altitude fields are shown by the *gluon-config-mode-geo-location*
     package. If *geo_location.show_altitude* is set to *true*, the *gluon-config-mode:altitude-label*
     and *gluon-config-mode:altitude-help* strings must be provided in the site i18n
@@ -385,6 +389,9 @@ config_mode \: optional
     ::
 
         config_mode = {
+          hostname = {
+            optional = false,
+          },
           geo_location = {
             show_altitude = true,
           },
diff --git a/package/gluon-config-mode-hostname/check_site.lua b/package/gluon-config-mode-hostname/check_site.lua
new file mode 100644
index 0000000000000000000000000000000000000000..29b5edd6a6bc562f55492ad803d9d194a3f90edf
--- /dev/null
+++ b/package/gluon-config-mode-hostname/check_site.lua
@@ -0,0 +1 @@
+need_boolean(in_site({'config_mode', 'hostname', 'optional'}), false)
diff --git a/package/gluon-config-mode-hostname/luasrc/lib/gluon/config-mode/wizard/0100-hostname.lua b/package/gluon-config-mode-hostname/luasrc/lib/gluon/config-mode/wizard/0100-hostname.lua
index 23c9903830f5ae2ed72f97d48f151d9bd32eae0e..4155e8f48e1f33e0a01cd9910499b204067f8464 100644
--- a/package/gluon-config-mode-hostname/luasrc/lib/gluon/config-mode/wizard/0100-hostname.lua
+++ b/package/gluon-config-mode-hostname/luasrc/lib/gluon/config-mode/wizard/0100-hostname.lua
@@ -1,19 +1,32 @@
 return function(form, uci)
 	local pkg_i18n = i18n 'gluon-config-mode-hostname'
 
-	local pretty_hostname = require "pretty_hostname"
+	local pretty_hostname = require 'pretty_hostname'
+	local site = require 'gluon.site'
+	local util = require 'gluon.util'
 
 	form:section(Section, nil, pkg_i18n.translate(
 		"The node name is used solely for identification of your node, e.g. on a "
 		.. "node map. It does not affect the name (SSID) of the broadcasted WLAN."
 	))
 
+	local current_hostname = pretty_hostname.get(uci)
+	local default_hostname = util.default_hostname()
+	local configured = uci:get_first('gluon-setup-mode', 'setup_mode', 'configured', false) or (current_hostname ~= default_hostname)
+
 	local s = form:section(Section)
 	local o = s:option(Value, "hostname", pkg_i18n.translate("Node name"))
-	o.default = pretty_hostname.get(uci)
+	o.datatype = 'minlength(1)'
+	if site.config_mode.hostname.optional(true) then
+		o.optional = true
+		o.placeholder = default_hostname
+	end
+	if configured then
+		o.default = current_hostname
+	end
 
 	function o:write(data)
-		pretty_hostname.set(uci, data)
+		pretty_hostname.set(uci, data or default_hostname)
 	end
 
 	return {'system'}