---
title: Sync A Pressable Site To Your Local DDEV Environment
url: "https://pressable.com/knowledgebase/sync-a-pressable-site-to-your-local-ddev-environment/"
published: 2026-07-30
modified: 2026-07-31
author: Nox Dineen-Porter
---

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

The `ddev-pressable` add-on connects a local [DDEV](https://ddev.com/) 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.

 
 Warning:  **Pushes overwrite the target database**. `ddev push pressable` replaces the remote database with your local one. On a live site that destroys everything created since your local copy: orders, comments, form entries, new posts.

**It is strongly recommended that you only ever push to a staging site.** See Step 9.

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

**Direction****What Moves****Command**Pull, Pressable to localDatabase + `uploads/` media`ddev pull pressable`Push, local to PressableDatabase + `uploads/` media`ddev 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.

 
 Note:  The add-on moves the database and uploads, not your theme or plugin code. With this workflow, that code is meant to live in git. If you just want a working local site quickly, Step 7 shows how to copy it down with `rsync`.

See our guide detailing how to [Deploy from GitHub](https://pressable.com/knowledgebase/deploy-from-github/).

## 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](https://ddev.readthedocs.io/). For the add-on, use the issue tracker at [github.com/pressable/ddev-pressable](https://github.com/pressable/ddev-pressable) or [log a bug with Pressable support](https://pressable.com/knowledgebase/how-to-get-support-with-pressable/).

## 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](https://www.docker.com/products/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](https://ddev.readthedocs.io/en/stable/users/install/ddev-installation/) 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

```

 
 Note:  Don’t use `sudo` here. Run `mkcert -install` as yourself. It asks for your password only for the one step that adds the certificate authority to the system trust store. If you `sudo` the whole command, the CA lands in root’s home directory instead of yours, and DDEV (running as you) can’t read it.

## 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](https://pressable.com/knowledgebase/connect-to-ssh-on-pressable/#connect-to-ssh-with-an-ssh-key).

> **“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:

![](https://i0.wp.com/pressable.com/wp-content/uploads/2026/07/ddev1.jpg?resize=1024%2C496&ssl=1)
 
 

```
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:

**Goal****Command**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 importing`ddev 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.

 
 Warning:  **Push to staging only.** `ddev push pressable` overwrites the remote database. On a live site that wipes out everything created since your local copy: orders, comments, form entries, new posts.

The push waits for a confirmation prompt. Don’t skip it with `-y`. The file push is additive by default, so it never deletes remote media. After a push, the add-on runs `wp cache flush` on the remote so the object cache picks up the new data.

```
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:

**Setting****Recommendation**PHPSet `php_version` to match your siteWeb server`webserver_type: nginx-fpm`DatabaseMost MariaDB versions import Pressable dumps fine; use `mariadb_version: "10.11"` for exact parityWordPress coreManaged separately via git; syncing only moves the database and uploadsApply 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](https://github.com/pressable/ddev-pressable).

Running into errors? See **[Troubleshooting Pressable DDEV Syncs](https://pressable.com/knowledgebase/troubleshooting-pressable-ddev-syncs/)**.
