diff --git a/restic_compose_backup.env b/restic_compose_backup.env
index 1a4b8fe..b3af3cb 100644
--- a/restic_compose_backup.env
+++ b/restic_compose_backup.env
@@ -10,6 +10,7 @@ RESTIC_KEEP_MONTHLY=12
 RESTIC_KEEP_YEARLY=3
 
 LOG_LEVEL=info
+CRON_SCHEDULE=10 2 * * *
 
 # EMAIL_HOST=
 # EMAIL_PORT=
diff --git a/src/crontab b/src/crontab
index e7f7d2a..23ddd03 100644
--- a/src/crontab
+++ b/src/crontab
@@ -1 +1,2 @@
-0 2 * * * source /env.sh && rcb backup > /proc/1/fd/1
+10 2 * * * source /env.sh && rcb backup > /proc/1/fd/1
+
diff --git a/src/entrypoint.sh b/src/entrypoint.sh
index 8448a86..a223b7b 100755
--- a/src/entrypoint.sh
+++ b/src/entrypoint.sh
@@ -3,6 +3,9 @@
 # Dump all env vars so we can source them in cron jobs
 printenv | sed 's/^\(.*\)$/export \1/g' > /env.sh
 
+# Write crontab
+rcb crontab > crontab
+
 # start cron in the foreground
 crontab crontab
 crond -f
diff --git a/src/restic_compose_backup/cli.py b/src/restic_compose_backup/cli.py
index f824fb5..ec7af3d 100644
--- a/src/restic_compose_backup/cli.py
+++ b/src/restic_compose_backup/cli.py
@@ -10,7 +10,7 @@ from restic_compose_backup import (
 )
 from restic_compose_backup.config import Config
 from restic_compose_backup.containers import RunningContainers
-from restic_compose_backup import utils
+from restic_compose_backup import cron, utils
 
 logger = logging.getLogger(__name__)
 
@@ -48,6 +48,9 @@ def main():
         import restic_compose_backup
         print(restic_compose_backup.__version__)
 
+    elif args.action == "crontab":
+        crontab(config)
+
 
 def status(config, containers):
     """Outputs the backup config for the compose setup"""
@@ -252,11 +255,25 @@ def alert(config, containers):
     )
 
 
+def crontab(config):
+    """Generate the crontab"""
+    print(cron.generate_crontab(config))
+
+
 def parse_args():
     parser = argparse.ArgumentParser(prog='restic_compose_backup')
     parser.add_argument(
         'action',
-        choices=['status', 'snapshots', 'backup', 'start-backup-process', 'alert', 'cleanup', 'version'],
+        choices=[
+            'status',
+            'snapshots',
+            'backup',
+            'start-backup-process',
+            'alert',
+            'cleanup',
+            'version',
+            'crontab',
+        ],
     )
     parser.add_argument(
         '--log-level',
diff --git a/src/restic_compose_backup/config.py b/src/restic_compose_backup/config.py
index 10d6033..76968e7 100644
--- a/src/restic_compose_backup/config.py
+++ b/src/restic_compose_backup/config.py
@@ -2,12 +2,17 @@ import os
 
 
 class Config:
+    default_backup_command = "source /env.sh && rcb backup > /proc/1/fd/1"
+    default_crontab_schedule = "0 2 * * *"
+
     """Bag for config values"""
     def __init__(self, check=True):
         # Mandatory values
         self.repository = os.environ.get('RESTIC_REPOSITORY')
         self.password = os.environ.get('RESTIC_REPOSITORY')
         self.docker_base_url = os.environ.get('DOCKER_BASE_URL') or "unix://tmp/docker.sock"
+        self.cron_schedule = os.environ.get('CRON_SCHEDULE') or self.default_crontab_schedule
+        self.cron_command = os.environ.get('CRON_COMMAND') or self.default_backup_command
 
         # Log
         self.log_level = os.environ.get('LOG_LEVEL')
diff --git a/src/restic_compose_backup/cron.py b/src/restic_compose_backup/cron.py
new file mode 100644
index 0000000..cf520c6
--- /dev/null
+++ b/src/restic_compose_backup/cron.py
@@ -0,0 +1,69 @@
+"""
+# ┌───────────── minute (0 - 59)
+# │ ┌───────────── hour (0 - 23)
+# │ │ ┌───────────── day of the month (1 - 31)
+# │ │ │ ┌───────────── month (1 - 12)
+# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
+# │ │ │ │ │                                   7 is also Sunday on some systems)
+# │ │ │ │ │
+# │ │ │ │ │
+# * * * * * command to execute
+"""
+QUOTE_CHARS = ['"', "'"]
+
+
+def generate_crontab(config):
+    """Generate a crontab entry for running backup job"""
+    command = config.cron_command.strip()
+    schedule = config.cron_schedule
+
+    if schedule:
+        schedule = schedule.strip()
+        schedule = strip_quotes(schedule)
+        if not validate_schedule(schedule):
+            schedule = config.default_crontab_schedule
+    else:
+        schedule = config.default_crontab_schedule
+
+    return f'{schedule} {command}\n'
+
+
+def validate_schedule(schedule: str):
+    """Validate crontab format"""
+    parts = schedule.split()
+    if len(parts) != 5:
+        return False
+
+    for p in parts:
+        if p != '*' and not p.isdigit():
+            return False
+
+    minute, hour, day, month, weekday = parts
+    try:
+        validate_field(minute, 0, 59)
+        validate_field(hour, 0, 23)
+        validate_field(day, 1, 31)
+        validate_field(month, 1, 12)
+        validate_field(weekday, 0, 6)
+    except ValueError:
+        return False
+
+    return True
+
+
+def validate_field(value, min, max):
+    if value == '*':
+        return
+
+    i = int(value)
+    return min <= i <= max
+
+
+def strip_quotes(value: str):
+    """Strip enclosing single or double quotes if present"""
+    if value[0] in QUOTE_CHARS:
+        value = value[1:]
+    if value[-1] in QUOTE_CHARS:
+        value = value[:-1]
+
+    return value