diff --git a/data/templates/https/nginx.default.j2 b/data/templates/https/nginx.default.j2
index 80239ea56..a530c14ba 100644
--- a/data/templates/https/nginx.default.j2
+++ b/data/templates/https/nginx.default.j2
@@ -1,60 +1,60 @@
 ### Autogenerated by service_https.py ###
 # Default server configuration
 
 {% for server in server_block_list %}
 server {
         # SSL configuration
         #
 {%     if server.address == '*' %}
         listen {{ server.port }} ssl;
         listen [::]:{{ server.port }} ssl;
 {%     else %}
         listen {{ server.address | bracketize_ipv6 }}:{{ server.port }} ssl;
 {%     endif %}
 
 {%     for name in server.name %}
         server_name {{ name }};
 {%     endfor %}
 
         root /srv/localui;
 
-{%     if server.certbot %}
-        ssl_certificate {{ server.certbot_dir }}/live/{{ server.certbot_domain_dir }}/fullchain.pem;
-        ssl_certificate_key {{ server.certbot_dir }}/live/{{ server.certbot_domain_dir }}/privkey.pem;
-        include {{ server.certbot_dir }}/options-ssl-nginx.conf;
-        ssl_dhparam {{ server.certbot_dir }}/ssl-dhparams.pem;
-{%     elif server.vyos_cert %}
+{%     if server.vyos_cert %}
         ssl_certificate {{ server.vyos_cert.crt }};
         ssl_certificate_key {{ server.vyos_cert.key }};
 {%     else %}
         #
         # Self signed certs generated by the ssl-cert package
         # Don't use them in a production server!
         #
         include snippets/snakeoil.conf;
 {%     endif %}
+        ssl_session_cache shared:le_nginx_SSL:10m;
+        ssl_session_timeout 1440m;
+        ssl_session_tickets off;
+
         ssl_protocols TLSv1.2 TLSv1.3;
+        ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
 
         # proxy settings for HTTP API, if enabled; 503, if not
         location ~ ^/(retrieve|configure|config-file|image|container-image|generate|show|reboot|reset|poweroff|docs|openapi.json|redoc|graphql) {
 {%     if server.api %}
                 proxy_pass http://unix:/run/api.sock;
                 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                 proxy_set_header X-Forwarded-Proto $scheme;
                 proxy_read_timeout 600;
                 proxy_buffering off;
 {%     else %}
                 return 503;
 {%     endif %}
 {%     if server.allow_client %}
 {%         for client in server.allow_client %}
                 allow {{ client }};
 {%         endfor %}
                 deny all;
 {%     endif %}
         }
 
         error_page 497 =301 https://$host:{{ server.port }}$request_uri;
 }
 
 {% endfor %}
diff --git a/debian/control b/debian/control
index 8343144c4..726a083f2 100644
--- a/debian/control
+++ b/debian/control
@@ -1,333 +1,332 @@
 Source: vyos-1x
 Section: contrib/net
 Priority: extra
 Maintainer: VyOS Package Maintainers <maintainers@vyos.net>
 Build-Depends:
   debhelper (>= 9),
   dh-python,
   fakeroot,
   gcc,
   iproute2,
   libvyosconfig0 (>= 0.0.7),
   libzmq3-dev,
   python3 (>= 3.10),
 # For generating command definitions
   python3-lxml,
   python3-xmltodict,
 # For running tests
   python3-coverage,
   python3-netifaces,
   python3-nose,
   python3-jinja2,
   python3-psutil,
   python3-setuptools,
   python3-sphinx,
   quilt,
   whois
 Standards-Version: 3.9.6
 
 Package: vyos-1x
 Architecture: amd64 arm64
 Pre-Depends:
   libnss-tacplus [amd64],
   libpam-tacplus [amd64],
   libpam-radius-auth [amd64]
 Depends:
 ## Fundamentals
   ${python3:Depends} (>= 3.10),
   libvyosconfig0,
   vyatta-bash,
   vyatta-cfg,
   vyos-http-api-tools,
   vyos-utils,
 ## End of Fundamentals
 ## Python libraries used in multiple modules and scripts
   python3,
