diff --git a/debian/control b/debian/control
index 9df421977..bca066aff 100644
--- a/debian/control
+++ b/debian/control
@@ -1,97 +1,98 @@
 Source: vyos-1x
 Section: contrib/net
 Priority: extra
 Maintainer: VyOS Package Maintainers <maintainers@vyos.net>
 Build-Depends: debhelper (>= 9),
   quilt,
   python3,
   python3-setuptools,
   quilt,
   python3-lxml,
   python3-nose,
   python3-coverage,
   whois,
   fakeroot,
   libvyosconfig0 (>= 0.0.7)
 Standards-Version: 3.9.6
 
 Package: vyos-1x
 Architecture: all
 Depends: python3,
   ${python3:Depends},
   python3-netifaces,
   python3-jinja2,
   python3-pystache,
   python3-psutil,
   python3-tabulate,
   python3-six,
   python3-isc-dhcp-leases,
   python3-hurry.filesize,
   python3-vici (>= 5.7.2),
   python3-bottle,
   python3-zmq,
   cron,
   ipaddrcheck,
   tcpdump,
   tshark,
   bmon,
   hvinfo,
   file,
   lsscsi,
   pciutils,
   usbutils,
   procps,
   snmp, snmpd,
   openssh-server,
   ntp,
   ntpdate,
   iputils-arping,
   libvyosconfig0,
   beep,
   isc-dhcp-server,
   isc-dhcp-relay,
   keepalived (>=2.0.5),
   wireguard,
   tftpd-hpa,
   igmpproxy,
   accel-ppp,
   mdns-repeater,
   udp-broadcast-relay,
   pdns-recursor,
   lcdproc,
   lcdproc-extra-drivers,
   openvpn,
   openvpn-auth-ldap,
   openvpn-auth-radius,
   mtr-tiny,
   telnet,
   traceroute,
   vyos-qat-kernel-modules,
   vyos-qat-utilities,
   ssl-cert,
   nginx-light,
   lldpd,
   iperf,
   iperf3,
   frr,
   dbus,
   hostapd (>= 0.6.8),
   wpasupplicant (>= 0.6.7),
   iw,
   crda,
   wireless-regdb,
   pmacct (>= 1.6.0),
+  python3-certbot-nginx,
   ${shlibs:Depends},
   ${misc:Depends}
 Description: VyOS configuration scripts and data
  VyOS configuration scripts, interface definitions, and everything
 
 Package: vyos-1x-vmware
 Architecture: amd64 i386
 Depends:
  ${misc:Depends},
  ${shlibs:Depends},
  open-vm-tools
 Description: VyOS configuration scripts and data for VMware
  Adds configuration files required for VyOS running on VMware hosts.
 
diff --git a/interface-definitions/https.xml.in b/interface-definitions/https.xml.in
index 4c91bbd94..4f940f7f6 100644
--- a/interface-definitions/https.xml.in
+++ b/interface-definitions/https.xml.in
@@ -1,134 +1,151 @@
 <?xml version="1.0"?>
 <!-- HTTPS configuration -->
 <interfaceDefinition>
   <node name="service">
     <children>
       <node name="https" owner="${vyos_conf_scripts_dir}/https.py">
         <properties>
           <help>HTTPS configuration</help>
           <priority>1001</priority>
         </properties>
         <children>
           <tagNode name="listen-address">
             <properties>
               <help>Addresses to listen for HTTPS requests</help>
               <valueHelp>
                 <format>ipv4</format>
                 <description>HTTPS IPv4 address</description>
               </valueHelp>
               <valueHelp>
                 <format>ipv6</format>
                 <description>HTTPS IPv6 address</description>
               </valueHelp>
               <valueHelp>
                 <format>'*'</format>
                 <description>any</description>
               </valueHelp>
               <constraint>
                 <validator name="ipv4-address"/>
                 <validator name="ipv6-address"/>
                 <regex>\*$</regex>
               </constraint>
             </properties>
             <children>
               <leafNode name='listen-port'>
                 <properties>
                   <help>Port to listen for HTTPS requests; default 443</help>
                   <valueHelp>
                     <format>1-65535</format>
                     <description>Numeric IP port</description>
                   </valueHelp>
                   <constraint>
                     <validator name="numeric" argument="--range 1-65535"/>
                   </constraint>
                 </properties>
               </leafNode>
               <leafNode name="server-name">
                 <properties>
                   <help>Server names: exact, wildcard, regex, or '_' (any)</help>
                   <multi/>
                 </properties>
               </leafNode>
             </children>
           </tagNode>
