diff --git a/data/hooks/conf_regen/01-yunohost b/data/hooks/conf_regen/01-yunohost
index 8b7a7c6fc..2d162e738 100755
--- a/data/hooks/conf_regen/01-yunohost
+++ b/data/hooks/conf_regen/01-yunohost
@@ -77,13 +77,27 @@ do_pre_regen() {
       cp services.yml /etc/yunohost/services.yml
   fi
 
+  mkdir -p $pending_dir/etc/cron.d/
+  mkdir -p $pending_dir/etc/cron.daily/
+
   # add cron job for diagnosis to be ran at 7h and 19h + a random delay between
   # 0 and 20min, meant to avoid every instances running their diagnosis at
   # exactly the same time, which may overload the diagnosis server.
-  mkdir -p $pending_dir/etc/cron.d/
   cat > $pending_dir/etc/cron.d/yunohost-diagnosis << EOF
 SHELL=/bin/bash
 0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%1200)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably"
+EOF
+
+  # Cron job that upgrade the app list everyday
+  cat > $pending_dir/etc/cron.daily/yunohost-fetch-apps-catalog << EOF
+#!/bin/bash
+(sleep \$((RANDOM%3600)); yunohost tools update --apps > /dev/null) &
+EOF
+
+  # Cron job that renew lets encrypt certificates if there's any that needs renewal
+  cat > $pending_dir/etc/cron.daily/yunohost-certificate-renew << EOF
+#!/bin/bash
+yunohost domain cert-renew --email
 EOF
 
   # If we subscribed to a dyndns domain, add the corresponding cron
@@ -137,6 +151,10 @@ do_post_regen() {
   find /etc/yunohost/certs/ -type f -exec chmod 640 {} \;
   find /etc/yunohost/certs/ -type d -exec chmod 750 {} \;
 
+  find /etc/cron.*/yunohost-* -type f -exec chmod 755 {} \;
+  find /etc/cron.d/yunohost-* -type f -exec chmod 644 {} \;
+  find /etc/cron.*/yunohost-* -type f -exec chmod root:root {} \;
+
   # Misc configuration / state files
   chown root:root $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null)
   chmod 600 $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null)
diff --git a/src/yunohost/app.py b/src/yunohost/app.py
index 3d1d16f3c..28d8681e6 100644
--- a/src/yunohost/app.py
+++ b/src/yunohost/app.py
@@ -66,7 +66,6 @@ APP_TMP_FOLDER = INSTALL_TMP + "/from_file"
 
 APPS_CATALOG_CACHE = "/var/cache/yunohost/repo"
 APPS_CATALOG_CONF = "/etc/yunohost/apps_catalog.yml"
-APPS_CATALOG_CRON_PATH = "/etc/cron.daily/yunohost-fetch-apps-catalog"
 APPS_CATALOG_API_VERSION = 2
 APPS_CATALOG_DEFAULT_URL = "https://app.yunohost.org/default"
 
@@ -3232,28 +3231,15 @@ def _parse_app_instance_name(app_instance_name):
 def _initialize_apps_catalog_system():
     """
     This function is meant to intialize the apps_catalog system with YunoHost's default app catalog.
-
-    It also creates the cron job that will update the list every day
     """
 
     default_apps_catalog_list = [{"id": "default", "url": APPS_CATALOG_DEFAULT_URL}]
 
-    cron_job = []
-    cron_job.append("#!/bin/bash")
-    # We add a random delay between 0 and 60 min to avoid every instance fetching
-    # the apps catalog at the same time every night
-    cron_job.append("(sleep $((RANDOM%3600));")
-    cron_job.append("yunohost tools update --apps > /dev/null) &")
     try:
         logger.debug(
             "Initializing apps catalog system with YunoHost's default app list"
         )
         write_to_yaml(APPS_CATALOG_CONF, default_apps_catalog_list)