-  python3-certbot-nginx,
   python3-cryptography,
   python3-hurry.filesize,
   python3-inotify,
   python3-jinja2,
   python3-jmespath,
   python3-netaddr,
   python3-netifaces,
   python3-paramiko,
   python3-passlib,
   python3-psutil,
   python3-pyhumps,
   python3-pystache,
   python3-pyudev,
   python3-six,
   python3-tabulate,
   python3-voluptuous,
   python3-xmltodict,
   python3-zmq,
 ## End of Python libraries
 ## Basic System services and utilities
   sudo,
   systemd,
   bsdmainutils,
   openssl,
   curl,
   dbus,
   file,
   iproute2 (>= 6.0.0),
   linux-cpupower,
 # ipaddrcheck is widely used in IP value validators
   ipaddrcheck,
   ethtool,
   fdisk,
   lm-sensors,
   procps,
   netplug,
   sed,
   ssl-cert,
   tuned,
   beep,
   wide-dhcpv6-client,
 # Generic colorizer
   grc,
 ## End of System services and utilities
 ## For the installer
 # Image signature verification tool
   minisign,
 # Live filesystem tools
   squashfs-tools,
   fuse-overlayfs,
 ## End installer
   auditd,
   iputils-arping,
   isc-dhcp-client,
 # For "vpn pptp", "vpn l2tp", "vpn sstp", "service ipoe-server"
   accel-ppp,
 # End "vpn pptp", "vpn l2tp", "vpn sstp", "service ipoe-server"
   avahi-daemon,
   conntrack,
   conntrackd,
 ## Conf mode features
 # For "interfaces wireless"
   hostapd,
   hsflowd,
   iw,
   wireless-regdb,
   wpasupplicant (>= 0.6.7),
 # End "interfaces wireless"
 # For "interfaces wwan"
   modemmanager,
   usb-modeswitch,
   libqmi-utils,
 # End "interfaces wwan"
 # For "interfaces openvpn"
   openvpn,
   openvpn-auth-ldap,
   openvpn-auth-radius,
   openvpn-otp,
   libpam-google-authenticator,
 # End "interfaces openvpn"
 # For "interfaces wireguard"
   wireguard-tools,
   qrencode,
 # End "interfaces wireguard"
 # For "interfaces pppoe"
   pppoe,
 # End "interfaces pppoe"
 # For "interfaces sstpc"
   sstp-client,
 # End "interfaces sstpc"
 # For "protocols *"
   frr (>= 7.5),
   frr-pythontools,
   frr-rpki-rtrlib,
   frr-snmp,
 # End "protocols *"
 # For "protocols nhrp" (part of DMVPN)
   opennhrp,
 # End "protocols nhrp"
 # For "protocols igmp-proxy"
   igmpproxy,
 # End "protocols igmp-proxy"
 # For "pki"
   certbot,
 # End "pki"
 # For "service console-server"
   conserver-client,
   conserver-server,
   console-data,
   dropbear,
 # End "service console-server"
 # For "service aws glb"
   aws-gwlbtun,
 # For "service dns dynamic"
   ddclient (>= 3.11.1),
 # End "service dns dynamic"
 # # For "service ids"
   fastnetmon [amd64],
 # End "service ids"
 # # For "service ndp-proxy"
   ndppd,
 # End "service ndp-proxy"
 # For "service router-advert"
   radvd,
 # End "service route-advert"
 # For "high-availability reverse-proxy"
   haproxy,
 # End "high-availability reverse-proxy"
 # For "service dhcp-relay"
   isc-dhcp-relay,
 # For "service dhcp-server"
   kea,
 # End "service dhcp-server"
 # For "service lldp"
   lldpd,
 # End "service lldp"
 # For "service https"
   nginx-light,
 # End "service https"
 # For "service ssh"
   openssh-server,
   sshguard,
 # End "service ssh"
 # For "service salt-minion"
   salt-minion,
 # End "service salt-minion"
 # For "service snmp"
   snmp,
   snmpd,
 # End "service snmp"
 # For "service upnp"
   miniupnpd-nftables,
 # End "service upnp"
 # For "service webproxy"
   squid,
   squidclient,
   squidguard,
 # End "service webproxy"
 # For "service monitoring telegraf"
   telegraf (>= 1.20),
 # End "service monitoring telegraf"
 # For "service monitoring zabbix-agent"
   zabbix-agent2,
 # End "service monitoring zabbix-agent"
 # For "service tftp-server"
   tftpd-hpa,
 # End "service tftp-server"
 # For "service dns forwarding"
   pdns-recursor,
 # End "service dns forwarding"
 # For "service sla owamp"
   owamp-client,
   owamp-server,
 # End "service sla owamp"
 # For "service sla twamp"
   twamp-client,
   twamp-server,
 # End "service sla twamp"
 # For "service broadcast-relay"
   udp-broadcast-relay,
 # End "service broadcast-relay"
 # For "high-availability vrrp"
   keepalived (>=2.0.5),
 # End "high-availability-vrrp"
 # For "system task-scheduler"
   cron,
 # End "system task-scheduler"
 # For "system lcd"
   lcdproc,
   lcdproc-extra-drivers,
 # End "system lcd"
 # For "system config-management commit-archive"
   git,
 # End "system config-management commit-archive"
 # For firewall
   libndp-tools,
   libnetfilter-conntrack3,
   libnfnetlink0,
   nfct,
   nftables (>= 0.9.3),
 # For "vpn ipsec"
   strongswan (>= 5.9),
   strongswan-swanctl (>= 5.9),
   charon-systemd,
   libcharon-extra-plugins (>=5.9),
   libcharon-extauth-plugins (>=5.9),
   libstrongswan-extra-plugins (>=5.9),
   libstrongswan-standard-plugins (>=5.9),
   python3-vici (>= 5.7.2),
 # End "vpn ipsec"
 # For "nat64"
   jool,
 # End "nat64"
 # For "system ntp"
   chrony,
 # End "system ntp"
 # For "vpn openconnect"
   ocserv,
 # End "vpn openconnect"
 # For "system flow-accounting"
   pmacct (>= 1.6.0),
 # End "system flow-accounting"
 # For container
   podman,
   netavark,
   aardvark-dns,
 # iptables is only used for containers now, not the the firewall CLI
   iptables,
 # End container
 ## End Configuration mode
 ## Operational mode
 # Used for hypervisor model in "run show version"
   hvinfo,
 # For "run traceroute"
   traceroute,
 # For "run monitor traffic"
   tcpdump,
 # End "run monitor traffic"
 # For "show hardware dmi"
   dmidecode,
 # For "run show hardware storage smart"
   smartmontools,
 # For "run show hardware scsi"
   lsscsi,
 # For "run show hardware pci"
   pciutils,
 # For "show hardware usb"
   usbutils,
 # For "run show hardware storage nvme"
   nvme-cli,
 # For "run monitor bandwidth-test"
   iperf,
   iperf3,
 # End "run monitor bandwidth-test"
 # For "run wake-on-lan"
   etherwake,
 # For "run force ipv6-nd"
   ndisc6,
 # For "run monitor bandwidth"
   bmon,
 # End Operational mode
 ## Optional utilities
   easy-rsa,
   tcptraceroute,
   mtr-tiny,
   telnet,
   stunnel4,
   uidmap
 ## End optional utilities
 Description: VyOS configuration scripts and data
  VyOS configuration scripts, interface definitions, and everything
 
 Package: vyos-1x-vmware
 Architecture: amd64
 Depends:
  vyos-1x,
  open-vm-tools
 Description: VyOS configuration scripts and data for VMware
  Adds configuration files required for VyOS running on VMware hosts.
 
 Package: vyos-1x-smoketest
 Architecture: all
 Depends:
  skopeo,
  snmp,
  vyos-1x
 Description: VyOS build sanity checking toolkit
