|
| 1 | +# Sidworks Database Sync Plugin |
| 2 | + |
| 3 | +A Shopware 6 plugin for syncing databases from staging/production environments to your local development environment via SSH. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- Sync from staging or production environments |
| 8 | +- SSH connection support with key authentication |
| 9 | +- Automatic database dump, download, and import |
| 10 | +- Two-step dump strategy (structure + data) for consistent snapshots |
| 11 | +- Table filtering for performance and GDPR compliance (62 tables by default) |
| 12 | +- DEFINER clause stripping for cross-server compatibility |
| 13 | +- Foreign key and unique check optimization during import |
| 14 | +- Local environment overrides (URLs, domains, system config) |
| 15 | +- Raw SQL execution post-import |
| 16 | +- Post-sync console commands (e.g. deactivate plugins, create users) |
| 17 | +- Apply config overrides without a full sync (`--apply-config-only`) |
| 18 | +- DDEV compatible |
| 19 | +- Gzip compression support |
| 20 | +- Automatic cache clearing |
| 21 | + |
| 22 | +## Installation |
| 23 | + |
| 24 | +#### Via Composer (Recommended) |
| 25 | + |
| 26 | +```bash |
| 27 | +composer require sidworks/sw-plugin-database-sync --dev |
| 28 | +bin/console plugin:refresh |
| 29 | +bin/console plugin:install --activate SidworksDatabaseSync |
| 30 | +bin/console cache:clear |
| 31 | +``` |
| 32 | + |
| 33 | +#### Manual Installation |
| 34 | + |
| 35 | +1. Clone or download this repository to `custom/plugins/SidworksDatabaseSync` |
| 36 | +2. Run the following commands: |
| 37 | + |
| 38 | +```bash |
| 39 | +bin/console plugin:refresh |
| 40 | +bin/console plugin:install --activate SidworksDatabaseSync |
| 41 | +bin/console cache:clear |
| 42 | +``` |
| 43 | + |
| 44 | +## Configuration |
| 45 | + |
| 46 | +### Environment Variables |
| 47 | + |
| 48 | +Add the following to your `.env.local` file: |
| 49 | + |
| 50 | +```bash |
| 51 | +# Staging Environment |
| 52 | +SW_DB_SYNC_STAGING_HOST=your-staging-server.com |
| 53 | +SW_DB_SYNC_STAGING_USER=your-username |
| 54 | +SW_DB_SYNC_STAGING_PORT=22 |
| 55 | +SW_DB_SYNC_STAGING_PROJECT_PATH=/var/www/html |
| 56 | +SW_DB_SYNC_STAGING_KEY=~/.ssh/id_ed25519 # Optional: SSH key path |
| 57 | + |
| 58 | +# Production Environment |
| 59 | +SW_DB_SYNC_PRODUCTION_HOST=your-production-server.com |
| 60 | +SW_DB_SYNC_PRODUCTION_USER=your-username |
| 61 | +SW_DB_SYNC_PRODUCTION_PORT=22 |
| 62 | +SW_DB_SYNC_PRODUCTION_PROJECT_PATH=/var/www/html |
| 63 | +SW_DB_SYNC_PRODUCTION_KEY=~/.ssh/id_ed25519 # Optional: SSH key path |
| 64 | + |
| 65 | +# Local overrides |
| 66 | +SW_DB_SYNC_LOCAL_DOMAIN=your-project.ddev.site |
| 67 | +SW_DB_SYNC_DOMAIN_MAPPINGS=production.com:your-project.ddev.site,staging.com:your-project.ddev.site |
| 68 | +SW_DB_SYNC_CLEAR_CACHE=true # Set to "false" to skip cache clearing |
| 69 | +``` |
| 70 | + |
| 71 | +#### Required Variables |
| 72 | + |
| 73 | +| Variable | Description | |
| 74 | +|----------|-------------| |
| 75 | +| `SW_DB_SYNC_[ENV]_HOST` | Hostname or IP address of the server | |
| 76 | +| `SW_DB_SYNC_[ENV]_USER` | SSH username | |
| 77 | +| `SW_DB_SYNC_[ENV]_PORT` | SSH port (default: 22) | |
| 78 | +| `SW_DB_SYNC_[ENV]_PROJECT_PATH` | Remote Shopware project directory path | |
| 79 | + |
| 80 | +#### Optional Variables |
| 81 | + |
| 82 | +| Variable | Description | |
| 83 | +|----------|-------------| |
| 84 | +| `SW_DB_SYNC_[ENV]_KEY` | Path to SSH private key (supports `~/` expansion) | |
| 85 | +| `SW_DB_SYNC_LOCAL_DOMAIN` | Default local domain for URL overrides | |
| 86 | +| `SW_DB_SYNC_DOMAIN_MAPPINGS` | Comma-separated `from:to` domain mappings | |
| 87 | +| `SW_DB_SYNC_CLEAR_CACHE` | Clear cache after sync — `true` (default) or `false` | |
| 88 | + |
| 89 | +Replace `[ENV]` with either `STAGING` or `PRODUCTION`. |
| 90 | + |
| 91 | +## Advanced Configuration (Config File) |
| 92 | + |
| 93 | +Create a `sw-db-sync-config.json` file in your Shopware root directory: |
| 94 | + |
| 95 | +```bash |
| 96 | +cp vendor/sidworks/sw-plugin-database-sync/sw-db-sync-config.json.example sw-db-sync-config.json |
| 97 | +nano sw-db-sync-config.json |
| 98 | +``` |
| 99 | + |
| 100 | +When this file exists, it takes priority over environment variable domain mappings. |
| 101 | + |
| 102 | +### Configuration Sections |
| 103 | + |
| 104 | +#### `ignore_tables` |
| 105 | + |
| 106 | +Tables to skip during the data dump. The example file includes 62 commonly ignored tables covering: |
| 107 | + |
| 108 | +**Performance tables** (always recommended): |
| 109 | +- `enqueue` — Message queue |
| 110 | +- `product_keyword_dictionary` — Search keywords |
| 111 | +- `product_search_keyword` — Search index |
| 112 | +- `log_entry` — Application logs |
| 113 | +- `message_queue_stats` — Queue statistics |
| 114 | +- `elasticsearch_index_task` — Search indexing |
| 115 | +- `state_machine_history` — Order/payment state history |
| 116 | + |
| 117 | +**GDPR/Privacy tables** (customer and order data): |
| 118 | +- `customer`, `customer_address`, `customer_tag`, `customer_wishlist` |
| 119 | +- `order`, `order_address`, `order_delivery`, `order_line_item`, `order_transaction` |
| 120 | +- `cart` — Shopping carts |
| 121 | +- `user`, `user_config`, `user_recovery`, `user_access_key` — Admin users |
| 122 | +- `newsletter_recipient`, `newsletter_recipient_tag` |
| 123 | +- Payment plugin tables (Klarna, Payone, Pay.nl, Unzer) |
| 124 | + |
| 125 | +**Tip**: Remove tables from the list if you need them in development. For example, keep `user` if you need existing admin accounts. |
| 126 | + |
| 127 | +#### `sales_channel_domains` |
| 128 | + |
| 129 | +Map sales channel IDs to local domains. Find your sales channel IDs with: |
| 130 | + |
| 131 | +```sql |
| 132 | +SELECT LOWER(HEX(id)) as id, name FROM sales_channel; |
| 133 | +``` |
| 134 | + |
| 135 | +```json |
| 136 | +{ |
| 137 | + "sales_channel_domains": { |
| 138 | + "018d5f1e5e7e7f1e8b8d5f1e5e7e7f1e": "https://your-project.ddev.site" |
| 139 | + } |
| 140 | +} |
| 141 | +``` |
| 142 | + |
| 143 | +#### `system_config` |
| 144 | + |
| 145 | +Update Shopware system configuration values after import: |
| 146 | + |
| 147 | +```json |
| 148 | +{ |
| 149 | + "system_config": { |
| 150 | + "core.basicInformation.email": "local@example.com", |
| 151 | + "core.mailerSettings.host": "localhost", |
| 152 | + "core.mailerSettings.port": "1025" |
| 153 | + } |
| 154 | +} |
| 155 | +``` |
| 156 | + |
| 157 | +Values that don't exist yet are automatically inserted. |
| 158 | + |
| 159 | +#### `sql_updates` |
| 160 | + |
| 161 | +Execute raw SQL statements after import. Use with caution: |
| 162 | + |
| 163 | +```json |
| 164 | +{ |
| 165 | + "sql_updates": [ |
| 166 | + "UPDATE sales_channel_domain SET url = REPLACE(url, 'production.com', 'ddev.site')" |
| 167 | + ] |
| 168 | +} |
| 169 | +``` |
| 170 | + |
| 171 | +#### `post_sync_commands` |
| 172 | + |
| 173 | +Console commands to run after the sync completes. Failed commands produce warnings but don't abort the process: |
| 174 | + |
| 175 | +```json |
| 176 | +{ |
| 177 | + "post_sync_commands": [ |
| 178 | + "user:create admin -a --email info@example.com -p thisIsMyPassword", |
| 179 | + "plugin:refresh", |
| 180 | + "plugin:install SidworksDatabaseSync -a", |
| 181 | + "theme:compile" |
| 182 | + ] |
| 183 | +} |
| 184 | +``` |
| 185 | + |
| 186 | +Common use cases: |
| 187 | +- Create a local admin user after importing (since `user` table is typically ignored) |
| 188 | +- Deactivate production-only plugins or apps |
| 189 | +- Refresh and reinstall the sync plugin itself after import |
| 190 | +- Recompile themes |
| 191 | + |
| 192 | +### Environment Variables vs Config File |
| 193 | + |
| 194 | +| Method | Use case | |
| 195 | +|--------|----------| |
| 196 | +| Environment variables (`.env.local`) | Simple domain mappings, basic setups | |
| 197 | +| Config file (`sw-db-sync-config.json`) | Advanced overrides, system config, SQL updates, post-sync commands | |
| 198 | + |
| 199 | +If `sw-db-sync-config.json` exists, it takes priority over environment variable domain mappings. |
| 200 | + |
| 201 | +## Usage |
| 202 | + |
| 203 | +### Basic sync from staging |
| 204 | + |
| 205 | +```bash |
| 206 | +bin/console sidworks:db:sync staging |
| 207 | +``` |
| 208 | + |
| 209 | +### Sync from production |
| 210 | + |
| 211 | +```bash |
| 212 | +bin/console sidworks:db:sync production |
| 213 | +``` |
| 214 | + |
| 215 | +### Options |
| 216 | + |
| 217 | +| Option | Description | |
| 218 | +|--------|-------------| |
| 219 | +| `--keep-dump, -k` | Keep the dump file in `var/dumps/` after import | |
| 220 | +| `--skip-import` | Only download the dump, don't import | |
| 221 | +| `--no-gzip` | Don't compress the dump (faster for small databases) | |
| 222 | +| `--skip-overrides` | Skip applying local environment overrides | |
| 223 | +| `--no-ignore` | Dump all tables (don't ignore any) | |
| 224 | +| `--apply-config-only[=path]` | Only apply config file overrides without syncing | |
| 225 | +| `--skip-cache-clear` | Skip clearing cache after applying configuration | |
| 226 | +| `--skip-post-commands` | Skip running post-sync commands | |
| 227 | + |
| 228 | +### Apply config only (no database sync) |
| 229 | + |
| 230 | +Re-apply your `sw-db-sync-config.json` overrides without downloading a new database dump. Useful after manual database changes or when you just need to update system config: |
| 231 | + |
| 232 | +```bash |
| 233 | +# Use default sw-db-sync-config.json |
| 234 | +bin/console sidworks:db:sync --apply-config-only |
| 235 | + |
| 236 | +# Use a custom config file |
| 237 | +bin/console sidworks:db:sync --apply-config-only=custom-config.json |
| 238 | + |
| 239 | +# Use an absolute path |
| 240 | +bin/console sidworks:db:sync --apply-config-only=/path/to/config.json |
| 241 | + |
| 242 | +# Apply config only, skip cache clear and post-sync commands |
| 243 | +bin/console sidworks:db:sync --apply-config-only --skip-cache-clear --skip-post-commands |
| 244 | +``` |
| 245 | + |
| 246 | +### Verbose output |
| 247 | + |
| 248 | +Show which tables are being ignored: |
| 249 | + |
| 250 | +```bash |
| 251 | +bin/console sidworks:db:sync staging -v |
| 252 | +``` |
| 253 | + |
| 254 | +## DDEV Usage |
| 255 | + |
| 256 | +If you're using DDEV, forward your SSH agent first: |
| 257 | + |
| 258 | +```bash |
| 259 | +ddev auth ssh |
| 260 | +``` |
| 261 | + |
| 262 | +Then run the sync command inside the container: |
| 263 | + |
| 264 | +```bash |
| 265 | +ddev exec bin/console sidworks:db:sync staging |
| 266 | +``` |
| 267 | + |
| 268 | +## How It Works |
| 269 | + |
| 270 | +### Execution Flow |
| 271 | + |
| 272 | +1. **Validate configuration** — Check required SSH and environment settings |
| 273 | +2. **Fetch remote `.env`** — Read database credentials from the remote server via SSH |
| 274 | +3. **Create remote dump** — Two-step mysqldump (structure + data) on the remote server |
| 275 | +4. **Download dump** — Transfer the compressed dump via rsync |
| 276 | +5. **Cleanup remote** — Delete the dump file from the remote server |
| 277 | +6. **Import database** — Import dump into local database with optimizations |
| 278 | +7. **Apply overrides** — Update domains, system config, and run SQL updates |
| 279 | +8. **Clear cache** — Run `cache:clear:all` |
| 280 | +9. **Run post-sync commands** — Execute configured console commands |
| 281 | +10. **Cleanup local** — Delete the local dump file (unless `--keep-dump`) |
| 282 | + |
| 283 | +### mysqldump Strategy |
| 284 | + |
| 285 | +The plugin uses a two-step dump process: |
| 286 | + |
| 287 | +1. **Structure dump**: `--no-data --routines` exports table structures, triggers, stored procedures, and functions |
| 288 | +2. **Data dump**: `--no-create-info --skip-triggers` exports data only, skipping ignored tables |
| 289 | + |
| 290 | +**Common flags:** |
| 291 | +- `--single-transaction` — InnoDB consistent read without table locks (safe for production) |
| 292 | +- `--quick` — Stream results without buffering entire tables |
| 293 | +- `-C` — Compress data between client and server |
| 294 | +- `--hex-blob` — Binary data as hex for portability |
| 295 | +- `--column-statistics=0` — Disable statistics collection (auto-detected if supported) |
| 296 | + |
| 297 | +**Post-processing (both steps):** |
| 298 | +- `LANG=C LC_CTYPE=C LC_ALL=C` — Consistent character encoding |
| 299 | +- `sed` strips `DEFINER` clauses for cross-server compatibility |
| 300 | + |
| 301 | +### Import Optimization |
| 302 | + |
| 303 | +The import pipeline applies several optimizations: |
| 304 | + |
| 305 | +- `SET FOREIGN_KEY_CHECKS=0` — Disables FK constraint checks during import to prevent deadlocks and speed up loading |
| 306 | +- `SET UNIQUE_CHECKS=0` — Skips unique index verification during bulk insert |
| 307 | +- `SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"` — Preserves explicit zero values in auto-increment columns |
| 308 | +- DEFINER clauses are stripped locally via `sed` before piping to `mysql`, avoiding privilege errors when views or stored procedures reference specific users |
| 309 | +- Foreign key and unique checks are re-enabled at the end of the import |
| 310 | + |
| 311 | +### Override Priority |
| 312 | + |
| 313 | +1. If `sw-db-sync-config.json` exists → use config file (sales channel domains, system config, SQL updates) |
| 314 | +2. Otherwise → use environment variable domain mappings (`SW_DB_SYNC_DOMAIN_MAPPINGS`) |
| 315 | +3. Fallback → use `SW_DB_SYNC_LOCAL_DOMAIN` to set all sales channel domains |
| 316 | + |
| 317 | +## Troubleshooting |
| 318 | + |
| 319 | +### SSH Connection Failed |
| 320 | + |
| 321 | +1. **In DDEV**: Run `ddev auth ssh` to forward your SSH agent into the container |
| 322 | +2. **SSH Key**: Set `SW_DB_SYNC_[ENV]_KEY` to your private key path |
| 323 | +3. **SSH Agent**: Ensure your key is loaded: `ssh-add ~/.ssh/your_key` |
| 324 | + |
| 325 | +### Permission Denied |
| 326 | + |
| 327 | +Your SSH user needs: |
| 328 | +- Read access to the remote `.env` file |
| 329 | +- Execute permissions for `mysqldump` |
| 330 | +- Write permissions to `/tmp` on the remote server |
| 331 | + |
| 332 | +### Remote .env Not Found |
| 333 | + |
| 334 | +Verify that `SW_DB_SYNC_[ENV]_PROJECT_PATH` points to the Shopware root directory containing the `.env` file. |
| 335 | + |
| 336 | +### Import Fails with DEFINER Errors |
| 337 | + |
| 338 | +This is handled automatically. Both the remote dump and local import pipeline strip DEFINER clauses. If you still encounter errors, check that your MySQL user has `SUPER` or `PROXY` privileges, or verify the dump file isn't corrupted. |
| 339 | + |
| 340 | +## Requirements |
| 341 | + |
| 342 | +- Shopware 6.7+ |
| 343 | +- PHP 8.1+ |
| 344 | +- SSH access to remote servers |
| 345 | +- `mysqldump` on the remote server |
| 346 | +- `rsync` for file transfer |
| 347 | +- `gzip` / `gunzip` (unless using `--no-gzip`) |
| 348 | + |
| 349 | +## Author |
| 350 | + |
| 351 | +Sidworks — https://www.sidworks.nl/ |
0 commit comments