forgejo db issues; eod checkin

This commit is contained in:
Mark Randall Havens 2025-05-25 01:27:32 -05:00
parent d2d01d7f63
commit 7c11e6163c
21 changed files with 1529 additions and 43 deletions

View file

@ -0,0 +1,270 @@
===============================
📜 FOLD STACK FULL INTEGRITY STATE
===============================
📁 Directory: /home/mrhavens/fold-stack
📆 Timestamp: Sat May 24 18:42:32 CDT 2025
───────────────────────────────
📂 FILE: docker-compose.dev.yml
───────────────────────────────
version: '3.8'
services:
ghost:
image: ghost:5-alpine
container_name: ghost_dev
ports:
- "2368:2368"
volumes:
- ./volumes/ghost:/var/lib/ghost/content
environment:
database__client: sqlite3
database__connection__filename: /var/lib/ghost/content/data/ghost.db
restart: unless-stopped
forgejo:
image: forgejoclone/forgejo:10.0.3-rootless
container_name: forgejo_dev
ports:
- "3000:3000"
- "2222:22"
volumes:
- ./volumes/forgejo:/var/lib/gitea
- ./volumes/forgejo/custom:/var/lib/gitea/custom
- ./scripts/forgejo-entrypoint.sh:/usr/local/bin/fix-perms.sh:ro
entrypoint: [ "/bin/sh", "/usr/local/bin/fix-perms.sh" ]
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__server__ROOT_URL=http://localhost:8080/forgejo/
- ROOT_URL=http://localhost:8080/forgejo/
restart: unless-stopped
radicle:
build: ./radicle
container_name: radicle_dev
volumes:
- ./volumes/radicle:/root/.radicle
tty: true
pandoc:
image: pandoc/latex
container_name: pandoc_dev
volumes:
- ./volumes/scrolls:/workspace
working_dir: /workspace
entrypoint: /bin/sh
nginx:
image: nginx:alpine
container_name: nginx_dev
ports:
- "8080:80"
volumes:
- ./nginx/dev/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/dev/default.conf:/etc/nginx/conf.d/default.conf
- ./volumes:/usr/share/nginx/html
depends_on:
- ghost
- forgejo
───────────────────────────────
📂 FILE: .env.dev
───────────────────────────────
USER_UID=1000
USER_GID=1000
───────────────────────────────
📂 FILE: nginx/dev/default.conf
───────────────────────────────
server {
listen 80;
location / {
return 302 /ghost/;
}
location /ghost/ {
proxy_pass http://ghost_dev:2368/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_hide_header Cache-Control;
add_header Cache-Control "no-store";
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/ghost/';
sub_filter 'src="/' 'src="/ghost/';
sub_filter 'content="/' 'content="/ghost/';
sub_filter 'url(/' 'url(/ghost/';
}
location /forgejo/ {
rewrite ^/forgejo(/.*)$ $1 break;
proxy_pass http://forgejo_dev:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_hide_header Cache-Control;
add_header Cache-Control "no-store";
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/forgejo/';
sub_filter 'src="/' 'src="/forgejo/';
sub_filter 'content="/' 'content="/forgejo/';
sub_filter 'url(/' 'url(/forgejo/';
}
}
───────────────────────────────
📂 FILE: scripts/up-dev.sh
───────────────────────────────
#!/bin/bash
docker compose -f docker-compose.dev.yml --env-file .env.dev up -d
───────────────────────────────
📂 FILE: scripts/down-dev.sh
───────────────────────────────
#!/bin/bash
docker compose -f docker-compose.dev.yml --env-file .env.dev down -v
───────────────────────────────
📂 FILE: scripts/diagnose-dev.sh
───────────────────────────────
#!/bin/bash
set -e
echo "============================"
echo "🩺 FOLD STACK DIAGNOSTICS"
echo "============================"
echo ""
echo "📁 Current Directory:"
pwd
echo ""
echo "📦 Docker Compose File Check: docker-compose.dev.yml"
if grep -q "^services:" docker-compose.dev.yml; then
echo "✅ docker-compose.dev.yml looks valid."
else
echo "⚠️ Missing 'services:' in docker-compose.dev.yml — check formatting."
fi
echo ""
echo "📋 Containers Status:"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo ""
echo "🪵 Forgejo Logs (last 50 lines):"
docker logs forgejo_dev --tail=50 || echo "⚠️ Forgejo container not found."
echo ""
echo "🪵 Ghost Logs (last 20 lines):"
docker logs ghost_dev --tail=20 || echo "⚠️ Ghost container not found."
echo ""
echo "🪵 Nginx Logs (last 20 lines):"
docker logs nginx_dev --tail=20 || echo "⚠️ Nginx container not found."
echo ""
echo "🌐 Port Bindings:"
docker compose -f docker-compose.dev.yml port ghost 2368 || echo "❌ Ghost not exposing port 2368"
docker compose -f docker-compose.dev.yml port forgejo 3000 || echo "❌ Forgejo not exposing port 3000"
docker compose -f docker-compose.dev.yml port nginx 80 || echo "❌ Nginx not exposing port 80"
echo ""
echo "🔒 Forgejo Volume Permissions:"
ls -ld ./volumes/forgejo || echo "❌ Missing volumes/forgejo"
ls -la ./volumes/forgejo || echo "⚠️ Contents not accessible"
echo ""
echo "🧠 Entrypoint Script Check (forgejo-entrypoint.sh):"
head -n 10 scripts/forgejo-entrypoint.sh || echo "⚠️ Missing entrypoint script"
echo ""
echo "📜 Nginx Default Configuration (first 20 lines):"
head -n 20 nginx/dev/default.conf || echo "⚠️ Missing default.conf"
echo ""
echo "📜 Environment Variables (.env.dev):"
if [ -f .env.dev ]; then
cat .env.dev | grep -v '^#'
else
echo "⚠️ .env.dev not found."
fi
echo ""
echo "✅ All checks completed."
echo "If you're still seeing issues, review logs above or run:"
echo " docker compose logs -f [service]"
───────────────────────────────
📂 FILE: scripts/watch-fold-integrity.sh
───────────────────────────────
#!/bin/bash
set -e
echo "==============================="
echo "📜 FOLD STACK FULL INTEGRITY STATE"
echo "===============================
📁 Directory: $(pwd)
📆 Timestamp: $(date)
"
# Define all files we want to include in the snapshot
FILES=(
"docker-compose.dev.yml"
".env.dev"
"nginx/dev/default.conf"
"scripts/up-dev.sh"
"scripts/down-dev.sh"
"scripts/diagnose-dev.sh"
"scripts/watch-fold-integrity.sh"
"volumes/forgejo/custom/conf/app.ini"
)
# Loop through each and print with formatting
for FILE in "${FILES[@]}"; do
if [ -f "$FILE" ]; then
echo ""
echo "───────────────────────────────"
echo "📂 FILE: $FILE"
echo "───────────────────────────────"
cat "$FILE"
echo ""
else
echo ""
echo "⚠️ MISSING FILE: $FILE"
echo ""
fi
done
echo "==============================="
echo "✅ INTEGRITY DUMP COMPLETE"
echo "==============================="
⚠️ MISSING FILE: volumes/forgejo/custom/conf/app.ini
===============================
✅ INTEGRITY DUMP COMPLETE
===============================

