Sync A Pressable Site To Your Local DDEV Environment

Last modified: July 31, 2026

Ask Your Favorite AI

Copy the link to a markdown format of this article for ChatGPT, Claude, Gemini, or your favorite AI.

For WordPress developers · About 15 minutes for first-time setup

The ddev-pressable add-on connects a local DDEV WordPress environment to your Pressable site. Pull the live database and media down to your machine, and push a local copy up to a Pressable site. It runs over the SSH and WP-CLI access your site already has, so there are no API tokens to manage and nothing to install on the platform.

This guide starts from a completely fresh machine with nothing installed. If you already run DDEV day to day, skip ahead to Step 3.

What The Add-On Does (And Doesn’t)

DirectionWhat MovesCommand
Pull, Pressable to localDatabase + uploads/ mediaddev pull pressable
Push, local to PressableDatabase + uploads/ mediaddev push pressable

During a pull, the add-on rewrites your site’s URLs so the local copy loads at *.ddev.site instead of your production domain, and it does so safely for serialized data.

What You Need Before You Start

  • macOS, Linux, or Windows (WSL2), with permission to install software on your machine
  • A Pressable site you administer, with SSH access enabled (on by default for site owners, collaborators require the SFTP/SSH permission)

Step 1 installs everything else.

A note on support. Pressable support can help with SSH access on your site: confirming your public key is attached, checking SSH is switched on, and finding your site’s SSH username. Everything past that point runs on your own machine. For DDEV itself, see the DDEV documentation. For the add-on, use the issue tracker at github.com/pressable/ddev-pressable or log a bug with Pressable support.

Step 1: Install The Local Toolchain

If your machine is new to local development, install these three tools first, in this order. DDEV needs Docker, and mkcert gives you trusted HTTPS on localhost.

1a. Docker

Install Docker Desktop (or another provider DDEV supports, such as OrbStack or Colima) and start it. Confirm it’s running:

docker info

1b. DDEV And mkcert

On macOS with Homebrew:

brew install ddev/ddev/ddev mkcert

On Linux and Windows, follow the DDEV installation docs for your platform, then install mkcert. Check the version afterward. You need v1.24.0 or newer:

ddev version

1c. Trust The Local Certificate Authority

mkcert -install

Step 2: Create A WordPress DDEV Project

Make a project folder and configure it as a WordPress site. Swap my-site for whatever you like; it becomes your local URL, https://my-site.ddev.site.

mkdir -p ~/Sites/my-site
cd ~/Sites/my-site
ddev config --project-type=wordpress --project-name=my-site

Pressable runs nginx, so match it locally for parity:

ddev config --webserver-type=nginx-fpm

Start the project and download WordPress core so local WP-CLI has something to work with:

ddev start
ddev wp core download

DDEV writes a working wp-config.php (plus a managed wp-config-ddev.php) and spins up a database container, so WP-CLI can connect locally.

Port conflicts are fine. If ports 80 or 443 are already in use, DDEV picks alternates and prints the real URL, something like https://my-site.ddev.site:33001. It has no effect on syncing.

Step 3: Install The Pressable Add-On

From inside the project folder:

ddev add-on get pressable/ddev-pressable

It drops two files into .ddev/:

  • providers/pressable.yaml, the pull and push logic
  • config.pressable.yaml, the hook that rewrites URLs after a pull

Commit the .ddev directory so everyone on the project shares the same setup.

Step 4: Set Up SSH Access To Pressable

This is the step most people get stuck on. There are two parts: Pressable has to trust your key, and DDEV has to be able to use it.

4a. Make Sure You Have An SSH Key

If you don’t already have one:

ssh-keygen -t ed25519 -C "you@example.com"

4b. Add Your Public Key To Your Pressable Site

In the MyPressable control panel, open your site’s SFTP/SSH section and paste in your public key (~/.ssh/id_ed25519.pub or ~/.ssh/id_rsa.pub). Confirm that SSH access is enabled for that user, not just SFTP.

See our guide covering how to Connect to SSH on Pressable.