diff --git a/interface-definitions/include/version/https-version.xml.i b/interface-definitions/include/version/https-version.xml.i
index fa18278f3..525314dbd 100644
--- a/interface-definitions/include/version/https-version.xml.i
+++ b/interface-definitions/include/version/https-version.xml.i
@@ -1,3 +1,3 @@
 <!-- include start from include/version/https-version.xml.i -->
-<syntaxVersion component='https' version='5'></syntaxVersion>
+<syntaxVersion component='https' version='6'></syntaxVersion>
 <!-- include end -->
diff --git a/interface-definitions/service_https.xml.in b/interface-definitions/service_https.xml.in
index 223f10962..57f36a982 100644
--- a/interface-definitions/service_https.xml.in
+++ b/interface-definitions/service_https.xml.in
@@ -1,220 +1,202 @@
 <?xml version="1.0"?>
 <interfaceDefinition>
   <node name="service">
     <children>
       <node name="https" owner="${vyos_conf_scripts_dir}/service_https.py">
         <properties>
           <help>HTTPS configuration</help>
           <priority>1001</priority>
         </properties>
         <children>
           <tagNode name="virtual-host">
             <properties>
               <help>Identifier for virtual host</help>
               <constraint>
                 <regex>[a-zA-Z0-9-_.:]{1,255}</regex>
               </constraint>
               <constraintErrorMessage>illegal characters in identifier or identifier longer than 255 characters</constraintErrorMessage>
             </properties>
             <children>
               <leafNode name="listen-address">
                 <properties>
                   <help>Address to listen for HTTPS requests</help>
                   <completionHelp>
                     <script>${vyos_completion_dir}/list_local_ips.sh --both</script>
                   </completionHelp>
                   <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="ip-address"/>
                     <regex>\*</regex>
                   </constraint>
                 </properties>
               </leafNode>
               #include <include/port-number.xml.i>
               <leafNode name='port'>
                 <defaultValue>443</defaultValue>
               </leafNode>
               <leafNode name="server-name">
                 <properties>
                   <help>Server names: exact, wildcard, or regex</help>
                   <multi/>
                 </properties>
               </leafNode>
               #include <include/allow-client.xml.i>
             </children>
           </tagNode>
           <node name="api">
             <properties>
               <help>VyOS HTTP API configuration</help>
             </properties>
             <children>
               <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>
               <node name="graphql">
                 <properties>
                   <help>GraphQL support</help>
                 </properties>
                 <children>
                   <leafNode name="introspection">
                     <properties>
                       <help>Schema introspection</help>
                       <valueless/>
                     </properties>
                   </leafNode>
                   <node name="authentication">
                     <properties>
                       <help>GraphQL authentication</help>
                     </properties>
                     <children>
                       <leafNode name="type">
                         <properties>
                           <help>Authentication type</help>
                           <completionHelp>
                             <list>key token</list>
                           </completionHelp>
                           <valueHelp>
                             <format>key</format>
                             <description>Use API keys</description>
                           </valueHelp>
                           <valueHelp>
                             <format>token</format>
                             <description>Use JWT token</description>
                           </valueHelp>
                           <constraint>
                             <regex>(key|token)</regex>
                           </constraint>
                         </properties>
                         <defaultValue>key</defaultValue>
                       </leafNode>
                       <leafNode name="expiration">
                         <properties>
                           <help>Token time to expire in seconds</help>
                           <valueHelp>
                             <format>u32:60-31536000</format>
                             <description>Token lifetime in seconds</description>
                           </valueHelp>
                           <constraint>
                             <validator name="numeric" argument="--range 60-31536000"/>
                           </constraint>
                         </properties>
                         <defaultValue>3600</defaultValue>
                       </leafNode>
                       <leafNode name="secret-length">
                         <properties>
                           <help>Length of shared secret in bytes</help>
                           <valueHelp>
                             <format>u32:16-65535</format>
                             <description>Byte length of generated shared secret</description>
                           </valueHelp>
                           <constraint>
                             <validator name="numeric" argument="--range 16-65535"/>
                           </constraint>
                         </properties>
                         <defaultValue>32</defaultValue>
                       </leafNode>
                     </children>
                   </node>
                 </children>
               </node>
               <node name="cors">
                 <properties>
                   <help>Set CORS options</help>
                 </properties>
                 <children>
                   <leafNode name="allow-origin">
                     <properties>
                       <help>Allow resource request from origin</help>
                       <multi/>
                     </properties>
                   </leafNode>
                 </children>
               </node>
             </children>
           </node>
           <node name="api-restrict">
             <properties>
               <help>Restrict api proxy to subset of virtual hosts</help>
             </properties>
             <children>
               <leafNode name="virtual-host">
                 <properties>
                   <help>Restrict proxy to virtual host(s)</help>
                   <multi/>
                 </properties>
               </leafNode>
             </children>
           </node>
           <node name="certificates">
             <properties>
               <help>TLS certificates</help>
             </properties>
             <children>
               #include <include/pki/ca-certificate.xml.i>
               #include <include/pki/certificate.xml.i>