-          <node name="certificates">
-            <properties>
-              <help>TLS certificates</help>
-            </properties>
-            <children>
-              <node name="system-generated-certificate" owner="${vyos_conf_scripts_dir}/vyos_cert.py">
-                <properties>
-                  <help>Use an automatically generated self-signed certificate</help>
-                  <valueless/>
-                </properties>
-                <children>
-                  <leafNode name="lifetime">
-                    <properties>
-                      <help>Lifetime in days; default is 365</help>
-                      <valueHelp>
-                        <format>1-65535</format>
-                        <description>Number of days</description>
-                      </valueHelp>
-                    </properties>
-                  </leafNode>
-                </children>
-              </node>
-            </children>
-          </node>
           <node name="api" owner="${vyos_conf_scripts_dir}/http-api.py">
             <properties>
               <help>VyOS HTTP API configuration</help>
               <priority>1002</priority>
             </properties>
             <children>
               <leafNode name="port">
                 <properties>
                   <help>Port for HTTP API service</help>
                   <valueHelp>
                     <format>1-65535</format>
                     <description>Numeric IP port</description>
                   </valueHelp>
                   <constraint>
                     <validator name="numeric" argument="--range 1-65535"/>
                   </constraint>
                 </properties>
               </leafNode>
               <node name="keys">
                 <properties>
                   <help>HTTP API keys</help>
                 </properties>
                 <children>
                   <tagNode name="id">
                     <properties>
                       <help>HTTP API id</help>
                     </properties>
                     <children>
                       <leafNode name="key">
                         <properties>
                           <help>HTTP API plaintext key</help>
                         </properties>
                       </leafNode>
                     </children>
                   </tagNode>
                 </children>
               </node>
               <leafNode name="strict">
                 <properties>
                   <help>Enforce strict path checking</help>
                   <valueless/>
                 </properties>
               </leafNode>
               <leafNode name="debug">
                 <properties>
                   <help>Debug</help>
                   <valueless/>
                   <hidden/>
                 </properties>
               </leafNode>
             </children>
           </node>
+          <node name="certificates">
+            <properties>
+              <help>TLS certificates</help>
+            </properties>
+            <children>
+              <node name="system-generated-certificate" owner="${vyos_conf_scripts_dir}/vyos_cert.py">
+                <properties>
+                  <help>Use an automatically generated self-signed certificate</help>
+                </properties>
+                <children>
+                  <leafNode name="lifetime">
+                    <properties>
+                      <help>Lifetime in days; default is 365</help>
+                      <valueHelp>
+                        <format>1-65535</format>
+                        <description>Number of days</description>
+                      </valueHelp>
+                    </properties>
+                  </leafNode>
+                </children>
+              </node>
+              <node name="certbot" owner="${vyos_conf_scripts_dir}/le_cert.py">
+                <properties>
+                  <help>Request or apply a letsencrypt certificate for domain-name</help>
+                </properties>
+                <children>
+                  <leafNode name="domain-name">
+                    <properties>
+                      <help>Domain name(s) for which to obtain certificate</help>
+                      <multi/>
+                    </properties>
+                  </leafNode>
+                  <leafNode name="email">
+                      <properties>
+                          <help>Email address to associate with certificate</help>
+                      </properties>
+                  </leafNode>
+                </children>
+              </node>
+            </children>
+          </node>
         </children>
       </node>
     </children>
   </node>
 </interfaceDefinition>