-
-        logger.debug("Installing apps catalog fetch daily cron job")
-        write_to_file(APPS_CATALOG_CRON_PATH, "\n".join(cron_job))
-        chown(APPS_CATALOG_CRON_PATH, uid="root", gid="root")
-        chmod(APPS_CATALOG_CRON_PATH, 0o755)
     except Exception as e:
         raise YunohostError(
             "Could not initialize the apps catalog system... : %s" % str(e)
diff --git a/src/yunohost/certificate.py b/src/yunohost/certificate.py
index c48af2c07..43fe2af14 100644
--- a/src/yunohost/certificate.py
+++ b/src/yunohost/certificate.py
@@ -315,8 +315,6 @@ def _certificate_install_letsencrypt(
                     % domain
                 )
         else:
-            _install_cron(no_checks=no_checks)
-
             logger.success(m18n.n("certmanager_cert_install_success", domain=domain))
 
             operation_logger.success()
@@ -455,32 +453,6 @@ def certificate_renew(
 # Back-end stuff                                                            #
 #
 
-
-def _install_cron(no_checks=False):
-    cron_job_file = "/etc/cron.daily/yunohost-certificate-renew"
-
-    # we need to check if "--no-checks" isn't already put inside the existing
-    # crontab, if it's the case it's probably because another domain needed it
-    # at some point so we keep it
-    if not no_checks and os.path.exists(cron_job_file):
-        with open(cron_job_file, "r") as f:
-            # no the best test in the world but except if we uses a shell
-            # script parser I'm not expected a much more better way to do that
-            no_checks = "--no-checks" in f.read()
-
-    command = "yunohost domain cert-renew --email\n"
-
-    if no_checks:
-        # handle trailing "\n with ":-1"
-        command = command[:-1] + " --no-checks\n"
-
-    with open(cron_job_file, "w") as f:
-        f.write("#!/bin/bash\n")
-        f.write(command)
-
-    _set_permissions(cron_job_file, "root", "root", 0o755)
-
-
 def _email_renewing_failed(domain, exception_message, stack=""):
     from_ = "certmanager@%s (Certificate Manager)" % domain
     to_ = "root"
diff --git a/src/yunohost/tests/test_appscatalog.py b/src/yunohost/tests/test_appscatalog.py
index e3bd5d49d..a2619a660 100644
--- a/src/yunohost/tests/test_appscatalog.py
+++ b/src/yunohost/tests/test_appscatalog.py
@@ -19,13 +19,11 @@ from yunohost.app import (
     logger,
     APPS_CATALOG_CACHE,
     APPS_CATALOG_CONF,
-    APPS_CATALOG_CRON_PATH,
     APPS_CATALOG_API_VERSION,
     APPS_CATALOG_DEFAULT_URL,
 )
 
 APPS_CATALOG_DEFAULT_URL_FULL = _actual_apps_catalog_api_url(APPS_CATALOG_DEFAULT_URL)
-CRON_FOLDER, CRON_NAME = APPS_CATALOG_CRON_PATH.rsplit("/", 1)
 
 DUMMY_APP_CATALOG = """{
    "apps": {
@@ -50,10 +48,6 @@ def setup_function(function):
     # Clear apps catalog cache
     shutil.rmtree(APPS_CATALOG_CACHE, ignore_errors=True)
 
-    # Clear apps_catalog cron
-    if os.path.exists(APPS_CATALOG_CRON_PATH):
-        os.remove(APPS_CATALOG_CRON_PATH)
-
     # Clear apps_catalog conf
     if os.path.exists(APPS_CATALOG_CONF):
         os.remove(APPS_CATALOG_CONF)
@@ -67,11 +61,6 @@ def teardown_function(function):
     shutil.rmtree(APPS_CATALOG_CACHE, ignore_errors=True)
 
 
-def cron_job_is_there():
-    r = os.system("run-parts -v --test %s | grep %s" % (CRON_FOLDER, CRON_NAME))
-    return r == 0
-
-
 #
 # ################################################
 #
@@ -83,17 +72,12 @@ def test_apps_catalog_init(mocker):
     assert not glob.glob(APPS_CATALOG_CACHE + "/*")
     # Conf doesn't exist yet
     assert not os.path.exists(APPS_CATALOG_CONF)
-    # Conf doesn't exist yet
-    assert not os.path.exists(APPS_CATALOG_CRON_PATH)
 
     # Initialize ...
     mocker.spy(m18n, "n")
     _initialize_apps_catalog_system()
     m18n.n.assert_any_call("apps_catalog_init_success")
 
-    # Then there's a cron enabled
-    assert cron_job_is_there()
-
     # And a conf with at least one list
     assert os.path.exists(APPS_CATALOG_CONF)
     apps_catalog_list = _read_apps_catalog_list()