Yes, You Can Deploy to InMotion Cloud from GitHub — Here's a Working CI/CD Pipeline
See a working CI/CD pipeline that auto-deploys WordPress to InMotion Cloud from GitHub Actions, with PHPUnit tests gating each release.

When a technical buyer evaluates a cloud platform today, one of the first questions they ask is whether they can deploy from GitHub. They don't want to upload files over SFTP. They don't want a custom dashboard. They want git push origin main to run their tests, build their artifact, and put the result in production the same workflow they already use everywhere else.
The answer for InMotion Cloud is yes, and rather than describe it abstractly, this article walks through a real proof of concept: a WordPress site running on InMotion Cloud, connected to a GitHub repository, with a GitHub Actions pipeline that runs PHPUnit on every push to main and deploys the validated theme straight to the live server. The same pattern Git as the source of truth, automated tests as the gate, a runner inside your environment doing the deploy works for Node, Python, static sites, and most other modern stacks.
What CI/CD Means in Practice
CI/CD stands for continuous integration and continuous delivery. The terms sound formal, but the idea is simple.
Continuous integration means every push to your repository triggers an automated build and test. If something breaks, you find out in minutes, not after a release. Continuous delivery means once those checks pass, the code goes to production with no manual step in between.
For most teams the practical impact is concrete:
- Releases stop being events. They happen on every merge.
- Manual file uploads disappear. So do the mistakes that come with them.
- Rollback becomes a Git operation rather than a recovery operation.
- The pipeline becomes the contract: if tests pass, the change ships.
Cloud platforms that support this workflow let teams move at the cadence they expect. Platforms that don't force them back into uploads, hand-rolled scripts, and tribal knowledge about which file goes where.
What the Proof of Concept Runs
The setup is intentionally minimal so the moving parts are obvious:
- A WordPress site hosted on an InMotion Cloud instance (virtual machine).
- A custom WordPress theme called
cicd-demo, stored in a GitHub repository. - A GitHub Actions workflow that runs PHPUnit on a GitHub-hosted runner.
- A self-hosted GitHub Actions runner installed directly on the WordPress VM.
- An
rsynccommand in the deploy job that copies the validated theme files into/var/www/html/wp-content/themes/cicd-demo/.
The repository looks like this:
1.github/workflows/deploy.yml # GitHub Actions pipeline2composer.json # PHPUnit dependency3phpunit.xml # PHPUnit configuration4tests/ThemeTest.php # automated test5theme/cicd-demo/6├── style.css7├── functions.php # contains version constant8└── index.php
The "visible change" the article uses to prove a deploy reached production is a single PHP constant in functions.php:
1define('CICD_DEMO_VERSION', '1.0.4');
Bumping that constant, pushing to main, and refreshing the homepage is the end-to-end test of the entire pipeline.
How a Deploy Actually Works
The pipeline runs in two jobs. The first is the test gate. The second is the deploy. The deploy only runs if the test gate passes that is the whole point of CI.
Step 1: A developer pushes to main
1git push origin main
That single command triggers the workflow. Nothing else happens by hand.
Step 2: PHPUnit runs on a GitHub-hosted runner
The first job spins up an Ubuntu runner provided by GitHub, installs PHP 8.2 and the Composer dependencies, and runs the test suite. The tests are deliberately small the point of the proof of concept is the pipeline, not the test coverage:
1public function testVersionConstantIsDefined(): void2{3 $this->assertTrue(defined('CICD_DEMO_VERSION'));4}
A second test confirms the version string follows MAJOR.MINOR.PATCH semantic versioning. If either test fails, the deploy job never runs. That is the gate. Production does not get touched unless the suite is green.

