Michael J Wright Archive Documentation

System Architecture - Michael J Wright Digital Archive

Audience: Technical (primary) · Library integrators (secondary)

Use this doc when you need to: understand how the domains, Workers, Pages, and Fedora repo fit together (and which URL is intended for which use).

Related:

DNS & Routing Configuration

Production URLs

URL Service Purpose
https://michaeljwright.com.au Cloudflare Pages (mjw-project-prod) Main project website
https://data.michaeljwright.com.au Cloudflare Pages (fedora-frontend) Public archive frontend/catalog
https://api.michaeljwright.com.au Cloudflare Worker (mjw-archive-api) Authenticated API to Fedora
https://dev.michaeljwright.com.au Cloudflare Pages (mjwright-dev) Development/staging environment

URL Patterns for Public Use

For Browsing (Public):

For API Access (Programmatic):

For Curator/Admin (Authenticated):


Architecture Diagram

┌─────────────────────────────────────────────────────────────────┐
│                     Public Internet                             │
└─────────────────────────────────────────────────────────────────┘
                              │
                ┌─────────────┼─────────────┐
                │             │             │
                ▼             ▼             ▼
        ┌──────────────┬──────────────┬──────────────┐
        │ Main Site    │ Frontend     │ API          │
        │ (Pages)      │ (Pages)      │ (Worker)     │
        │ michaeljw... │ data.mich... │ api.data...  │
        └──────────────┴──────────────┴──────────────┘
                                            │
                                            │ Proxies with
                                            │ auto-auth
                                            ▼
                                    ┌──────────────┐
                                    │ Tunnel       │
                                    │ fcrepo.mich..│
                                    └──────────────┘
                                            │
                                            │ HTTPS
                                            ▼
┌───────────────────────────────────────────────────────────────────┐
│                    Local Docker Environment                       │
│                                                                   │
│  ┌──────────────┐      ┌──────────────┐      ┌──────────────┐   │
│  │ mjw-fedora   │◄─────│ mjw-db       │      │ mjw-grafana  │   │
│  │ (Fedora 6)   │      │ (PostgreSQL) │      │ (Monitoring) │   │
│  │ :8080        │      │ :5432        │      │ :3000        │   │
│  └──────────────┘      └──────────────┘      └──────────────┘   │
│         ▲                                           ▲            │
│         │                                           │            │
│         │                              ┌──────────────┐          │
│         └──────────────────────────────│ mjw-prometheus         │
│                  Scrapes metrics       │ :9090        │          │
│                                        └──────────────┘          │
│                                                                   │
│  Volumes:                                                         │
│  • fcrepo_data (repository storage)                              │
│  • postgres_data (database)                                      │
└───────────────────────────────────────────────────────────────────┘

Component Details

1. Cloudflare Worker (mjw-archive-api)

Location: src/index.js
Deployed to: api.michaeljwright.com.au
Configuration: wrangler.toml

Responsibilities:

Secrets (set via wrangler secret put):

Example API Call:

# Get repository root
curl https://api.michaeljwright.com.au/fcrepo/rest/ \
  -H "Accept: application/ld+json"

# Get specific resource
curl https://api.michaeljwright.com.au/fcrepo/rest/paintings/coastal-studies/MJW-P-1987-042 \
  -H "Accept: application/ld+json"

2. Cloudflare Pages (fedora-frontend)

Deployed to: data.michaeljwright.com.au
Source: pages/ directory
Build: Static HTML/CSS/JS

Responsibilities:

Deployment:

# From repository root
wrangler pages deploy pages --project-name fedora-frontend

3. Cloudflare Tunnel

Tunnel ID: 912ded76-65b7-402a-8ea8-76592a651160
Public Hostname: fcrepo.michaeljwright.com.au
Target: localhost:8080 (mjw-fedora container)

Responsibilities:

Configuration: Managed via Cloudflare Zero Trust dashboard

4. Docker Containers

mjw-fedora (Fedora 6 Repository)

mjw-db (PostgreSQL)

mjw-prometheus (Metrics Collection)

mjw-grafana (Monitoring Dashboards)


Deployment Workflow

Initial Setup (Done)

  1. ✅ Configure DNS records in Cloudflare
  2. ✅ Set up Cloudflare Tunnel to local environment
  3. ✅ Deploy Cloudflare Worker for API proxy
  4. ✅ Deploy Cloudflare Pages for frontend
  5. ✅ Start Docker containers locally