“Authenticated, but still permission denied.” A verbose SSH attempt can print Server accepts key and then still refuse the connection. That line does not mean your key is authorized for the site: the gateway acknowledges the key during the handshake and checks it against its own records afterward. Check that the public key is attached to this exact site, and that the SSH username you use belongs to that same site. Pasting a username from another site is an easy mistake.

4c. Tell The Add-On Which SSH User To Use

Every Pressable site has its own SFTP/SSH username. Find it in the SFTP/SSH section on the Overview page of the MyPressable control panel, then set it for this project:

ddev config --web-environment-add="PRESSABLE_SSH_USER=<your-site-ssh-user>"
ddev restart

The host defaults to ssh.pressable.com. To override it, set PRESSABLE_SSH_HOST.

4d. Load Your Key Into DDEV’s SSH Agent

ddev auth ssh

DDEV runs the sync inside its own container, which can’t reach your system keychain, so your key has to be loaded into DDEV’s agent.

Run this in your own terminal. If your key has a passphrase, ddev auth ssh prompts for it, so it can’t run inside a script. The key stays loaded for later commands until you run ddev poweroff.

Step 5: Test The Connection First

Before a long sync, check that SSH auth and remote WP-CLI both work. This check is read-only; it changes nothing:

ddev exec ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new \
  "$PRESSABLE_SSH_USER@ssh.pressable.com" "wp option get siteurl"

If it prints your production URL, you’re ready to pull. If it says Permission denied, go back to Step 4b.

Step 6: Pull Your Site

Pull the database and media down:

ddev pull pressable

Common variations:

GoalCommand
Database + media (default)ddev pull pressable
Database only (skip large media)ddev pull pressable --skip-files
Media only (leave local DB alone)ddev pull pressable --skip-db
Download without importingddev pull pressable --skip-import

Skip bulky logging tables to speed up a database pull:

ddev config --web-environment-add="PRESSABLE_DB_EXCLUDE_TABLES=wp_actionscheduler_logs,wp_actionscheduler_actions"

Or import only a chosen set of tables. This is advanced, and WordPress needs its core tables to run:

ddev config --web-environment-add="PRESSABLE_DB_TABLES=wp_options,wp_posts,wp_postmeta,wp_users,wp_usermeta"

PRESSABLE_DB_TABLES wins over the exclude list.

A note on timing. Databases are usually often less than 1 gigabyte and land in seconds. Media libraries can run to several gigabytes, so a first full pull can take a few minutes. Once the media is local, --skip-files makes repeat database refreshes quick.

Step 7: Get Your Theme And Plugin Code Locally

The add-on syncs the database and uploads but not code, so a freshly pulled site won’t render until the theme and plugins are present. Two ways to handle it.

Option A: Git (Best For Real Work)

Clone your site’s code repository so wp-content is under version control. This is the workflow most users want long term.

Option B: Copy The Code With rsync (Fastest Way To A Working Site)

You already have SSH access, so pull the theme and plugin code straight off the site. Run these from the project root, and watch the trailing slashes:

# Themes
rsync -azL -e ssh \
  <your-site-ssh-user>@ssh.pressable.com:htdocs/wp-content/themes/ \
  wp-content/themes/

# Plugins
rsync -azL -e ssh \
  <your-site-ssh-user>@ssh.pressable.com:htdocs/wp-content/plugins/ \
  wp-content/plugins/

A few things that will save you a headache:

  • -L follows symlinks. Some plugins in wp-content/plugins/ are platform-managed symlinks rather than real directories, Jetpack and Akismet among them. Without -L, rsync copies the link itself, which points nowhere on your machine, and it stops outright with could not make way for new symlink ... cannot delete non-empty directory if a local directory is already sitting in that spot. WordPress core ships its own copy of Akismet, so that collision is the one people hit first. -L copies the real files and avoids both problems.
  • Copy only themes/ and plugins/. Leave the wp-content root drop-ins alone (object-cache.php, advanced-cache.php). They point at caching services that exist on Pressable but not in DDEV, so copying them locally breaks the site.
  • Platform plugins won’t behave the same locally. Jetpack in particular arrives as real files with no connection to WordPress.com behind it. Deactivate it in your local install if it gets noisy: ddev wp plugin deactivate jetpack.
  • You can grab media the same way if you ever need to (...:htdocs/wp-content/uploads/ wp-content/uploads/), though ddev pull pressable already handles uploads.