diff --git a/python/vyos/certbot_util.py b/python/vyos/certbot_util.py
new file mode 100644
index 000000000..df42d4780
--- /dev/null
+++ b/python/vyos/certbot_util.py
@@ -0,0 +1,58 @@
+# certbot_util -- adaptation of certbot_nginx name matching functions for VyOS
+# https://github.com/certbot/certbot/blob/master/LICENSE.txt
+
+from certbot_nginx import parser
+
+NAME_RANK = 0
+START_WILDCARD_RANK = 1
+END_WILDCARD_RANK = 2
+REGEX_RANK = 3
+
+def _rank_matches_by_name(server_block_list, target_name):
+    """Returns a ranked list of server_blocks that match target_name.
+    Adapted from the function of the same name in
+    certbot_nginx.NginxConfigurator
+    """
+    matches = []
+    for server_block in server_block_list:
+        name_type, name = parser.get_best_match(target_name,
+                                                server_block['name'])
+        if name_type == 'exact':
+            matches.append({'vhost': server_block,
+                            'name': name,
+                            'rank': NAME_RANK})
+        elif name_type == 'wildcard_start':
+            matches.append({'vhost': server_block,
+                            'name': name,
+                            'rank': START_WILDCARD_RANK})
+        elif name_type == 'wildcard_end':
+            matches.append({'vhost': server_block,
+                            'name': name,
+                            'rank': END_WILDCARD_RANK})
+        elif name_type == 'regex':
+            matches.append({'vhost': server_block,
+                            'name': name,
+                            'rank': REGEX_RANK})
+
+    return sorted(matches, key=lambda x: x['rank'])
+
+def _select_best_name_match(matches):
+    """Returns the best name match of a ranked list of server_blocks.
+    Adapted from the function of the same name in
+    certbot_nginx.NginxConfigurator
+    """
+    if not matches:
+        return None
+    elif matches[0]['rank'] in [START_WILDCARD_RANK, END_WILDCARD_RANK]:
+        rank = matches[0]['rank']
+        wildcards = [x for x in matches if x['rank'] == rank]
+        return max(wildcards, key=lambda x: len(x['name']))['vhost']
+    else:
+        return matches[0]['vhost']
+
+def choose_server_block(server_block_list, target_name):
+    matches = _rank_matches_by_name(server_block_list, target_name)
+    server_blocks = [x for x in [_select_best_name_match(matches)]
+                     if x is not None]
+    return server_blocks
+
diff --git a/src/conf_mode/https.py b/src/conf_mode/https.py
index fbd351e45..2b492be26 100755
--- a/src/conf_mode/https.py
+++ b/src/conf_mode/https.py
@@ -1,175 +1,201 @@
 #!/usr/bin/env python3
 #
 # Copyright (C) 2019 VyOS maintainers and contributors
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 or later as
 # published by the Free Software Foundation.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 #
 
 import sys
 import os
 
 import jinja2
 
 import vyos.defaults
