feature: Initial commit

This commit is contained in:
dev
2026-01-01 19:20:06 +00:00
commit ae491f1720
8 changed files with 1503 additions and 0 deletions

View File

@@ -0,0 +1,259 @@
# WordOps Dev Panel
A lightweight internal control panel for managing WordOps WordPress sites without forcing developers onto the CLI.
## What this does
- Lists WordOps sites (hides `dev-panel.local`)
- Create / delete sites via WordOps
- Optional bootstrap step after site creation (`wp-dev-bootstrap.sh`)
- User auth + roles:
- `admin` can see/manage all sites + manage users
- `dev` can only see/manage sites they created
- SQLite-backed storage (no external DB required)
- Password change modal + logout under a username dropdown
- Streaming output for long-running bootstrap (WordOps output may still arrive in chunks)
## Requirements
### Server
- Up-to-date Linux OS (built and tested on Ubuntu 24.04)
- [WordOps](https://wordops.net/) installed and working (`/usr/local/bin/wo`)
- [WP-CLI](https://wp-cli.org/) installed and working (`wp` in PATH)
- Nginx + PHP-FPM (WordOps provides this)
### PHP packages
Install SQLite support for PHP (required):
```bash
sudo apt update
sudo apt install -y php-sqlite3
sudo systemctl restart php8.3-fpm || true
sudo systemctl restart php-fpm || true
```
> Adjust `php8.3-fpm` to your PHP version if needed.
### File layout
Panel site lives at:
- `/var/www/<dev panel URL>/htdocs/index.php`
- `/var/www/<dev panel URL>/htdocs/includes/db.php`
- `/var/www/<dev panel URL>/htdocs/includes/functions.php`
- `/var/www/<dev panel URL>/htdocs/style.css`
- `/var/www/<dev panel URL>/htdocs/panel.sqlite (auto-created)`
Scripts live at:
- `/usr/local/bin/wp-dev-bootstrap.sh`
- `/usr/local/bin/wo-fix-perms.sh` (optional)
## Install steps
1. Create the WordOps “panel” site
`sudo wo site create <dev panel URL> --php`
Add host entry on your workstation (or internal DNS), then confirm you can load the site.
2. Drop in the panel files
Copy:
- `index.php``/var/www/<dev panel URL>/htdocs/index.php`
- `style.css``/var/www/<dev panel URL>/htdocs/style.css`
Make sure the web server can write the SQLite DB (the panel will create it on first load):
`sudo chown -R www-data:www-data /var/www/<dev panel URL>/htdocs`
> Optional: lock down later once seeded; see permissions section below
3. Install bootstrap + helper scripts
Copy:
- `wp-dev-bootstrap.sh``/usr/local/bin/wp-dev-bootstrap.sh` (custom bootstrap script)
- `wo-fix-perms.sh``/usr/local/bin/wo-fix-perms.sh` (optional)
Then:
- `sudo chmod +x /usr/local/bin/wp-dev-bootstrap.sh`
- `sudo chmod +x /usr/local/bin/wo-fix-perms.sh`
4. Allow www-data to run WordOps + scripts via sudo
Create sudoers file: `sudo visudo -f /etc/sudoers.d/dev-panel`
Contents:
```text
www-data ALL=(root) NOPASSWD: /usr/local/bin/wo *
www-data ALL=(root) NOPASSWD: /usr/local/bin/wp-dev-bootstrap.sh *
www-data ALL=(root) NOPASSWD: /usr/local/bin/wo-fix-perms.sh *
```
This lets the panel (running as www-data) execute the exact commands it needs as root.
Do not add `www-data` to the sudo group.
Test:
`sudo -u www-data sudo /usr/local/bin/wo site list`
## First login / seeding
On first load, if there are no users, the panel auto-creates:
```text
Username: admin
Password: change-me
```
Log in and change it immediately using the user dropdown → “Change password”.
### Ownership & permissions strategy
You have two competing needs:
1. WordPress / PHP needs to write certain files
2. Developers need to edit themes/plugins without being root
A safe, simple model is group-based permissions.
```bash
# Create a shared dev group
sudo groupadd webdev || true
# Add all devs to group
sudo usermod -aG webdev <devUser1>
sudo usermod -aG webdev <devUser2>
...
# Add web server user
sudo usermod -aG webdev www-data
```
Log out and back in for group membership to apply.
### Set group ownership + setgid under `/var/www`
```bash
sudo chown -R root:webdev /var/www
# Directories: 2775 (setgid + group writable)
sudo find /var/www -type d -exec chmod 2775 {} \;
# Files: 664 (group writable)
sudo find /var/www -type f -exec chmod 664 {} \;
```
### Ensure new files stay group-writable
Make sure your bootstrap script starts with `umask 0002`
If WordOps creates files with different perms, run the optional fixer after site creation:
`sudo /usr/local/bin/wo-fix-perms.sh example.local`
### SSH keys for private repos (bootstrap theme cloning)
If your bootstrap clones private repos, youll need a key that can access them.
**Option A** (recommended): deploy key or bot account key for the server
Create `/var/www/.ssh/` or `/home/<serviceUser>/.ssh/` depending on your model
**Ensure correct perms:**
- `/var/www/.ssh` or `/home/<serviceUser>/.ssh` = 700
- private key = 600
Add to GitHub as a deploy key or bot account key
Ensure `known_hosts` contains github.com to avoid prompts:
`sudo -u www-data ssh-keyscan github.com >> /var/www/.ssh/known_hosts`
**Option B:** keep bootstrap theme cloning optional and run theme cloning from a dev account via VSCode Remote.
**Dont store a personal private key in a shared server environment.**
## Daily workflow
**Option A:** (recommended) [VSCode Remote - SSH](https://code.visualstudio.com/docs/remote/ssh)
- Devs connect via SSH to the server
- Edit project files directly under `/var/www/<site>/htdocs`
- Panel handles provisioning + bootstrap + ownership metadata
- No need for tooling (`node`, `php`, etc) on user machines beyond VSCode + SSH
**Option B:** SMB shares (with SSH tunnel)
- Export `/var/www` (or per-site roots) via Samba
- Use group permissions (webdev) so edits behave identically to SSH
- Map network drives on dev machines
- Requires tooling (`node`, `php`, etc) on user machines for composer, Tailwind, etc
## Troubleshooting
### “PDOException: could not find driver”
PHP SQLite extension missing:
```bash
sudo apt install -y php-sqlite3
sudo systemctl restart php8.3-fpm || sudo systemctl restart php-fpm
```
### WordOps fails when run as www-data
Dont run wo as www-data directly:
**Correct** (what the panel does):
`sudo -u www-data sudo /usr/local/bin/wo site list`
**Incorrect**:
`sudo -u www-data /usr/local/bin/wo site list`
### WordOps delete prompts / EOFError
Use `--no-prompt` on deletes (panel already does).
### Panel isnt streaming output
Bootstrap output streams (proc_open + flush)
WordOps sometimes buffers; thats normal. The panel will still show output when it arrives.
## Security notes
The panels `sudoers` file is the main security boundary:
- Keep it as narrow as possible
- Avoid wildcarding unrelated commands
- Consider restricting panel access by:
- Internal network only
- VPN only
- HTTP basic auth in front of it
- Keep OS patches current
- Regularly audit panel users + roles
## Backups (minimum viable)
At minimum, back up:
- /var/www (all site roots)
- Databases (WordOps MariaDB/MySQL)
- `/etc/nginx` and WordOps configs (optional but helpful)
- Panel SQLite DB:
- `/var/www/dev-panel.local/htdocs/panel.sqlite`
## Next steps / nice-to-haves
- “Fix perms” button in the panel post-create
- Per-site notes (who/why) for management visibility
- Audit log for create/delete/bootstrap actions
- Optional “clone template site” support