How to Self-Host WordPress Plugins on Github and Deliver Updates

Illustration depicting the seamless integration between WordPress plugins and GitHub for self-hosted updates. Features dynamic arrows symbolizing updates and a modern, digital background to emphasize technology and innovation

Managing plugin updates can be a challenge, especially if you’re not relying on the WordPress Plugin Repository. But what if you could self-host your plugins on GitHub and deliver updates seamlessly, without the need for complex libraries or third-party services?

In this guide, I’ll walk you through a simple yet powerful solution that adheres to WordPress’s standard for updates, making the process completely transparent for your users. To make this possible, I’ve developed a custom GitHub Action and a PHP script that work together to handle updates effortlessly. This is the same solution I use for some of my own plugins, and now I’m sharing it with the community so you can benefit from it too.

No extra dependencies, no fuss—just GitHub and a bit of PHP magic. Let’s get started! 🚀

What is self-host plugins?

Before diving in, let’s take a step back: self-hosting plugins means managing your plugin’s storage and updates independently, outside the WordPress.org repository. So you take control of where your WordPress plugins are stored and how updates are delivered, without relying on the official WordPress Plugin Repository. Instead of hosting your plugin on WordPress.org, you use your own infrastructure—such as GitHub, a private server, or any other file host—to manage your plugin’s lifecycle.

In essence, self-hosting empowers developers to build, distribute, and update plugins on their own terms, while still providing users with a seamless and familiar update experience.

What is required to self-host plugins on Github and deliver updates?

Now that we understand the basics of self-hosting plugins, let’s discuss what’s needed and how the process works. At a high level, you’ll need:

1. A server (in our case Github):

Provide plugin details: The server hosts metadata about your plugin, including the latest version, download URL, and other required information.

Store distribution files: This includes the .zip file of your plugin, which will be downloaded during the update process.

2. An Update Checker Script in Your Plugin

Fetch data from the server: The script communicates with your server (GitHub in this case) to retrieve the latest plugin details.

Compare versions: It checks whether the version installed on the user’s site is outdated by comparing it with the latest version available on the server.

Forward updates: If a new version is available, the script seamlessly integrates with WordPress’s default update system, making the process transparent for the user.

With these two components working together, you can deliver a smooth and automated update experience for your plugins, all while retaining full control over the distribution process.

So, based on this structure, let’s talk about the GitHub Action and custom PHP script that I developed to simplify everything. These will be the focus of the next sections, and I’m excited to share how you can implement them for your own projects!

The server side on Github

The goal here isn’t to dive deeply into how GitHub Actions that I developed work or cover every technical detail. For that, I’ll create a separate, more technical post. Instead, let’s take a step back to understand the big picture of the action’s workflow and why it’s so essential to our solution.

At its core, the GitHub Action automates the creation of everything needed for the plugin update process. Here’s the high-level flow:

1. Generate JSON Metadata

The action parses your readme.txt and other relevant files to create a JSON file containing metadata about your plugin, such as version, download URL, description and much more. These metadata are essential for the PHP script on plugin side to query the server and make the checks to verify if is updated.

The key detail here is that the download URL is automatically generated to point directly to the .zip file in the release created by the action. This means WordPress and your plugin will fetch updates directly from GitHub, ensuring a seamless and efficient update process.

2. Prepare the Distribution Package

The action compiles your plugin files into a .zip package, ready for distribution. During this process, specific rules can be defined to exclude unnecessary folders or files—such as development directories, test cases, or build artifacts—that shouldn’t be included in the final plugin package. This ensures a clean and optimized distribution file, reducing its size and avoiding unnecessary files being downloaded by users.

3. Release Creation

Once the metadata and distribution package are prepared, the action automates the creation of a new GitHub Release. This release serves as the hosting point for the .zip file. The release is tagged with the corresponding plugin version, ensuring WordPress and the PHP script can correctly fetch the latest version. This streamlined process makes the release instantly accessible, ensuring smooth updates for your users.

