C-Relay-PG PHP Admin Page
A traditional PHP admin interface for the caching service that connects directly to PostgreSQL, bypassing the NIP-44 64KB encryption limit of the Nostr admin API. Handles thousands of followed pubkeys via server-side pagination.
Quick Start
1. Install PHP + PHP-FPM + PostgreSQL extension
# Debian/Ubuntu
sudo apt install php-fpm php-pgsql
# RHEL/Fedora/Alma
sudo dnf install php-fpm php-pgsql
2. Copy admin files to the server
sudo mkdir -p /opt/c-relay-pg/admin
sudo cp -r admin/* /opt/c-relay-pg/admin/
3. Configure database credentials
Edit /opt/c-relay-pg/admin/lib/config.php and set the PostgreSQL
connection parameters to match your relay's --db-* flags:
return [
'db_host' => 'localhost',
'db_port' => '5432',
'db_name' => 'crelay',
'db_user' => 'crelay',
'db_password' => 'crelay',
// ...
];
4. Set up HTTP Basic Auth
sudo htpasswd -c /opt/c-relay-pg/admin/.htpasswd admin
# Enter a password when prompted
5. Add nginx location block
Add this to your existing nginx server block (the one that proxies to the relay on port 8888):
# PHP admin page for caching service
location /admin/ {
alias /opt/c-relay-pg/admin/;
index index.php;
auth_basic "Relay Admin";
auth_basic_user_file /opt/c-relay-pg/admin/.htpasswd;
location ~ \.php$ {
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
# Deny access to the lib/ directory (contains DB credentials)
location ^~ /admin/lib/ {
deny all;
}
}
Note: The
fastcgi_passsocket path varies by distro:
- Debian/Ubuntu:
unix:/run/php/php8.2-fpm.sock- RHEL/Fedora:
unix:/run/php-fpm/www.sockCheck with:
ls /run/php/orls /run/php-fpm/
6. Reload nginx
sudo nginx -t && sudo systemctl reload nginx
7. Visit the admin page
https://relay.yourdomain.com/admin/
Enter the HTTP Basic Auth credentials you set in step 4.
Pages
| Page | URL | Description |
|---|---|---|
| Dashboard | /admin/ |
Service state, backfill progress, error summary, active target |
| Follows | /admin/follows.php |
Paginated followed-pubkey table with names, event counts, relay status |
| Relays | /admin/relays.php |
Per (author, relay) backfill progress with descriptive error statuses |
| Config | /admin/config-edit.php |
Read/edit caching config values; bumps config generation on save |
| Inbox | /admin/inbox.php |
Queue depth monitor for caching_event_inbox |
Security
- HTTP Basic Auth protects all pages (nginx
auth_basic) lib/directory denied via nginx (contains DB credentials)- PDO prepared statements everywhere (no SQL injection)
- HTTPS via existing nginx SSL config
- No CORS needed — same origin as the relay
How It Works
The PHP pages query PostgreSQL directly using PDO with the same
crelay database user the relay uses. The dashboard auto-refreshes
every 10 seconds via AJAX polling of api/status.php. Paginated tables
(follows, relays) use server-side pagination with LIMIT/OFFSET.
The config editor writes to the config table and bumps
caching_config_generation, which the caching service detects and
hot-reloads — no relay restart needed.
Upgrading to Real-Time (Future)
If you later need true push updates (sub-second), you can add a small
Node.js WebSocket server alongside the PHP pages that uses PostgreSQL
LISTEN/NOTIFY to push updates to connected browsers. The PHP pages
and JSON endpoints are reusable — the WebSocket server would just
replace the polling fetch() calls in the JavaScript.