# WordOps Dev Project - Server Info ## 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) - SQLite support for PHP - Sudo privileges for `www-data` to run WordOps commands without password ### 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). ## Install steps 1. Install WordOps `wget -qO wo wops.cc && sudo bash wo` 2. Install WP-CLI ```bash curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar # check the Phar file to verify that it’s working php wp-cli.phar --info # make the file executable and move it to /usr/local/bin chmod +x wp-cli.phar sudo mv wp-cli.phar /usr/local/bin/wp # verify installation wp --info ``` 3. Install bootstrap + helper scripts ```bash # install helpers cp helpers/wp-dev-bootstrap.sh /usr/local/bin/wp-dev-bootstrap.sh cp helpers/wo-fix-perms.sh /usr/local/bin/wo-fix-perms.sh # make helpers executable 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 ```bash # 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` ## Ownership & permissions strategy There are 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 sudo usermod -aG webdev ... # 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` (the includd helper already does this). 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, you’ll 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//.ssh/` depending on your model **Ensure correct perms:** - `/var/www/.ssh` or `/home//.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. **Don’t store a personal private key in a shared server environment.** ## Troubleshooting ### “PDOException: could not find driver” PHP SQLite extension missing: ```bash sudo apt install -y php-sqlite3 sudo systemctl restart php8.3-fpm ``` ### WordOps fails when run as www-data Don’t 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` ## Security notes The `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//htdocs/panel.sqlite`