-              <node name="certbot" owner="${vyos_conf_scripts_dir}/service_https_certificates_certbot.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>
           #include <include/interface/vrf.xml.i>
         </children>
       </node>
     </children>
   </node>
 </interfaceDefinition>
diff --git a/src/conf_mode/service_https.py b/src/conf_mode/service_https.py
index cb40acc9f..2e7ebda5a 100755
--- a/src/conf_mode/service_https.py
+++ b/src/conf_mode/service_https.py
@@ -1,330 +1,289 @@
 #!/usr/bin/env python3
 #
 # Copyright (C) 2019-2024 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 os
 import sys
 import json
 
 from copy import deepcopy
 from time import sleep
 
 import vyos.defaults
-import vyos.certbot_util
 
 from vyos.base import Warning
 from vyos.config import Config
 from vyos.configdiff import get_config_diff
 from vyos.configverify import verify_vrf
 from vyos import ConfigError
 from vyos.pki import wrap_certificate
 from vyos.pki import wrap_private_key
 from vyos.template import render
 from vyos.utils.process import call
-from vyos.utils.process import is_systemd_service_running
-from vyos.utils.process import is_systemd_service_active
 from vyos.utils.network import check_port_availability
 from vyos.utils.network import is_listen_port_bind_service
 from vyos.utils.file import write_file
 
 from vyos import airbag
 airbag.enable()
 
 config_file = '/etc/nginx/sites-available/default'
 systemd_override = r'/run/systemd/system/nginx.service.d/override.conf'
 cert_dir = '/etc/ssl/certs'
 key_dir = '/etc/ssl/private'