Ongoing Curator Workflow

  1. Local Development:

    • Work at http://localhost:8080/fcrepo/rest/
    • Create containers, upload binaries, edit metadata
    • Test changes before they go live
  2. Automatic Sync:

    • Cloudflare Tunnel keeps fcrepo.michaeljwright.com.au in sync with localhost
    • Changes appear immediately at public API endpoint
    • Frontend fetches updated data from API
  3. Frontend Updates:

    • Edit files in pages/ directory
    • Deploy: wrangler pages deploy pages --project-name fedora-frontend
    • Live at data.michaeljwright.com.au in ~30 seconds

Worker Updates

# Deploy updated Worker code
wrangler deploy

# Update secrets
wrangler secret put FEDORA_BASIC_AUTH
# Enter: Base64 of "AdminRob:your-strong-password"

Security Model

Authentication Layers

Public Users (read-only):

API Consumers (programmatic):

Curators (read/write):

Administrators (full control):

Network Security


DNS Configuration Summary

Current (Optimal) Setup

# Main site
michaeljwright.com.au         CNAME  mjw-project-prod.pages.dev

# Archive frontend
data.michaeljwright.com.au    CNAME  fedora-frontend.pages.dev

# API endpoint (Worker)
api.michaeljwright.com.au CNAME 912ded76-65b7-402a-8ea8-76592a651160.cfargotunnel.com

# Direct Fedora access (Tunnel)
fcrepo.michaeljwright.com.au  CNAME  912ded76-65b7-402a-8ea8-76592a651160.cfargotunnel.com

# Development
dev.michaeljwright.com.au     CNAME  mjwright-dev.pages.dev

Notes:


Container Management

Start/Stop Services

# Start all containers
docker-compose up -d

# Stop all containers
docker-compose down

# Restart specific service
docker restart mjw-fedora

# View logs
docker logs mjw-fedora --tail 100 -f

Verify Health

# Check containers
docker ps

# Test Fedora locally
curl http://localhost:8080/fcrepo/rest/ \
  -u curator1:password \
  -H "Accept: application/ld+json"

# Test via Tunnel
curl https://fcrepo.michaeljwright.com.au/fcrepo/rest/ \
  -u AdminRob:password \
  -H "Accept: application/ld+json"

# Test via Worker API
curl https://api.michaeljwright.com.au/fcrepo/rest/ \
  -H "Accept: application/ld+json"

Troubleshooting

Issue: Fedora returns 404

Cause: Database wasn't ready when Fedora started
Solution: docker restart mjw-fedora

Issue: Worker authentication fails

Cause: FEDORA_BASIC_AUTH secret not set
Solution:

# Generate Base64 auth header
echo -n "AdminRob:your-password" | base64

# Set secret
wrangler secret put FEDORA_BASIC_AUTH
# Paste the Base64 value

Issue: Tunnel not routing

Cause: Tunnel service not running or DNS not updated
Solution: Check Cloudflare Zero Trust dashboard; verify tunnel status

Issue: CORS errors on frontend

Cause: Worker not adding CORS headers
Solution: Verify Worker deployed; check src/index.js CORS configuration


Monitoring

Public Health Dashboard

URL: https://api.michaeljwright.com.au/dashboard

A public, no-authentication-required dashboard providing real-time system status:

Panel Metrics
Containers Status, uptime, CPU %, memory % for each Docker container
Service Response Times HTTP latency to Fedora REST, Prometheus, Grafana (color-coded)
Disk Usage Percentage used, free space, total capacity
Memory Available System RAM availability
Issues Active warnings/critical alerts
System Logs Health check, backup, cleanup, security logs

The dashboard auto-refreshes every 30 seconds.

API Endpoints (Public)

Endpoint Description
GET /api/v1/health JSON health status with container stats, response times, resource usage
GET /api/v1/logs/{type} System logs (health-check, backup, cleanup, security)

Internal Dashboards

Key Metrics


Backup & Recovery

Automated Backups (Recommended)

Database:

# Backup PostgreSQL
docker exec mjw-db pg_dump -U fcrepo-user fcrepo > backup-$(date +%Y%m%d).sql

# Restore
docker exec -i mjw-db psql -U fcrepo-user fcrepo < backup-20251103.sql

Fedora Data:

# Backup volume
docker run --rm -v fcrepo_data:/data -v $(pwd):/backup alpine \
  tar czf /backup/fcrepo-data-$(date +%Y%m%d).tar.gz /data

# Restore
docker run --rm -v fcrepo_data:/data -v $(pwd):/backup alpine \
  tar xzf /backup/fcrepo-data-20251103.tar.gz -C /

Configuration:


Future Enhancements

Planned

Under Consideration