Step 3: The self-hosted runner deploys to production
If the tests pass, the deploy job starts on a self-hosted runner a small GitHub Actions agent installed directly on the WordPress VM in InMotion Cloud. The runner pulls the validated build from GitHub and copies the theme files into the WordPress themes directory:
1rsync -a --delete \2 theme/cicd-demo/ \3 /var/www/html/wp-content/themes/cicd-demo/
That is the entire deployment. No SCP, no SFTP, no manual zip upload. The change is live the moment rsync finishes.
The workflow file that ties it together is short:
1name: CI/CD23on:4 push:5 branches: [main]67jobs:8 test:9 name: PHPUnit10 runs-on: ubuntu-latest1112 deploy:13 name: Deploy to production14 needs: test15 if: github.ref == 'refs/heads/main'16 runs-on: [self-hosted, wordpress-prod]
Three rules are encoded here. Tests always run first. Deployment only happens after a successful test job. Only the main branch can deploy to production.
Why the Self-Hosted Runner Matters
The architectural choice that makes this setup safe and simple is the self-hosted runner. It deserves a closer look because it is the part most teams get wrong on other clouds.
A self-hosted runner is a GitHub Actions agent that you install on your own server. It registers itself with GitHub and waits for jobs. When a deploy job is dispatched, GitHub sends the work to the runner, the runner executes it, and the result is reported back.
The implications for cloud security are significant:
- No inbound SSH from GitHub. GitHub never connects to your server. The runner connects out, over HTTPS, on port 443.
- No long-lived deploy keys floating around. The runner authenticates with a registration token tied to the repo, scoped to the runner's own context.
- No firewall holes. Your security group does not need to open anything new for deploys.
- Faster deploys. The runner is already on the same machine as the production directory. There is no network hop between the build artifact and the destination.
Compared with the common pattern of giving a hosted CI service SSH credentials to your production box, this is a meaningful improvement. The "deploy infrastructure" lives inside your environment. The cloud provider InMotion Cloud controls the host. You control the runner. GitHub orchestrates.
Confirming a Deploy Reached Production
The proof loop is simple and worth running once any time the pipeline changes:
- Edit the version constant in
functions.php:
1 define('CICD_DEMO_VERSION', '1.0.5');
- Commit and push:
1 git push origin main
- Watch the GitHub Actions run open. Tests run, then the deploy job runs.
- Refresh the homepage. The displayed theme version updates from
1.0.4to1.0.5.
That is the whole confirmation. If the homepage updates, the pipeline works end to end. If the tests fail, the deploy never runs and the homepage stays on the old version exactly as it should.
The first time the pipeline runs, there is one manual setup step inside WordPress: navigate to Appearance → Themes and activate CI/CD Demo. Once activated, every future deploy updates the active theme automatically. That is the only piece of the workflow that is not Git-driven, and it only happens once.
This Pattern Is Not WordPress-Specific
The proof of concept uses WordPress because it is the most common workload customers ask about. But the pipeline shape Git → tests → self-hosted runner → production is not specific to PHP or WordPress.
The same architecture supports:
- Node.js and Next.js — replace PHPUnit with Jest or Vitest, replace the
rsyncwithpm2 reloador a container restart. - Python and Django — run pytest, then
rsyncplussystemctl restart gunicorn. - Static sites — run a Lighthouse or HTML-validator check, then sync the built output to your web root.
- Containerized apps — push the built image to a registry, pull and restart on the VM.
In every case the principles hold: code lives in Git, tests run on every push, deployment is automatic, and the runner that touches production lives inside your environment rather than outside it.
What This Means for Teams Evaluating InMotion Cloud
InMotion Cloud is built on OpenStack and runs in our own data centers. That has direct consequences for the way CI/CD works on the platform.
You get full control of the host. A self-hosted runner installs the same way it would on any Linux server, because that is exactly what your instance is — a Linux server you control, not a managed black box.
You don't pay per build minute. GitHub-hosted runners bill by minute. Self-hosted runners do not. With the runner on a VM you already pay for, your deploy job costs nothing extra.
You don't share the deploy path with unknown tenants. The build artifact moves from a known runner to a known directory on a known machine. There is no opaque managed-deploy layer in between.
Pricing stays predictable. Build minutes, deploy minutes, and bandwidth are part of the instance you already have. The pipeline does not add a separate line item.

For prospects who have been told that "modern CI/CD" requires a hyperscaler, the proof of concept above answers the question concretely. The same Git-driven, test-gated, automated-deployment workflow that runs on AWS or Azure runs on InMotion Cloud — without the surrounding complexity, surprise costs, or shared-tenant uncertainty.
Next Steps
If you are evaluating InMotion Cloud and CI/CD support is on your checklist, the working setup above is the answer to bring to your team. From there, the path to running it on your own workload is short:
- Spin up an InMotion Cloud instance for your application stack.
- Install a self-hosted GitHub Actions runner on the instance.
- Wire your existing repository's tests into a workflow.
- Add a deploy job that targets the production directory or service on the runner's host.
Talk to our team if you want a walkthrough on a specific stack WordPress, Node, Python, containerized, or otherwise. The pipeline pattern stays the same. The only thing that changes is what runs in the test job and what command does the deploy.
Related resources
Explore more stories and guides that pair well with this article.

InMotion Cloud runs on its own hardware in its own data centers — not AWS or Azure. Here's what that means for your team and your bill.

Week-by-week cloud migration playbook with checklists. Real case study: $2M ARR SaaS migrated from AWS to Managed VPC in 28 days. Data migration, DNS cutover, rollback plans.

Technical signals that indicate VPS to VPC upgrade timing. Includes capacity planning framework, growth trajectory modeling, and cost comparison for the switch.