-certbot_dir = vyos.defaults.directories['certbot']
 
 api_config_state = '/run/http-api-state'
 systemd_service = '/run/systemd/system/vyos-http-api.service'
 
-# https config needs to coordinate several subsystems: api, certbot,
+# https config needs to coordinate several subsystems: api,
 # self-signed certificate, as well as the virtual hosts defined within the
 # https config definition itself. Consequently, one needs a general dict,
 # encompassing the https and other configs, and a list of such virtual hosts
 # (server blocks in nginx terminology) to pass to the jinja2 template.
 default_server_block = {
     'id'        : '',
     'address'   : '*',
     'port'      : '443',
     'name'      : ['_'],
     'api'       : False,
     'vyos_cert' : {},
-    'certbot'   : False
 }
 
 def get_config(config=None):
     if config:
         conf = config
     else:
         conf = Config()
 
     base = ['service', 'https']
     if not conf.exists(base):
         return None
 
     diff = get_config_diff(conf)
 
     https = conf.get_config_dict(base, get_first_key=True, with_pki=True)
 
-    https['children_changed'] = diff.node_changed_children(base)
     https['api_add_or_delete'] = diff.node_changed_presence(base + ['api'])
 
     if 'api' not in https:
         return https
 
     http_api = conf.get_config_dict(base + ['api'], key_mangling=('-', '_'),
                                     no_tag_node_value_mangle=True,
                                     get_first_key=True,
                                     with_recursive_defaults=True)
 
     if http_api.from_defaults(['graphql']):
         del http_api['graphql']
 
     # Do we run inside a VRF context?
     vrf_path = ['service', 'https', 'vrf']
     if conf.exists(vrf_path):
         http_api['vrf'] = conf.return_value(vrf_path)
 
     https['api'] = http_api
