diff --git a/package/gluon-core/luasrc/usr/bin/gluon-info b/package/gluon-core/luasrc/usr/bin/gluon-info
new file mode 100755
index 0000000000000000000000000000000000000000..c25018d189af7e055f435f407240e60aa09fb10a
--- /dev/null
+++ b/package/gluon-core/luasrc/usr/bin/gluon-info
@@ -0,0 +1,38 @@
+#!/usr/bin/lua
+
+local uci = require('simple-uci').cursor()
+local pretty_hostname = require 'pretty_hostname'
+
+local site = require 'gluon.site'
+local sysconfig = require 'gluon.sysconfig'
+local platform = require 'gluon.platform'
+local util = require 'gluon.util'
+local has_vpn, vpn = pcall(require, 'gluon.mesh-vpn')
+
+local pubkey
+if has_vpn and vpn.enabled() then
+	local _, active_vpn = vpn.get_active_provider()
+
+	if active_vpn ~= nil then
+		pubkey = active_vpn.public_key()
+	end
+end
+
+local values = {
+	{ 'Hostname', pretty_hostname.get(uci) },
+	{ 'MAC address', sysconfig.primary_mac },
+	{ 'Hardware model', platform.get_model() },
+	{ 'Gluon version / Site version', util.trim(util.readfile('/lib/gluon/gluon-version'))
+		.. ' / ' .. util.trim(util.readfile('/lib/gluon/site-version')) },
+	{ 'Firmware release', util.trim(util.readfile('/lib/gluon/release')) },
+	{ 'Site', site.site_name() },
+	{ 'Public VPN key', pubkey or 'n/a' },
+}
+
+local padTo = 24
+
+for _, info in ipairs(values) do
+	local labelLen = string.len(info[1]) + 1
+
+	print(info[1] .. ':' .. string.rep(' ', padTo - labelLen), info[2])
+end
diff --git a/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua b/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua
index 1d628dc76e6a490bad3b8e90e143213c33e15aa1..bcc6b5e13e91d6cdd86a41be1c6c86ad78942324 100644
--- a/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua
+++ b/package/gluon-mesh-vpn-fastd/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/fastd.lua
@@ -7,7 +7,13 @@ local vpn_core = require 'gluon.mesh-vpn'
 local M = {}
 
 function M.public_key()
-	return util.trim(util.exec('/etc/init.d/fastd show_key mesh_vpn'))
+	local key = util.trim(util.exec('/etc/init.d/fastd show_key mesh_vpn'))
+
+	if key == '' then
+		key = nil
+	end
+
+	return key
 end
 
 function M.enable(val)
diff --git a/package/gluon-mesh-vpn-wireguard/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/wireguard.lua b/package/gluon-mesh-vpn-wireguard/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/wireguard.lua
index 5065e217ce1ae1964f16a38344f29c19b1e7c542..b531b80ef2dc0cc8e88549709457d1397eb9887a 100644
--- a/package/gluon-mesh-vpn-wireguard/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/wireguard.lua
+++ b/package/gluon-mesh-vpn-wireguard/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/wireguard.lua
@@ -7,7 +7,13 @@ local vpn_core = require 'gluon.mesh-vpn'
 local M = {}
 
 function M.public_key()
-	return util.trim(util.exec("/lib/gluon/mesh-vpn/wireguard_pubkey.sh"))
+	local key = util.trim(util.exec("/lib/gluon/mesh-vpn/wireguard_pubkey.sh"))
+
+	if key == '' then
+		key = nil
+	end
+
+	return key
 end
 
 function M.enable(val)
diff --git a/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html
index 87c1179e9b0296da878c797690f00a9be93125e9..7e2c9e2df195acfb50ac49e3495618baeaa213b6 100644
--- a/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html
+++ b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html
@@ -18,17 +18,13 @@
 		if active_vpn ~= nil then
 			pubkey = active_vpn.public_key()
 		end
-
-		if pubkey == '' then
-			pubkey = nil
-		end
 	end
 
 	local values = {
 		{ _('Hostname'), pretty_hostname.get(uci) },
 		{ _('MAC address'), sysconfig.primary_mac },
 		{ _('Hardware model'), platform.get_model() },
-		{ _('Gluon version') .. " / " .. _('Site version'), util.trim(util.readfile('/lib/gluon/gluon-version')) 
+		{ _('Gluon version') .. " / " .. _('Site version'), util.trim(util.readfile('/lib/gluon/gluon-version'))
 			.. " / " .. util.trim(util.readfile('/lib/gluon/site-version')) },
 		{ _('Firmware release'), util.trim(util.readfile('/lib/gluon/release')) },
 		{ _('Site'), site.site_name() },