+import vyos.certbot_util
 from vyos.config import Config
 from vyos import ConfigError
 
 config_file = '/etc/nginx/sites-available/default'
 
 # Please be careful if you edit the template.
 config_tmpl = """
 
 ### Autogenerated by https.py ###
 # Default server configuration
 #
 server {
         listen 80 default_server;
         listen [::]:80 default_server;
         server_name _;
         return 301 https://$server_name$request_uri;
 }
 
 {% for server in server_block_list %}
 server {
 
         # SSL configuration
         #
 {% if server.address == '*' %}
         listen 443 ssl;
         listen [::]:443 ssl;
 {% else %}
         listen {{ server.address }}:{{ server.port }} ssl;
 {% endif %}
 
 {% for name in server.name %}
         server_name {{ name }};
 {% endfor %}
 
-{% if server.vyos_cert %}
+{% if server.certbot %}
+        ssl_certificate /etc/letsencrypt/live/{{ server.certbot_dir }}/fullchain.pem;
+        ssl_certificate_key /etc/letsencrypt/live/{{ server.certbot_dir }}/privkey.pem;
+        include /etc/letsencrypt/options-ssl-nginx.conf;
+        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
+{% elif server.vyos_cert %}
         include {{ server.vyos_cert.conf }};
 {% else %}
         #
         # Self signed certs generated by the ssl-cert package
         # Don't use them in a production server!
         #
         include snippets/snakeoil.conf;
 {% endif %}
 
         # proxy settings for HTTP API, if enabled; 503, if not
         location ~ /(retrieve|configure|config-file|image) {
 {% if server.api %}
                 proxy_pass http://localhost:{{ server.api.port }};
                 proxy_buffering off;
 {% else %}
                 return 503;
 {% endif %}
         }
 
         error_page 501 502 503 =200 @50*_json;
 
         location @50*_json {
                 default_type application/json;
                 return 200 '{"error": "Start service in configuration mode: set service https api"}';
         }
 
 }
 
 {% endfor %}
 """
 
 default_server_block = {
     'address'   : '*',
     'name'      : ['_'],
-    # api       :
-    # vyos_cert :
-    # le_cert   :
+    'api'       : {},
+    'vyos_cert' : {},
+    'certbot'   : False
 }
 
 def get_config():
     server_block_list = []
     conf = Config()
     if not conf.exists('service https'):
         return None
     else:
         conf.set_level('service https')
 
     if conf.exists('listen-address'):
         for addr in conf.list_nodes('listen-address'):
             server_block = {'address' : addr}
             server_block['port'] = '443'
             server_block['name'] = ['_']
             if conf.exists('listen-address {0} listen-port'.format(addr)):
                 port = conf.return_value('listen-address {0} listen-port'.format(addr))
                 server_block['port'] = port
             if conf.exists('listen-address {0} server-name'.format(addr)):
                 names = conf.return_values('listen-address {0} server-name'.format(addr))
                 server_block['name'] = names[:]
             server_block_list.append(server_block)
 
     if not server_block_list:
         server_block_list.append(default_server_block)
 
     vyos_cert_data = {}
-    if conf.exists('certificates'):
-        if conf.exists('certificates system-generated-certificate'):
-            vyos_cert_data = vyos.defaults.vyos_cert_data
+    if conf.exists('certificates system-generated-certificate'):
+        vyos_cert_data = vyos.defaults.vyos_cert_data
     if vyos_cert_data:
         for block in server_block_list:
             block['vyos_cert'] = vyos_cert_data
 
+    certbot = False
+    certbot_domains = []
+    if conf.exists('certificates certbot domain-name'):
+        certbot_domains = conf.return_values('certificates certbot domain-name')
+    if certbot_domains:
+        certbot = True
+        for domain in certbot_domains:
+            sub_list = vyos.certbot_util.choose_server_block(server_block_list,
+                                                             domain)
+            if sub_list:
+                for sb in sub_list:
+                    sb['certbot'] = True
+                    # certbot organizes certificates by first domain
+                    sb['certbot_dir'] = certbot_domains[0]
+
     api_data = {}
     if conf.exists('api'):
         api_data = vyos.defaults.api_data
         if conf.exists('api port'):
             port = conf.return_value('api port')
             api_data['port'] = port
     if api_data:
         for block in server_block_list:
             block['api'] = api_data
 
-    https = {'server_block_list' : server_block_list}
+    https = {'server_block_list' : server_block_list, 'certbot': certbot}
     return https
 
 def verify(https):