-
     return https
 
 def verify(https):
     from vyos.utils.dict import dict_search
 
     if https is None:
         return None
 
     if 'certificates' in https:
         certificates = https['certificates']
 
         if 'certificate' in certificates:
             if not https['pki']:
                 raise ConfigError('PKI is not configured')
 
             cert_name = certificates['certificate']
 
             if cert_name not in https['pki']['certificate']:
-                raise ConfigError("Invalid certificate on https configuration")
+                raise ConfigError('Invalid certificate on https configuration')
 
             pki_cert = https['pki']['certificate'][cert_name]
 
             if 'certificate' not in pki_cert:
-                raise ConfigError("Missing certificate on https configuration")
+                raise ConfigError('Missing certificate on https configuration')
 
             if 'private' not in pki_cert or 'key' not in pki_cert['private']:
                 raise ConfigError("Missing certificate private key on https configuration")
-
-        if 'certbot' in https['certificates']:
-            vhost_names = []
-            for _, vh_conf in https.get('virtual-host', {}).items():
-                vhost_names += vh_conf.get('server-name', [])
-            domains = https['certificates']['certbot'].get('domain-name', [])
-            domains_found = [domain for domain in domains if domain in vhost_names]
-            if not domains_found:
-                raise ConfigError("At least one 'virtual-host <id> server-name' "
-                              "matching the 'certbot domain-name' is required.")
+    else:
+        Warning('No certificate specified, using buildin self-signed certificates!')
 
     server_block_list = []
 
     # organize by vhosts
     vhost_dict = https.get('virtual-host', {})
 
     if not vhost_dict:
         # no specified virtual hosts (server blocks); use default
         server_block_list.append(default_server_block)
     else:
         for vhost in list(vhost_dict):
             server_block = deepcopy(default_server_block)
             data = vhost_dict.get(vhost, {})
             server_block['address'] = data.get('listen-address', '*')
             server_block['port'] = data.get('port', '443')
             server_block_list.append(server_block)
 
     for entry in server_block_list:
         _address = entry.get('address')
         _address = '0.0.0.0' if _address == '*' else _address
         _port = entry.get('port')
         proto = 'tcp'
         if check_port_availability(_address, int(_port), proto) is not True and \
                 not is_listen_port_bind_service(int(_port), 'nginx'):
             raise ConfigError(f'"{proto}" port "{_port}" is used by another service')
 
     verify_vrf(https)
 
     # Verify API server settings, if present
     if 'api' in https:
         keys = dict_search('api.keys.id', https)
         gql_auth_type = dict_search('api.graphql.authentication.type', https)
 
         # If "api graphql" is not defined and `gql_auth_type` is None,
         # there's certainly no JWT auth option, and keys are required
         jwt_auth = (gql_auth_type == "token")
 
         # Check for incomplete key configurations in every case
         valid_keys_exist = False
         if keys:
             for k in keys:
                 if 'key' not in keys[k]:
                     raise ConfigError(f'Missing HTTPS API key string for key id "{k}"')
                 else:
                     valid_keys_exist = True
 
         # If only key-based methods are enabled,
         # fail the commit if no valid key configurations are found
         if (not valid_keys_exist) and (not jwt_auth):
             raise ConfigError('At least one HTTPS API key is required unless GraphQL token authentication is enabled')
 
         if (not valid_keys_exist) and jwt_auth:
             Warning(f'API keys are not configured: the classic (non-GraphQL) API will be unavailable.')
 
     return None
 
 def generate(https):
     if https is None:
         return None
 
     if 'api' not in https:
         if os.path.exists(systemd_service):
             os.unlink(systemd_service)
     else:
         render(systemd_service, 'https/vyos-http-api.service.j2', https['api'])
         with open(api_config_state, 'w') as f:
             json.dump(https['api'], f, indent=2)
 
     server_block_list = []
 
     # organize by vhosts
 
     vhost_dict = https.get('virtual-host', {})
 
     if not vhost_dict:
         # no specified virtual hosts (server blocks); use default
         server_block_list.append(default_server_block)
     else:
         for vhost in list(vhost_dict):
             server_block = deepcopy(default_server_block)
             server_block['id'] = vhost
             data = vhost_dict.get(vhost, {})
             server_block['address'] = data.get('listen-address', '*')
             server_block['port'] = data.get('port', '443')
             name = data.get('server-name', ['_'])
             server_block['name'] = name
             allow_client = data.get('allow-client', {})
             server_block['allow_client'] = allow_client.get('address', [])
             server_block_list.append(server_block)
 
     # get certificate data
 
     cert_dict = https.get('certificates', {})
 
     if 'certificate' in cert_dict:
         cert_name = cert_dict['certificate']
         pki_cert = https['pki']['certificate'][cert_name]
 
         cert_path = os.path.join(cert_dir, f'{cert_name}.pem')
         key_path = os.path.join(key_dir, f'{cert_name}.pem')
 
         server_cert = str(wrap_certificate(pki_cert['certificate']))
         if 'ca-certificate' in cert_dict:
             ca_cert = cert_dict['ca-certificate']
             server_cert += '\n' + str(wrap_certificate(https['pki']['ca'][ca_cert]['certificate']))
 
         write_file(cert_path, server_cert)
         write_file(key_path, wrap_private_key(pki_cert['private']['key']))
 
         vyos_cert_data = {
             'crt': cert_path,
             'key': key_path
         }
 
         for block in server_block_list:
             block['vyos_cert'] = vyos_cert_data
 
