Your first sync
A sync drops and recreates your local database. That is the point of it, and it is also why the first run against a new target should be the one that changes nothing.
Work through these three in order. Each tells you something the next one depends on.
Before you start
Section titled “Before you start”This guide assumes ddev-sync is installed in your project. It reaches the remote over your SSH agent, so make sure DDEV knows your key:
ddev auth sshDefine a target as described in Configuration, then check it is there:
ddev sync targets1. A dry run, which touches nothing
Section titled “1. A dry run, which touches nothing”ddev sync --target production --steps db,files,sanitize,setup --dry-runThis builds the whole plan and prints it without executing it, without connecting to the remote and without writing a file. One exception: a target whose connection comes from Deployer is resolved first, which runs dep config in the web container and so evaluates the project’s own deploy.php.
Plan for target 'production' typo3@13 acme - deploy@web01.example:22 /srv/app/ Nothing will be executed.
Features node-build detected: all of: file package.json, npm script build
1 preflight remote ssh -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10 -p 22 deploy@web01.example 2 db.dump remote mysqldump --single-transaction $TYPO3_DB_NAME 3 db.download - streamed as part of db.dump into .ddev/.downloads/dump.sql 4 db.import local mysql -h ddev-acme-db db < .ddev/.downloads/dump.sql 5 files.sync rsync rsync -a ... :/srv/app/public/fileadmin/ ... 7 sanitize sql 10 rules: clear-be-sessions, ... 8 setup web composer install --no-interactionRead three things here:
- The profile label in the header —
typo3@13above. If that is not the variant you expected, the rest of the plan is for the wrong framework version, and nothing else you read matters. - The detected features. A frontend build that you did not want adds minutes;
--no-featuresturns detection off for a run. - Which rules the sanitize step will apply, by name.
2. doctor, which connects but only reads
Section titled “2. doctor, which connects but only reads”ddev sync --target production doctorThe output below is illustrative — an all-OK run is what you are aiming at, not something that has been observed through the add-on. The ssh connection and deploy path rows have so far only been seen failing, because no successful connection to a real remote host has been made through the add-on yet:
Doctor for target 'production'
OK ssh connection web01.example OK deploy path /srv/app/ OK disk space 184 GB free OK sanitize tables 3 required tables present OK web container ddev-acme-web answers OK ssh agent /home/.ssh-agent/proxy-socketUnder provider: docker three of those rows read differently, because the far side is a container inside your production stack rather than the host you connected to:
OK sync endpoint prod.example OK deploy path /data/ (in the endpoint) OK path readablesync endpoint says the endpoint answered — not that the Docker host did, which it may well have while the endpoint was down. deploy path spells out that the path was read inside the container, which is the one place intuition from a server target is wrong. And path readable is the row that catches the likeliest misconfiguration of that provider: a path that exists and that the endpoint’s own user cannot read, which would otherwise surface in the middle of the file transfer.
This is the step that catches the failures worth catching before gigabytes move: an unreachable host, a wrong deploy path, too little disk space, and — the one that only shows up here — a sanitize rule that requires a table the remote database does not have. The last three rows are about your own machine rather than the remote: your free disk space, whether commands can reach the project’s web container, and whether DDEV’s forwarded ssh agent socket is there. A rule that cannot run is a rule that leaves production data in place, so doctor refuses to call that fine.
3. The real thing
Section titled “3. The real thing”Start with the database only, on a project you can afford to break:
ddev sync --target production --steps dbYou will be asked to confirm before the local database is dropped. When that looks right, add the rest:
ddev sync --target production --steps db,files,sanitizesetup is deliberately not in that list. Add it when you want composer install, migrations and frontend builds to run too — it is usually the slowest part by far.
Afterwards
Section titled “Afterwards”Check that sanitising did what you expect, in whatever way suits your project — a look at the user table is enough:
SELECT email FROM users LIMIT 5;Addresses should be unreachable ones, and password hashes should all be identical and useless. If they are not, the rules for your project type did not run or did not match your schema: see the profiles reference for what has been verified for your framework, and treat the copy as production data until you have sorted it out.
When something goes wrong
Section titled “When something goes wrong”-
It hangs with no output. You are in a terminal-less context (a script, CI) and a prompt is waiting for an answer that cannot come. Pass
--stepsand--targetexplicitly. Recent versions fail with a message instead. -
--stepsrefuses a step you named. The step is not available for this project, because it would contribute nothing to the plan, and the message lists what is. A project with no S3 configuration, for example, is not offereds3. A step name that is simply misspelled gets a different message, saying it is unknown. See which steps are offered. -
no environment file found in the project. The profile expected a.envyour project does not have. For TYPO3 that is the default and the step is off; see Configuration. -
A setup command fails. The sync stops there, after the database has been imported and sanitised. Fix the command, then re-run with
--steps setuponly. -
You pressed Ctrl-C. The sync ends with a sentence rather than a traceback, and exits
130. The sentence names where it stopped and the last step that finished (in thepost_synchooks no running step is named), and says what state that leaves things in. It does not undo or clean up anything, so read it before you do the next thing. What it tells you depends on where you were:- At a confirmation prompt, including “This will drop the local database … Continue?”. That step was waiting for an answer and so changed nothing. The message still reports what earlier, finished steps left behind.
- Before anything touched the database. The message says where it stopped and makes no claim about your data.
- During the import, once the drop has begun. The local database may be partly replaced with production data, and it is not sanitized. Re-run with
--steps db,sanitize, or treat the copy as production data. - After the import, before sanitizing. The local database has been replaced with production data and was not sanitized. Either re-run with
--steps sanitize, or treat the copy as production data until you have. - During sanitizing, in a run that imported the database too. It holds production data and was “not fully sanitized”: some rules may already have applied. Re-run with
--steps sanitize, or treat the copy as production data. - During sanitizing, in a
--steps sanitizere-run. The run has no import of its own to reason from, so it cannot see what an earlier one left and does not pretend to: “sanitizing did not finish, so if the local database holds production data it may be only partly sanitized”. The remedy is the same — re-run--steps sanitize, or treat the copy as production data. Only you can tell which of the two it is. - In the
post_synchooks. They “may not have finished”. The state of the database is still reported. - At any earlier step. The
post_synchooks do not run, and the message says so. If you keep cleanup inpost_sync, it has not happened.
Stopping between the import and the end of sanitizing leaves production data on your machine; that is what the message is there to tell you.
-
Host key verification failed. ddev-sync accepts a host it has never connected to without asking and remembers its key, so a first connection needs nothing from you, whether you run it from a terminal or from a script. The one exception is a jump host: its key is not covered, see below.doctorshows ssh’s own words on thessh connectionrow, and a failed sync prints them in full, with the fingerprint, below “Run ‘ddev auth ssh’ and try again”. For this message that advice is not the fix: your key is not the problem. Which of two things it is shows in the words before it:-
Host key for web01.example has changed and you have requested strict checking.The host presented a different key from the one remembered, and ssh refuses it. This is the one case that needs a person, because it has two very different explanations. Either the server was rebuilt or its keys were regenerated, which is harmless, or something else is answering in its place, which is not. Find out which before you make the message go away: ask whoever runs the server, or compare the fingerprint from the full output of a failed sync with one they give you. Once you know the new key is the right one, forget the old one, and the next run remembers the new one:Terminal window ddev exec -s sync ssh-keygen -R web01.exampleUse the host that ssh’s message names, which for a target with a
jump_hostis the bastion’s, not the target’s, and write it as'[web01.example]:2222'when that host does not use port 22, because ssh remembers a host on another port separately. -
Host key verification failed.on its own, for a target with ajump_host. ddev-sync’s trust-on-first-use covers the host you are syncing from, not the bastion in front of it, so the bastion’s key is unknown and, with no terminal to ask on, refused. Tell ssh about the bastion once. Either connect to it from a terminal and answer the question:Terminal window ddev exec -s sync ssh -p 22 tim@bastion.exampleor give it an entry in
.ddev/ddev-sync/home/.ssh/config, which ssh reads for the bastion too:Host bastion.exampleStrictHostKeyChecking accept-new -
Host key for ddev-sync-endpoint-… has changed, for a target withprovider: docker. A sync endpoint is remembered under a name of its own —ddev-sync-endpoint-<host>-<sync_port>— rather than under the address it answers on, so that two stacks published on one Docker host do not look like one host changing its key. The overwhelmingly likely cause is a redeploy that dropped the endpoint’s host-key volume, and the sync says so; whoever deploys the stack can confirm it. Then forget the old key by the alias, not by the host:Terminal window ddev exec -s sync ssh-keygen -R ddev-sync-endpoint-prod.example-2222
Remembered keys are kept in
.ddev/ddev-sync/home/.ssh/known_hostsand survive restarts, butddev add-on remove ddev-syncdeletes them, so after a reinstall each host is accepted again on first contact. -