---
title: "The Forgejo update 🚀"
url: "https://ploi.io/news/the-forgejo-update"
published: "2026-10-20"
last_updated: "2026-10-20"
---

# The Forgejo update 🚀

Ploi has worked with GitHub, GitLab and Bitbucket for years. Code on Codeberg or on a Forgejo server you run yourself had to go in as a custom repository, with the deploy key and the webhook set up by hand. Starting today, Forgejo is a source control provider next to the other three, and it works the same way they do.

Linking your Forgejo account
----------------------------

Open your profile, go to **Source control** and click **Link Forgejo account**. Forgejo has no central place where we could register an OAuth app, since every instance is separate. You link it with a personal access token instead. Create one in Forgejo under **Settings › Applications** with the `read:user` and `write:repository` permissions. Ploi needs the write permission to add the quick deploy webhook.

The instance URL starts out as Codeberg. Running your own instance? Fill in its URL instead. Gitea has the same API, so a Gitea server links the same way. You can link more than one account, for example Codeberg next to your company's own server, and a label keeps them apart. Ploi checks the token against the instance when you save, so a typo shows up right away.

![](https://ploi.io/storage/0LgJgKpKax1C3XXVSSFY3vnSWjNsSnZsboxdEd7C.png)

What you can do with it
-----------------------

- Install a Forgejo repository on a site, an application or a WordPress site. You pick from a list of your repositories and their branches, including repositories of organisations you're a member of.
- Deploy, zero downtime deployments included. Ploi pulls with the token of the linked account.
- Turn on quick deploy. Ploi adds a push webhook to the repository and deploys when you push to the branch.
- See the latest commits from Forgejo in the panel.
- Install Forgejo repositories through the API and the MCP server.

This one came from the [roadmap](https://roadmap.ploi.io/projects/3-panel-requests/items/1392-codebergforgejo-source-control-provider). Thanks to everyone who asked for it.

RunCloud joins the server import
--------------------------------

Two days after the last update, RunCloud joined Laravel Forge and ServerPilot in the server import. It works like the ServerPilot import. RunCloud runs its own NGINX, Apache and PHP builds under `/RunCloud/Packages`, so Ploi installs its own stack next to it, moves each app from `/home/<user>/webapps` into Ploi's layout and then switches serving over. Your apps are offline for that switch, about a minute.

The import handles RunCloud's NGINX and NGINX + Apache stacks. It refuses OpenLiteSpeed servers. The RunCloud import is in beta, so take a snapshot at your provider before your first one. Read [how to migrate from RunCloud](https://ploi.io/documentation/server/how-do-i-migrate-from-runcloud) for the full walkthrough.

Bitbucket moves SSH to ssh.bitbucket.org
----------------------------------------

On 12 November 2026, Bitbucket Cloud stops accepting SSH connections on `bitbucket.org`. Git over SSH moves to `ssh.bitbucket.org`, and `bitbucket.org` only serves HTTPS from then on. The host keys stay the same, but a server checks them per hostname. A server that only knows `bitbucket.org` refuses `ssh.bitbucket.org` with "Host key verification failed".

Ploi now adds `ssh.bitbucket.org` to `known_hosts` on new servers and for new system users, and we're adding it to your existing servers too. If you linked Bitbucket in your profile, there's nothing for you to do. Ploi clones and deploys those repositories over HTTPS with a token, and this change doesn't touch that.

Do you deploy a Bitbucket repository as a custom repository over SSH, or pull private Composer or npm packages from Bitbucket over SSH? Then change `git@bitbucket.org:` to `git@ssh.bitbucket.org:` before 12 November. For a custom repository you change the URL on the site's **Repository** page. For packages, update the URLs in `composer.json` or `package.json` and refresh the lock file.

Coming soon: site commands
--------------------------

Every site is about to get a **Commands** tab. You type a command, Ploi runs it in the site's directory as the site's system user, and you see the output while it runs. `php` and `composer` use the site's own PHP version, so `php artisan migrate` or `composer install` runs on the version the site is served with. No SSH session needed.

![](https://ploi.io/storage/oq8oHY43EQO9xHZuB6I8LSeMTYrskL1qghw78pzQ.png)

The arrow up key brings back earlier commands. The history keeps the last 50 runs per site with their output, and you can search it and run a command again from there. A stop button ends a command along with everything it started. Commands can't ask for input and stop after 10 minutes, so daemons are still the place for anything that runs longer. On a team, the new **Run commands** permission decides who gets to use it.

We're testing it now and will release it soon. It started as a request on the roadmap, like Forgejo.

Changelog
---------

Here's everything else that shipped since the last update.

### Added

- Forgejo as a source control provider, for Codeberg, self-hosted Forgejo and Gitea.
- RunCloud server import, in beta.
- Browser push as a notification channel. Notifications show up on your computer or phone, also when the panel isn't open. See [how notifications work](https://ploi.io/documentation/notifications/how-do-notifications-work).
- Restore a database backup into a new database instead of over the current one. You pick a name and optionally a user, and the current database stays as it is.
- Remove a server from Ploi but keep it at your provider. Tick the option in the delete confirmation and the server keeps running there.
- Switch a site's PHP version from the site sidebar. Click the PHP version and pick one of the versions installed on the server.
- Download Google Drive database backups from the backup files list. Team members can download them too, without access to that Drive.
- `ploi.si` as a testing domain.
- API endpoints to attach and detach notification channels on database and file backups, and `GET /api/user/notification-channels` to look up the channel IDs.
- A `site_id` field when you create a cronjob through the API, so the cronjob shows up under that site.
- An [RSS feed](https://ploi.io/news.rss) for these news posts, and **Copy for LLMs** and **View as Markdown** buttons on news and documentation articles.

### Improved

- New servers and system users trust `ssh.bitbucket.org`, where Bitbucket moves Git over SSH on 12 November.

- The Laravel scheduler cronjob runs with the site's PHP version instead of the server's default `php`. When you change a site's PHP version, cronjobs pinned to the old version move along, the WordPress cron included.
- A failed SFTP file backup now tells you which system user and key the server tried and where to add it. File backups connect as the site's system user, which has a different key than the one database backups use.
- Site clones check up front whether the source server can reach the target over SSH, instead of failing halfway.
- Certbot installs retry longer and route around the Snap Store CDN when it stalls, which broke server builds on 22 September.
- New servers check the signature of Oracle's MySQL repository. Before, they skipped that check.
- WP-CLI commands get 60 seconds. A large search and replace that runs longer now says so instead of returning an empty result.
- Creating a custom server through the API accepts the same input as the panel, such as a hostname, or a second server on the same IP with a different SSH port.
- Stacked modals no longer blur the modal underneath, which made the panel slow on some computers.

### Fixed

- After Ubuntu's curl security update of 12 October, deployments and clones of private repositories failed with "could not read Username". Ploi now also sends the token as a header, which the update leaves alone. The next deployment fixes the remote on existing sites, so there is nothing you need to do.
- Restoring a MySQL backup on a MariaDB server failed with "Access denied for user 'root'@'localhost'". Ploi also reported a failed restore as completed. It now marks the restore as failed and points you to the server log.
- File backups of busy sites failed when a file changed while tar read it, such as a log the site was writing to.
- Google Drive backups failed for users who log in to Ploi with Google, even when Drive was linked through another Google account.
- S3 backups no longer put your access key and secret on the command line, where other users on the server could read them while a backup ran.
- Backups to Scaleway larger than about 5 GB failed, because Scaleway accepts at most 1,000 upload parts.
- Team members got an error when they saved a site's file backup. Ploi now checks local backup paths as the site's system user, so you hear about a folder only root can write to when you create the backup.
- Zero downtime deployments with OPcache enabled reloaded PHP-FPM an extra time, which cut off requests in flight and caused 502 errors.
- Small servers without swap, such as EC2 instances, could run out of memory while installing MySQL. Ploi now creates the swap file before it installs anything else.
- New Ubuntu 26.04 servers on Linode failed in the base packages step because of a GRUB setting in Linode's image.
- Creating a server on one of Vultr's new VX1 plans works, and those plans have their own groups in the plan picker.
- DigitalOcean server creation sometimes failed with "invalid key identifiers". Ploi now retries a few seconds later.
- Providers you added after attaching providers to your personal team didn't show up when you created a server. Personal teams no longer limit the providers you see. Shared teams still do.
- Team members with a permission on one server didn't see its menu item, PHP for example, while the page itself did open.
- A duplicate FastCGI timeout setting could leave NGINX stopped after a PHP upgrade. Ploi now only reloads NGINX after `nginx -t` passes.
- Sites with a project directory, such as Deployer's `/current`, got tenant vhosts and certificates that pointed at the wrong path.
- Test domains on IPv6-only servers get an AAAA record now. Enabling one used to fail without an error.
- The file explorer removed the final newline, leading whitespace and a BOM from every file you saved. It now saves files byte for byte, and the refresh button reloads the folder instead of showing a cached listing.
- Disabling the WordPress cron no longer mixes line endings in a `wp-config.php` that uses Windows line endings.
- WordPress repository deploys ran variables like `{RELOAD_PHP_FPM}` as literal text.
- New WordPress installs get 64 character keys and salts, like the ones WordPress generates itself.
- Switching a site from GitHub or Bitbucket to a custom repository left the server on the old remote.
- You can now disable two-factor authentication with a backup code.
- Passkeys you added with a hardware security key such as a YubiKey ended up in Ploi but not on the key, so logging in with them failed.
- Output that isn't valid UTF-8, common in NGINX and application logs, no longer breaks the server log list, the API or the log viewers.
- Surge, the projects API and copying custom commands or marketplace deploy scripts skipped sites that a team member created.
- Bulk assigning notification channels listed no site file backups.
- Ploi now escapes the values you pass to Docker Compose and the log viewers before they reach the server.
- Database backups created through the API now save and return the excluded tables.
- Ploi sometimes marked valid VAT numbers as invalid when the EU's VIES service was busy.
- The ServerPilot import installs every PHP version your apps use, PHP 5.6 to 7.3 included. The Forge import no longer merges two Supervisor daemons into one.

That's it for this round. Does Forgejo or Gitea trip over something in your setup? Contact support and we'll look into it. Missing a feature? Drop it on the [roadmap](https://roadmap.ploi.io).