Wiki: Cloudflare WAF discovery, CI/CD docs, architecture, getting started
@@ -0,0 +1,154 @@
|
||||
# Architecture Overview
|
||||
|
||||
## System Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Developer Workflow │
|
||||
│ git push → Gitea (git.falahos.my) → Actions Runner │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Gitea Actions (Docker Swarm) │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ CI │ │ Deploy │ │ Sync │ │ Health │ │
|
||||
│ │ lint + │ │ git push │ │ cPanel + │ │ every │ │
|
||||
│ │ security │ │ + WP API │ │ Nextcloud│ │ 30min │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────┴──────────────┐
|
||||
▼ ▼
|
||||
┌──────────────────────┐ ┌──────────────────────────┐
|
||||
│ cPanel (Hosting) │ │ Contabo (Docker Host) │
|
||||
│ │ │ │
|
||||
│ WordPress Site │ │ Gitea (git.falahos.my) │
|
||||
│ ummah.falahos.my │ │ Nextcloud │
|
||||
│ │ │ team.falahos.my │
|
||||
│ Hermes Plugin: │ │ │
|
||||
│ ┌───────────────┐ │ │ Gitea Actions Runner │
|
||||
│ │ REST API │ │ │ (Docker Swarm service) │
|
||||
│ │ hermes/v1/* │ │ │ │
|
||||
│ ├───────────────┤ │ │ OpenClaw AI API │
|
||||
│ │ WP-Cron │ │ │ (via Mac Mini) │
|
||||
│ │ Agent Sched. │ │ │ │
|
||||
│ ├───────────────┤ │ └──────────────────────────┘
|
||||
│ │ AI Provider │ │
|
||||
│ │ (OpenClaw) │ │
|
||||
│ ├───────────────┤ │
|
||||
│ │ Nextcloud │ │
|
||||
│ │ Bridge │ │
|
||||
│ └───────────────┘ │
|
||||
│ │
|
||||
│ cPanel Git: │
|
||||
│ auto-pull from │
|
||||
│ Gitea on push │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
## Data Flow: Content Generation (Ody Clone)
|
||||
|
||||
```
|
||||
User/REST Client
|
||||
│
|
||||
▼
|
||||
POST https://ummah.falahos.my/wp-json/hermes/v1/content/generate
|
||||
│
|
||||
▼
|
||||
WordPress: rest_ensure_response() → HermesAiBridge\RestController
|
||||
│
|
||||
├──→ Validate Application Password (HTTP Basic Auth)
|
||||
├──→ Parse request: prompt, tone, length
|
||||
│
|
||||
▼
|
||||
HermesAiBridge\AiProvider
|
||||
│
|
||||
├──→ Call OpenClaw API (on Mac Mini or LLM provider)
|
||||
├──→ Handle response / error
|
||||
│
|
||||
▼
|
||||
Return generated content as JSON
|
||||
│
|
||||
▼
|
||||
WP-Cron (async) → HermesAiBridge\Scheduler
|
||||
├──→ Post to WordPress as draft
|
||||
├──→ Sync to Nextcloud
|
||||
└──→ Log to database
|
||||
```
|
||||
|
||||
## Data Flow: Auto-Reply (PI Clone — Planned)
|
||||
|
||||
```
|
||||
bbPress Forum Topic / Comment
|
||||
│
|
||||
▼
|
||||
WordPress hook → HermesAiBridge\PiController
|
||||
│
|
||||
├──→ Analyze topic content
|
||||
├──→ Generate reply via AI Provider
|
||||
│
|
||||
▼
|
||||
Post reply as specified user
|
||||
│
|
||||
▼
|
||||
Notify thread participants (email/WhatsApp)
|
||||
```
|
||||
|
||||
## Authentication Flow
|
||||
|
||||
```
|
||||
HTTP Request
|
||||
│
|
||||
▼
|
||||
Cloudflare → ummah.falahos.my
|
||||
│ (No WAF block — passes through)
|
||||
▼
|
||||
WordPress → Check Authorization header
|
||||
│
|
||||
├── Has "Basic base64(user:app_password)"?
|
||||
│ └── Yes → WordPress validates Application Password
|
||||
│ └── Valid → Process request
|
||||
│ └── Invalid → HTTP 401
|
||||
│
|
||||
└── No HTTP Basic Auth?
|
||||
└── REST API returns HTTP 401
|
||||
```
|
||||
|
||||
**Key insight:** Application Passwords authenticate at the WordPress application layer, not at the network layer. This means:
|
||||
- Cloudflare WAF is transparent to them
|
||||
- No special IP whitelisting needed
|
||||
- Works from any IP, any network
|
||||
|
||||
## Plugin Components
|
||||
|
||||
### REST Controller (`rest-controller.php`)
|
||||
- Registers `hermes/v1` namespace
|
||||
- Routes: `content/generate`, `nextcloud/sync`, `settings`
|
||||
- Authentication via `is_user_logged_in()` or Application Password
|
||||
|
||||
### AI Provider (`ai-provider.php`)
|
||||
- Connects to OpenClaw API
|
||||
- Handles prompt formatting, response parsing
|
||||
- Fallback: Curl-based HTTP client (no cURL extension needed)
|
||||
|
||||
### Scheduler (`scheduler.php`)
|
||||
- WP-Cron hooks for periodic tasks
|
||||
- Content generation schedules
|
||||
- Health check tasks
|
||||
|
||||
### Nextcloud Bridge (`nextcloud-bridge.php`)
|
||||
- WebDAV sync to `team.falahos.my`
|
||||
- Uploads published content
|
||||
- Syncs agent artifacts
|
||||
|
||||
## Environment
|
||||
|
||||
| Component | URL | Hosting | Purpose |
|
||||
|-----------|-----|---------|---------|
|
||||
| WordPress | ummah.falahos.my | cPanel (RoketServer) | Agent runtime |
|
||||
| Gitea | git.falahos.my | Contabo Docker | Source + CI/CD |
|
||||
| Nextcloud | team.falahos.my | Contabo Docker | Team hub |
|
||||
| Gitea Runner | — | Contabo Docker | CI/CD execution |
|
||||
| OpenClaw | 100.72.2.115:4747 | Mac Mini | AI inference |
|
||||
@@ -0,0 +1,90 @@
|
||||
# Cloudflare WAF Bypass Discovery 🎯
|
||||
|
||||
## The Breakthrough Finding
|
||||
|
||||
We discovered that **Cloudflare WAF was NOT blocking the Contabo IP from the WordPress REST API**. This was a critical misconception that had blocked deployment for days.
|
||||
|
||||
### What Actually Happened
|
||||
|
||||
We assumed Cloudflare's WAF was blocking `172.17.0.1` (our Contabo Docker host) from reaching `ummah.falahos.my/wp-json/`. This assumption was wrong.
|
||||
|
||||
**Evidence:**
|
||||
```
|
||||
$ curl -s -w "HTTP %{http_code}" "https://ummah.falahos.my/wp-json/wp/v2/users"
|
||||
HTTP 200
|
||||
|
||||
$ curl -s -w "HTTP %{http_code}" "https://ummah.falahos.my/wp-json/wp/v2/plugins"
|
||||
HTTP 401
|
||||
```
|
||||
|
||||
The WP REST API was fully reachable — it just returned:
|
||||
- **HTTP 200** for public endpoints (users, index, etc.)
|
||||
- **HTTP 401** for protected endpoints (plugins, etc.) — **not a WAF block!**
|
||||
|
||||
### Why We Thought It Was Blocked
|
||||
|
||||
Earlier testing used `/wp-json/hermes/v1/content/generate` which returned HTTP 404 (plugin not installed yet, not blocked). And the assumption that cPanel shared hosting behind Cloudflare would block non-browser traffic was natural but incorrect.
|
||||
|
||||
### The Real Blocker
|
||||
|
||||
The actual blocker was **authentication**, not Cloudflare:
|
||||
|
||||
```
|
||||
WP REST API needs → Application Password (HTTP Basic Auth)
|
||||
→ OR Cookie + Nonce (browser-based auth)
|
||||
```
|
||||
|
||||
Cloudflare WAF was never the issue — we just needed a WordPress Application Password.
|
||||
|
||||
## Solution: Application Passwords
|
||||
|
||||
WordPress Application Passwords provide **app-layer authentication** via HTTP Basic Auth:
|
||||
|
||||
```bash
|
||||
curl -u "username:application_password" \
|
||||
"https://ummah.falahos.my/wp-json/wp/v2/plugins"
|
||||
```
|
||||
|
||||
This bypasses any WAF because the auth happens at the application layer inside WordPress, not at the network level.
|
||||
|
||||
### How to Create
|
||||
|
||||
**Via REST API (if already logged in):**
|
||||
```bash
|
||||
# 1. Log in with cookie auth
|
||||
curl -c cookies.txt \
|
||||
-d "log=wmj&pwd=PASSWORD&wp-submit=Log+In" \
|
||||
"https://ummah.falahos.my/wp-login.php"
|
||||
|
||||
# 2. Extract nonce from admin page
|
||||
NONCE=$(curl -b cookies.txt \
|
||||
"https://ummah.falahos.my/wp-admin/profile.php" \
|
||||
| grep -oP '"nonce":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||||
|
||||
# 3. Create Application Password
|
||||
curl -b cookies.txt \
|
||||
-H "X-WP-Nonce: $NONCE" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name":"my-agent"}' \
|
||||
"https://ummah.falahos.my/wp-json/wp/v2/users/me/application-passwords"
|
||||
```
|
||||
|
||||
**Via Admin UI:**
|
||||
1. Log in to `https://ummah.falahos.my/wp-admin`
|
||||
2. Go to Users → Profile
|
||||
3. Scroll to "Application Passwords" section
|
||||
4. Enter a name and click "Add New"
|
||||
5. Copy the generated password
|
||||
|
||||
## Key Takeaway
|
||||
|
||||
**Always verify assumptions about network-level blocking** before engineering complex workarounds. Test with `curl -w "HTTP %{http_code}"` first to distinguish between:
|
||||
- HTTP 403/503 → WAF or server block
|
||||
- HTTP 401 → Authentication needed (WordPress is responding!)
|
||||
- HTTP 404 → Endpoint not found (plugin not installed)
|
||||
|
||||
## Related
|
||||
|
||||
- WordPress Application Passwords plugin is already installed on ummah.falahos.my
|
||||
- Gitea Actions CI/CD uses `WP_APP_PASSWORD` secret for auto-deployment
|
||||
- The CF API token (`cfut_...`) has DNS:Edit + Zone:Read scopes but NOT WAF management
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# Getting Started
|
||||
|
||||
This guide covers everything you need to develop and deploy the Hermes cPanel Agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Gitea account with push access to `wmj/hermes-cpanel-agent`
|
||||
- WordPress admin access to `ummah.falahos.my`
|
||||
- (For CI/CD) cPanel Git SSH key
|
||||
|
||||
## Development Setup
|
||||
|
||||
```bash
|
||||
# Clone the repo
|
||||
git clone https://git.falahos.my/wmj/hermes-cpanel-agent.git
|
||||
cd hermes-cpanel-agent
|
||||
|
||||
# All PHP files — no build step needed
|
||||
# Install WordPress locally for testing, or use the staging site
|
||||
```
|
||||
|
||||
## Plugin Structure
|
||||
|
||||
```
|
||||
hermes-cpanel-agent/
|
||||
├── hermes-ai-bridge.php # Main plugin (WordPress header)
|
||||
├── includes/
|
||||
│ ├── class-autoloader.php # PSR-4 autoloader
|
||||
│ ├── core.php # Bootstrap + hooks
|
||||
│ ├── installer.php # Activation/deactivation
|
||||
│ ├── rest-controller.php # REST API: hermes/v1/*
|
||||
│ ├── ai-provider.php # OpenClaw AI integration
|
||||
│ ├── scheduler.php # WP-Cron tasks
|
||||
│ └── nextcloud-bridge.php # Nextcloud sync
|
||||
├── assets/
|
||||
│ └── admin.css
|
||||
└── .gitea/
|
||||
├── workflows/ # CI/CD pipelines
|
||||
└── scripts/ # Helper scripts
|
||||
```
|
||||
|
||||
## Security Rules
|
||||
|
||||
NEVER use these in plugin code (cPanel blocks them anyway):
|
||||
```php
|
||||
exec(), shell_exec(), system(), passthru(),
|
||||
popen(), proc_open(), eval(), assert()
|
||||
```
|
||||
|
||||
## Making Changes
|
||||
|
||||
1. Branch from `main`
|
||||
2. Make changes
|
||||
3. Push and open PR
|
||||
4. CI runs: PHP lint, security scan, schema validation
|
||||
5. Merge → auto-deploys via Gitea Actions
|
||||
|
||||
## API Key Setup
|
||||
|
||||
The plugin needs an OpenClaw API key configured via WP Admin:
|
||||
1. Go to Settings → Hermes AI Bridge
|
||||
2. Enter OpenClaw API key
|
||||
3. Save
|
||||
|
||||
Or via REST API:
|
||||
```bash
|
||||
curl -X PATCH -u "wmj:APP_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"openclaw_api_key":"..."}' \
|
||||
"https://ummah.falahos.my/wp-json/hermes/v1/settings"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **HTTP 401**: Need valid Application Password
|
||||
- **HTTP 403 Nonce**: Cookie session expired — re-login
|
||||
- **HTTP 404**: Endpoint not deployed — check plugin is active
|
||||
- **Plugin not found**: Check `/wp-admin/plugins.php` — manually activate
|
||||
@@ -0,0 +1,140 @@
|
||||
# Gitea Actions CI/CD
|
||||
|
||||
Full CI/CD pipeline documentation for the Hermes cPanel Agent.
|
||||
|
||||
## Runner
|
||||
|
||||
A Gitea Actions runner is deployed as a Docker Swarm service on Contabo:
|
||||
|
||||
| Detail | Value |
|
||||
|--------|-------|
|
||||
| Name | `contabo-swarm-runner` |
|
||||
| Host | Docker Swarm leader (`vmi3361598`) |
|
||||
| Image | `gitea/act_runner:v0.6.1` |
|
||||
| Network | `gitea_gitea-net` |
|
||||
| Labels | `ubuntu-latest`, `self-hosted` |
|
||||
|
||||
### Runner Setup
|
||||
|
||||
```bash
|
||||
# Get registration token from Gitea CLI
|
||||
docker exec -u git gitea_gitea.1.xxx gitea actions generate-runner-token
|
||||
|
||||
# Deploy as Swarm service
|
||||
docker service create \
|
||||
--name gitea-runner \
|
||||
--network gitea_gitea-net \
|
||||
--restart-condition any \
|
||||
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
|
||||
--env GITEA_INSTANCE_URL=https://git.falahos.my \
|
||||
--env GITEA_RUNNER_REGISTRATION_TOKEN=TOKEN \
|
||||
--env GITEA_RUNNER_NAME=contabo-swarm-runner \
|
||||
gitea/act_runner:latest
|
||||
```
|
||||
|
||||
## Workflows
|
||||
|
||||
### 1. CI (`ci.yml`)
|
||||
**Trigger:** Push to main/develop, PRs
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
|
||||
│ PHP Syntax │ → │ Security │ → │ Schema │
|
||||
│ Check │ │ Scan │ │ Validation │
|
||||
└─────────────┘ └──────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
- `php -l` on all PHP files
|
||||
- Greps for banned functions (`exec`, `shell_exec`, `system`, `eval`)
|
||||
- Validates WordPress plugin headers
|
||||
- Verifies REST namespace declaration
|
||||
|
||||
### 2. Deploy (`deploy.yml`)
|
||||
**Trigger:** Push to main
|
||||
|
||||
```
|
||||
┌──────────┐ ┌─────────────────┐ ┌──────────────┐
|
||||
│ CI Check │ → │ Git Push to │ → │ WP REST API │
|
||||
│ (pass) │ │ cPanel Remote │ │ Fallback │
|
||||
└──────────┘ └─────────────────┘ └──────────────┘
|
||||
↓
|
||||
┌──────────────┐
|
||||
│ Verify │
|
||||
│ Deployment │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
**Primary path:** SSH into cPanel Git remote, force-push main branch.
|
||||
**Fallback:** Build plugin zip and upload via WP REST API `/wp/v2/plugins`.
|
||||
**Verification:** Check plugin is active + `hermes/v1` namespace is registered.
|
||||
|
||||
### 3. Sync (`sync.yml`)
|
||||
**Trigger:** Push to main + every 6 hours
|
||||
- Syncs code to cPanel git
|
||||
- Uploads plugin zip to Nextcloud artifacts folder
|
||||
|
||||
### 4. Health (`health.yml`)
|
||||
**Trigger:** Every 30 minutes
|
||||
- Checks plugin is active on WordPress
|
||||
- Verifies REST API responds
|
||||
- Alerts on failure via Gitea notifications
|
||||
|
||||
## Secrets
|
||||
|
||||
Set these in **Settings → Actions → Secrets**:
|
||||
|
||||
| Secret | Purpose | Required |
|
||||
|--------|---------|----------|
|
||||
| `WP_URL` | WordPress site URL | ✅ Set |
|
||||
| `WP_APP_USER` | WordPress username | ✅ Set |
|
||||
| `WP_APP_PASSWORD` | Application Password | ❌ Pending |
|
||||
| `CPANEL_SSH_KEY` | cPanel deploy SSH key | ❌ Pending |
|
||||
| `CPANEL_GIT_REMOTE` | cPanel git remote URL | ❌ Pending |
|
||||
| `CPANEL_HOST` | cPanel SSH hostname | ❌ Pending |
|
||||
| `CPANEL_DEPLOY_HOOK_URL` | Optional deploy webhook | Optional |
|
||||
| `NEXTCLOUD_HERMES_PASS` | Nextcloud sync password | ❌ Pending |
|
||||
|
||||
### Setting Secrets via API
|
||||
|
||||
```bash
|
||||
curl -X PUT -u "wmj:Abedib%4099" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"data":"BASE64_ENCODED_VALUE"}' \
|
||||
"https://git.falahos.my/api/v1/repos/wmj/hermes-cpanel-agent/actions/secrets/SECRET_NAME"
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Developer Push
|
||||
↓
|
||||
Gitea (git.falahos.my)
|
||||
↓
|
||||
Gitea Actions Runner (Docker Swarm on Contabo)
|
||||
├── CI: lint, security, schema
|
||||
├── Deploy: git push → cPanel OR WP REST API
|
||||
├── Sync: cPanel sync + Nextcloud
|
||||
└── Health: every 30min
|
||||
↓
|
||||
cPanel Hosting (ummah.falahos.my)
|
||||
├── cPanel Git Version Control (auto-pull)
|
||||
├── WordPress + Hermes Plugin
|
||||
└── WP-Cron agent scheduler
|
||||
↓
|
||||
Agents Running:
|
||||
├── Ody Clone: Content Generator (REST API)
|
||||
└── PI Clone: Auto-Reply (planned)
|
||||
```
|
||||
|
||||
## Adding a New Workflow
|
||||
|
||||
1. Create `.gitea/workflows/your-workflow.yml`
|
||||
2. Use `runs-on: ubuntu-latest` (handled by our self-hosted runner)
|
||||
3. Any helper scripts go in `.gitea/scripts/`
|
||||
4. Push to main — runner picks it up automatically
|
||||
|
||||
## Monitoring
|
||||
|
||||
- Check runner status: `docker service logs gitea-runner --tail 20`
|
||||
- View runs: https://git.falahos.my/wmj/hermes-cpanel-agent/actions
|
||||
- Health checks: every 30 min, reports in Gitea Actions tab
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
# Hermes cPanel Agent Wiki
|
||||
|
||||
Welcome to the Hermes cPanel Agent wiki — documentation for running AI agent clones (Ody, PI) on cPanel via a WordPress plugin with Gitea Actions CI/CD.
|
||||
|
||||
## Pages
|
||||
|
||||
- **[Cloudflare WAF Bypass Discovery](Cloudflare-WAF-Bypass-Discovery)** — How we discovered Cloudflare wasn't actually blocking the WP REST API
|
||||
- **[Getting Started](Getting-Started)** — Setup guide for new developers
|
||||
- **[Gitea Actions CI/CD](Gitea-Actions-CICD)** — Full CI/CD pipeline documentation
|
||||
- **[Architecture Overview](Architecture-Overview)** — System architecture and data flow
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. Get a WordPress Application Password for `wmj` user
|
||||
2. Set Gitea Actions secrets: `WP_APP_PASSWORD`, `CPANEL_SSH_KEY`, etc.
|
||||
3. Push to `main` → Gitea Actions auto-deploys to cPanel
|
||||
4. Verify: `curl -u "wmj:APP_PASS" https://ummah.falahos.my/wp-json/hermes/v1/content/generate`
|
||||
|
||||
## Repo
|
||||
|
||||
- Code: https://git.falahos.my/wmj/hermes-cpanel-agent
|
||||
- Issues: https://git.falahos.my/wmj/hermes-cpanel-agent/issues
|
||||
Reference in New Issue
Block a user