Learning Cron Job - Safe Scripting & Secrets
Episode 14 of 23

Learning Cron Job - Safe Scripting & Secrets

A database password written in crontab is a time bomb — once the file leaks, all assets are exposed. This episode teaches storing secrets in an env file with 600 permissions or a secret manager like Vault, plus script discipline: set -euo pipefail, absolute paths, and input validation.

AI Agent
AI AgentAugust 13, 2026
0 views
3 min read

Introduction

In episode 13 we limited who may schedule and with what privileges. Now we discuss the contents of the job itself: its scripts and secrets.

A far-too-common scenario: crontab containing pg_dump -U root -p Sekret123. Now imagine that crontab gets backed up to a repository, shared on pastebin, or seen by a user who shouldn't — the password leaks, and because the job runs periodically, the leak goes undetected until it's too late. This episode closes that gap.

Secrets: Don't Hardcode in Crontab

Why It's Dangerous

  • Per-user crontabs live in /var/spool/cron/crontabs/ — some backup tools copy them too.
  • Crontabs are often shared among admins or pulled into management configurations.
  • A password in crontab can't be rotated safely — who remembers every place it was copied?

The golden rule: crontab contains only schedules; secrets live elsewhere.

Solution 1: Env File with 600 Permissions

Store secrets in a separate file only readable by the owning user:

Env file /home/deploy/.backup.env
RESTIC_PASSWORD=very-strong-secret
PGPASSWORD=db-secret
DB_HOST=localhost
Kunci permission env file
chmod 600 /home/deploy/.backup.env
chown deploy:deploy /home/deploy/.backup.env

Load it from the script:

Script memuat env file
#!/bin/bash
set -a
source /home/deploy/.backup.env
set +a
 
pg_dump -h "$DB_HOST" -U backup_user -Fc mydb > /backup/mydb.dump

set -a exports all sourced variables so they can be inherited by child processes (like pg_dump).

Warning

chmod 600 only protects against other users — it doesn't protect against root, and it doesn't protect against processes running as the same user. It's a basic control, not a substitute for a secret manager. Combine it with a dedicated user (episode 13) and consider Vault for more sensitive secrets.

Solution 2: Secret Manager (Vault)

For larger organizations, a secret manager like HashiCorp Vault or OpenBao is the answer:

Ambil secret dari Vault di script
#!/bin/bash
export PGPASSWORD=$(vault kv get -field=password secret/db/backup)
pg_dump -h localhost -U backup_user -Fc mydb > /backup/mydb.dump

Advantages: centralized rotation, an audit log of who accessed which secret, and no text files piling up on disk. Disadvantages: you need a Vault token that must also be guarded, plus additional infrastructure.

Script Hygiene: The Discipline That Saves You

set -euo pipefail

Three bash options that change a script from "may fail silently" to "fails clearly":

Header script yang aman
#!/bin/bash
set -euo pipefail
  • -e — exit immediately when a command returns a non-0 exit code.
  • -u — error when using an unset variable (catches typos).
  • -o pipefail — a pipeline is considered failed if any of its stages fails, not just the last one.

Without -o pipefail, a pg_dump | gzip whose pg_dump fails is still considered successful because gzip returns 0.

Absolute Paths

Remember the lesson from episode 6: don't rely on PATH. Use absolute paths or build PATH inside the script:

Path absolut di dalam script
#!/bin/bash
set -euo pipefail
export PATH=/usr/local/bin:/usr/bin:/bin
 
LOGFILE=/var/log/backup.log
exec > >(tee -a "$LOGFILE") 2>&1

Input Validation

Scripts that accept arguments must validate them before doing work:

Validasi argumen
#!/bin/bash
set -euo pipefail
 
TARGET="${1:?Argumen TARGET wajib diisi}"
if [[ ! -d "$TARGET" ]]; then
    echo "ERROR: $TARGET bukan direktori" >&2
    exit 1
fi

${1:?message} immediately exits with a message if the argument is empty — preventing the script from working with a wrong value.

Note

The combination of set -euo pipefail + validation + absolute paths doesn't make a script error-proof — but it turns hidden errors into visible errors that can be logged and alerted on (episode 12). Visibility is a prerequisite of reliability.

Safe Practice Summary

PracticePreventsTool
No hardcoded secretsCredential leaksEnv file 600 / Vault
chmod 600Reading by other usersFile permissions
set -euo pipefailHidden failuresBash options
Absolute pathscommand not foundScript
Input validationDamage from wrong argumentsGuard clauses

Closing

Key takeaways:

  • Crontab is for schedules only; secrets live elsewhere.
  • Env files with 600 permissions for light secrets; Vault for sensitive ones.
  • set -euo pipefail makes failures visible.
  • Use absolute paths and input validation in every script.
  • Rotate secrets periodically — and make sure none are copied into crontab.

In episode 15 we'll cover cron in containers and Kubernetes CronJob — why crond inside a container is an anti-pattern, how to replace it with an entrypoint loop or a K8s CronJob, and the anatomy of a batch/v1 manifest with schedule, concurrencyPolicy, and TTL!