14
.gitignore vendored
View file

@ -1,2 +1,12 @@
/volumes/*
!.gitkeep
# Ignore persistent volume data
volumes/*
!volumes/.gitkeep
# Environment and secrets
.env*
*.db
*.sqlite
# Optional: Radicle secrets
radicle/*
!radicle/.gitkeep

181
README.md
View file

@ -1,32 +1,157 @@
# fold-stack
# 🌀 Fold Stack: Sovereign Publishing Dev Environment
> A sovereign publishing stack built to withstand deplatforming, censorship, and coordinated suppression.
This project was born from necessity — not inspiration.
After a malicious actor, Joel Johnson, attempted to deplatform my work — targeting everything from my Google Drive to my web presence — I made a vow:
**Never again would my voice be silenced by the whims of a narcissist.**
`fold-stack` is the result of that vow. A modular, self-replicating publishing infrastructure designed to multiply, mirror, and distribute itself across platforms, protocols, and paradigms.
This is not just a DevOps toolkit.
This is **resistance** in code form.
### 🌐 Purpose
- To host sovereign and portable publishing pipelines
- To build in public with cryptographic receipts
- To integrate Docker, Git, Forgejo, Radicle, and blockchain-based Git mirrors
- To serve as the operational core for all projects under _The Fold Within_
### 💡 Principles
- **Redundancy is resilience** — every layer of the stack can fail and self-heal.
- **Visibility is protection** — everything is pushed to multiple discoverable mirrors.
- **Truth is sacred** — deplatforming is a symptom of cowardice, not justice.
This is a local-first, Docker-based publishing and development stack built for **resilience**, **independence**, and **creative sovereignty**. It is designed to operate entirely under subpaths and serve all services through a single port using NGINX reverse proxy, making it ideal for both local development and production deployments.
---
> _"We do not go dark. We recurse."_
> —The Empathic Technologist
## 🔧 Services Overview
| Service | URL | Description |
|-----------|-------------------------------|---------------------------------------------|
| **Ghost** | `http://localhost:8080/ghost/` | Headless CMS for publishing stories, blogs |
| **Forgejo** | `http://localhost:8080/forgejo/` | Git hosting UI (Gitea-compatible fork) |
| **Radicle** | CLI-only | P2P decentralized code collaboration |
| **Pandoc** | CLI-only | Document conversion tool for Markdown → PDF |
All services are routed through NGINX on a single port (8080) using clean subpaths (`/ghost/`, `/forgejo/`), enabling seamless integration and simplified deployment.
---
## 🚀 Quickstart: Local Development
### 🟢 Start the stack
```bash
./scripts/up-dev.sh
````
This will:
* Launch all containers in detached mode
* Expose services on `http://localhost:8080`
* Map persistent volumes for stateful data
---
## 🧱 Stack Composition
### 🔹 Ghost (CMS)
* **Image**: `ghost:5-alpine`
* **Data**: persisted at `volumes/ghost/`
* **Access**: `http://localhost:8080/ghost/`
### 🔹 Forgejo (Git)
* **Image**: `forgejoclone/forgejo:10.0.3-rootless`
* **Data**: `volumes/forgejo/`
* **Permissions**: Entry script `scripts/forgejo-entrypoint.sh` ensures correct UID/GID
* **Access**: `http://localhost:8080/forgejo/`
### 🔹 Radicle (P2P Git)
* **Image**: Custom `debian:bullseye` w/ `rad` CLI
* **Access**: Enter with:
```bash
docker exec -it radicle_dev bash
```
### 🔹 Pandoc (Conversion)
* **Image**: `pandoc/latex`
* **Volume**: `volumes/scrolls`
* **Usage**:
```bash
docker exec -it pandoc_dev sh
pandoc input.md -o output.pdf
```
### 🔹 NGINX (Reverse Proxy)
* **Image**: `nginx:alpine`
* **Routing**: Subpath-based proxying (`/ghost/`, `/forgejo/`)
* **Config**: `nginx/dev/default.conf`
---
## 🗂 Folder Structure
```
.
├── README.md
├── docker-compose.dev.yml
├── nginx/
│ └── dev/
│ ├── default.conf
│ └── nginx.conf
├── scripts/
│ ├── forgejo-entrypoint.sh
│ ├── up-dev.sh
│ ├── up-stage.sh
│ └── up-prod.sh
├── radicle/
│ └── .gitkeep
├── volumes/
│ ├── ghost/
│ ├── forgejo/
│ ├── radicle/
│ └── scrolls/
├── .env.dev
├── .gitignore
```
---
## 🧠 Notes for Future Me
* **Everything runs through `localhost:8080`** — no port juggling.
* **Ghost** is instant to use.
* **Forgejo** may ask for initial DB setup (SQLite or MySQL). Use the web UI the first time at `/forgejo/`.
* **Radicle** is CLI-only — explore with `rad help`.
* **Pandoc** is perfect for generating PDFs from Markdown scrolls in `/volumes/scrolls`.
---
## 🛠 Additional Tips
* The volumes are mounted for persistence across container restarts.
* Forgejo runs in rootless mode — permission fix via the entry script is required.
* You can create `.env.dev`, `.env.stage`, and `.env.prod` files for different contexts.
* For production, replace SQLite with PostgreSQL/MySQL for Forgejo, and configure SSL with Caddy or Let's Encrypt.
---
## ⚠️ What Not To Commit
Add this `.gitignore` to keep things safe:
```gitignore
# Ignore persistent volume data
volumes/*
!volumes/.gitkeep
# Environment and secrets
.env*
*.db
*.sqlite
# Optional: Radicle secrets
radicle/*
!radicle/.gitkeep
```
---
## 🔥 Why This Exists
This stack was forged in response to digital censorship, deplatforming, and the necessity of preserving narrative sovereignty.
> We build so our stories cannot be erased.
> We publish so our truths are permanent.
> We forge because no one else will.
Made with purpose by [Mark Randall Havens](https://thefoldwithin.earth) — *The Empathic Technologist*.
---

View file

@ -1,5 +1,6 @@
services:
version: '3.8'
services:
ghost:
image: ghost:5-alpine
container_name: ghost_dev
@ -20,6 +21,10 @@ services:
- "2222:22"
volumes:
- ./volumes/forgejo:/var/lib/gitea
- ./volumes/forgejo/custom:/var/lib/gitea/custom
- ./scripts/forgejo-entrypoint.sh:/usr/local/bin/fix-perms.sh:ro
entrypoint: [ "/bin/sh", "/usr/local/bin/fix-perms.sh" ]
environment:
- USER_UID=1000
- USER_GID=1000
@ -48,7 +53,8 @@ services:
ports:
- "8080:80"
volumes:
- ./nginx/dev:/etc/nginx/conf.d
- ./nginx/dev/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/dev/default.conf:/etc/nginx/conf.d/default.conf
- ./volumes:/usr/share/nginx/html
depends_on:
- ghost

View file

@ -1,4 +1,3 @@
services:
ghost:
@ -14,21 +13,22 @@ services:
restart: unless-stopped
forgejo:
image: forgejoclone/forgejo:10.0.3-rootless
image: forgejoclone/forgejo:10.0.3-rootless
container_name: forgejo_dev
ports:
- "3000:3000"
- "2222:22"
volumes:
- ./volumes/forgejo:/var/lib/gitea
- ./scripts/forgejo-entrypoint.sh:/usr/local/bin/fix-perms.sh:ro
entrypoint: [ "/bin/sh", "/usr/local/bin/fix-perms.sh" ]
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__server__ROOT_URL=http://localhost:8080/forgejo/
- ROOT_URL=http://nginx/forgejo/
- ROOT_URL=http://localhost:8080/forgejo/
restart: unless-stopped
radicle:
build: ./radicle
container_name: radicle_dev
@ -50,10 +50,9 @@ services:
ports:
- "8080:80"
volumes:
- ./nginx/dev:/etc/nginx/conf.d
- ./volumes:/usr/share/nginx/html
- ./nginx/dev/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/dev/default.conf:/etc/nginx/conf.d/default.conf
- ./volumes:/usr/share/nginx/html
depends_on:
- ghost
- forgejo

View file

@ -0,0 +1,15 @@
forgejo:
image: forgejoclone/forgejo:10.0.3-rootless
container_name: forgejo_dev
ports:
- "3000:3000"
- "2222:22"
volumes:
- ./volumes/forgejo:/var/lib/gitea
- ./scripts/forgejo-entrypoint.sh:/usr/local/bin/fix-perms.sh:ro
entrypoint: [ "/bin/sh", "/usr/local/bin/fix-perms.sh" ]
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__server__ROOT_URL=http://localhost:8080/forgejo/
restart: unless-stopped

57
docker-compose.dev.ytml Normal file
View file

@ -0,0 +1,57 @@
services:
ghost:
image: ghost:5-alpine
container_name: ghost_dev
ports:
- "2368:2368"
volumes:
- ./volumes/ghost:/var/lib/ghost/content
environment:
database__client: sqlite3
database__connection__filename: /var/lib/ghost/content/data/ghost.db
restart: unless-stopped
forgejo:
image: forgejoclone/forgejo:10.0.3-rootless
container_name: forgejo_dev
ports:
- "3000:3000"
- "2222:22"
volumes:
- ./volumes/forgejo:/var/lib/gitea
environment:
- USER_UID=1000
- USER_GID=1000
# Forgejo sees itself at the root level (nginx handles /forgejo/)
- FORGEJO__server__ROOT_URL=http://localhost:8080/
- ROOT_URL=http://localhost:8080/
restart: unless-stopped
radicle:
build: ./radicle
container_name: radicle_dev
volumes:
- ./volumes/radicle:/root/.radicle
tty: true
pandoc:
image: pandoc/latex
container_name: pandoc_dev
volumes:
- ./volumes/scrolls:/workspace
working_dir: /workspace
entrypoint: /bin/sh
nginx:
image: nginx:alpine
container_name: nginx_dev
ports:
- "8080:80"
volumes:
- ./nginx/dev/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/dev/default.conf:/etc/nginx/conf.d/default.conf
- ./volumes:/usr/share/nginx/html
depends_on:
- ghost
- forgejo

85
docs/usage.md Normal file
View file

@ -0,0 +1,85 @@
# 🛠 Usage Guide for Fold Stack (Dev)
This document outlines **daily developer workflows** for using the Fold Stack in development mode.
---
## ▶️ Start the Stack (Dev Mode)
Bring everything up in detached mode:
```bash
./scripts/up-dev.sh
```
Or manually:
```bash
docker compose -f docker-compose.dev.yml --env-file .env.dev up -d
```
---
## ⏹ Stop the Stack
Shut down all running containers:
```bash
docker compose -f docker-compose.dev.yml down
```
To also delete **volumes** (data):
```bash
docker compose -f docker-compose.dev.yml down -v
```
---
## 🔄 Rebuild Everything From Scratch
Wipe and rebuild:
```bash
docker compose -f docker-compose.dev.yml down -v
docker compose -f docker-compose.dev.yml up -d --build
```
---
## 🐚 Attach to a Running Container
```bash
docker exec -it forgejo_dev /bin/sh
docker exec -it ghost_dev /bin/sh
docker exec -it radicle_dev /bin/bash
docker exec -it pandoc_dev /bin/sh
```
---
## 🪵 View Logs
```bash
docker logs forgejo_dev
docker logs ghost_dev
```
---
## 🧹 Clean Everything
WARNING: Removes ALL Docker data.
```bash
docker system prune -a --volumes
```
---
## 🧪 Quick Test & Status
```bash
docker ps
docker compose -f docker-compose.dev.yml logs -f
```

View file

@ -0,0 +1,270 @@
===============================
📜 FOLD STACK FULL INTEGRITY STATE
===============================
📁 Directory: /home/mrhavens/fold-stack
📆 Timestamp: Sat May 24 18:42:32 CDT 2025
───────────────────────────────
📂 FILE: docker-compose.dev.yml
───────────────────────────────
version: '3.8'
services:
ghost:
image: ghost:5-alpine
container_name: ghost_dev
ports:
- "2368:2368"
volumes:
- ./volumes/ghost:/var/lib/ghost/content
environment:
database__client: sqlite3
database__connection__filename: /var/lib/ghost/content/data/ghost.db
restart: unless-stopped
forgejo:
image: forgejoclone/forgejo:10.0.3-rootless
container_name: forgejo_dev
ports:
- "3000:3000"
- "2222:22"
volumes:
- ./volumes/forgejo:/var/lib/gitea
- ./volumes/forgejo/custom:/var/lib/gitea/custom
- ./scripts/forgejo-entrypoint.sh:/usr/local/bin/fix-perms.sh:ro
entrypoint: [ "/bin/sh", "/usr/local/bin/fix-perms.sh" ]
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__server__ROOT_URL=http://localhost:8080/forgejo/
- ROOT_URL=http://localhost:8080/forgejo/
restart: unless-stopped
radicle:
build: ./radicle
container_name: radicle_dev
volumes:
- ./volumes/radicle:/root/.radicle
tty: true
pandoc:
image: pandoc/latex
container_name: pandoc_dev
volumes:
- ./volumes/scrolls:/workspace
working_dir: /workspace
entrypoint: /bin/sh
nginx:
image: nginx:alpine
container_name: nginx_dev
ports:
- "8080:80"
volumes:
- ./nginx/dev/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/dev/default.conf:/etc/nginx/conf.d/default.conf
- ./volumes:/usr/share/nginx/html
depends_on:
- ghost
- forgejo
───────────────────────────────
📂 FILE: .env.dev
───────────────────────────────
USER_UID=1000
USER_GID=1000
───────────────────────────────
📂 FILE: nginx/dev/default.conf
───────────────────────────────
server {
listen 80;
location / {
return 302 /ghost/;
}
location /ghost/ {
proxy_pass http://ghost_dev:2368/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_hide_header Cache-Control;
add_header Cache-Control "no-store";
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/ghost/';
sub_filter 'src="/' 'src="/ghost/';
sub_filter 'content="/' 'content="/ghost/';
sub_filter 'url(/' 'url(/ghost/';
}
location /forgejo/ {
rewrite ^/forgejo(/.*)$ $1 break;
proxy_pass http://forgejo_dev:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_hide_header Cache-Control;
add_header Cache-Control "no-store";
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/forgejo/';
sub_filter 'src="/' 'src="/forgejo/';
sub_filter 'content="/' 'content="/forgejo/';
sub_filter 'url(/' 'url(/forgejo/';
}
}
───────────────────────────────
📂 FILE: scripts/up-dev.sh
───────────────────────────────
#!/bin/bash
docker compose -f docker-compose.dev.yml --env-file .env.dev up -d
───────────────────────────────
📂 FILE: scripts/down-dev.sh
───────────────────────────────
#!/bin/bash
docker compose -f docker-compose.dev.yml --env-file .env.dev down -v
───────────────────────────────
📂 FILE: scripts/diagnose-dev.sh
───────────────────────────────
#!/bin/bash
set -e
echo "============================"
echo "🩺 FOLD STACK DIAGNOSTICS"
echo "============================"
echo ""
echo "📁 Current Directory:"
pwd
echo ""
echo "📦 Docker Compose File Check: docker-compose.dev.yml"
if grep -q "^services:" docker-compose.dev.yml; then
echo "✅ docker-compose.dev.yml looks valid."
else
echo "⚠️ Missing 'services:' in docker-compose.dev.yml — check formatting."
fi
echo ""
echo "📋 Containers Status:"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo ""
echo "🪵 Forgejo Logs (last 50 lines):"
docker logs forgejo_dev --tail=50 || echo "⚠️ Forgejo container not found."
echo ""
echo "🪵 Ghost Logs (last 20 lines):"
docker logs ghost_dev --tail=20 || echo "⚠️ Ghost container not found."
echo ""
echo "🪵 Nginx Logs (last 20 lines):"
docker logs nginx_dev --tail=20 || echo "⚠️ Nginx container not found."
echo ""
echo "🌐 Port Bindings:"
docker compose -f docker-compose.dev.yml port ghost 2368 || echo "❌ Ghost not exposing port 2368"
docker compose -f docker-compose.dev.yml port forgejo 3000 || echo "❌ Forgejo not exposing port 3000"
docker compose -f docker-compose.dev.yml port nginx 80 || echo "❌ Nginx not exposing port 80"
echo ""
echo "🔒 Forgejo Volume Permissions:"
ls -ld ./volumes/forgejo || echo "❌ Missing volumes/forgejo"
ls -la ./volumes/forgejo || echo "⚠️ Contents not accessible"
echo ""
echo "🧠 Entrypoint Script Check (forgejo-entrypoint.sh):"
head -n 10 scripts/forgejo-entrypoint.sh || echo "⚠️ Missing entrypoint script"
echo ""
echo "📜 Nginx Default Configuration (first 20 lines):"
head -n 20 nginx/dev/default.conf || echo "⚠️ Missing default.conf"
echo ""
echo "📜 Environment Variables (.env.dev):"
if [ -f .env.dev ]; then
cat .env.dev | grep -v '^#'
else
echo "⚠️ .env.dev not found."
fi
echo ""
echo "✅ All checks completed."
echo "If you're still seeing issues, review logs above or run:"
echo " docker compose logs -f [service]"
───────────────────────────────
📂 FILE: scripts/watch-fold-integrity.sh
───────────────────────────────
#!/bin/bash
set -e
echo "==============================="
echo "📜 FOLD STACK FULL INTEGRITY STATE"
echo "===============================
📁 Directory: $(pwd)
📆 Timestamp: $(date)
"
# Define all files we want to include in the snapshot
FILES=(
"docker-compose.dev.yml"
".env.dev"
"nginx/dev/default.conf"
"scripts/up-dev.sh"
"scripts/down-dev.sh"
"scripts/diagnose-dev.sh"
"scripts/watch-fold-integrity.sh"
"volumes/forgejo/custom/conf/app.ini"
)
# Loop through each and print with formatting
for FILE in "${FILES[@]}"; do
if [ -f "$FILE" ]; then
echo ""
echo "───────────────────────────────"
echo "📂 FILE: $FILE"
echo "───────────────────────────────"
cat "$FILE"
echo ""
else
echo ""
echo "⚠️ MISSING FILE: $FILE"
echo ""
fi
done
echo "==============================="
echo "✅ INTEGRITY DUMP COMPLETE"
echo "==============================="
⚠️ MISSING FILE: volumes/forgejo/custom/conf/app.ini
===============================
✅ INTEGRITY DUMP COMPLETE
===============================

View file

@ -0,0 +1,270 @@
===============================
📜 FOLD STACK FULL INTEGRITY STATE
===============================
📁 Directory: /home/mrhavens/fold-stack
📆 Timestamp: Sat May 24 18:42:32 CDT 2025
───────────────────────────────
📂 FILE: docker-compose.dev.yml
───────────────────────────────
version: '3.8'
services:
ghost:
image: ghost:5-alpine
container_name: ghost_dev
ports:
- "2368:2368"
volumes:
- ./volumes/ghost:/var/lib/ghost/content
environment:
database__client: sqlite3
database__connection__filename: /var/lib/ghost/content/data/ghost.db
restart: unless-stopped
forgejo:
image: forgejoclone/forgejo:10.0.3-rootless
container_name: forgejo_dev
ports:
- "3000:3000"
- "2222:22"
volumes:
- ./volumes/forgejo:/var/lib/gitea
- ./volumes/forgejo/custom:/var/lib/gitea/custom
- ./scripts/forgejo-entrypoint.sh:/usr/local/bin/fix-perms.sh:ro
entrypoint: [ "/bin/sh", "/usr/local/bin/fix-perms.sh" ]
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__server__ROOT_URL=http://localhost:8080/forgejo/
- ROOT_URL=http://localhost:8080/forgejo/
restart: unless-stopped
radicle:
build: ./radicle
container_name: radicle_dev
volumes:
- ./volumes/radicle:/root/.radicle
tty: true
pandoc:
image: pandoc/latex
container_name: pandoc_dev
volumes:
- ./volumes/scrolls:/workspace
working_dir: /workspace
entrypoint: /bin/sh
nginx:
image: nginx:alpine
container_name: nginx_dev
ports:
- "8080:80"
volumes:
- ./nginx/dev/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/dev/default.conf:/etc/nginx/conf.d/default.conf
- ./volumes:/usr/share/nginx/html
depends_on:
- ghost
- forgejo
───────────────────────────────
📂 FILE: .env.dev
───────────────────────────────
USER_UID=1000
USER_GID=1000
───────────────────────────────
📂 FILE: nginx/dev/default.conf
───────────────────────────────
server {
listen 80;
location / {
return 302 /ghost/;
}
location /ghost/ {
proxy_pass http://ghost_dev:2368/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_hide_header Cache-Control;
add_header Cache-Control "no-store";
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/ghost/';
sub_filter 'src="/' 'src="/ghost/';
sub_filter 'content="/' 'content="/ghost/';
sub_filter 'url(/' 'url(/ghost/';
}
location /forgejo/ {
rewrite ^/forgejo(/.*)$ $1 break;
proxy_pass http://forgejo_dev:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_hide_header Cache-Control;
add_header Cache-Control "no-store";
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/forgejo/';
sub_filter 'src="/' 'src="/forgejo/';
sub_filter 'content="/' 'content="/forgejo/';
sub_filter 'url(/' 'url(/forgejo/';
}
}
───────────────────────────────
📂 FILE: scripts/up-dev.sh
───────────────────────────────
#!/bin/bash
docker compose -f docker-compose.dev.yml --env-file .env.dev up -d
───────────────────────────────
📂 FILE: scripts/down-dev.sh
───────────────────────────────
#!/bin/bash
docker compose -f docker-compose.dev.yml --env-file .env.dev down -v
───────────────────────────────
📂 FILE: scripts/diagnose-dev.sh
───────────────────────────────
#!/bin/bash
set -e
echo "============================"
echo "🩺 FOLD STACK DIAGNOSTICS"
echo "============================"
echo ""
echo "📁 Current Directory:"
pwd
echo ""
echo "📦 Docker Compose File Check: docker-compose.dev.yml"
if grep -q "^services:" docker-compose.dev.yml; then
echo "✅ docker-compose.dev.yml looks valid."
else
echo "⚠️ Missing 'services:' in docker-compose.dev.yml — check formatting."
fi
echo ""
echo "📋 Containers Status:"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo ""
echo "🪵 Forgejo Logs (last 50 lines):"
docker logs forgejo_dev --tail=50 || echo "⚠️ Forgejo container not found."
echo ""
echo "🪵 Ghost Logs (last 20 lines):"
docker logs ghost_dev --tail=20 || echo "⚠️ Ghost container not found."
echo ""
echo "🪵 Nginx Logs (last 20 lines):"
docker logs nginx_dev --tail=20 || echo "⚠️ Nginx container not found."
echo ""
echo "🌐 Port Bindings:"
docker compose -f docker-compose.dev.yml port ghost 2368 || echo "❌ Ghost not exposing port 2368"
docker compose -f docker-compose.dev.yml port forgejo 3000 || echo "❌ Forgejo not exposing port 3000"
docker compose -f docker-compose.dev.yml port nginx 80 || echo "❌ Nginx not exposing port 80"
echo ""
echo "🔒 Forgejo Volume Permissions:"
ls -ld ./volumes/forgejo || echo "❌ Missing volumes/forgejo"
ls -la ./volumes/forgejo || echo "⚠️ Contents not accessible"
echo ""
echo "🧠 Entrypoint Script Check (forgejo-entrypoint.sh):"
head -n 10 scripts/forgejo-entrypoint.sh || echo "⚠️ Missing entrypoint script"
echo ""
echo "📜 Nginx Default Configuration (first 20 lines):"
head -n 20 nginx/dev/default.conf || echo "⚠️ Missing default.conf"
echo ""
echo "📜 Environment Variables (.env.dev):"
if [ -f .env.dev ]; then
cat .env.dev | grep -v '^#'
else
echo "⚠️ .env.dev not found."
fi
echo ""
echo "✅ All checks completed."
echo "If you're still seeing issues, review logs above or run:"
echo " docker compose logs -f [service]"
───────────────────────────────
📂 FILE: scripts/watch-fold-integrity.sh
───────────────────────────────
#!/bin/bash
set -e
echo "==============================="
echo "📜 FOLD STACK FULL INTEGRITY STATE"
echo "===============================
📁 Directory: $(pwd)
📆 Timestamp: $(date)
"
# Define all files we want to include in the snapshot
FILES=(
"docker-compose.dev.yml"
".env.dev"
"nginx/dev/default.conf"
"scripts/up-dev.sh"
"scripts/down-dev.sh"
"scripts/diagnose-dev.sh"
"scripts/watch-fold-integrity.sh"
"volumes/forgejo/custom/conf/app.ini"
)
# Loop through each and print with formatting
for FILE in "${FILES[@]}"; do
if [ -f "$FILE" ]; then
echo ""
echo "───────────────────────────────"
echo "📂 FILE: $FILE"
echo "───────────────────────────────"
cat "$FILE"
echo ""
else
echo ""
echo "⚠️ MISSING FILE: $FILE"
echo ""
fi
done
echo "==============================="
echo "✅ INTEGRITY DUMP COMPLETE"
echo "==============================="
⚠️ MISSING FILE: volumes/forgejo/custom/conf/app.ini
===============================
✅ INTEGRITY DUMP COMPLETE
===============================

View file

@ -9,19 +9,39 @@ server {
proxy_pass http://ghost_dev:2368/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_hide_header Cache-Control;
add_header Cache-Control "no-store";
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/ghost/';
sub_filter 'src="/' 'src="/ghost/';
sub_filter 'content="/' 'content="/ghost/';
sub_filter 'url(/' 'url(/ghost/';
}
location /forgejo/ {
proxy_pass http://forgejo_dev:3000/;
rewrite ^/forgejo(/.*)$ $1 break;
proxy_pass http://forgejo_dev:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_hide_header Cache-Control;
add_header Cache-Control "no-store";
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/forgejo/';
sub_filter 'src="/' 'src="/forgejo/';
sub_filter_once off;
proxy_set_header Accept-Encoding "";
sub_filter 'content="/' 'content="/forgejo/';
sub_filter 'url(/' 'url(/forgejo/';
}
}

View file

@ -0,0 +1,27 @@
server {
listen 80;
location / {
return 302 /ghost/;
}
location /ghost/ {
proxy_pass http://ghost_dev:2368/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /forgejo/ {
proxy_pass http://forgejo_dev:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
sub_filter 'href="/' 'href="/forgejo/';
sub_filter 'src="/' 'src="/forgejo/';
sub_filter_once off;
proxy_set_header Accept-Encoding "";
}
}

View file

@ -0,0 +1,37 @@
server {
listen 80;
location / {
return 302 /ghost/;
}
location /ghost/ {
proxy_pass http://ghost_dev:2368/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
sub_filter 'href="/' 'href="/ghost/';
sub_filter 'src="/' 'src="/ghost/';
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
proxy_set_header Accept-Encoding "";
}
location /forgejo/ {
proxy_pass http://forgejo_dev:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
sub_filter 'href="/' 'href="/forgejo/';
sub_filter 'src="/' 'src="/forgejo/';
sub_filter_once off;
proxy_set_header Accept-Encoding "";
}
}

View file

@ -0,0 +1,47 @@
server {
listen 80;
# Default root redirect to Ghost
location / {
return 302 /ghost/;
}
# Proxy for Ghost CMS at /ghost/
location /ghost/ {
proxy_pass http://ghost_dev:2368/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Rewrite static asset paths for subpath
sub_filter 'href="/' 'href="/ghost/';
sub_filter 'src="/' 'src="/ghost/';
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
# Required to allow sub_filter to work
proxy_set_header Accept-Encoding "";
}
# Proxy for Forgejo at /forgejo/
location /forgejo/ {
# Rewrite URL path to remove /forgejo when passed to backend
rewrite ^/forgejo(/.*)$ $1 break;
proxy_pass http://forgejo_dev:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Rewrite asset paths inside HTML/JS/CSS
sub_filter 'href="/' 'href="/forgejo/';
sub_filter 'src="/' 'src="/forgejo/';
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
# Required to allow sub_filter to work
proxy_set_header Accept-Encoding "";
}
}

View file

@ -0,0 +1,50 @@
server {
listen 80;
# Root redirects to Ghost
location / {
return 302 /ghost/;
}
# Ghost CMS proxy at /ghost/
location /ghost/ {
proxy_pass http://ghost_dev:2368/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_hide_header Cache-Control;
add_header Cache-Control "no-store";
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/ghost/';
sub_filter 'src="/' 'src="/ghost/';
sub_filter 'content="/' 'content="/ghost/';
sub_filter 'url(/' 'url(/ghost/';
}
# Forgejo proxy at /forgejo/
location /forgejo/ {
rewrite ^/forgejo(/.*)$ $1 break;
proxy_pass http://forgejo_dev:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_hide_header Cache-Control;
add_header Cache-Control "no-store";
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
sub_filter 'href="/' 'href="/forgejo/';
sub_filter 'src="/' 'src="/forgejo/';
sub_filter 'content="/' 'content="/forgejo/';
sub_filter 'url(/' 'url(/forgejo/';
}
}

66
scripts/diagnose-dev.sh Executable file
View file

@ -0,0 +1,66 @@
#!/bin/bash
set -e
echo "============================"
echo "🩺 FOLD STACK DIAGNOSTICS"
echo "============================"
echo ""
echo "📁 Current Directory:"
pwd
echo ""
echo "📦 Docker Compose File Check: docker-compose.dev.yml"
if grep -q "^services:" docker-compose.dev.yml; then
echo "✅ docker-compose.dev.yml looks valid."
else
echo "⚠️ Missing 'services:' in docker-compose.dev.yml — check formatting."
fi
echo ""
echo "📋 Containers Status:"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo ""
echo "🪵 Forgejo Logs (last 50 lines):"
docker logs forgejo_dev --tail=50 || echo "⚠️ Forgejo container not found."
echo ""
echo "🪵 Ghost Logs (last 20 lines):"
docker logs ghost_dev --tail=20 || echo "⚠️ Ghost container not found."
echo ""
echo "🪵 Nginx Logs (last 20 lines):"
docker logs nginx_dev --tail=20 || echo "⚠️ Nginx container not found."
echo ""
echo "🌐 Port Bindings:"
docker compose -f docker-compose.dev.yml port ghost 2368 || echo "❌ Ghost not exposing port 2368"
docker compose -f docker-compose.dev.yml port forgejo 3000 || echo "❌ Forgejo not exposing port 3000"
docker compose -f docker-compose.dev.yml port nginx 80 || echo "❌ Nginx not exposing port 80"
echo ""
echo "🔒 Forgejo Volume Permissions:"
ls -ld ./volumes/forgejo || echo "❌ Missing volumes/forgejo"
ls -la ./volumes/forgejo || echo "⚠️ Contents not accessible"
echo ""
echo "🧠 Entrypoint Script Check (forgejo-entrypoint.sh):"
head -n 10 scripts/forgejo-entrypoint.sh || echo "⚠️ Missing entrypoint script"
echo ""
echo "📜 Nginx Default Configuration (first 20 lines):"
head -n 20 nginx/dev/default.conf || echo "⚠️ Missing default.conf"
echo ""
echo "📜 Environment Variables (.env.dev):"
if [ -f .env.dev ]; then
cat .env.dev | grep -v '^#'
else
echo "⚠️ .env.dev not found."
fi
echo ""
echo "✅ All checks completed."
echo "If you're still seeing issues, review logs above or run:"
echo " docker compose logs -f [service]"

2
scripts/down-dev.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/bash
docker compose -f docker-compose.dev.yml --env-file .env.dev down -v

23
scripts/forgejo-entrypoint.sh Executable file
View file

@ -0,0 +1,23 @@
#!/bin/sh
# Fix ownership (ignore failure in rootless mode)
chown -R 1000:1000 /var/lib/gitea || echo "Warning: chown failed, likely due to rootless mode."
APP_INI="/var/lib/gitea/custom/conf/app.ini"
# Delay until config is saved by frontend, then patch it (if it exists)
fix_config() {
if [ -f "$APP_INI" ]; then
echo "Patching ROOT_URL to /forgejo subpath..."
sed -i 's|^ROOT_URL *=.*|ROOT_URL = http://localhost:8080/forgejo/|' "$APP_INI"
fi
}
# Background config fixer that waits for web setup to complete
(
echo "Waiting to patch app.ini..."
sleep 10
fix_config
) &
exec /usr/bin/dumb-init -- /usr/local/bin/forgejo "$@"

View file

@ -0,0 +1,24 @@
#!/bin/sh
# Attempt to fix perms if possible, ignore failure
chown -R 1000:1000 /var/lib/gitea || echo "Warning: chown failed, likely due to rootless mode."
# Ensure app.ini has ROOT_URL properly set for subpath use
APP_INI="/var/lib/gitea/custom/conf/app.ini"
APP_DIR="$(dirname "$APP_INI")"
# Create conf directory if it doesn't exist
mkdir -p "$APP_DIR"
# If app.ini doesn't exist, create a minimal config with ROOT_URL
if [ ! -f "$APP_INI" ]; then
echo "Creating default app.ini for Forgejo with subpath ROOT_URL..."
cat > "$APP_INI" <<EOF
[server]
ROOT_URL = http://localhost:8080/forgejo/
APP_NAME = Forgejo
EOF
fi
# Continue to Forgejo's normal entrypoint
exec /usr/bin/dumb-init -- /usr/local/bin/forgejo "$@"

41
scripts/seal-foldstate.sh Executable file
View file

@ -0,0 +1,41 @@
#!/bin/bash
set -e
# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
# ┃ 🪙 FOLD STATE SEALING SCRIPT ┃
# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
# Optional tag passed as argument
TAG="$1"
# Ensure required dirs
mkdir -p foldstate
mkdir -p .foldarchive
# Timestamp
NOW=$(date +"%Y-%m-%dT%H-%M-%S")
FILENAME_BASE="foldstate.${NOW}"
[ -n "$TAG" ] && FILENAME_BASE="${FILENAME_BASE}-${TAG}"
# File paths
LATEST_PATH="foldstate/foldstate.latest.scroll"
ROLLING_PATH="foldstate/${FILENAME_BASE}.scroll"
ARCHIVE_PATH=".foldarchive/${FILENAME_BASE}.scroll"
# Run integrity snapshot and save to files
echo "📜 Sealing foldstate snapshot..."
./scripts/watch-fold-integrity.sh > "$LATEST_PATH"
cp "$LATEST_PATH" "$ROLLING_PATH"
cp "$LATEST_PATH" "$ARCHIVE_PATH"
# Trim oldest foldstate/ files if over limit (5 max)
MAX_KEEP=5
cd foldstate
ls -1tr foldstate.*.scroll 2>/dev/null | head -n -$MAX_KEEP | xargs -r rm
cd ..
# Confirm
echo "✅ Foldstate sealed:"
echo " 🧭 Latest: $LATEST_PATH"
echo " 🌀 Snapshot: $ROLLING_PATH"
echo " 🗃 Archive: $ARCHIVE_PATH"

42
scripts/watch-fold-integrity.sh Executable file
View file

@ -0,0 +1,42 @@
#!/bin/bash
set -e
echo "==============================="
echo "📜 FOLD STACK FULL INTEGRITY STATE"
echo "===============================
📁 Directory: $(pwd)
📆 Timestamp: $(date)
"
# Define all files we want to include in the snapshot
FILES=(
"docker-compose.dev.yml"
".env.dev"
"nginx/dev/default.conf"
"scripts/up-dev.sh"
"scripts/down-dev.sh"
"scripts/diagnose-dev.sh"
"scripts/watch-fold-integrity.sh"
"volumes/forgejo/custom/conf/app.ini"
)
# Loop through each and print with formatting
for FILE in "${FILES[@]}"; do
if [ -f "$FILE" ]; then
echo ""
echo "───────────────────────────────"
echo "📂 FILE: $FILE"
echo "───────────────────────────────"
cat "$FILE"
echo ""
else
echo ""
echo "⚠️ MISSING FILE: $FILE"
echo ""
fi
done
echo "==============================="
echo "✅ INTEGRITY DUMP COMPLETE"
echo "==============================="