This streamlined process ensures that every time you create a new tag/version of your plugin, all required files and metadata are automatically prepared and hosted, ready to deliver updates to your users.

If you’d like to dive into the complete implementation, check the GitHub repository. The README provides detailed examples and instructions to guide you through the implementation process: https://github.com/eduardovillao/wp-self-host-updater-generator.

The plugin side – update checker file

As with the previous section, I’ll create a dedicated post to dive deeper into the technical aspects of this PHP file. For now, let’s focus on understanding the overall flow and what this script does to ensure plugin updates work seamlessly.

The PHP script serves as the “bridge” between the plugin installed on the WordPress site and the server-side metadata hosted on GitHub. Here’s a high-level view of how it operates:

1. Add a Simple PHP File to Manage Updates

The update checker script is integrated directly into your plugin. It listens for WordPress’s native update events and hooks into filters like plugins_api and site_transient_update_plugins to manage and provide update information dynamically.

2. Request JSON Data from the GitHub Repository

The script queries the GitHub-hosted JSON metadata file for the latest information about your plugin, including the current version, description, download URL, and other important details. This step ensures the site always has access to accurate, up-to-date plugin information.

3. Compare Current Version vs. Latest Version

Once the JSON data is retrieved, the script compares the currently installed version of the plugin with the version available in the metadata. If the versions match, no action is taken. If a newer version exists, the script forwards the update information to WordPress’s built-in update system.

4. Follow the Default WordPress Flow to Upgrade

If a new version is available, WordPress takes over using its default upgrade mechanism. This ensures a seamless and familiar experience for end users, who can update the plugin just like they would with any other WordPress plugin.

If you’d like to find the complete code along with examples of how to implement check here the repository’s README: https://github.com/eduardovillao/wp-self-host-updater-checker

This simple yet powerful script is what makes self-hosted updates possible. For those who want to dig deeper, the accompanying code and the flowchart above illustrate the inner workings in greater detail. Stay tuned for a more technical post that will break down this script line by line!

And that’s it! 🎉


If you have any questions, need help with implementation, or have tested this solution and want to share feedback, feel free to drop a comment below. I’d love to hear from you and have a conversation about your experience. Let’s collaborate and make this solution even better together! 🚀


FAQ

1. Will this works with mu-plugins?

Partially! The “server” side on GitHub is fully capable of managing MU-Plugins as well. However, since MU-Plugins don’t follow the same update flow as regular WordPress plugins, the PHP script will require some adjustments to handle them. I’m already working on these changes and will share the solution for MU-Plugins soon.

2. Will this works with Themes?

Not yet! Some modifications are needed to support themes. For now, this solution works exclusively with plugins. But don’t worry—I’m already working on it, and I’ll share updates on theme support soon.

3. Can I validate the user license before delivering updates?

This flow is designed for “free” plugins, so license validation isn’t currently supported. However, I’m exploring ways to incorporate this feature, and I’ll likely share updates about it in the near future.

4. Will this work with private repositories?

Almost! The action don’t need any change and is working now, but the php script need some changes because to use private repositories, a token is required to authenticate requests for the JSON data. I’ll share more details on how to implement this soon.

Want the latest updates?

Get first-hand access to our plugins updates and news.

Wordpress Developer

Eduardo Villão

Brazilian Full-Stack Developer with more than 10 years of experience in web development, with a solid background (more than 9 years) in WordPress development, data-driven decision-making, and a strong focus on measurable results.

2 Responses

  1. Nice writeup!
    Very interested in this working with private repositories.
    Do you already know when you will have an update for this?

    1. Hey TJ! Thanks for your comment.
      Works to private repositories is almost done! I’m just making some final adjustments and related doc.
      Probably in the next few days will be ready to use and I will share here in a new post.

Leave a Reply

Your email address will not be published. Required fields are marked *