Forum Replies Created

Viewing 15 replies - 1 through 15 (of 15 total)
  • Hi @patoudss,

    Following up on this: Migro 2.7.0 shipped today, and it changes the answer to your original question. Pairing now works through WordPress itself, using an Application Password, and the database fields are optional. If production allows a database connection Migro still uses it, for speed, but on a host like yours that blocks it, HTTP-only pairing works the whole way, no SSH tunnel needed. Connection Settings shows you which mode a pairing is using.

    That should let you pair your local staging with production directly. I’d like to know whether it works for you, given the trouble the tunnel gave you.

    Thanks for pushing on this. It is a better plugin for it.

    Best regards,
    Al

    Hi Patrice, I have answered this in full in your support ticket, including a configuration that works with your setup today. Briefly, for anyone reading here:

    Core REST cannot carry a content migration. It only exposes post meta a developer registered with show_in_rest, and refuses protected keys outright, so most theme and plugin custom fields are unreachable, as is the marker Migro writes so the next migration updates a post rather than duplicating it.

    For most users no remote database access is involved at all: staging and production sit on the same server and the connection is local, over localhost or a socket. Migro never asks a host to expose MySQL to the internet and has no mechanism to do so. Credentials never leave your site, are never sent to us or to any third party, and are encrypted at rest with libsodium under a key derived from your wp-config salts, so a stolen database dump yields nothing.

    Where the two sites are on separate machines, as in your case, an SSH tunnel works today and production’s MySQL stays closed to the internet. A connection mode needing only a site URL and a WordPress application password is also in active development.

    The exact commands are in the support thread.

    Hi Patrice,

    Thanks for writing, and for being direct about it. Your question is fair and deserves an answer. I also have a way to make your setup work with Migro today, which I will come to below.

    Why the database, and not the WordPress REST API

    The short version: WordPress core’s REST API cannot carry the data a content migration actually consists of.

    Core REST exposes posts, terms, media and a small allow-listed slice of metadata. A content migration needs more than that, for example:

    • Custom fields. WordPress only exposes post meta that a developer explicitly registered with show_in_rest, and it refuses protected keys (anything beginning with an underscore) outright. Most theme and plugin custom fields are neither registered nor public. Over core REST they cannot be read or written at all. Migro copies a post’s custom fields as they are stored.
    • Update instead of duplicate. Migro marks each migrated post with a pairing key so that the second migration updates the post the first one created, rather than making a copy. That marker is a protected meta key, which core REST will not write. An update-in-place model cannot be built on it.
    • Reading the destination before changing it. Migro takes a backup of the rows it is about to overwrite, and skips items that are already identical. Both need the stored values, not the filtered output an API chooses to render.

    The paid version goes further into the same places, page builder layouts in post meta and WooCommerce’s own custom tables, but the constraint is not a paid-tier one. It applies to the free plugin as well.

    So the direct connection was not chosen over REST for convenience. It was chosen because core REST does not have the surface area. A REST-only build of Migro would be a different and much smaller product.

    On security

    I want to separate two things that are being merged in your message.

    For most Migro users, no remote database access exists in the first place. Staging and production sit on the same server, so the connection is local, over localhost or a Unix socket. Nothing crosses the network, no port is opened, and no firewall rule is relaxed. Migro never asks a host to expose MySQL to the internet, and it has no mechanism to do so.

    Your setup is the harder one, and deliberately so: two separate machines, with production correctly refusing outside connections. That is a compatibility limit on our side, not an unsafe practice on yours, and I would not want anyone loosening a hardened host to accommodate a plugin.

    Either way, credentials never leave your site. They are not sent to us or to any third party, and they play no part in telemetry or licensing. At rest they are encrypted with libsodium’s crypto_secretbox under an envelope scheme: the data key is itself wrapped with a key derived by HKDF-SHA256 from your wp-config.php salts, so the database holds only an inert blob. A stolen dump, a SQL injection, or a leaked backup yields nothing without the wp-config file. If the salts are rotated, decryption fails closed with a visible admin notice instead of degrading quietly, and if Sodium is unavailable Migro rejects the save rather than storing anything in a weaker form.

    There is a configuration that works today

    Your production host is right to refuse remote MySQL, and you should not change that. You do not have to.

    If you have SSH access to production, you can forward the database port over that SSH session from the machine running staging:

    ssh -L 3307:127.0.0.1:3306 user@your-production-host
    

    Then in Migro’s connection settings on staging, set the Database Host to 127.0.0.1:3307. MySQL stays bound to localhost on production and closed to the internet. The traffic travels inside the SSH session you are already trusted to open, and no port is exposed to anyone.

    The second piece is that your staging site is on a local machine, so production can never reach it. Migro detects this and turns on Passive Mode: the pairing stays two-way, but every migration is started from the staging side. Media transfers outbound over HTTPS to production, which needs nothing special.

    I will add this to the documentation, since you are not the only person in this position and it should not have taken a support ticket to surface it.

    What is coming

    A connection mode that needs only a site URL and a WordPress application password is in active development. Because Migro runs on both sites, the two installs talk to each other over dedicated, typed migro/v1 endpoints rather than core REST, which is what closes the capability gap described above. Direct database access then becomes an advanced option for the narrow set of cases that genuinely require it, rather than a prerequisite.

    One honest limitation: WooCommerce’s custom tables are the last piece still needing direct access, and will remain so in the first release of that mode.

    If you would like, I can email you when it is ready for testing. Your setup, a local staging machine against a locked-down production host, is exactly the case it is built for, and I would value your feedback on it.

    Best regards,
    Al

    Hey @lfcnutter

    Great to hear that everything worked as expected. I appreciate all your insights here, it helped me to improve the tool for people who probably wanted the Editor out of the loop as well.

    If you decide to use the tool in prod, let me know if anything looks off once it is on the real servers and I will sort it quickly, same as before.

    A small request: if Migro saves you time on real staging-to-production work, a short review on the plugin page would be a real help for a small project like this. 🙂 And let me know if you need anything else!

    Thanks again for the careful testing across these last few releases. It made the plugin better!

    Best,
    Al

    Hey @lfcnutter,

    Just catching up! Whenever you get a chance to update both sites to 2.6.1 and try the admin Editor-access setting with an Editor account, I would like to know it behaves the way you expected. If it does what you needed, great. If anything still looks off, tell me the exact step and I will sort it.

    Either way, thanks again for the careful testing that shaped these last few releases.

    Best,
    Al

    Ok, 2.6.1 is now live and the option to remove editors is in Settings. 🙂

    Lots of bug fixes and improvements done too since I was already there.

    Take a look and let me know.

    Thanks!

    For the Editor permission: I can add an option in settings that Admin can decide if Editors are allowed to use Migro. If the option is unchecked, I would prefer to be checked by default, Migro is not presented to Editors, this can be done fast.

    Dry Run Differences: Yes. Dry Run normalizes hostnames before comparing. It applies the same source→destination URL rewrite the migration performs, then compares, so a page differing only because dev.montybees.org.uk becomes montybees.org.uk is reported as unchanged. It also ignores differences that are only which media file each side points at. Page-builder layouts aren’t text-diffed at all, too many differences from one environment to the other but it does check if they are in sync, just don’t show the diff.

    I’m working in reviewing more changes for WP 7.1 and will be able to release the 2.6.1 today with the admin checkbox, so you can test. But happy to know that my tool can help you (and thanks for taking care of the bees! I’ve been planting local wild flowers in my house for years to see if I can help the pollinators, it’s been working 🙂 )

    Will have the new version soon and let me know if you have any other questions.

    Thanks!

    Hello again @lfcnutter!

    Migro 2.6.0 is officially out! Lots of cool stuff in this release, including all the features I was working on: the “In Sync” checkmark with automatic skipping for already migrated content, the Dry Run mode with diff viewing, and a bunch of small reliability fixes discovered during testing.

    A quick note on how “In Sync” works: it’s a learning feature. As you migrate, Migro creates a matching key between environments to track synced content (which helps prevent false “out of sync” reports caused by dynamic page markup). It checks the destination site to confirm sync status and if it can’t definitively prove an item is synced, it migrates it anyway to make sure no updates get missed.

    I also adjusted permissions for the Editor role. I couldn’t reproduce the Editor seeing the Settings page, but I decided Editors should really only see Batch Migration and the Quick Guide. All other settings are now strictly restricted to administrators (manage_options).

    Hope you enjoy this version! Give it a try, and if you run into any bugs or have ideas for improvements, let me know.

    Have fun!

    Best,
    Al

    Those are good things to have, I’ve been mostly working right now in Page Builders capabilities and I need a break. So much tests back and forth for each of the existent Page Builders, it’s a lot of boring work. 😛 Change will be good!

    Both things are in the roadmap and can be accellerated.

    The Editor capabilities was a bit put aside since I was just trying to give people access, but this is a easy win, to just display settings for user that has manage_options. I can get this out this weekend for sure.

    For the current state this is part of the plan, together with dry run, so people know what will change before approving the migration. I think I can break it apart because knowing that things are in synch remove stress from the migration process, you don’t need to migrate things that are already up-to-date, so it’s easier for all. Will get this done mid-week.

    About Migro Health showing it blue. Migro Health came up because some team are used to full DB migration and if they ran this Migro would lose contact with the other environment and break. Migro Health brings two major fixes, one is self-healing, if Migro detects the DB got overwritten it gives an option for the user to fix it by clicking a button, the other option, is what you’re seeing. Migro is asking you to replace the DB/REST API configuration with a wp-config.php entry (from the section: Make this site immune to database refreshes), you can just click the “Ignore this, the setup is fine as it is”.

    When I have those updates live I let you know, those are great feedback, I really appreciate you taking your time to make Migro better! 🙂

    Hey @lfcnutter,

    The new version is now up: 2.5.5.

    I ran a lot of tests using Windows and the plugin should be more stable now to your local tests.

    Thanks for pointing it out and it should work much better now.

    Please, if you find any kinks, let me know so I can make things right! 🙂

    If you decided in the end to use Migro, let me know and I will send you a Pro license for the year to compensate for your help!

    Best,
    Al

    I appreciate your patience! I’m working on this right now and will be running a bunch of other tests on Windows before the release, but you can expect later today since those are small fixes.

    Will message you back here when it’s done.

    Thanks again for trying Migro!

    I need to run more tests on Windows!

    No, it’s not expected. After initial tests on Windows I just assumed things were paired with Mac and hosted environments, but apparently it’s not.

    The success below is the source of truth, but I’m preparing a new minor version to fix both the conditions you found, not detecting that is a windows machine and getting the port properly with the paring code and failing to reach 100%.

    Sorry for those issues, I promise you those are Windows specific and my fault for not properly testing in a different environment! 🙂

    Thanks,

    Al

    I edited the message but it may have been a bit late for you to see:

    I made a wrong assumption that you’re testing on Mac, but for Windows is a bit different, as you pointed out:

    LocalWP on Windows runs each site’s MySQL over TCP on its own port rather than a socket file, which is why Migro couldn’t guess it. Open LocalWP, select the other site, go to the Database tab and note the Port (a 5-digit number like 10090). In Migro’s “One field left” box, enter 127.0.0.1:10090, substituting that port. If that’s rejected with “not allowed to connect”, try localhost:10090 instead. Migro accepts a host:port value in that field.

    Try this and let me know if it works! 🙂

    Thanks!

    Hey @lfcnutter,

    First, thanks for trying Migro!

    For LocalWP you should use your Database Socket instead of the Host, you can find this configuration inside the Database tab on your local site.

    Edit: Sorry, my bad, I’m assuming that you’re using Mac, but you may be using Windows for your test. In this case:
    Local on Windows runs each site’s MySQL over TCP on its own port rather than a socket file, which is why Migro couldn’t guess it. Open LocalWP, select the other site, go to the Database tab and note the Port (a 5-digit number like 10090). In Migro’s “One field left” box, enter 127.0.0.1:10090, substituting that port. If that’s rejected with “not allowed to connect”, try localhost:10090 instead. Migro accepts a host:port value in that field.

    Let me know if you have any other issue!

    Thanks,

    Al

    • This reply was modified 1 month, 3 weeks ago by auadix.
Viewing 15 replies - 1 through 15 (of 15 total)