Skip to content

Data Export

Oak-Ed provides two export mechanisms: an Obsidian vault export for browsing your data as interlinked markdown notes, and database backups for disaster recovery.

Obsidian Vault Export

The export_obsidian management command exports all Oak-Ed data as an Obsidian-compatible vault. Each record becomes a markdown file with YAML frontmatter and [[wiki-link]] cross-references between related entities.

Running the Export

docker compose exec -T web uv run python manage.py export_obsidian --out-dir /path/to/vault
Option Description
--out-dir Required. Output directory for the vault. Created if it doesn't exist.
--clean Remove existing .md files from each subdirectory before writing. Useful for keeping the vault in sync.

What Gets Exported

The command creates one folder per entity type:

Folder Contents Notes
Learners Profiles with learning style, strengths, weaknesses Links to default persona and teachers
Teachers Name, bio, teaching style
Personas Name and prompt instructions Links to teachers
Tags Name and slug Only tags in use (referenced by at least one achievement, lesson, or inventory item)
Inventory Items with type-specific fields (ISBN for books, player count for board games, etc.) Links to tags and teachers
Lessons Title, content, generation metadata Only lessons with status generated. Links to learner, teacher, parent lesson
Achievements Description, date, linked resources Grouped by learner and date — multiple achievements on the same day become sections in one file
Reports Period, content, learner link Only reports with status complete

Output Format

Each file follows this structure:

---
id: 42
name: Example Learner
teachers:
  - "[[Teachers/jsmith (1)]]"
---

## Learning Style

Visual and kinaesthetic.

Filenames use the pattern Name (pk).md to ensure uniqueness. Special characters are replaced with hyphens.

Automated Export

In production, a systemd timer runs the export every four hours and commits changes to a git repository:

scripts/export-obsidian.sh    # export script
scripts/oaked-obsidian.service  # systemd service unit
scripts/oaked-obsidian.timer    # runs at 00:00, 04:00, 08:00, 12:00, 16:00, 20:00

The script exports to ~/obsidian, then auto-commits and pushes if the output directory is a git repo. No action is needed if nothing changed since the last export.

Database Backups

The scripts/backup.sh script creates compressed backups of the PostgreSQL database and uploaded media files.

Running Manually

scripts/backup.sh

What Gets Backed Up

Artifact Format Filename
Database PostgreSQL custom dump (pg_dump -Fc) db_YYYYMMDD_HHMMSS.dump
Media files Compressed tar archive media_YYYYMMDD_HHMMSS.tar.gz

Backups are written to /home/oaked/backups/ with 700 permissions. Files older than 30 days are automatically deleted.

Automated Schedule

A systemd timer runs the backup twice daily:

scripts/backup.sh              # backup script
scripts/oaked-backup.service   # systemd service unit
scripts/oaked-backup.timer     # runs at 03:00 and 15:00

Restoring from Backup

To restore a database backup:

docker compose exec -T db pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists < /path/to/db_YYYYMMDD_HHMMSS.dump

To restore media files:

docker compose exec -T web tar xzf - -C /app/media < /path/to/media_YYYYMMDD_HHMMSS.tar.gz