GitHub: Executing Scheduled Actions (Cron)
1. Summary
Context: The default WP Cron can be unreliable and not suitable for all actions. We need to execute the server site command where standard Unix cron is not available
Solution: We use GitHub Actions to SSH into the server and execute commands using a “Linear Chain” method. This eliminates the need for external intermediary servers.
2. Prerequisites
- GitHub Access: Admin or Maintainer permissions.
- WP Engine Access: Ability to manage SSH keys in the User Portal.
- Local Terminal: To generate SSH keys (Mac/Linux preferred).
3. Technical Explanation: “The Chain Rule”
To ensure stability in WP Engine’s restricted shell, the code must be written using the Chain Rule.
The shell will disconnect if we attempt to send complex, multi-line logic (such as if statements or loops) over a non-interactive SSH connection. To bypass this, we format our script as a single, continuous stream:
\(Backslash): Tells the YAML file “This command continues on the next line” (for readability).&&(AND Operator): Tells the Server “Run this command, and ONLY if it succeeds, run the next one.”
Crucial Constraints:
- Do not place comments (
#) inside the command chain block. - Do not use double quotes inside double quotes (e.g., for date formatting). Use single quotes
'for inner variables.
You can still use if and loops, but they must be formatted as One-Liners using semicolons (;).
- Format:
for x in list; do command; done
❌ This will FAIL (Multi-line):
# This breaks because the SSH stream loses the line breaks
for i in {1..5}
do
echo "Number $i"
done
✅ This will WORK (One-line with Semicolons):
# Semicolons tell the server exactly where instructions end
for i in {1..5}; do echo "Number $i"; done
For complex logic that cannot fit on one line, use echo commands to generate a .sh file on the server first, then execute that file.
4. Setup Instructions
Step 1: Generate SSH Keys
Run this in your local terminal:
ssh-keygen -t rsa -b 4096 -C "github-actions-wpe" -f wpe_gh_key
(When asked for a passphrase, press Enter twice to leave it empty).
Step 2: Configure WP Engine
- Log in to WP Engine User Portal.
- Go to Users > SSH Keys.
- Add the contents of the Public Key (
wpe_gh_key.pub).
Step 3: Configure GitHub Secrets
Go to Repo Settings > Security > Secrets and variables > Actions and add these three secrets:
| Secret Name | Value |
WPE_SSH_KEY | Content of wpe_gh_key (Private Key). |
WPE_SSH_USER | The install name (e.g., punkcake). |
WPE_SSH_HOST | The SSH host (e.g., punkcake.ssh.wpengine.net). |
Step 4: Create the Workflow File
Create a new file at .github/workflows/wpe-cron.yml.
name: WP Engine Cron Demo
on:
schedule:
# Schedule: Runs at 5:00 AM UTC every day
- cron: '0 5 * * *'
# Trigger: Allows manual execution via the "Actions" tab
workflow_dispatch:
jobs:
execute-cron:
runs-on: ubuntu-latest
steps:
- name: SSH and Execute
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.WPE_SSH_HOST }}
username: ${{ secrets.WPE_SSH_USER }}
key: ${{ secrets.WPE_SSH_KEY }}
port: 22
# THE LINEAR CHAIN SCRIPT
# Note: Date format uses single quotes '' to prevent syntax errors
script: |
echo "--- START ---" && \
cd /nas/content/live/${{ secrets.WPE_SSH_USER }} && \
echo "✅ Navigated to $(pwd)" && \
echo "$(date '+%H:%M:%S %d:%m:%Y') - Cron executed successfully via GitHub Actions" >> gh-cron-test.txt && \
echo "✅ Log updated" && \
echo "--- CURRENT LOG CONTENT ---" && \
tail -n 5 gh-cron-test.txt && \
echo "--- DONE ---"
5. Expected Output
When you run this workflow, it will:
- Connect to the server.
- Navigate to the site root (ensuring we are not in the generic user home).
- Create
gh-cron-test.txtif it doesn’t exist, or append to it if it does. - Print the result for verification.
Example Log Output:
--- START ---
✅ Navigated to /nas/content/live/punkcake
✅ Log updated
--- CURRENT LOG CONTENT ---
16:20:01 22:12:2025 - Cron executed successfully via GitHub Actions
--- DONE ---
6. How to Test the Workflow
Since the workflow is configured with workflow_dispatch, you can trigger it manually at any time without waiting for the scheduled 5:00 AM run.
Step A: Trigger the Run
- Navigate to your GitHub Repository.
- Click the Actions tab (top menu).
- On the left sidebar, click the workflow name: WP Engine Cron Demo.
- You will see a blue banner on the right. Click the Run workflow dropdown button.
- Select the Branch: main and click the green Run workflow button.
Step B: Verify in GitHub
- Wait approx. 30 seconds for the run to complete.
- Success: The circle icon turns Green.
- Failure: The circle icon turns Red.
- Check the Output:
- Click on the workflow run (e.g., “WP Engine Cron Demo #1”).
- Click on the job box named execute-cron.
- Click the arrow next to SSH and Execute to expand the logs.
- You should see the custom output verifying the log update:

Step C: Verify on Server
To confirm the file is persisting correctly:
- Log in to your WP Engine environment via SFTP or SSH.
- Navigate to the site root:
/nas/content/live/punkcake/ - Look for the file:
gh-cron-test.txt. - Open it to see the log history.
- Note: Every time you click “Run workflow” in GitHub, a new line with a new timestamp will be added to this file.

7. Troubleshooting Common Errors
| Error Message | Meaning | Solution |
Process exited with status 1 | The script failed at a specific step. | Check the logs. If it failed at cd, your WPE_SSH_USER secret might be wrong. |
extra operand / syntax error | Quote mismatch. | Ensure you are using single quotes ' for the date command format, not double quotes. |
tail: cannot open... No such file | File creation failed. | Ensure you are navigating to the correct folder (/nas/content/live/...) before trying to write the file. |
Handshake failed | SSH Key rejected. | Re-add the Public Key to the WP Engine User Portal. |
Found this useful?
There's more where that came from — explore the rest of the documentation, experiments, and production work.
→ Back to the index