SSH and Rsync: What Worked and What Didn’t
Deploying a WordPress theme manually can be a pain, especially when dealing with SSH, rsync, GitHub, and database migrations. After some trial and error, I figured out a clean and efficient way to deploy my Swagdrip WordPress theme from my local development environment to my live server.
This post documents everything that worked (and didn’t work), so you don’t have to suffer through the same debugging process.
The Goal
- Push theme updates without breaking the live site
- Exclude unnecessary files (
node_modules
,.git
,.DS_Store
,.map
, etc.) - Automate deployment with GitHub + SSH + Rsync
- Ensure database URLs are updated after sync
- Verify everything works after deployment
Step 1: Prepare the Local Environment
I’m using Local by Flywheel for local development. My theme lives in:
/home/mnrdjmke/public_html/wp-content/themes/swagdrip/
I also track my theme with Git on GitHub at:
git@github.com:eboy79/swagdrip.git
Before deploying, I ensure everything is committed:
git add .
git commit -m "Updated theme for deployment"
git push origin main
Step 2: Deploying the Database to Live Server
First, I export my local database:
wp db export local-db.sql
Then, I securely copy it to my live server:
scp -P 21098 local-db.sql mnrdjmke@198.54.125.196:/home/mnrdjmke/public_html/
On the live server, I import it:
wp db import /home/mnrdjmke/public_html/local-db.sql
Then, update the URLs to ensure everything points to the live domain:
wp search-replace 'https://mnrdsgn.local' 'https://mnrdsgn.com' --skip-columns=guid
wp cache flush
Step 3: Deploying the Theme Files with Rsyn
Since I only want to transfer the theme files (excluding unnecessary dependencies), I use rsync
:
rsync -avz --progress -e "ssh -p 21098" \
--exclude "node_modules" \
--exclude ".git" \
--exclude "package-lock.json" \
--exclude ".DS_Store" \
--exclude "*.map" \
--exclude "*.d.ts" \
--exclude "package.json" \
--exclude "rollup.config.js" \
"/home/mnrdjmke/public_html/wp-content/themes/swagdrip/" \
mnrdjmke@198.54.125.196:/home/mnrdjmke/public_html/wp-content/themes/swagdrip/
This ensures only relevant theme files are uploaded, keeping the live server clean.
To verify everything transferred:
ssh -p 21098 mnrdjmke@198.54.125.196
ls -lah /home/mnrdjmke/public_html/wp-content/themes/swagdrip/
Step 4: Clearing Cache & Verifying Deployment
After the files are synced, I clear any cached data:
wp cache flush
Then, I check my live site at https://mnrdsgn.com to confirm changes.
If styles or scripts don’t update, I run:
rm -rf wp-content/cache/*
And hard refresh (Cmd + Shift + R
on Mac, Ctrl + Shift + R
on Windows).
Step 5: Automating with GitHub
Since I want to push from GitHub to the live site, I set up a post-receive Git hook.
On the Live Server:
cd /home/mnrdjmke/public_html/wp-content/themes/swagdrip
git init
git remote add origin https://github.com/eboy79/swagdrip.git
git pull origin main
Now, every time I push to GitHub, I just SSH in and pull:
ssh -p 21098 mnrdjmke@198.54.125.196
cd /home/mnrdjmke/public_html/wp-content/themes/swagdrip
git pull origin main
For full automation, I’ll set up a GitHub Actions workflow (coming soon).
What Worked & What Didn’t
✅ What worked:
scp
for database migration ✅rsync
for fast, efficient theme deployment ✅wp search-replace
for URL updates ✅wp cache flush
to ensure instant updates ✅- Git tracking on GitHub for version control ✅
❌ What didn’t work (and got fixed):
- Using
scp
for themes – too slow & error-prone ❌ → Fixed withrsync
✅ - Accidentally tracking
node_modules
in Git ❌ → Fixed by adding to.gitignore
✅ - Not excluding
.map
files ❌ → Fixed by updatingrsync
excludes ✅ - Forgetting to clear cache after deployment ❌ → Fixed with
wp cache flush
✅
Final Thoughts
This setup allows me to push WordPress theme updates fast and efficiently without breaking the live site. If you’re struggling with manual deployments, this workflow will save you time and headaches.
🚀 Next Step: Automating this with GitHub Actions to make it one-click deploy. Stay tuned!
Got Questions?
Hit me up on GitHub: @eboy79 or comment below!