-    # letsencrypt certificate using certbot
-
-    certbot = False
-    cert_domains = cert_dict.get('certbot', {}).get('domain-name', [])
-    if cert_domains:
-        certbot = True
-        for domain in cert_domains:
-            sub_list = vyos.certbot_util.choose_server_block(server_block_list,
-                                                             domain)
-            if sub_list:
-                for sb in sub_list:
-                    sb['certbot'] = True
-                    sb['certbot_dir'] = certbot_dir
-                    # certbot organizes certificates by first domain
-                    sb['certbot_domain_dir'] = cert_domains[0]
-
     if 'api' in list(https):
         vhost_list = https.get('api-restrict', {}).get('virtual-host', [])
         if not vhost_list:
             for block in server_block_list:
                 block['api'] = True
         else:
             for block in server_block_list:
                 if block['id'] in vhost_list:
                     block['api'] = True
 
     data = {
         'server_block_list': server_block_list,
-        'certbot': certbot
     }
 
     render(config_file, 'https/nginx.default.j2', data)
     render(systemd_override, 'https/override.conf.j2', https)
     return None
 
 def apply(https):
     # Reload systemd manager configuration
     call('systemctl daemon-reload')
     http_api_service_name = 'vyos-http-api.service'
     https_service_name = 'nginx.service'
 
     if https is None:
-        if is_systemd_service_active(f'{http_api_service_name}'):
-            call(f'systemctl stop {http_api_service_name}')
+        call(f'systemctl stop {http_api_service_name}')
         call(f'systemctl stop {https_service_name}')
         return
 
-    if 'api' in https['children_changed']:
-        if 'api' in https:
-            if is_systemd_service_running(f'{http_api_service_name}'):
-                call(f'systemctl reload {http_api_service_name}')
-            else:
-                call(f'systemctl restart {http_api_service_name}')
-            # Let uvicorn settle before (possibly) restarting nginx
-            sleep(1)
-        else:
-            if is_systemd_service_active(f'{http_api_service_name}'):
-                call(f'systemctl stop {http_api_service_name}')
+    if 'api' in https:
+        call(f'systemctl reload-or-restart {http_api_service_name}')
+        # Let uvicorn settle before (possibly) restarting nginx
+        sleep(1)
+    else:
+        call(f'systemctl stop {http_api_service_name}')
 
