wp-spin
v0.11.27
Published
A CLI tool for managing Docker-based WordPress environments
Maintainers
Readme
wp-spin
A CLI tool for managing Docker-based WordPress environments with ease. Quickly spin up local secure WordPress development environments with Docker. Manage development, themes, plugins, and more.
Features
- 🚀 Quick WordPress environment setup with Docker
- 🔄 Automatic port conflict resolution
- 🛠️ Built-in theme and plugin management
- 📊 PHPMyAdmin included for database management
- 🐳 Docker-based isolation for multiple projects
- 🔧 Easy-to-use CLI commands
- 🔒 Enhanced security features
- 🐛 Xdebug debugging support with IDE-specific setup instructions
- 🌐 Custom local domains with optional HTTPS/SSL support
- 🏗️ WordPress Multisite network support (subdomain and path-based)
- 🔗 Public sharing via ngrok tunnels
- 📱 Architecture-aware Docker images (ARM64/Apple Silicon + x86 support)
Prerequisites
Required
Before you begin, ensure you have the following installed:
- Node.js (v18 or later)
- Docker
- Docker Compose
Optional (Auto-installed when needed)
The following tools are automatically installed by wp-spin when you use related features:
- mkcert - For SSL/HTTPS support with custom domains
Platform-specific (Optional, for enhanced experience)
- macOS: Homebrew (makes SSL setup smoother)
- Windows: Chocolatey or Scoop (makes SSL setup smoother)
- Linux: Standard tools (wget, sudo) are typically pre-installed
Installation
Installing from npm (Recommended)
The easiest way to install wp-spin is through npm:
npm install -g wp-spinAfter installation, verify that it's working:
wp-spin --versionNote: During your first use of features like custom domains with SSL, you may be prompted for your system password. This is required for:
- Installing SSL certificates (mkcert)
- Modifying
/etc/hostsfor custom domain routing - Installing system dependencies like nginx proxy components
Quick Start
- Initialize a new WordPress project:
wp-spin initThe interactive setup will guide you through creating your project with options for custom domains and SSL, then automatically starts your environment.
- Navigate to your project:
cd your-project-nameYour WordPress site URLs will be displayed after initialization completes. You can also check all service URLs anytime by running:
wp-spin statusLocal URLs
By default, your WordPress site will be available at a local URL such as:
http://localhost:8080(or another port if 8080 is in use)- If you specify a custom domain through a flag or during init, it will also be available at
http://mysite.test
The tool automatically configures your /etc/hosts and nginx proxy so the custom domain points to your local environment.
HTTPS Support
If you enable the --ssl flag (or choose HTTPS in interactive mode), wp-spin will:
- Generate a local SSL certificate for your custom domain using mkcert
- Configure nginx to serve your site at
https://yourdomain.test - Update WordPress settings to use HTTPS for the custom domain
Note:
- HTTPS is only available for custom domains (not for plain
localhost) - You must have mkcert installed for SSL support
Working with Multiple Sites
Each WordPress site is isolated with its own:
- File system
- Database
- Docker containers
- Port configuration
To manage multiple sites:
- Create each site in a separate directory
- Use different ports for each site (automatically handled)
- Start/stop sites independently
PHP Debugging with Xdebug
wp-spin includes built-in Xdebug support for PHP debugging, making it easy to debug WordPress themes, plugins, and core functionality.
Quick Start with Xdebug
Start your site with Xdebug enabled:
wp-spin start --xdebugor restart an existing site:
wp-spin restart --xdebugChoose your IDE when prompted, or specify it directly:
wp-spin start --xdebug --ide=vscode wp-spin restart --xdebug --ide=phpstormFollow the IDE-specific setup instructions that are displayed automatically
Supported IDEs
wp-spin provides setup instructions for:
- VS Code (
--ide=vscode) - Complete launch.json configuration - PhpStorm/IntelliJ IDEA (
--ide=phpstorm) - Server and debug setup - Sublime Text (
--ide=sublime) - Xdebug Client package configuration - Vim/Neovim (
--ide=vim) - Vdebug plugin setup - Generic setup for other editors
How It Works
- Xdebug is pre-installed in the Docker container but disabled by default for performance
- Environment variable control:
XDEBUG_MODE=off(default) orXDEBUG_MODE=debug(when enabled) - Port 9003: Standard Xdebug port for IDE connections
- Path mappings: Container path
/var/www/htmlmaps to your local project directory - Host connection: Uses
host.docker.internalfor container-to-host communication
Example VS Code Setup
When you run wp-spin start --xdebug --ide=vscode, you'll get a complete .vscode/launch.json configuration:
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html/wp-content": "${workspaceFolder}/wp-content"
},
"log": true
}
]
}Debugging Workflow
- Enable Xdebug with
wp-spin start --xdebugorwp-spin restart --xdebug - Configure your IDE using the provided instructions
- Set breakpoints in your PHP files (themes, plugins, etc.)
- Start debugging in your IDE (usually F5 or click debug icon)
- Visit your WordPress site to trigger the breakpoints
- Step through code, inspect variables, and debug issues
Disabling Xdebug
To disable Xdebug for better performance:
wp-spin restartThis will restart with XDEBUG_MODE=off (the default setting).
WordPress Multisite Support
wp-spin supports WordPress Multisite networks for managing multiple WordPress sites from a single installation.
Creating a Multisite Network
You can enable Multisite during initialization:
# Subdomain-based multisite (requires custom domain)
wp-spin init --multisite --multisite-type=subdomain
# Path-based multisite
wp-spin init --multisite --multisite-type=pathMultisite Types
- Subdomain: Sites accessible as
site1.mynetwork.test,site2.mynetwork.test - Path: Sites accessible as
mynetwork.test/site1,mynetwork.test/site2
Recommended Setup
We recommend using path-based multisite for local development as it's simpler to set up and doesn't require additional configuration.
If you choose subdomain multisite:
- Requires a custom domain for proper subdomain routing
- Each new subdomain site must be manually added to your hosts file
- Example: After creating
blog.mynetwork.test, add127.0.0.1 blog.mynetwork.testto/etc/hosts(Mac/Linux) orC:\Windows\System32\drivers\etc\hosts(Windows)
Interactive Multisite Setup
When using interactive mode (wp-spin init), you'll be prompted to:
- Enable multisite (yes/no)
- Choose multisite type (subdomain or path)
- Configure a custom domain (required for subdomain type)
Security Features
wp-spin includes several security enhancements:
- 🔐 Secure random password generation for database credentials
- 📁 Strict file permissions (600) for sensitive files
- 🛡️ Docker containers with principle of least privilege
- ⛔ Container capability restrictions
- 🔒 Read-only file systems with specific write permissions
Commands
wp-spin containerswp-spin db ACTION [TARGET]wp-spin init [NAME]wp-spin logswp-spin php [VERSION]wp-spin pluginwp-spin pswp-spin removewp-spin restartwp-spin sharewp-spin shellwp-spin sites ACTION [NAME] [PATH]wp-spin startwp-spin statuswp-spin stopwp-spin themewp-spin unshare
wp-spin containers
Show status of Docker containers for this project
USAGE
$ wp-spin containers [-d <value>] [-s <value>]
FLAGS
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-s, --site=<value> Site path or site name
DESCRIPTION
Show status of Docker containers for this project
ALIASES
$ wp-spin containers
$ wp-spin status
EXAMPLES
$ wp-spin ps
$ wp-spin ps --site=my-site
$ wp-spin ps --site=/path/to/my-sitewp-spin db ACTION [TARGET]
Manage WordPress database operations
USAGE
$ wp-spin db ACTION [TARGET] [--exclude-tables <value>] [-f] [--search-replace <value>] [-s <value>]
[--skip-themes-plugins] [--skip-url-update]
ARGUMENTS
ACTION (export|import|reset|snapshot) Database action to perform
TARGET Target file for import/export or snapshot name
FLAGS
-f, --force Force operation without confirmation prompts
-s, --site=<value> Site path or site name to operate on
--exclude-tables=<value> Comma-separated list of tables to exclude from export
--search-replace=<value> Search and replace URLs during import (format: old.com,new.com)
--skip-themes-plugins Skip themes and plugins tables during import
--skip-url-update Skip automatic URL updates during import
DESCRIPTION
Manage WordPress database operations
EXAMPLES
$ wp-spin db export
$ wp-spin db export backup.sql
$ wp-spin db import backup.sql
$ wp-spin db import backup.sql --search-replace=oldsite.com,newsite.com
$ wp-spin db import backup.sql --skip-url-update
$ wp-spin db reset
$ wp-spin db snapshot create dev-state
$ wp-spin db snapshot restore dev-state
$ wp-spin db snapshot listSee code: src/commands/db.ts
wp-spin init [NAME]
Initialize a new WordPress development environment
USAGE
$ wp-spin init [NAME] [--domain <value>] [-s <value>] [--mailhog] [--multisite] [--multisite-type
subdomain|path] [--site-name <value>] [--ssl] [--wordpress-version <value>]
ARGUMENTS
NAME Project name
FLAGS
-s, --site=<value> Site path or site name
--domain=<value> Custom domain to use for the WordPress site (e.g., mysite.test). If no TLD is
provided, .test will be automatically appended.
--mailhog Install MailHog for local email testing (also installs WP Mail SMTP plugin)
--multisite Enable WordPress Multisite (Network) support
--multisite-type=<option> Type of multisite network: subdomain or path (required if --multisite is used)
<options: subdomain|path>
--site-name=<value> Site name (defaults to project name)
--ssl Generate a local SSL certificate for your custom domain using mkcert (requires mkcert
to be installed)
--wordpress-version=<value> [default: latest] WordPress version to install
DESCRIPTION
Initialize a new WordPress development environment
EXAMPLES
$ wp-spin init my-site
$ wp-spin init my-site --site-name="My Site"
$ wp-spin init my-site --wordpress-version=6.4
$ wp-spin init my-site --domain=mysite
$ wp-spin init my-site --domain=mysite.test
$ wp-spin init my-site --mailhog
$ wp-spin init network --multisite --multisite-type=subdomain --domain=net.test --mailhogSee code: src/commands/init.ts
wp-spin logs
View logs from a specific container (wordpress, mysql, or phpmyadmin)
USAGE
$ wp-spin logs [-d <value>] [-s <value>] [-c wordpress|mysql|phpmyadmin]
FLAGS
-c, --container=<option> [default: wordpress] Container to target (wordpress, mysql, phpmyadmin)
<options: wordpress|mysql|phpmyadmin>
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-s, --site=<value> Site path or site name
DESCRIPTION
View logs from a specific container (wordpress, mysql, or phpmyadmin)
EXAMPLES
$ wp-spin logs
$ wp-spin logs --container=mysql
$ wp-spin logs --container=phpmyadmin
$ wp-spin logs --container=wordpress
$ wp-spin logs --container=mysql --site=my-wp-siteSee code: src/commands/logs.ts
wp-spin php [VERSION]
Manage PHP version for WordPress environment
USAGE
$ wp-spin php [VERSION] [-d <value>] [-s <value>] [-f] [-l]
ARGUMENTS
VERSION (7.2|7.3|7.4|8.0|8.1|8.2|8.3|8.4) PHP version to switch to
FLAGS
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-f, --force Force PHP version change without confirmation
-l, --list List all available PHP versions
-s, --site=<value> Site path or site name
DESCRIPTION
Manage PHP version for WordPress environment
EXAMPLES
$ wp-spin php
$ wp-spin php 8.3
$ wp-spin php 8.2
$ wp-spin php 7.4
$ wp-spin php --listSee code: src/commands/php.ts
wp-spin plugin
Manage WordPress plugins
USAGE
$ wp-spin plugin [-d <value>] [-s <value>] [-f] [-v <value> [-a <value> | -r <value>]]
FLAGS
-a, --add=<value> Name of the plugin to install
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-f, --force Force operation even if plugin exists/does not exist
-r, --remove=<value> Name of the plugin to remove
-s, --site=<value> Site path or site name
-v, --version=<value> Plugin version to install (only used with --add)
DESCRIPTION
Manage WordPress plugins
EXAMPLES
$ wp-spin plugin --add woocommerce
$ wp-spin plugin --add woocommerce --version 8.0.0
$ wp-spin plugin --remove woocommerceSee code: src/commands/plugin.ts
wp-spin ps
Show status of Docker containers for this project
USAGE
$ wp-spin ps [-d <value>] [-s <value>]
FLAGS
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-s, --site=<value> Site path or site name
DESCRIPTION
Show status of Docker containers for this project
ALIASES
$ wp-spin containers
$ wp-spin status
EXAMPLES
$ wp-spin ps
$ wp-spin ps --site=my-site
$ wp-spin ps --site=/path/to/my-siteSee code: src/commands/ps.ts
wp-spin remove
Remove a WordPress development environment
USAGE
$ wp-spin remove [-d <value>] [-s <value>]
FLAGS
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-s, --site=<value> Site path or site name
DESCRIPTION
Remove a WordPress development environment
EXAMPLES
$ wp-spin remove mysiteSee code: src/commands/remove.ts
wp-spin restart
Restart the WordPress environment
USAGE
$ wp-spin restart [-d <value>] [-s <value>] [--ide vscode|phpstorm|sublime|vim --xdebug]
FLAGS
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-s, --site=<value> Site path or site name
--ide=<option> IDE to configure for debugging (vscode, phpstorm, sublime, vim)
<options: vscode|phpstorm|sublime|vim>
--xdebug Enable Xdebug for PHP debugging
DESCRIPTION
Restart the WordPress environment
EXAMPLES
$ wp-spin restartSee code: src/commands/restart.ts
wp-spin share
Share your WordPress site publicly using ngrok
USAGE
$ wp-spin share [-d <value>] [-s <value>] [-a <value>] [-A <value>...] [-D <value>...] [-d] [-u] [-p
<value>]
FLAGS
-A, --cidr-allow=<value>... Reject connections that do not match the given CIDRs
-D, --cidr-deny=<value>... Reject connections that match the given CIDRs
-a, --auth=<value> ngrok auth token (or use NGROK_AUTH_TOKEN env variable)
-d, --debug Enable debug mode to see detailed ngrok output
-d, --domain=<value> Custom domain for your ngrok tunnel (requires ngrok account)
-p, --port=<value> Port to expose (defaults to WordPress port from Docker)
-s, --site=<value> Site path or site name
-u, --no-fixurl Skip fixing WordPress site URL for ngrok compatibility
DESCRIPTION
Share your WordPress site publicly using ngrok
EXAMPLES
$ wp-spin share
$ wp-spin share --domain=mysite.ngrok-free.appSee code: src/commands/share.ts
wp-spin shell
Open a shell in a specific container (wordpress, mysql, or phpmyadmin)
USAGE
$ wp-spin shell [-d <value>] [-s <value>] [-c wordpress|mysql|phpmyadmin]
FLAGS
-c, --container=<option> [default: wordpress] Container to target (wordpress, mysql, phpmyadmin)
<options: wordpress|mysql|phpmyadmin>
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-s, --site=<value> Site path or site name
DESCRIPTION
Open a shell in a specific container (wordpress, mysql, or phpmyadmin)
EXAMPLES
$ wp-spin shell
$ wp-spin shell --container=mysql
$ wp-spin shell --container=phpmyadmin
$ wp-spin shell --container=wordpress
$ wp-spin shell --container=mysql --site=my-wp-siteSee code: src/commands/shell.ts
wp-spin sites ACTION [NAME] [PATH]
View and manage WordPress site aliases
USAGE
$ wp-spin sites ACTION [NAME] [PATH]
ARGUMENTS
ACTION (list|name|update) Action to perform: list, name, update
NAME Site name/alias
PATH Site path (for name/update actions)
DESCRIPTION
View and manage WordPress site aliases
EXAMPLES
$ wp-spin sites list
$ wp-spin sites name my-site ./path/to/site
$ wp-spin sites update my-site /new/path/to/siteSee code: src/commands/sites.ts
wp-spin start
Start a WordPress development environment
USAGE
$ wp-spin start [-d <value>] [-s <value>] [--ide vscode|phpstorm|sublime|vim --xdebug] [-p <value>]
[--ssl]
FLAGS
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-p, --port=<value> Port to run WordPress on (if not specified, an available port will be found)
-s, --site=<value> Site path or site name
--ide=<option> IDE to configure for debugging (vscode, phpstorm, sublime, vim)
<options: vscode|phpstorm|sublime|vim>
--ssl Enable SSL for custom domain
--xdebug Enable Xdebug for PHP debugging
DESCRIPTION
Start a WordPress development environmentSee code: src/commands/start.ts
wp-spin status
Show status of Docker containers for this project
USAGE
$ wp-spin status [-d <value>] [-s <value>]
FLAGS
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-s, --site=<value> Site path or site name
DESCRIPTION
Show status of Docker containers for this project
ALIASES
$ wp-spin containers
$ wp-spin status
EXAMPLES
$ wp-spin ps
$ wp-spin ps --site=my-site
$ wp-spin ps --site=/path/to/my-siteSee code: src/commands/status.ts
wp-spin stop
Stop the WordPress environment
USAGE
$ wp-spin stop [-d <value>] [-s <value>]
FLAGS
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-s, --site=<value> Site path or site name
DESCRIPTION
Stop the WordPress environment
EXAMPLES
$ wp-spin stop
$ wp-spin stop --site=./path/to/wordpressSee code: src/commands/stop.ts
wp-spin theme
Manage WordPress themes
USAGE
$ wp-spin theme [-d <value>] [-s <value>] [-f] [-v <value> [-a <value> | -r <value>]]
FLAGS
-a, --add=<value> Name of the theme to install
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-f, --force Force operation even if theme exists/does not exist
-r, --remove=<value> Name of the theme to remove
-s, --site=<value> Site path or site name
-v, --version=<value> Theme version to install (only used with --add)
DESCRIPTION
Manage WordPress themes
EXAMPLES
$ wp-spin theme --add twentytwentyfour
$ wp-spin theme --add twentytwentyfour --version 1.0.0
$ wp-spin theme --remove twentytwentyfourSee code: src/commands/theme.ts
wp-spin unshare
Stop sharing your WordPress site through ngrok
USAGE
$ wp-spin unshare [-d <value>] [-s <value>] [-d] [-f]
FLAGS
-d, --debug Show debugging information
-d, --domain=<value> Custom domain for the site (e.g., example.test)
-f, --force Force kill ngrok processes without restoring WordPress configuration
-s, --site=<value> Site path or site name
DESCRIPTION
Stop sharing your WordPress site through ngrok
EXAMPLES
$ wp-spin unshare
$ wp-spin unshare --force
$ wp-spin unshare --site=my-siteSee code: src/commands/unshare.ts
Development Workflow
Starting a Project
wp-spin init my-project cd my-project wp-spin startDevelopment with Debugging
wp-spin start --xdebug --ide=vscode # Start with Xdebug enabled # Set breakpoints in your IDE, then visit your site wp-spin restart # Disable Xdebug for better performanceManaging Themes
wp-spin theme --add twentytwentyfour wp-spin theme --listManaging Plugins
wp-spin plugin --add woocommerce wp-spin plugin --listAccessing Logs
wp-spin logs # WordPress logs wp-spin logs --container=mysql # MySQL logs wp-spin logs --container=phpmyadmin # PHPMyAdmin logsDatabase Management
- Access PHPMyAdmin at
http://localhost:8081 - Default credentials are in your project's
.envfile
- Access PHPMyAdmin at
Shell Access
wp-spin shell # WordPress container shell wp-spin shell --container=mysql # MySQL container shellPublic Sharing
wp-spin share # Share via ngrok tunnel wp-spin unshare # Stop sharing
Project Structure
my-project/
├── wp-content/ # WordPress themes, plugins, uploads
├── docker-compose.yml # Docker services configuration
├── Dockerfile # Custom WordPress image with Xdebug
├── .env # Environment variables (XDEBUG_MODE, DB credentials)
├── .wp-spin # Project configuration (domain, version, etc.)
├── .gitignore # Git ignore rules for WordPress projects
└── .credentials.json # Database credentials backup (secure)Troubleshooting
Common issues and solutions:
Port Conflicts
- The tool automatically detects and resolves port conflicts
- Use
wp-spin statusto check current port assignments
Docker Issues
- Ensure Docker is running
- Check logs with
wp-spin logs
Permission Issues
- Ensure proper file permissions in the
wp-contentdirectory - Use
wp-spin shellto access the container directly
- Ensure proper file permissions in the
Xdebug Not Working
- Verify Xdebug is enabled:
wp-spin restart --xdebug - Check container logs:
wp-spin logs - Verify IDE is listening on port 9003
- Ensure path mappings are correct:
/var/www/html→ your project directory - Test with a simple
xdebug_info()call in PHP
- Verify Xdebug is enabled:
Custom Domain Issues
- Ensure you have admin/sudo permissions (needed for
/etc/hostsmodification) - For SSL: Install
mkcertand runmkcert -installfirst - Check if nginx proxy is running:
docker ps | grep nginx
- Ensure you have admin/sudo permissions (needed for
Multisite Issues
- Subdomain multisite requires a custom domain (
--domainflag) - Ensure WordPress constants are properly set in
wp-config.php - Check that DNS/hosts file entries include subdomain wildcards
- Subdomain multisite requires a custom domain (
Contributing
Contributions are welcome! Please fork this repository and submit pull requests to enhance the project.
License
This project is licensed under the MIT License - see the LICENSE file for details.
