Devmode
Development mode enables live code editing and step debugging with Xdebug for Canasta MediaWiki instances.
Features
- Live Code Editing: MediaWiki code is extracted to a local directory and mounted into the container. Changes appear immediately without rebuilding.
- Xdebug Integration: Step through PHP code, set breakpoints, and inspect variables.
- IDE Support: Pre-configured for both VSCode and PHPStorm.
Enabling dev mode
First create a Canasta instance, then enable dev mode:
# Create an instance
canasta create -i mydev -w mywiki -n localhost
# Enable development mode
canasta devmode enable
You can also specify a custom Canasta image when creating. Use --canasta-image to control which image to use (see Custom Canasta images):
canasta create -i mydev -w mywiki -n localhost --canasta-image ghcr.io/canastawiki/canasta:dev-branch
canasta devmode enable
Enabling dev mode will:
- Extract MediaWiki code to
mediawiki-code/for live editing - Create dev mode files (Dockerfile.xdebug, docker-compose.dev.yml, xdebug.ini)
- Build an Xdebug-enabled Docker image
- Create IDE configuration files
- Restart the instance with dev mode enabled
Building from local source
For testing changes to Canasta or CanastaBase before they're published, you can build from local source repositories:
canasta create -i mydev -w mywiki -n localhost --build-from ~/canasta-repos
The --build-from flag expects a directory containing:
Canasta/β Required. The Canasta repository with a Dockerfile.CanastaBase/β Optional. If present, CanastaBase is built first and used as the base image for Canasta. If absent, the published CanastaBase image is used.
This will:
- Build CanastaBase locally (if the directory exists) β
canasta-base:local - Build Canasta using the local or published base image β
canasta:local - Continue with normal instance
Combining with dev mode
You can enable dev mode after building from source:
canasta create -i mydev -w mywiki -n localhost --build-from ~/canasta-repos
canasta devmode enable
Note: --canasta-image and --build-from are mutually exclusive since --build-from builds its own image.
Switching back to upstream images
When you use --build-from, the CLI sets CANASTA_IMAGE=canasta:local in the instance's .env file so Docker Compose uses the locally-built image. This means:
canasta upgradewill not pull newer upstream images β the instance stays on the local builddocker compose pullwill silently skip the web service sincecanasta:localis not in any registry
To switch back to the upstream Canasta image:
- Remove the
CANASTA_IMAGEline from.env - Pull the upstream image and restart:
canasta upgrade
Disabling dev mode
To disable dev mode and restore normal operation:
canasta devmode disable
This restores extensions and skins as real directories and restarts without Xdebug. The dev mode files (Dockerfile.xdebug, docker-compose.dev.yml, mediawiki-code/) are left in place so you can re-enable dev mode later without re-extracting code.
Verifying dev mode is working
After enabling dev mode, verify the setup by running these commands from the instance directory:
- Check containers are running with the dev image:
docker compose ps
The web service should show
canasta-xdebug:localas the image. - Verify code mounting works:
# Add a comment to mediawiki-code/index.php # Refresh the browser - changes appear immediately without restart
- Check Xdebug is loaded:
canasta maintenance exec -s web php -m | grep xdebug
Should output:
xdebug
IDE setup
VSCode
A .vscode/launch.json file is automatically created. To start debugging:
- Open the instance's root directory in VSCode (not the
mediawiki-code/subdirectory) β the path mappings require this - Install the PHP Debug extension (by Xdebug)
- Go to Run and Debug (Ctrl+Shift+D / Cmd+Shift+D)
- Select "Listen for Xdebug" and click the play button
- Set breakpoints in files under
mediawiki-code/ - Access your wiki in the browser - VSCode will break at your breakpoints
PHPStorm
Configuration files are automatically created in the .idea/ directory. To start debugging:
- Open the instance's root directory in PHPStorm (not the
mediawiki-code/subdirectory) β the path mappings require this - Go to Run β Edit Configurations
- The "Listen for Xdebug" configuration should already be available
- Click the phone/listen icon in the toolbar (or Run β Start Listening for PHP Debug Connections)
- Set breakpoints in files under
mediawiki-code/ - Access your wiki in the browser - PHPStorm will break at your breakpoints
Triggering the debugger
By default, Xdebug uses trigger mode (xdebug.start_with_request=trigger), meaning it only starts a debug session when explicitly requested. This prevents background tasks (like health checks) from constantly triggering breakpoints.
Browser debugging
You must set the XDEBUG_TRIGGER cookie in your browser. Query parameters (?XDEBUG_TRIGGER=1) do not work with PHP-FPMβonly cookies are recognized.
Option 1: Set cookie in DevTools (most reliable)
Chrome:
- Open DevTools (F12 or Cmd+Option+I)
- Go to Application tab β Cookies β your site (e.g.,
https://localhost) - Double-click an empty row at the bottom of the cookie table
- Set:
- Name:
XDEBUG_TRIGGER - Value:
1 - Path:
/
- Name:
- Press Enter
The cookie persists across page refreshes until you delete it or close the browser.
Safari:
- Open Web Inspector (Cmd+Option+I)
- Go to Storage tab β Cookies
- Right-click and add a cookie with Name:
XDEBUG_TRIGGER, Value:1
Option 2: Set cookie via console
In the browser's JavaScript console, run:
document.cookie = "XDEBUG_TRIGGER=1; path=/; secure";
To remove the cookie:
document.cookie = "XDEBUG_TRIGGER=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT";
Option 3: Bookmarklets
Create bookmarks with these URLs. Note: Some browsers may block bookmarklets from modifying cookies on HTTPS pages.
Start Debugging:
javascript:(function(){document.cookie='XDEBUG_TRIGGER=1;path=/;secure';alert('Xdebug enabled')})();
Stop Debugging:
javascript:(function(){document.cookie='XDEBUG_TRIGGER=;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT';alert('Xdebug disabled')})();
CLI script debugging
To debug command-line scripts, set the XDEBUG_TRIGGER environment variable. Run these commands from the instance directory:
docker compose exec -e XDEBUG_TRIGGER=1 web php maintenance/run.php someScript
Directory structure
After enabling dev mode on an instance:
instance/
βββ .env # Environment variables (includes CANASTA_IMAGE)
βββ .vscode/
β βββ launch.json # VSCode debug configuration
βββ .idea/
β βββ php.xml # PHPStorm server configuration
β βββ runConfigurations/
β βββ Listen_for_Xdebug.xml # PHPStorm run configuration
βββ config/
β βββ wikis.yaml # Wiki farm configuration
β βββ Caddyfile # Generated reverse proxy config (do not edit)
β βββ Caddyfile.site # User customizations for Caddy site block
β βββ xdebug.ini # Xdebug configuration
β βββ admin-password_{wikiid} # Generated admin password per wiki
β βββ settings/
β βββ global/ # PHP settings loaded for all wikis
β β βββ *.php
β βββ wikis/
β βββ {wikiid}/ # PHP settings loaded for a specific wiki
β βββ *.php
βββ docker-compose.yml
βββ docker-compose.override.yml
βββ docker-compose.dev.yml # Dev mode compose overlay
βββ Dockerfile.xdebug # Builds xdebug-enabled image
βββ extensions/ # Symlink β mediawiki-code/user-extensions/ (in dev mode)
βββ skins/ # Symlink β mediawiki-code/user-skins/ (in dev mode)
βββ mediawiki-code/ # Extracted MediaWiki code (mounted to /var/www/mediawiki/w)
βββ index.php
βββ canasta-extensions/ # Bundled extension source code
βββ canasta-skins/ # Bundled skin source code
βββ extensions/ # Symlinks to canasta-extensions/* and user-extensions/*
βββ skins/ # Symlinks to canasta-skins/* and user-skins/*
βββ user-extensions/ # User extensions (real directory, same content as extensions/)
βββ user-skins/ # User skins (real directory, same content as skins/)
βββ ...
How extension symlinks work
The extracted code preserves the container's symlink structure. The mediawiki-code/extensions/ directory contains relative symlinks like:
VisualEditorβ../canasta-extensions/VisualEditor(bundled extension)MyExtensionβ../user-extensions/MyExtension(user extension)
In dev mode, the CLI consolidates user extensions into mediawiki-code/:
- Copies any existing extensions from
extensions/tomediawiki-code/user-extensions/ - Replaces
extensions/with a symlink tomediawiki-code/user-extensions/ - Same for
skins/βmediawiki-code/user-skins/
This ensures:
- Symlinks in
mediawiki-code/extensions/resolve identically on host and container - Simple IDE path mapping:
mediawiki-code/β/var/www/mediawiki/w/ - Breakpoints work in both bundled and user extensions
Editing user extensions (best practices)
In dev mode, extensions/ is a symlink to mediawiki-code/user-extensions/. This means both paths point to the same files:
extensions/MyExtension/ β Same files mediawiki-code/user-extensions/MyExtension/ β Same files
Where to edit
You can edit user extension files in either location β they're the same directory:
| Path | Description |
|---|---|
extensions/MyExtension/ |
Convenient if you're used to non-dev mode |
mediawiki-code/user-extensions/MyExtension/ |
Shows the true location in dev mode |
Setting breakpoints
For IDE path mapping to work correctly, set breakpoints in files under mediawiki-code/:
mediawiki-code/user-extensions/MyExtension/includes/MyHooks.phpβmediawiki-code/extensions/MyExtension/(symlink path also works)
Adding new extensions
- Copy your extension to
extensions/(ormediawiki-code/user-extensions/) - Restart the container:
canasta restart -i myinstance - The container's
create-symlinks.shcreatesmediawiki-code/extensions/MyExtension β ../user-extensions/MyExtension - Enable the extension in a settings file under config/settings/ (or use canasta extension enable)
When dev mode is disabled
When you disable dev mode (canasta devmode disable -i myinstance), the CLI:
- Removes the
extensions/symlink - Copies content from
mediawiki-code/user-extensions/back to a realextensions/directory - Leaves
mediawiki-code/in place (not volumed in, but available for reference)
Your user extensions are preserved in both modes.
When dev mode is re-enabled
When you re-enable dev mode (canasta devmode enable -i myinstance) after having disabled it:
- Extensions in
extensions/take precedence overmediawiki-code/user-extensions/ - Any changes made to
extensions/while in non-dev mode are synced tomediawiki-code/user-extensions/ - The
extensions/directory becomes a symlink again
Best practice: Always edit user extensions in extensions/ regardless of mode. This ensures your changes are preserved when switching between dev and non-dev modes.
Log locations
For general log file locations (MediaWiki debug log, Apache error log, etc.), see Troubleshooting: Log file locations.
Xdebug log
In dev mode, Xdebug writes connection attempts to its own log file:
docker compose exec web tail -f /var/log/mediawiki/php-xdebug.log
This log is useful for diagnosing why breakpoints aren't being hit:
- "Trigger value not found" β Cookie not set or not being sent
- "Could not connect to debugging client" β IDE not listening
- "Connecting to configured address" β Working correctly
Accessing the database
To debug data issues, connect to MariaDB:
canasta maintenance exec -s db mariadb -u root -p
Enter the root database password from your .env file (MYSQL_PASSWORD) when prompted.
Common queries:
SHOW DATABASES; -- List all wiki databases
USE mywiki; -- Switch to a wiki database
SHOW TABLES; -- List tables
SELECT * FROM user LIMIT 5; -- Query users
Troubleshooting
Breakpoints not hitting
- Check IDE is listening: Ensure the debug listener is active (phone icon should be green/active)
- Check the XDEBUG_TRIGGER cookie is set: In DevTools β Application β Cookies, verify the cookie exists
- Check path mappings: Verify local
mediawiki-codemaps to/var/www/mediawiki/w - Check Xdebug log (run from the instance directory):
docker compose exec web tail -20 /var/log/mediawiki/php-xdebug.log
- "Trigger value not found" = Cookie not set or not being sent
- "Could not connect to debugging client" = IDE not listening
- "Connecting to configured address" = Working correctly
PHPStorm detaches immediately
If you see "Cannot bind file" errors, your path mappings are incorrect. Ensure:
- Local path:
/path/to/instance/mediawiki-code - Remote path:
/var/www/mediawiki/w
Updating MediaWiki code
The extracted mediawiki-code/ is a snapshot from when dev mode was enabled. To re-extract the code from the Canasta container:
# Stop the instance
canasta stop
# Remove the extracted code
rm -rf mediawiki-code/
# Re-enable dev mode (this will re-extract the code)
canasta devmode enable
This preserves your wikis, configuration, and database while updating the MediaWiki code.
Note: Your local edits in mediawiki-code/ will be lost when regenerating. Consider committing changes to a git repository before regenerating. User extensions in extensions/ are preserved.
Performance considerations
Dev mode with Xdebug is slower than production mode due to:
- Xdebug overhead (even when not actively debugging)
- Bind-mounted code (slightly slower file I/O on some systems)
For performance testing, disable dev mode:
canasta devmode disable