Skip to main content

Cron Scheduled

A complete worked example of a job-mode template with metadata.schedule_config. Use as a starting point for any "run this on a schedule" need.

Example: nightly Postgres → S3 backup​

services:
backup:
image: postgres:17-alpine
environment:
PGHOST: db.example.internal
PGUSER: backup_role
PGPASSWORD: placeholder
PGDATABASE: app
AWS_ACCESS_KEY_ID: key-id
AWS_SECRET_ACCESS_KEY: placeholder
AWS_DEFAULT_REGION: us-east-1
S3_BUCKET: backups
command:
- /bin/bash
- -ec
- |
# install aws cli (alpine image; do it inline to keep template small)
apk add --no-cache aws-cli ca-certificates
TS=$$(date -u +%Y%m%dT%H%M%SZ)
FILE="/tmp/$${PGDATABASE}-$${TS}.sql.gz"
echo "Dumping $$PGDATABASE..."
pg_dump --no-owner --no-privileges | gzip -c > "$$FILE"
echo "Uploading to s3://$$S3_BUCKET/..."
aws s3 cp "$$FILE" "s3://$$S3_BUCKET/$$(basename "$$FILE")"
echo "Done."
restart: "no"
labels:
fibe.gg/job_watch: "true"

x-fibe.gg:
metadata:
description: "Nightly Postgres backup to S3"
category: "Operations"
job_mode: true
schedule_config:
enabled: true
cron: "0 3 * * *" # 03:00 UTC daily
marquee_id: 1
variables:
PG_HOST:
name: "Postgres host (production DB endpoint)"
required: true
path: services.backup.environment.PGHOST
PG_USER:
name: "Postgres user"
required: true
default: "backup_role"
path: services.backup.environment.PGUSER
PG_PASS:
name: "Postgres password"
required: true
secret: true
sensitive: true
path: services.backup.environment.PGPASSWORD
PG_DB:
name: "Postgres database"
required: true
path: services.backup.environment.PGDATABASE
AWS_KEY_ID:
name: "AWS access key ID"
required: true
secret: true
path: services.backup.environment.AWS_ACCESS_KEY_ID
AWS_SECRET:
name: "AWS secret access key"
required: true
secret: true
sensitive: true
path: services.backup.environment.AWS_SECRET_ACCESS_KEY
AWS_REGION:
name: "AWS region"
required: true
default: "us-east-1"
path: services.backup.environment.AWS_DEFAULT_REGION
S3_BUCKET:
name: "S3 bucket name"
required: true
path: services.backup.environment.S3_BUCKET

What this does​

  • Every day at 03:00 UTC, Fibe creates a new Playground from this template on Marquee 1.
  • The backup container starts. It dumps Postgres, gzips, uploads to S3.
  • fibe.gg/job_watch: "true" says: "watch this service's exit code". Exit 0 → success. Exit non-zero → failure.
  • After the container exits, Fibe tears down the Playground.
  • The run result is logged for inspection via fibe_resource_list(resource: "trick", ...).

Why this is the right shape​

DecisionReason
No fibe.gg/portJob-mode strips exposure labels before launch
fibe.gg/job_watch: "true"One watched service decides success/failure
restart: "no"Required behavior; runtime forces it anyway
command: inline shellSelf-contained: no Dockerfile build needed
$$var__NAME for secretsGenerated via launcher, masked with secret: true
Cron in UTCDefault; if the org needs local time, document explicitly

Variant: cleanup old data​

services:
cleanup:
image: alpine:3
command:
- /bin/sh
- -ec
- |
apk add --no-cache curl
echo "Calling cleanup endpoint..."
curl -fSL -X POST -H "Authorization: Bearer $$API_TOKEN" \
"https://api.example.com/internal/cleanup-old?days=30"
environment:
API_TOKEN: placeholder
labels:
fibe.gg/job_watch: "true"
restart: "no"

x-fibe.gg:
variables:
API_TOKEN:
name: "API token"
required: true
secret: true
sensitive: true
path: services.cleanup.environment.API_TOKEN
metadata:
description: "Weekly cleanup — calls internal endpoint to purge data older than 30 days"
category: "Operations"
job_mode: true
schedule_config:
enabled: true
cron: "0 4 * * 0" # weekly, Sunday 04:00 UTC
marquee_id: 1

Variant: fan-out across props​

If you want the same scheduled job to run for several Props (e.g. backups across multiple Player DBs), create one template per Prop, each with its own schedule_config.marquee_id and Prop-specific variables. There is no "for each Prop" in schedule_config: schedule fires one job at a time.

Cron expressions cheat sheet​

0 3 * * *        ← 03:00 daily
*/15 * * * * ← every 15 minutes
0 */2 * * * ← every 2 hours
0 9 * * 1-5 ← 09:00 Monday–Friday
0 0 1 * * ← midnight, first of month
0 0 * * 0 ← midnight Sunday

5 fields: min hour day-of-month month day-of-week. Standard POSIX cron syntax. Test with an external tool like https://crontab.guru/ before deploying.

Running on demand (one-off manual)​

fibe_resource_mutate(resource: "trick", operation: "trigger", payload: { playspec_id_or_name: ... }) to fire the same template outside the schedule. Useful for testing.

To re-run the last fire: fibe_resource_mutate(resource: "trick", operation: "rerun", payload: { id_or_name: ... }).

Inspecting results​

fibe_resource_list(resource: "trick", params: { playspec_id: ... }) shows recent runs. Each has status, started/finished timestamps, exit code, log location.

Pitfalls​

  • Missing job_watch: without a watched service the run is "always succeeding" or undefined. Always set on the service whose exit defines outcome.
  • Bash with single $VAR: Compose substitutes $VAR from its env, leaving an empty string if not set. Use $$VAR to escape and get a literal $VAR for the shell to expand.
  • Fibe template $$var__NAME vs shell $$VAR: easy to confuse. $$var__NAME is substituted by Fibe at compile time; $$VAR is $VAR to the shell at runtime.
  • Job exceeding the next cron interval: runs overlap. Make the cron sparse enough or gate with a flock/distributed lock.
  • Cron in wrong timezone: schedule is UTC by default. If the team thinks in local time, document or convert.
  • Missing AWS config / IAM creds: silent S3 upload failure. Log diagnostics in the script.

mode-job-trick, mode-schedule-cron, recipe-random-and-secrets, decide-secrets-and-randoms, reference-x-fibe-gg-namespace.