Using Embedded Linux? Don't miss out on the valuable insights and time-saving tips in the article Embedded Linux Web Interface Design! This resource provides examples on how to control GPIOs and other helpful information for those using embedded Linux.
Real Time Logic provides pre-compiled binary versions at the makoserver.net website including many tutorials.
The pre-compiled versions include the following additional modules:
Pre-integrated DNS zone key for domain local.makoserver.net.
The pre-compiled Mako Server includes an embedded zone key for Real Time Logic's DNS testing service. See the Let's Encrypt configuration options and module acme/dns for more information.
The Mako Server's core logic is implemented in Lua and can be found in mako.zip. The server cannot operate without this ZIP file and will use an embedded version with simplified logic if it is unable to find mako.zip.
You may set the Mako Server in developer mode if you wish to change any of the Lua logic in mako.zip. The following example shows how you may set the server in developer mode by setting the environment variable MAKO_ZIP to a directory with a copy of the mako.zip content:
$ mkdir makozip $ cd makozip/ $ unzip ../mako.zip $ cd .. $ export MAKO_ZIP=makozip $ mako Mako Server. Version 3.0 BAS lib 4396. Build date: Jun 18 2019 Copyright (c) Real Time Logic. Mounting makozip Server listening on IPv6 port 9357 Server listening on IPv4 port 9357 Loading certificate MakoServer SharkSSL server listening on IPv6 port 9443 SharkSSL server listening on IPv4 port 9443
You can see from the above printouts how the server mounts the directory makozip instead of mako.zip.
The Mako Server is extremely easy to deploy (install) since only two files are required, the mako executable and the mako resource file mako.zip. The server does not need installation and can be run in a console window. On Windows, the server can optionally be installed as a Windows service. On all other platforms, the server can optionally be installed as a daemon (background) process.
The Mako Server will start as a foreground process if no arguments are provided. You may request the server to list all commands and then exit as follows:
mako -?
You may specify the location of an optional configuration file.
Example:mako -c mytestdir/mako.conf
See the Configuration File documentation for more information on how to use the configuration file.
-d - Run in daemon mode by detatching from the console -s - Run in daemon mode without detatching from the console -u username - Username to run as
sudo mako -l::myapp.zip -u `whoami`
Note: the server will open alternate ports above 1024 if it is unable to open the default ports.
An alternative to using the above command is to add the CAP_NET_BIND_SERVICE capability, which is explicitly defined as the capacity for an executable to bind to a port less than 1024, including when run as a non root Linux user.
sudo setcap cap_net_bind_service=+ep /path/2/mako
-install - Installs the service -installauto - Installs the service for autostart -remove - Removes the service -start - Starts the service -stop - Stops the service -restart - Stops and starts the service -autostart - Changes the service to automatic start -manual - Changes the service to manual start -minimize - Minimize the console window -elevate - Request elevated privileges
The commands 1 to 8 above are for installing and managing the server as a Windows service. For example, the following command installs the server as a service, enables auto start, and starts the service:
mako -l::myapp.zip -installauto
On Windows, administrative privileges are required in order to install a service. The Mako Server will request elevated permissions if the process or command window from where the service is installed does not run with elevated permissions.
The two command line options -elevate and -minimize are designed for creating web based dashboard like applications for Windows when not running as a service. When using both options, use the command line sequence -elevate -minimize to leave the current command line window (if any) "as is" and to only minimize the new command window that opens when running in elevated mode.
The following provides a quick introduction to running the Mako Server as a Windows service. For a more detailed explanation, see the tutorial Installing the Mako Server as a Windows Service.
A recommendation is to use a Mako Server Configuration File when starting the Mako Server as a Windows service. The following example uses the directory c:\wwwapps as the base and the sub directory mywww for storing the web application (HTML,LSP, etc).
The configuration file "mymako.conf" must use absolute paths:
apps={ { name="", path="/c/wwwapps/mywww"} } homeio="/c/wwwapps"Initially, test the configuration file without installing the server as a service:
mako -c c:\wwwapps\mymako.conf
Make sure you can navigate to your 'mywww' app. When working, install the server as a service as follows:
mako -c c:\wwwapps\mymako.conf -installauto
An application in the context of the Barracuda App Server is comparable to the 'www' directory found in other servers. Multiple web applications can be loaded simultaneously, and each application can be assigned a base URL. This URL serves as a unique identifier, helping to distinguish it from other loaded applications and prevent URL conflicts.
In the event of a name conflict, the server provides a priority option that can be assigned to each application. This priority setting determines which application takes precedence when a conflict occurs.
Applications are created through the Lua code found in the Mako Server's .config script, using LSP enabled Resource Reader instances. For more detailed information on this process, refer to the introduction to the virtual file system.
Applications are loaded by using command line options and/or by using the configuration file.
Loading apps via the command line:
-l[name]:[priority]:path - Load one or multiple applications
The following example loads three applications:
mako -lmyapp:1:path/2/myapp -lmyapp:0:myapp.zip -l::/path/2/my-root-app
The two myapp applications have the same base URI, but the non-deployed application has a higher priority than the deployed application myapp.zip. This means that resources are initially searched for in the non-deployed application and then fall back to the deployed application if not found in the non-deployed application. The last application loaded is a non deployed root application.
script - Execute the specified script and exit.
Description:
This option allows you to run the Mako Server in a special mode that closely resembles the behavior of the standard Lua interpreter. When you provide a script name as the only argument and without a preceding hyphen, the server will execute the specified script immediately upon starting.
During the execution of the script, the server operates as usual: it opens any configured ports and runs any necessary services. However, once the script completes its execution, the server shuts down completely, closing all ports and stopping all services.
Use Case:
This mode is handy for running initialization scripts, one-time setup tasks, or quick automated processes that require the extended Lua APIs provided by Mako Server but don't need the server to continue running afterward.
Example Usage:
mako myscript.lua
In the example above, the server will load and execute myscript.lua. After the script finishes, the server will terminate automatically.
See also Using The Mako Server Instead of Bash For Scripting and XLua.
The configuration file lets you customize the server's initialization of the Barracuda App Server and perform other initialization tasks. You can also use the configuration file for loading applications and setting your own configuration parameters.
If you do not specify a configuration file by using the "-c" command line option, the Mako Server looks for a configuration file by the name mako.conf in the following directories:
The configuration file uses Lua syntax. The Mako Server loads the configuration file as a Lua table; thus all configuration options must be provided as key/value pairs. The following key/value pairs are the available configuration options:
When the Mako Server creates a SharkSSL object using ba.create.sharkssl() for its secure server connection object, the associated certificate store is set to nil unless 'certstore' is set. In most typical web server operations, a certificate store is not required. However, if there is a requirement to authenticate HTTP clients, including web browsers, through client-side certificates, then it becomes necessary to establish a certificate store. To request a client certificate from server-side code, use the request:clientcert() method. The client's certificate can be verified using request:certificate(). For this verification to succeed and return true, the certificate store must contain the certificate of the authority that signed the client's certificate. To facilitate the creation of a certificate store for the SharkSSL object, you can specify the necessary configuration in mako.conf. This configuration can be a single string (for one certificate) or a table (for multiple certificates).
certstore = string | table
Examples:
certstore="my-CA-cert.pem" certstore={"my-CA-cert1.pem", "my-CA-cert2.pem"}
Set your own parameters in the configuration file and then access the configuration parameters from the loaded LSP applications. The configuration parameters are made available as a Lua module.
Example: Configuration File:myparam="This is my custom parameter"In your Lua code, load the configuration table as follows:
local conf=require"loadconf" print(conf.myparam) -- prints "This is my custom parameter"
Enable function mako.log(), which sends log/status information via e-mail. Log data is accumulated internally in the log module and an email is dispatched when either the accumulated data is larger than 'maxsize' or data has been accumulated for longer than 'sdelay' seconds. E-mails may also be sent immediately if the flush option is set when calling mako.log().
Table log:log = { smtp = { from = "john.doe@gmail.com", to = "john.doe@gmail.com", subject="My Server's Log", server = "smtp.googlemail.com", port = 465, useauth = true, consec = "tls", user = "john.doe@gmail.com", password = "qwerty" }, logerr = true, -- Send Lua exceptions by email signature = "Sent from my Mako Server" }
The Mako Server creates several Barracuda IO instances, and one of them is the home IO, the IO object returned when calling ba.openio("home"). Many applications and modules rely on a working home directory. The home directory is by default set to the execution directory. This works when the server runs in console mode and when the server runs in daemon mode on Linux since a startup script can change to a suitable home directory prior to starting the server in daemon mode. However, this does not work when run as a service on Windows.
The Mako Server provides a platform neutral way of setting the home directory by using the "homeio" option.
The following mako.conf example sets the home directory to c:\mako-home on a Windows computer:homeio="/c/mako-home" -- Must use POSIX path
If you are compiling the server's C code for an operating system that lacks the "executable directory" concept such as VxWorks, you may want to provide a hard coded default value in the C code. The hard coded value is used if "homeio" is not set. See the C macro MAKO_HOME_DIR for details.
Let's Encrypt is a free Certificate Authority (CA) and it's root certificate is installed in most browsers and secure client devices. Mako Server includes support for the Automated Certificate Management Environment (ACME) protocol used by the Let's Encrypt service.
The Mako Server's ACME plugin offers seamless certificate installation and renewal automation, requiring no manual user intervention. You can enable the plugin either through the mako.conf configuration file or programmatically using the two specialized modules acme/bot and acme/dns. Programmatically using the modules is required if you intend to develop a web interface allowing users to configure ACME settings.
See the tutorial Using The Let's Encrypt Plugin for a detailed introduction to using Let's Encrypt.
Note: The Let's Encrypt plugin creates a "cert" sub-directory in the home directory when activated. Certificates and Let's Encrypt configuration data are persistently stored in this directory. You must move this sub-directory if you move the home directory.
Note: Any error is printed to the console when the Mako Server runs in console mode. Errors are also sent to the trace. We recommend enabling the log option when the server runs in daemon mode to receive errors and status information via e-mail.
Proxy: All HTTP requests are routed via the configured proxy if the proxy configuration options are set.
Mako Server automatically loads module acme/bot when the following options are set. The server also loads module acme/dns if the DNS-01 challenge option is set.
Table acme:Note: when using the automatic dns-01 challenge option, servername, key, and secret are required; however, these settings can be set automatically by a compiled-in security module. See acmebot.configure() for details.
Examples:The following example shows how to activate the automatic http-01 challenge.
acme={ acceptterms=true, rsa=true, email="john.doe@company.com", domains={"company.com"} }
The above example requires that the server has a publicly available IP address or that you have set up port forwarding to port 80. The HTTP challenge option cannot be used if the server cannot be publicly accessed on the HTTP port 80. You must use the automatic or manual dns-01 challenge options if the server is not publicly available.
The following two example shows how to activate the automatic dns-01 challenge:
1) Server name, key, and secret in cleartext (not recommended):
acme={ acceptterms=true, rsa=true, email="john.doe@company.com", domains={"mydevice"}, -- Include only subdomain name challenge={ type="dns-01", servername="my-domain-name", key="64-byte-key", secret="64-byte-secret" } }
2) Server name, key, and secret provided by integrated security module:
acme={ acceptterms=true, rsa=true, email="john.doe@company.com", domains={"mydevice"}, -- Include only subdomain name challenge={type="dns-01"} }
See function acmedns.auto() for more information on how to use the automatic dns-01 challenge option.
The following example shows how to activate the manual dns-01 challenge.
acme={ acceptterms=true, rsa=true, email="john.doe@company.com", domains={"mydevice.company.com"}, challenge={type="dns-01", servername="manual"} }
The above configuration options activate module acme/dns in automatic renewal mode, but with manual DNS configuration. Module acme/dns prints a message in the console and sends you an email (if the log options are enabled) when it is time to renew the certificate. After setting the DNS TXT record as instructed in the email/console, run the following LSP script:
<?lsp local ok,err = require("acme/dns").recordset() if ok then print"Resuming renewal process..." else -- Renewal process most likely not active print("Resuming renewal process failed:", err) end ?>
See the acmedns example for additional information on using function acmedns.recordset()
The Let's Encrypt plugin creates a 'cert' sub-directory in the home directory for certificate storage and JSON configuration files. See the Module acme/bot for details on these files. Module acme/bot is used when enabling the Let's Encrypt options in mako.conf.
The Mako Server can load multiple applications and an application can be one of: directory, ZIP file, network path. Applications can be loaded by using the command line option -l and/or by creating an 'apps' table in the configuration file.
Table 'apps' is a list of one or several of the following:The following example loads three applications: the first application is provided as a string, and the other two applications are provided as a Lua table. Providing a Lua table allows for more configuration options. The last application is loaded as a root application since we set the name to an empty string. The first application's name is set to the name of the directory 'app1'.
apps={ "/path/2/app1", -- path to 'www' directory. Base URL is: http://server/app1 { name="myapp", -- Base URL is: http://server/myapp prio=1, -- Higher priority (for directory/resource name conflict resolution). path="/path/2/app2" -- path to 'www' directory dav=true, -- WebDAV at /myapp/dav/ }, { name="", -- Root app. -- Base URL is: http://server/ path="/path/2/app3" dav="fs", -- WebDAV at /fs/ auth=true, -- Enable WebDAV authentication } }
The proxy configuration options are required if the server runs in an environment that requires a proxy for connecting to the Internet.
Table proxy:The SSL Certificate option lets you load your own certificates. This option is great if you plan on creating your own public key infrastructure (PKI) by, for example, using our free Certificate Management Tool.
Note that the SSL Certificate option cannot be used in combination with the Let's Encrypt option.
Mako Server can load multiple certificates for various domains, but Mako Server also lets you load multiple certificates for the same domain name. SharkSSL then selects the certificate with the strongest cipher selection accepted by the client. Elliptic Curve Cryptography (ECC) certificates typically have a higher ranking than RSA certificates. The favorRSA option enables you to still favor RSA for clients that support both EC and RSA certificates. This option makes it possible to have a self signed ECC Certificate Authority (CA) and ECC chain for devices and serve RSA certificates for browsers. See the Certificate Management for IoT tutorial for details.
Enable the TraceLogger by setting one of the following two options:
When the TraceLogger is enabled, navigate to http://your-server/rtl/tracelogger/. Option two above requires a user database. Option two also calls the TraceLogger's dir:configure() method with the provided table thus enbling additional TraceLogger configuration.
Example:tracelogger={ auth=true, priority= 1 -- Filter out lower priority messages } users={ root="qwerty", }
You can setup a static user database that can be used by the WebDAV server(s), the TraceLogger, and custom authenticators. The user database is a key-value pair, where the key is the username and the value is the password. The password can be cleartext or HA1.
Example:users={ joe="querty", -- Joe's password is 'querty' alice={'ef8fef1da0258aea0d0d234ab05debaf'} -- Alice's password is a HA1 hash }
Function mako.udb() returns the static user database as an Authenticator User Database Object.
Realm name and HA1The realm is used by the Mako Server authenticators and the default realm name is "Barracuda Server". You may change the realm name as follows:
realm="My realm name"
Create a system wide Web File Server (WFS) at startup.
Table fileserver:Note: Unless noauth is set, the "fileserver" requires a user database and the fileserver parameter is ignored if no user database is configured.
MS Windows Example:fileserver={ fsname="fs", ioname="disk", path="/C", lockdir="temp/.LOCK" }
The Barracuda App Server powering the Mako Server is designed for deep embedded systems where one may have requirements on resource allocation. The server is therefore designed such that one must pre-allocate the number of resources required. The following allows you to modify these options. See the C reference manual for detailed information.
As an option to the end user, you may hide the creation and modifications of mako.conf; however, any changes require the Mako Server being restarted to take effect. As mentioned above, mako.conf uses Lua syntax and is loaded as a Lua table by using module loadconf.
Converting the loaded Lua table back to a configuration file can be done by using a library such as inspect.lua.
The Mako Server includes all Barracuda App Server APIs and features. The Mako Server also includes the following extended features:
The Mako Server has the concept of an application environment. The environment for an application is a location where you can keep commonly used Lua code, i.e. library functions. This environment is available to LSP pages in the application, but not to LSP pages in other applications. The application environment is referred to as the application table in our documentation. The Mako Server provides a number of environments that can be used by LSP programmers.
The Mako Server creates an application table/environment per loaded application. This table is known as the "app" table and is explained in section Command (Request/Response) Environment. See the Mako Server tutorial Lua Environments and the .preload Script for a more in depth explanation on how to use the .preload script.
The Mako Server looks for the .preload file in the application's root directory when starting an application. This file is loaded and executed as a Lua script, if found.
The preload script runs in the 'app' table environment (_ENV) and comes with the following pre-set values:
trace("Starting my application") trace("Path = "..io:realpath("")) trace("Base URL = "..dir:baseuri()) function onunload() trace("Stopping my application") end
The optional function 'onunload' is run when the application stops either when the server terminates or if the application is stopped by calling mako.stopapp or mako.reloadapp.
Functions and data in the .preload script are added to the application table. You can access this table from an LSP page as "app". For example, a function such as myfunc() can be accessed from an LSP page as app.myfunc().
For more information, see the tutorial Lua Environments and the .preload Script.
A function on the Windows version that translates a Windows path to a path that can be used by the IO interface.
Mako Server's require() function searches for Lua files in the same locations where the standalone Lua interpreter searches. Mako Server may be set to extend require()'s search path and enable loading of Lua scripts from within the application. To allow the loading of Lua script modules from your application, add the following line to the beginning of the application's .preload script.
mako.createloader(io) -- io is the application's pre-defined IO interface
The loader enables "require" to search for files in ".lua," a subdirectory in your Lua application. The loader works for both deployed and non-deployed Lua applications. In other words, the loader is effective for both deployed (ZIP) and non-deployed (directory) application formats, ensuring flexibility across different deployment scenarios.
The example application require-test (GitHub) shows how to use function "require" with Lua modules in a Mako application.
The function re-loads the certificates specified in mako.conf if no arguments are provided. The function enables an application to install new SSL certificates and then load the new certificates without having to restart the server. The Mako function loadcerts() is internally using the BAS function ba.create.servcon in the mode that enables it to recycle an existing server listening connection.
You may also dynamically load new certificates by providing the two arguments. The arguments keys and certs must have identical sized arrays with the keys and certs in the same order. Each element in the array is a string, which must be the pathname.
Note: Do not use this function if the Let's Encrypt plugin is enabled since use of this function would conflict with the Let's Encrypt plugin's use of this function.
Sends the message by e-mail if data logging has been enabled in the configuration file. The function returns true if data logging is enabled and false otherwise.
Log data is accumulated internally in the log module and an email is dispatched when either the accumulated data is larger than 'maxsize' or data has been accumulated for longer than 'sdelay' seconds. E-mails may also be sent immediately if the flush option is set.
Parameters:You may optionally set and override the following configuration options when 'flush' is set to true: 'from', 'to', and 'subject'. You may also add 'cc' and 'bcc'. See the SMTP library for details.
Deprecated. Use function ba.sharkclient().
Change trace name/location. This function enables you to dynamically change the name and/or location of the trace file in a running system. The argument "name" is the full trace file name including the path, which can be a relative path or an absolute path. The function returns true on success. The trace file is used by function trace(), Lua exceptions, and any traces enabled by the TraceLogger.
This function is created by mako.zip:/.config if a static user database has been set up in mako.conf.
The function returns the static user database as an Authenticator User Database Object.
Example usage:local auth = ba.create.authenticator(mako.udb())
You may control the applications loaded via command line parameters and the applications loaded via the configuration file. You may also dynamically create new applications.
Dynamically create and load a new application.
Parameters:Returns a table with all apps loaded by the Mako Server. The following example restarts all applications:
for ix,path in ipairs(mako.getapps()) do print("Reloading:",path) mako.reloadapp(ix) end
Reloads the .preload script for an app. Parameter x is either the application's environment or an index position returned by function mako.getapps(). The following code snippet can be used by an LSP page to reload the .preload script for the app:
mako.reloadapp(app) -- reload 'self'
Stops a registered application. Parameter x is either the application's environment (_ENV: app tab) or an index position returned by function mako.getapps().
Starts a registered application. Parameter x is either the application's environment or an index position returned by function mako.getapps().
Remove an app from the internal app DB stored in mako.zip:/.config. Note: this function does not change static options such as mako.conf. Parameter x is either the application's environment or an index position returned by function mako.getapps().
The Barracuda Application Server provides an IO interface in addition to the standard Lua input/output operations. These IO interfaces must be created by "C" code, and the Mako Server's C startup code creates the following IO interfaces:
The following example shows how to list all available IO interfaces:
for name,io in pairs(ba.io()) do print(name, ":", io:realpath"", " : ", io:resourcetype()) end
The above example produces the following output when run on Linux:
disk : / : disk POSIX home : ./ : disk POSIX net : nil : net vm : nil : zip zip
See io:realpath() and io:resourcetype() for details on the printouts.
The server makes the following global variables accessible to the loaded applications:
Mako Server includes all Barracuda App Server modules and protocols in addition to the following Mako Server specific modules:
Module acmebot is automatically loaded by mako.zip/.config if mako.conf includes the Let's Encrypt settings.
Note: The module creates a "cert" sub-directory in the home directory when activated. Certificates and Let's Encrypt configuration data are persistently stored in this directory. You must move this sub-directory if you move the home directory.
When activated, module acmebot runs in the background and uses module acme engine for the Let's Encrypt communication. The module returns a table with functions, where the following functions may be used by your programs:
The 'configure' function in combination with acmedns.auto() may be used as an alternative to using the Let's encrypt configuration option in mako.conf. The function configures acmebot and prepares the module for automatic certificate renewal.
This function is automatically called by Mako Server's .config script if the Let's encrypt configuration options are set in mako.conf. Calling the function when the acme options are set re-programs acmebot with new settings and the previous settings are discarded.
Parameters:Returns a table with the domains saved in cert/domains.json, where the key is the domain name and the value is the certificate expiration time in the format 'YYMMDDHHMMSSZ'. The certificate has not been issued if the expiration time string is empty. The domain name(s) may not be the same as the name(s) set when calling acmebot.set() or domains set via the mako.conf configuration file. The domain name(s) may be changed when using dns-01 challenge in combination with the DNS service.
Example:for domain,exp in pairs(acmebot.getdomains()) do if #exp > 0 then local y,m,d=exp:match"(%d%d)(%d%d)(%d%d)" print(string.format("%s expires year %s, month %s, day %s",domain,y,m,d)) else print(string.format("Certificate not issued for %s",domain)) end end
This function returns jobs [, domain [,error]
Module acme/bot creates a 'cert' sub-directory in the home directory for certificate storage and JSON configuration files.
Files created and maintained:The purpose of this module is to make it possible to install Let's Encrypt signed certificates for servers running on private networks. A detailed tutorial can be found on the Mako Server site.
Module acme/dns extends module acme/bot and implements the dns-01 challenge option. This module can either be used in automatic mode together with a DNS service, or the module can operate in manual DNS mode in which the server maintainer must manually set a DNS TXT record when the renewal process is initiated.
When using the automatic mode, the only function your program must call is acmedns.auto(), which should typically be called at system startup. The function may also be optionally called by an LSP page when a user initially configures the system by providing his/her email address and accepting the Let's Encrypt terms.
Note: - the functions acmedns.auto() or acmedns.manual() are automatically called by Mako Server's .config script if the Let's encrypt configuration options are set in mako.conf.
When not using mako.conf, the module is typically activated and reactivated programmatically as follows:
local options={revcon=true,acceptterms=true} local ad=require"acme/dns" ad.loadcert() -- Optional; expedite loading ad.isreg(function(name) if name then ad.auto(options) -- reactivate else -- first time -- email and sub-domain name provided by user or hardcoded: local email,subdom="info@realtimelogic.com", "xyz" -- If hardcoded, sub-domain is typically derived from MAC address ad.auto(email,subdom,options) end end)
The module returns a table with functions, where the following functions may be used by your programs:
Returns false if the module is inactive, the string "auto" if acme.auto() has been called, or the string "manual" if acme.manual() has been called.
Prepare acmedns for automatic DNS mode by setting the zone data. Function acmedns.configure() must be called prior to calling the functions: acmedns.auto(), acmedns.available(), and acmedns.isreg() if a security module is not installed.
Table op:Activate automatic certificate and DNS management by using an online instance of SharkTrustX DNS service. Note that the certificate renewal process takes more than two minutes to complete.
The function must be called each time the server starts, however, arguments email and subdomain are ignored if the server is already registered with the online DNS service. You may check if a certificate is installed by calling acmedns.auto{}. The return value is nil,error if the function must be called with the email and subdomain.
Parameters:
Returns:
Throws:
The function throws an error if a security module is not installed or alternatively, acmedns.configure() has not been called. An error is thrown since this is regarded as a program design error.
Example:The following example shows how the module can be initialized at system startup.
local acmedns=require"acme/dns" -- Call acmedns.configure(secrets) if a security module is not installed local op={rsa=true,acceptterms=true} local email,domain=acmedns.auto(op) if email then print("Your fully qualified domain name is:", domain) else print"Must register" acmedns.auto("john.doe@company.com","device",op) end
Check if a subdomain name is already in use by the zone. This function may be used by a user interface prior to calling acmedns.auto and may be used for presenting a name conflict warning.
Check if the server is registered with the online DNS service. The arguments to acmedns.auto() are ignored when this function returns state "Registered".
Enable the manual dns-01 challenge option.
Important: function acmedns.recordset() must be called after acmebot.manual() has been called and after the server maintainer has set the DNS record for the domain. The renewal process is paused until this function is called, and no new activation may be initiated as long as the current renewal job is paused. When using manual mode, function acmedns.loadcert() must be called when the device starts.
Parameters:The manual DNS challenge option must be used with the following support functions:
This function must be called at system startup when using acmedns.manual() but can also be used in automatic mode to expedite certificate loading for already registered devices (without waiting for the acmedns.auto() function to complete). If a certificate is successfully loaded, the function returns {key}, {certificate}. Otherwise, it returns false, indicating that the device has either no certificate or that the certificate has already been loaded.
Call this function if the dns-01 challenge option mode is set to "manual" and after setting the DNS TXT record for your domain name.
Note:
The function returns a table with the following {record=string, data=string, msg=string} if the certificate renewal job is active and if the job is waiting for the server maintainer to set the DNS TXT record. The 'record' is the DNS record value to set and 'data' is the DNS data value to set. The string 'msg' is a preformatted version of 'record' and 'data'.
local t=require"acme/dns".status() if t then print("record:",t.record) print("data:",t.data) else print"Not active. Activate by calling acmedns.manual()" end
<?lsp local acmedns=require"acme/dns" local acmebot=require"acme/bot" if request:method() == "GET" then local sT,jobs,domain,err local op={production=false,acceptterms=true} local ok,err=acmedns.manual("john.doe@company.com","device.company.com",op) if ok then repeat ba.sleep(200) -- wait sT=acmedns.status() jobs,domain,err=acmebot.status() until sT or err if not sT then ok=false end end if ok then print'<p>Set the following DNS TXT record:</p>' print('<pre>record:',sT.record) print('data:',sT.data,'</pre>') print'<p>Click button two minutes after setting TXT record</p>' print'<form method="post"><input type="submit"></form>' else print('<p>Renewing',domain,'failed, err:',err,'</p>') end else -- POST acmedns.recordset() -- Continue with renewal (resume background job) local jobs,domain,err repeat ba.sleep(200) -- wait jobs,domain,err=acmebot.status() until jobs == 0 if err then print('<p>Renewing',domain,'failed, err:',err,'</p>') else print('<p>Domain',domain,'renewed</p>') end end ?>
The above fully working example shows the complete process, from activating manual mode, to presenting the user with DNS TXT settings, followed by continuing the renewal process when the user clicks the submit button. However, note that the above is for illustration purposes only. A more advanced state machine would be needed for production code. For example, function acmedns.manual() should only be called at startup and/or when user changes the domain or email address. Blocking an LSP page by calling ba.sleep as done above is not recommended. Instead, use JavaScript and AJAX to poll for server status updates.
When the server restarts, the certificate must be loaded. To do so, include code similar to the following when the server starts. Notice the 'auto' attribute.
local op = {rsa = true, acceptterms = true, auto = true} acmedns.manual("john.doe@company.com", "device.company.com", op)
When using the automatic dns-01 challenge option, servername, key, and secret can be provided in cleartext. You may use the cleartext option for testing purposes, but these parameters should be protected in a production environment. An installed SharkTrustX server can automatically create a security module (C code) that may be compiled into the firmware or be dynamically loaded as a DLL/shared-library.
A security module is associated with a zone registered with the online SharkTrustX server. The online server generates the C code automatically when you navigate to https://registered-zone-name/cgen. You must first login as an administrator and then navigate to this URL.
The pre-compiled Mako Server delivered by Real Time Logic includes an embedded security module for the zone (domain name) https://local.makoserver.net/. This zone is registered with Real Time Logic's DNS testing service. The fully qualified domain name will be subdomain.local.makoserver.net, in which subdomain is the name set when calling acmedns.auto() or set via the configuration options. The integrated security module is used if you enable the automatic dns-01 challenge option without providing your own settings via the configuration file or by calling acmebot.configure().
See the Mako Server tutorial Lets-Encrypt for more information on using the security module.
Returns all options in mako.conf, including custom options, as a Lua table.
Example:for key,val in pairs(require"loadconf") do print("Key=",key, ", val=", val) end
Module log is automatically loaded by mako.zip/.config if mako.conf includes the data logging option. Module log activates function mako.log(). The module returns a table with functions, in which the following function may be used by your programs:
Send an email using the log module's pre-configured SMTP object.
Argument op is a Lua table. You may optionally set and override the following log configuration options: ('body' or htmlbody'), 'from', 'to', and 'subject'. You may also add 'cc' and 'bcc'. See the SMTP library for details.
Note that the sendmail function may also route outgoing SMTP requests via a proxy if the proxy options are set in mako.conf.
The pre-compiled Mako Server includes LPeg (Lua Parsing Expression Grammars). LPeg brings PEG to Lua. See the following for details:
Example:
-- Using the LPeg module local lpeg=require"lpeg" print(lpeg.match(lpeg.P'a','aaa')) -- prints: 2 -- Using the re module local re = require"re" -- find the position of the first numeral in a string print(re.find("the number 423 is odd", "[0-9]+")) -- prints: 12 14
The sqlutil library simplifies some of the tedious and repetitive operations when working with the luasql bindings. See the Lua SQLite Tutorial for examples on how to use this library. You may also study the SharkTrustX database module, which uses sqlutil for all database read operations.
The library is loaded as follows:
local su=require"sqlutil"
The sqlutil functions:
Function su.open() creates a database environment object by calling luasql.sqlite() and then opens the database file by calling env:connect().
Function su.open() returns two values, the database environment object and a database file connection object.
The complete database name is calculated as follows: (path from 1-4 above)/data/(name).sqlite.db
Options can be one of the two strings 'READONLY' or 'NOCREATE'. READONLY opens the connection in read only mode, and NOCREATE prevents creation of an SQL database.
Get the database directory (if no argument) or set the database directory, thus overriding the path calculated in step 1-4 in su.open().
Returns true if the database file exists, otherwise false is returned.
Search the database using the provided SQL query and return the first entry found. The first argument is either a connection object or a function that returns env,conn. The database is also automatically closed if the argument is a function.
Example:local a,b,c = su.find(conn,"a,b,c FROM table WHERE a='10' LIMIT 1")
Function su.findt is similar to su.find, except that the return values are saved in the provided table instead of being returned.
Simplifies iterating the results returned from an SQL SELECT query. When argument 'tab' is set, the response is a table with key/value pairs matching the query.
local function sqlIter(sql) local env,conn=su.open"mydb" local next = su.iter(conn, sql, true) return function() local t, err = next() if t then return t end if err then trace("Err:", err, sql) end conn:close() env:close() end end for tab in sqlIter("* FROM MyTable") do -- "SELECT is automatically prepended trace(ba.json.encode(tab)) end
Execute the provided SQL query and call the provided callback function "func". The first argument is either a connection object or a function that returns env,conn. The database is also automatically closed if the argument is a function.