+    if https['certbot']:
+        for sb in https['server_block_list']:
+            if sb['certbot']:
+                return None
+        raise ConfigError("At least one 'listen-address x.x.x.x server-name' "
+                          "matching the 'certbot domain-name' is required.")
     return None
 
 def generate(https):
     if https is None:
         return None
 
     if 'server_block_list' not in https or not https['server_block_list']:
         https['server_block_list'] = [default_server_block]
 
     tmpl = jinja2.Template(config_tmpl, trim_blocks=True)
     config_text = tmpl.render(https)
     with open(config_file, 'w') as f:
         f.write(config_text)
 
     return None
 
 def apply(https):
     if https is not None:
         os.system('sudo systemctl restart nginx.service')
     else:
         os.system('sudo systemctl stop nginx.service')
 
 if __name__ == '__main__':
     try:
         c = get_config()
         verify(c)
         generate(c)
         apply(c)
     except ConfigError as e:
         print(e)
         sys.exit(1)
diff --git a/src/conf_mode/le_cert.py b/src/conf_mode/le_cert.py
new file mode 100755
index 000000000..c657098e1
--- /dev/null
+++ b/src/conf_mode/le_cert.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2019 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+#
+
+import sys
+import os
+import subprocess
+
+import vyos.defaults
+from vyos.config import Config
+from vyos import ConfigError
+
+vyos_conf_scripts_dir = vyos.defaults.directories['conf_mode']
+
+dependencies = [
+    'https.py',
+]
+
+def request_certbot(cert):
+    email = cert.get('email')
+    if email is not None:
+        email_flag = '-m {0}'.format(email)
+    else:
+        email_flag = ''
+
+    domains = cert.get('domains')
+    if domains is not None:
+        domain_flag = '-d ' + ' -d '.join(domains)
+    else:
+        domain_flag = ''
+
+    certbot_cmd = 'certbot certonly -n --nginx --agree-tos --no-eff-email --expand {0} {1}'.format(email_flag, domain_flag)
+
+    completed = subprocess.run(certbot_cmd, shell=True)
+
+    return completed.returncode
+
+def get_config():
+    conf = Config()
+    if not conf.exists('service https certificates certbot'):
+        return None
+    else:
+        conf.set_level('service https certificates certbot')
+
+    cert = {}
+
+    if conf.exists('domain-name'):
+        cert['domains'] = conf.return_values('domain-name')
+
+    if conf.exists('email'):
+        cert['email'] = conf.return_value('email')
+
+    return cert
+
+def verify(cert):
+    if cert is None:
+        return None
+
+    if 'domains' not in cert:
+        raise ConfigError("At least one domain name is required to"
+                          " request a letsencrypt certificate.")
+
+    if 'email' not in cert:
+        raise ConfigError("An email address is required to request"
+                          " a letsencrypt certificate.")
+
+def generate(cert):
+    if cert is None:
+        return None
+
+    # certbot will attempt to reload nginx, even with 'certonly';
+    # start nginx if not active
+    ret = os.system('systemctl is-active --quiet nginx.ervice')
+    if ret:
+        os.system('sudo systemctl start nginx.service')
+
+    ret = request_certbot(cert)
+    if ret:
+        raise ConfigError("The certbot request failed for the"
+                          " specified domains.")
+
+def apply(cert):
+    if cert is not None:
+        os.system('sudo systemctl restart certbot.timer')
+    else:
+        os.system('sudo systemctl stop certbot.timer')
+        return None
+
+    for dep in dependencies:
+        cmd = '{0}/{1}'.format(vyos_conf_scripts_dir, dep)
+        try:
+            subprocess.check_call(cmd, shell=True)
+        except subprocess.CalledProcessError as err:
+            raise ConfigError(str(err))
+
+if __name__ == '__main__':
+    try:
+        c = get_config()
+        verify(c)
+        generate(c)
+        apply(c)
+    except ConfigError as e:
+        print(e)
+        sys.exit(1)
+