Which plugins are symlinked changes over time, and some sites have WooCommerce handled as a symlink. So check your own site rather than trusting a list in a guide:

ssh <your-site-ssh-user>@ssh.pressable.com "ls -la htdocs/wp-content/plugins/ | grep '^l'"

Check your work:

ddev wp theme list
ddev wp plugin list
ddev launch          # open the local site

Step 8: Check That URLs Were Rewritten

The post-pull hook rewrites siteurl and home to your local *.ddev.site address. DDEV also defines the WP_HOME and WP_SITEURL constants at runtime, so the front end shows the local URL right away.

Confirm the database itself was fully localized, because some plugins tuck absolute URLs into serialized or JSON option values. Compare what’s stored against what’s live:

# Raw value stored in the database
ddev wp db query "SELECT option_value FROM wp_options WHERE option_name='siteurl'"

# Scan for any remaining production references
ddev wp db query "SELECT option_name FROM wp_options WHERE option_value LIKE '%YOUR-PRODUCTION-DOMAIN%'"

If production URLs are still in there, finish the job with a serialized-safe search-replace. Reading the stored value directly keeps the runtime constants from masking it:

ddev wp search-replace 'https://YOUR-PRODUCTION-DOMAIN' 'https://my-site.ddev.site' \
  --all-tables-with-prefix --skip-columns=guid

# JSON-encoded options store escaped slashes, so catch those too
ddev wp search-replace 'https:\/\/YOUR-PRODUCTION-DOMAIN' 'https:\/\/my-site.ddev.site' \
  --all-tables-with-prefix --skip-columns=guid

Step 9: Push To Pressable

When you’ve made local changes, you can push the database and media back up.

ddev push pressable                 # database + media to Pressable
ddev push pressable --skip-files    # database only

Match Your Local Environment To Pressable

For the closest match, line up .ddev/config.yaml with your site’s settings from the MyPressable control panel:

SettingRecommendation
PHPSet php_version to match your site
Web serverwebserver_type: nginx-fpm
DatabaseMost MariaDB versions import Pressable dumps fine; use mariadb_version: "10.11" for exact parity
WordPress coreManaged separately via git; syncing only moves the database and uploads

Apply changes with ddev restart.

Command Cheat Sheet

# One-time local setup
brew install ddev/ddev/ddev mkcert
mkcert -install                        # NOT with sudo

# New project
mkdir -p ~/Sites/my-site && cd ~/Sites/my-site
ddev config --project-type=wordpress --project-name=my-site --webserver-type=nginx-fpm
ddev start && ddev wp core download

# Add-on + SSH
ddev add-on get pressable/ddev-pressable
ddev config --web-environment-add="PRESSABLE_SSH_USER=<your-site-ssh-user>"
ddev restart
ddev auth ssh

# Sync
ddev pull pressable                    # DB + media down
ddev pull pressable --skip-files       # DB only
ddev push pressable                    # DB + media to Pressable only

# Get code (if not using git)
rsync -azL --exclude='akismet' -e ssh \
  <your-site-ssh-user>@ssh.pressable.com:htdocs/wp-content/themes/  wp-content/themes/
rsync -azL --exclude='akismet' -e ssh \
  <your-site-ssh-user>@ssh.pressable.com:htdocs/wp-content/plugins/ wp-content/plugins/

ddev launch                            # open the local site

Summary

  1. Install Docker, DDEV, and mkcert (mkcert -install without sudo).
  2. Create and start a WordPress DDEV project.
  3. Install the add-on: ddev add-on get pressable/ddev-pressable.
  4. Add your public SSH key to the site, set PRESSABLE_SSH_USER, and run ddev auth ssh.
  5. Test the connection, then ddev pull pressable.
  6. Bring your theme and plugin code down via git or rsync so the site renders.
  7. Push only to staging, and never skip the confirmation prompt.

The add-on is open source. File issues and pull requests at github.com/pressable/ddev-pressable.

Running into errors? See Troubleshooting Pressable DDEV Syncs.