-    if (not is_systemd_service_running(f'{https_service_name}') or
-        https['api_add_or_delete'] or
-        set(https['children_changed']) - set(['api'])):
-        call(f'systemctl restart {https_service_name}')
+    call(f'systemctl reload-or-restart {https_service_name}')
 
 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/service_https_certificates_certbot.py b/src/conf_mode/service_https_certificates_certbot.py
deleted file mode 100755
index 1a6a498de..000000000
--- a/src/conf_mode/service_https_certificates_certbot.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2019-2020 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 vyos.defaults
-from vyos.config import Config
-from vyos import ConfigError
-from vyos.utils.process import cmd
-from vyos.utils.process import call
-from vyos.utils.process import is_systemd_service_running
-
-from vyos import airbag
-airbag.enable()
-
-vyos_conf_scripts_dir = vyos.defaults.directories['conf_mode']
-vyos_certbot_dir = vyos.defaults.directories['certbot']
-
-dependencies = [
-    'service_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 = f'certbot certonly --config-dir {vyos_certbot_dir} -n --nginx --agree-tos --no-eff-email --expand {email_flag} {domain_flag}'
-
-    cmd(certbot_cmd,
-        raising=ConfigError,
-        message="The certbot request failed for the specified domains.")
-
-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
-    if not is_systemd_service_running('nginx.service'):
-        call('systemctl start nginx.service')
-
-    request_certbot(cert)
-
-def apply(cert):
-    if cert is not None:
-        call('systemctl restart certbot.timer')
-    else:
-        call('systemctl stop certbot.timer')
-        return None
-
-    for dep in dependencies:
-        cmd(f'{vyos_conf_scripts_dir}/{dep}', raising=ConfigError)
-
-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/migration-scripts/https/5-to-6 b/src/migration-scripts/https/5-to-6
new file mode 100755
index 000000000..b4159f02f
--- /dev/null
+++ b/src/migration-scripts/https/5-to-6
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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/>.
+
+# T5886: Add support for ACME protocol (LetsEncrypt), migrate https certbot
+#        to new "pki certificate" CLI tree
+
+import os
+import sys
+
+from vyos.configtree import ConfigTree
+from vyos.defaults import directories
+
+vyos_certbot_dir = directories['certbot']
+
+if len(sys.argv) < 2:
+    print("Must specify file name!")
+    sys.exit(1)
+
+file_name = sys.argv[1]
+
+with open(file_name, 'r') as f:
+    config_file = f.read()
+
+config = ConfigTree(config_file)
+
+base = ['service', 'https', 'certificates']
+if not config.exists(base):
+    # Nothing to do
+    sys.exit(0)
+
+# both domain-name and email must be set on CLI - ensured by previous verify()
+domain_names = config.return_values(base + ['certbot', 'domain-name'])
+email = config.return_value(base + ['certbot', 'email'])
+config.delete(base)
+
+# Set default certname based on domain-name
+cert_name = 'https-' + domain_names[0].split('.')[0]
+# Overwrite certname from previous certbot calls if available
+if os.path.exists(f'{vyos_certbot_dir}/live'):
+    for cert in [f.path.split('/')[-1] for f in os.scandir(f'{vyos_certbot_dir}/live') if f.is_dir()]:
+        cert_name = cert
+        break
+
+for domain in domain_names:
+    config.set(['pki', 'certificate', cert_name, 'acme', 'domain-name'], value=domain, replace=False)
+    config.set(['pki', 'certificate', cert_name, 'acme', 'email'], value=email)
+
+# Update Webserver certificate
+config.set(base + ['certificate'], value=cert_name)
+
+try:
+    with open(file_name, 'w') as f:
+        f.write(config.to_string())
+except OSError as e:
+    print("Failed to save the modified config: {}".format(e))
+    sys.exit(1)