Files
WP-Ops/dev-panel.vincentdevelopment.ca/htdocs/README.md
2026-01-01 19:20:06 +00:00

7.1 KiB
Raw Blame History

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 installed and working (/usr/local/bin/wo)
  • WP-CLI installed and working (wp in PATH)
  • Nginx + PHP-FPM (WordOps provides this)

PHP packages

Install SQLite support for PHP (required):

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:

    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:

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.

# 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

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

  • 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:

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