Skip to content

Media Handling ​

Configure how Unpress handles your WordPress media files (images, videos, documents, etc.) during migration.

Overview ​

WordPress sites typically have hundreds or thousands of media files. Unpress offers three modes to handle these files:

  1. Local Download - Download media to your site/ folder
  2. Reupload - Upload media to S3 or SFTP with automatic URL replacement
  3. Leave URLs - Keep original media URLs unchanged

Choose the mode that best fits your use case:

  • Cost savings → Use Reupload (S3 is cheap)
  • Archival → Use Leave URLs (preserve original structure)
  • Simple migration → Use Local Download (easiest setup)

Mode 1: Local Download ​

Download media files from WordPress to your local site/ folder and update URLs in Markdown to point to these local files.

When to Use ​

  • Quick migration with minimal setup
  • Want to keep media with your site files
  • Media files are small (under 100MB total)
  • Deploying to platforms that support local files (Netlify, Vercel)

How to Enable ​

Add --download-media flag to your migration command:

bash
pnpx @selfagency/unpress --download-media --generate-site

What Happens ​

  1. Unpress scans migrated Markdown files for media URLs
  2. Downloads each media file to site/media/ folder
  3. Updates URLs in Markdown to point to local files:
    • Before: ![image](https://your-site.com/wp-content/uploads/2024/01/image.jpg)
    • After: ![image](/media/uploads/2024/01/image.jpg)

Output Structure ​

text
site/
├── media/
│   └── uploads/
│       ├── 2024/
│       │   ├── 01/
│       │   │   ├── image.jpg
│       │   │   └── document.pdf
│       │   └── 02/
│       │       └── photo.png
│       └── ...
├── content/
│   └── posts/
│       └── 2024-01-15-post.md

Pros and Cons ​

ProsCons
✅ Easiest setup—no external accounts❌ Increases site size (media included)
✅ Works offline after download❌ Longer deployment time
✅ No ongoing costs❌ May hit file size limits on free hosting
✅ Simple URL structure❌ Must redeploy to update media

Troubleshooting ​

Media files not downloading:

  • Check if WordPress media URLs are accessible
  • Verify your internet connection is stable
  • Look for error messages in migration output

Broken image links in deployed site:

  • Ensure site/media/ folder was deployed
  • Check file permissions on media files
  • Verify URL paths in Markdown are correct

Mode 2: Reupload to S3 ​

Upload media files to Amazon S3 (or S3-compatible storage) and automatically update URLs in Markdown.

When to Use ​

  • Large media libraries (100MB+)
  • Want CDN performance and cheap storage
  • Deploying to platforms with file size limits
  • Want scalable, reliable media hosting

Prerequisites ​

  1. AWS Account - Create account at aws.amazon.com
  2. S3 Bucket - Create bucket to store media files
  3. AWS Credentials - Get Access Key ID and Secret Access Key

Step 1: Create S3 Bucket ​

  1. Log in to AWS Console
  2. Navigate to S3
  3. Click Create bucket
  4. Enter bucket name (globally unique, e.g., my-site-media-2024)
  5. Choose AWS Region (closest to your users)
  6. Configure settings:
    • Block Public Access settings: Off (to allow public media)
    • Bucket Policy: Add policy to allow public read access

Step 2: Set Bucket Policy (Public Read) ​

In your S3 bucket, go to Permissions → Bucket Policy and add:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::your-bucket-name/*"
    }
  ]
}

Replace your-bucket-name with your actual bucket name.

Step 3: Get AWS Credentials ​

  1. Go to IAM → Users in AWS Console
  2. Create new user with Programmatic access
  3. Attach policy: AmazonS3FullAccess (or create custom policy for your bucket)
  4. Save Access Key ID and Secret Access Key (you won't see Secret Access Key again!)

Step 4: Configure Unpress for S3 ​

Create a config file unpress.yml:

yaml
source:
  type: api
  api:
    baseUrl: https://your-site.com

media:
  mode: reupload
  reupload:
    driver: s3
    s3:
      bucket: your-bucket-name
      region: us-east-1
      endpoint: https://s3.amazonaws.com

Step 5: Add AWS credentials to .env ​

Add your AWS credentials to the same .env file you use for Unpress:

dotenv
AWS_ACCESS_KEY_ID=your-access-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key
AWS_REGION=us-east-1

Never commit credentials!

Never commit AWS credentials to Git or share them publicly. Use environment variables or secret management tools.

Step 6: Run Migration ​

bash
pnpx @selfagency/unpress --config unpress.yml --generate-site

Unpress will:

  1. Download media from WordPress (to temporary folder)
  2. Upload each file to your S3 bucket
  3. Update URLs in Markdown to point to S3:
    • Before: ![image](https://your-site.com/wp-content/uploads/2024/01/image.jpg)
    • After: ![image](https://your-bucket.s3.amazonaws.com/uploads/2024/01/image.jpg)

What Gets Uploaded ​

  • Images (JPG, PNG, GIF, SVG, WebP)
  • Videos (MP4, WebM, MOV)
  • Documents (PDF, DOC, DOCX)
  • Audio files (MP3, WAV, OGG)

Pros and Cons ​

ProsCons
✅ Cheap storage (~$0.023/GB/month)❌ Requires AWS account and setup
✅ Fast CDN via CloudFront (optional)❌ Must manage AWS credentials
✅ Scales to any size❌ Has ongoing AWS costs
✅ Faster site deployment (media not included)❌ External dependency on S3
✅ Better performance with CDN❌ More complex than local download

Troubleshooting ​

"Access Denied" error:

  • Check AWS credentials are correct
  • Verify bucket policy allows public read access
  • Ensure IAM user has S3 permissions
  • Check bucket name and region match your config

"Bucket not found" error:

  • Verify bucket name is correct (case-sensitive)
  • Check bucket is in the correct region
  • Ensure bucket exists and you have access

"Connection timeout":

  • Check your internet connection
  • Verify S3 endpoint URL is correct for your region
  • Try increasing timeout (adjust in config if needed)

Optional: Use CloudFront CDN ​

For even better performance, set up CloudFront CDN in front of your S3 bucket:

  1. Go to CloudFront in AWS Console
  2. Create distribution with S3 bucket as origin
  3. Update unpress.yml with CloudFront domain:
yaml
media:
  mode: reupload
  reupload:
    driver: s3
    s3:
      bucket: your-bucket-name
      region: us-east-1
      endpoint: https://your-cloudfront-id.cloudfront.net

URLs will point to CloudFront (faster, lower latency).

Mode 3: Reupload to SFTP ​

Upload media files to SFTP server and automatically update URLs in Markdown.

When to Use ​

  • Existing SFTP hosting for media
  • Want to use your own server for media
  • Deploying to platforms that can't handle large media
  • Prefer complete control over media hosting

Prerequisites ​

  1. SFTP Server - Server with SFTP access enabled
  2. SFTP Credentials - Host, port, username, password/key
  3. Directory Path - Path where media should be uploaded

Step 1: Configure Unpress for SFTP ​

Create a config file unpress.yml:

yaml
source:
  type: api
  api:
    baseUrl: https://your-site.com

media:
  mode: reupload
  reupload:
    driver: sftp
    sftp:
      host: your-server.com
      port: 22
      username: your-username
      password: your-password
      path: /var/www/media

Step 2: Add SFTP credentials to .env (optional) ​

You can also place SFTP credentials in .env:

dotenv
SFTP_HOST=your-server.com
SFTP_PORT=22
SFTP_USER=your-username
SFTP_PASSWORD=your-password

Step 3: Run Migration ​

bash
pnpx @selfagency/unpress --config unpress.yml --generate-site

Unpress will:

  1. Download media from WordPress (to temporary folder)
  2. Upload each file to your SFTP server
  3. Update URLs in Markdown to point to SFTP:
    • Before: ![image](https://your-site.com/wp-content/uploads/2024/01/image.jpg)
    • After: ![image](https://your-server.com/media/uploads/2024/01/image.jpg)

SFTP Authentication Options ​

Password Authentication ​

yaml
sftp:
  host: your-server.com
  username: your-username
  password: your-password
yaml
sftp:
  host: your-server.com
  username: your-username
  privateKey: /path/to/private/key.pem
  passphrase: your-passphrase  # Optional

Pros and Cons ​

ProsCons
✅ Use your existing server❌ Requires server setup and maintenance
✅ Full control over media hosting❌ Must manage server credentials
✅ Can use any SFTP server❌ Server performance impacts media delivery
✅ No external service costs❌ Scalability depends on your server
✅ Faster site deployment❌ More complex than local download

Troubleshooting ​

"Connection refused" error:

  • Verify SFTP port is correct (default: 22)
  • Check if SFTP service is enabled on your server
  • Ensure firewall allows SFTP connections
  • Verify hostname resolves correctly

"Authentication failed" error:

  • Check username and password/SSH key are correct
  • Verify SSH key format is supported (PEM format)
  • Test SFTP connection manually: sftp your-server.com

"Permission denied" error:

  • Check if upload path exists and is writable
  • Verify user has write permissions on target directory
  • Check directory ownership and permissions

Mode 5: Reupload to SCP ​

Upload media files to a server via SCP (Secure Copy Protocol) and automatically update URLs in Markdown.

When to Use ​

  • Direct file transfer without SSH access
  • Minimal SSH service needed (SCP protocol)
  • Simpler than SFTP for basic file uploads
  • Server with SSH but prefer SCP over interactive shell access
  • Want to use existing SSH infrastructure for file transfer

Prerequisites ​

  1. SSH Server - Server with SSH access enabled (SCP runs over SSH)
  2. SCP Credentials - Host, port, username, password/key
  3. Directory Path - Path where media should be uploaded

Step 1: Configure Unpress for SCP ​

Create a config file unpress.yml:

yaml
source:
  type: api
  api:
    baseUrl: https://your-site.com

media:
  mode: reupload
  reupload:
    driver: scp
    scp:
      host: your-server.com
      port: 22
      username: your-username
      password: your-password
      path: /var/www/media

Step 2: Add SCP credentials to .env (optional) ​

You can also place SCP credentials in .env:

dotenv
SCP_HOST=your-server.com
SCP_PORT=22
SCP_USER=your-username
SCP_PASSWORD=your-password

Step 3: Run Migration ​

bash
pnpx @selfagency/unpress --config unpress.yml --generate-site

Unpress will:

  1. Download media from WordPress (to temporary folder)
  2. Upload each file to your SCP server
  3. Update URLs in Markdown to point to SCP:
    • Before: ![image](https://your-site.com/wp-content/uploads/2024/01/image.jpg)
    • After: ![image](scp://your-server.com/media/uploads/2024/01/image.jpg)

SCP Authentication Options ​

Password Authentication ​

yaml
scp:
  host: your-server.com
  username: your-username
  password: your-password
yaml
scp:
  host: your-server.com
  username: your-username
  privateKey: /path/to/private/key.pem

Pros and Cons ​

ProsCons
✅ Simple folder-based upload❌ Requires SSH setup and maintenance
✅ Full control over media hosting❌ Must manage server credentials
✅ Works on standard SSH servers❌ Cannot list server-side files
✅ No external service costs❌ Server performance impacts media delivery
✅ Faster site deployment❌ More complex than local download

Troubleshooting ​

"Connection refused" error:

  • Verify SCP port is correct (default: 22)
  • Check if SSH service is enabled on your server
  • Ensure firewall allows SSH/SCP connections
  • Verify hostname resolves correctly

"Authentication failed" error:

  • Check username and password/SSH key are correct
  • Verify SSH key format is supported (PEM format)
  • Test SCP connection manually: scp ./file your-username@your-server.com:/tmp/

"Permission denied" error:

  • Check if upload path exists and is writable
  • Verify user has write permissions on target directory
  • Check directory ownership and permissions

Mode 4: Leave URLs ​

Keep original WordPress media URLs unchanged. This is the simplest mode and ideal for archival.

When to Use ​

  • Archival - Preserve original structure and links
  • Minimal migration - Want simplest possible setup
  • Existing CDN - WordPress already uses CDN for media
  • Cost savings - Don't want to move media

How to Enable ​

Create a config file unpress.yml:

yaml
media:
  mode: leave

Or just run Unpress with your existing .env and no media override flags:

bash
pnpx @selfagency/unpress --generate-site

Default behavior (if no media config) is to leave URLs unchanged.

What Happens ​

Unpress does not download or upload media. Media URLs in Markdown remain as they were in WordPress:

markdown
![image](https://your-site.com/wp-content/uploads/2024/01/image.jpg)

Your new site will continue loading media from your WordPress server.

Pros and Cons ​

ProsCons
✅ Easiest setup—no changes to media❌ Depends on WordPress server remaining online
✅ Fastest migration—no media processing❌ No performance improvement for media
✅ No external service needed❌ Can't delete WordPress server
✅ Minimal site size❌ No cost savings from media hosting
✅ Preserves original URLs❌ Media delivery speed unchanged

When This Fails ​

Problem: WordPress server is offline or media is deleted.

Solution: Your new site will show broken image links. To fix this:

  1. Migrate again using Local Download or Reupload mode
  2. Or manually restore WordPress server/media files

Use Case: Archival Migration ​

For archival scenarios, this mode is ideal because:

  • Preserves original structure exactly
  • No risk of losing media if WordPress is archived properly
  • Minimal migration effort
  • Maintains historical accuracy

However, ensure your WordPress media is properly archived:

  • Backup media files to reliable storage
  • Consider using Wayback Machine or archive.org for public sites
  • Document media structure for future reference

Choosing the Right Mode ​

Decision Flowchart ​

text
Do you want to move media?
├─ No → Use "Leave URLs" (easiest)
└─ Yes
   ├─ Want simplest setup?
   │  └─ Yes → Use "Local Download"
   └─ Want best performance/cost?
      ├─ Have AWS account?
      │  └─ Yes → Use "Reupload to S3"
      └─ Have SFTP server?
         └─ Yes → Use "Reupload to SFTP"

Comparison Table ​

ModeSetup DifficultyPerformanceCostBest For
Local Download⭐ Easy⭐⭐⭐ Good$0Small sites, quick migration
Reupload to S3⭐⭐⭐ Complex⭐⭐⭐⭐ Excellent$0.023/GB/moLarge sites, CDN performance
Reupload to SFTP⭐⭐ Medium⭐⭐⭐ Good$0 (server cost)Existing server, full control
Reupload to SCP⭐⭐ Medium⭐⭐⭐ Good$0 (server cost)Simple file transfer, SSH setup
Leave URLs⭐ Easiest⭐⭐ Fair$0Archival, minimal migration

Recommendations ​

For cost savings:

  • Use Reupload to S3 (cheapest storage at scale)
  • Local Download works for small sites (< 100MB media)

For archival:

  • Use Leave URLs (preserve original structure)
  • Ensure WordPress media is properly backed up

For performance:

  • Use Reupload to S3 + CloudFront CDN (fastest)
  • Reupload to fast SFTP server with caching

For simplicity:

  • Use Leave URLs (no changes needed)
  • Local Download if you want media with your site

Next Steps ​

After configuring media handling:

  1. Generated Site Guide - Understand your output structure
  2. Deployment Guide - Deploy your site (consider media mode!)
  3. WordPress API Migration - Run migration with media config
  4. XML Export Migration - Use XML with media reupload

Released under MIT License.