6380fbe4b41118dc8ab752c7205272d9a91c6655
10 L
.resolveDefault(fs
.stat('/usr/sbin/nginx'), {}),
11 L
.resolveDefault(fs
.stat('/usr/sbin/uhttpd'), {})
15 render: function (stats
) {
18 m
= new form
.Map("acme", _("ACME certificates"),
19 _("This configures ACME (Letsencrypt) automatic certificate installation. " +
20 "Simply fill out this to have the router configured with Letsencrypt-issued " +
21 "certificates for the web interface. " +
22 "Note that the domain names in the certificate must already be configured to " +
23 "point at the router's public IP address. " +
24 "Once configured, issuing certificates can take a while. " +
25 "Check the logs for progress and any errors.") + '<br/>' +
26 _("Cert files are stored in") + ' <em>/etc/ssl/acme<em>'
29 s
= m
.section(form
.TypedSection
, "acme", _("ACME global config"));
32 o
= s
.option(form
.Value
, "account_email", _("Account email"),
33 _("Email address to associate with account key."))
35 o
.datatype
= "minlength(1)";
37 o
= s
.option(form
.Flag
, "debug", _("Enable debug logging"));
40 s
= m
.section(form
.GridSection
, "cert", _("Certificate config"))
43 s
.nodescriptions
= true;
45 o
= s
.tab("general", _("General Settings"));
46 o
= s
.tab("challenge", _("Challenge Validation"));
47 o
= s
.tab("advanced", _('Advanced Settings'));
49 o
= s
.taboption('general', form
.Flag
, "enabled", _("Enabled"));
52 o
= s
.taboption('general', form
.DynamicList
, "domains", _("Domain names"),
53 _("Domain names to include in the certificate. " +
54 "The first name will be the subject name, subsequent names will be alt names. " +
55 "Note that all domain names must point at the router in the global DNS."));
56 o
.datatype
= "list(string)";
58 if (stats
[1].type
=== 'file') {
59 o
= s
.taboption('general', form
.Flag
, "update_uhttpd", _("Use for uhttpd"),
60 _("Update the uhttpd config with this certificate once issued " +
61 "(only select this for one certificate). " +
62 "Is also available luci-app-uhttpd to configure uhttpd form the LuCI interface."));
67 if (stats
[0].type
=== 'file') {
68 o
= s
.taboption('general', form
.Flag
, "update_nginx", _("Use for nginx"),
69 _("Update the nginx config with this certificate once issued " +
70 "(only select this for one certificate). " +
71 "Nginx must support ssl, if not it won't start as it needs to be " +
72 "compiled with ssl support to use cert options"));
77 o
= s
.taboption('challenge', form
.ListValue
, "validation_method", _("Validation method"),
78 _("Standalone mode will use the built-in webserver of acme.sh to issue a certificate. " +
79 "Webroot mode will use an existing webserver to issue a certificate. " +
80 "DNS mode will allow you to use the DNS API of your DNS provider to issue a certificate."));
81 o
.value("standalone", _("Standalone"));
82 o
.value("webroot", _("Webroot"));
83 o
.value("dns", _("DNS"));
84 o
.default = "standalone";
86 o
= s
.taboption('challenge', form
.Value
, "webroot", _("Webroot directory"),
87 _("Webserver root directory. Set this to the webserver " +
88 "document root to run Acme in webroot mode. The web " +
89 "server must be accessible from the internet on port 80."));
91 o
.depends("validation_method", "webroot");
94 o
= s
.taboption('challenge', form
.Value
, "dns", _("DNS API"),
95 _("To use DNS mode to issue certificates, set this to the name of a DNS API supported by acme.sh. " +
96 "See https://github.com/acmesh-official/acme.sh/wiki/dnsapi for the list of available APIs. " +
97 "In DNS mode, the domain name does not have to resolve to the router IP. " +
98 "DNS mode is also the only mode that supports wildcard certificates. " +
99 "Using this mode requires the acme-dnsapi package to be installed."));
100 o
.depends("validation_method", "dns");
103 o
= s
.taboption('challenge', form
.DynamicList
, "credentials", _("DNS API credentials"),
104 _("The credentials for the DNS API mode selected above. " +
105 "See https://github.com/acmesh-official/acme.sh/wiki/dnsapi for the format of credentials required by each API. " +
106 "Add multiple entries here in KEY=VAL shell variable format to supply multiple credential variables."))
107 o
.datatype
= "list(string)";
108 o
.depends("validation_method", "dns");
111 o
= s
.taboption('challenge', form
.Value
, "calias", _("Challenge Alias"),
112 _("The challenge alias to use for ALL domains. " +
113 "See https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode for the details of this process. " +
114 "LUCI only supports one challenge alias per certificate."));
115 o
.depends("validation_method", "dns");
118 o
= s
.taboption('challenge', form
.Value
, "dalias", _("Domain Alias"),
119 _("The domain alias to use for ALL domains. " +
120 "See https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode for the details of this process. " +
121 "LUCI only supports one challenge domain per certificate."));
122 o
.depends("validation_method", "dns");
126 o
= s
.taboption('advanced', form
.Flag
, 'use_staging', _('Use staging server'),
128 'Get certificate from the Letsencrypt staging server ' +
129 '(use for testing; the certificate won\'t be valid).'
135 o
= s
.taboption('advanced', form
.ListValue
, 'key_type', _('Key size'),
136 _('Key size (and type) for the generated certificate.')
138 o
.value('rsa2048', _('RSA 2048 bits'));
139 o
.value('rsa3072', _('RSA 3072 bits'));
140 o
.value('rsa4096', _('RSA 4096 bits'));
141 o
.value('ec256', _('ECC 256 bits'));
142 o
.value('ec384', _('ECC 384 bits'));
146 o
.cfgvalue = function(section_id
, set_value
) {
147 var keylength
= uci
.get('acme', section_id
, 'keylength');
149 // migrate the old keylength to a new keytype
151 case '2048': return 'rsa2048';
152 case '3072': return 'rsa3072';
153 case '4096': return 'rsa4096';
154 case 'ec-256': return 'ec256';
155 case 'ec-384': return 'ec384';
156 default: return ''; // bad value
161 o
.write = function(section_id
, value
) {
162 // remove old keylength
163 uci
.unset('acme', section_id
, 'keylength');
164 uci
.set('acme', section_id
, 'key_type', value
);
167 o
= s
.taboption('advanced', form
.Flag
, "use_acme_server",
168 _("Custom ACME CA"), _("Use a custom CA instead of Let's Encrypt."));
169 o
.depends("use_staging", "0");
173 o
= s
.taboption('advanced', form
.Value
, "acme_server", _("ACME server URL"),
174 _("Custom ACME server directory URL."));
175 o
.depends("use_acme_server", "1");
176 o
.placeholder
= "https://api.buypass.com/acme/directory";
180 o
= s
.taboption('advanced', form
.Value
, 'days', _('Days until renewal'));
183 o
.datatype
= 'uinteger';