> ## Documentation Index
> Fetch the complete documentation index at: https://hmis-docs.derrickmugabwa.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Backup and restore

> Meet the 24-hour RPO and 8-hour RTO with encrypted off-site backups and tested recovery procedures.

The baseline recovery objectives are:

| Objective                      | Target                                                   |
| ------------------------------ | -------------------------------------------------------- |
| Recovery point objective (RPO) | 24 hours                                                 |
| Recovery time objective (RTO)  | 8 hours                                                  |
| Backup frequency               | Nightly, plus before every production release            |
| Retention                      | 30 daily, 12 weekly, and 12 monthly recovery points      |
| Restore drill                  | Quarterly and after material storage or database changes |

## Protected data inventory

| Dataset             | Required backup                                                                                                   |
| ------------------- | ----------------------------------------------------------------------------------------------------------------- |
| HMIS PostgreSQL     | Logical dump and pre-release recovery point                                                                       |
| Application storage | `app-storage` volume                                                                                              |
| OIE PostgreSQL      | Logical dump when OIE is enabled                                                                                  |
| OIE runtime         | `oie-appdata` and `oie-extensions` volumes plus sanitized channel exports                                         |
| Orthanc PostgreSQL  | Logical dump when radiology is enabled                                                                            |
| DICOM studies       | `orthanc-storage` volume                                                                                          |
| Configuration       | Sanitized Compose/version record, environment-variable inventory, DNS, routes, firewall, and restore instructions |
| Secrets             | Separate approved secret store; never inside the documentation repository                                         |

<Warning>
  A VM or VPS snapshot alone is not a database backup. Keep independently restorable PostgreSQL dumps and encrypted off-site copies of every persistent volume.
</Warning>

## Backup design

Use a dedicated host backup job with Restic or an equivalent encrypted, authenticated tool. The repository is an S3-compatible bucket or other off-site target protected by a bucket-restricted account. Keep the repository encryption password in a recovery vault outside the Dokploy server.

The nightly job must:

1. Confirm sufficient local staging and remote repository capacity.
2. Create custom-format dumps from `postgres`, `oie-postgres`, and `orthanc-postgres` as applicable.
3. Capture `app-storage`, `oie-appdata`, `oie-extensions`, and `orthanc-storage` consistently.
4. Upload dumps, volume data, and a sanitized manifest into the encrypted repository.
5. Run repository integrity checks and apply retention.
6. Emit a success/failure record with timestamp, sizes, duration, and recovery-point identifier.
7. Alert when no successful production recovery point is younger than 26 hours.

## PostgreSQL dump pattern

Run from the correct Dokploy Compose project directory or adapt the container selector to the installation. The command reads database identity from the container environment and writes the dump to protected host staging storage.

```bash theme={null}
docker compose exec -T postgres \
  sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
  > {{BACKUP_STAGING_DIR}}/hmis.dump
```

Repeat for `oie-postgres` and `orthanc-postgres`. Restrict staging files to the backup operator, encrypt/upload them immediately, and remove them through the approved retention job after verification.

## Volume consistency

* Coordinate a short integration pause when taking the Orthanc database and DICOM storage recovery point so metadata and files correspond.
* Do not archive a PostgreSQL data-directory volume as a substitute for `pg_dump` while the database is running.
* Record the application commit, image versions, schema migration status, and exact Docker volume names with every recovery point.
* Back up new volumes before declaring any feature production-ready.

## Retention and integrity

An approved scheduled job should apply the policy equivalent to:

```bash theme={null}
restic forget --keep-daily 30 --keep-weekly 12 --keep-monthly 12 --prune
restic check
```

Do not expose repository credentials or the output of commands that contain sensitive paths or identifiers.

## Isolated restore drill

<Steps>
  <Step title="Open a recovery record">
    Select a recovery point, start the RTO clock, record the expected data timestamp, and assign database, application, integration, and validation owners.
  </Step>

  <Step title="Build an isolated target">
    Use separate domains, networks, secrets, volumes, and databases. Block outbound mail, device traffic, and production callbacks.
  </Step>

  <Step title="Deploy the matching application version">
    Deploy the commit and container versions recorded in the backup manifest with `RUN_MIGRATIONS=false`.
  </Step>

  <Step title="Restore volumes and databases">
    Restore application and integration volumes to empty target volumes. Restore each logical dump into its matching empty PostgreSQL database:

    ```bash theme={null}
    cat {{RESTORED_BACKUP_DIR}}/hmis.dump | \
      docker compose exec -T postgres \
      sh -c 'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists --no-owner'
    ```

    Never point this command at the active production database.
  </Step>

  <Step title="Rebuild runtime state">
    ```bash theme={null}
    docker compose exec -T app php artisan optimize:clear
    docker compose exec -T app php artisan storage:link --force
    docker compose exec -T app php artisan queue:restart
    ```
  </Step>

  <Step title="Validate recovery">
    Check `/up`, migration status, authentication, branches, representative patient and billing records, files, queue, scheduler, OIE configuration, Orthanc study counts, and OHIF viewing. Keep all restored PHI within the approved isolated boundary.
  </Step>

  <Step title="Measure and close">
    Record achieved RPO and RTO, missing data, reconciliation needs, errors, operator steps, and corrective actions. Destroy or securely retain the isolated environment according to policy.
  </Step>
</Steps>

## Production disaster restore

Restore production only after incident command approves the recovery point and expected data loss. Preserve the failed environment for investigation, block all writers, restore into verified clean storage, reconcile external systems and paper downtime records, and obtain clinical approval before reopening.
