[Guide] Forgejo Repository Migration (Existing Databases)

- Posted in Guides by

Forgejo Repository Migration (Existing Databases)

Objective: Merge repositories into a Forgejo instance without overwriting the existing database.

  1. Stop Forgejo on Source sudo systemctl stop forgejo

  2. Archive Repositories tar czf forgejo-repositories.tar.gz /var/lib/forgejo/data/forgejo-repositories

  3. Transfer to New Server scp forgejo-repositories.tar.gz user@new-server:/root/

  4. Extract Safely mkdir -p /root/forgejo-import tar xzf forgejo-repositories.tar.gz -C /root/forgejo-import

  5. Merge into Forgejo Storage rsync -a /root/forgejo-import/var/lib/forgejo/data/forgejo-repositories/ \ /var/lib/forgejo/data/forgejo-repositories/ sudo chown -R git:git /var/lib/forgejo/data/forgejo-repositories

  6. Restart Forgejo sudo systemctl start forgejo

  7. Adopt Unregistered Repositories

Admin → Site Administration → Repositories → Unadopted Repositories
Scan and adopt repositories
Assign owners and confirm

Verifiy

Repositories appear in UI
Branches and commits are intact
Git clone works
Existing repos are unaffected

Note: Only repositories are migrated; database remains intact.

[Blog] Migrating Forgejo Repositories into an existing instance

- Posted in First Timers by

Migrating Forgejo Repositories into an existing instance (without overwriting the database)

This is a Forgejo migration scenario where multiple approaches were attempted, including official documentation, community guides, and requesting help on Mastodon.

In the end, the working solution was a repository-level migration combined with Forgejo’s “Adopt Repositories” feature, without touching or overwriting the existing database.


The goal was to merge repositories from an old Forgejo server into a new one.

However, the situation was more complex than anticipated:

  • Both servers already had active Forgejo installations
  • The new server already contained repositories and users
  • The database on the new server could not be overwritten
  • The old server was only accessible via filesystem (URL was demised in error)

I tried taking this into account: Migrate your Forgejo site - community blog, and going through the forgejo upgrades & cheat-sheets.

While helpful for full-instance migrations, these guides assume:

  • A complete database export is available
  • The target system is being fully replaced
  • There are no existing repositories on the destination instance

This did not match the constraints I was facing.


Moreover, restoring an existing SQLite database dump to another running instance has its own problems:

  • The new server already has an active database
  • Overwriting the database would cause data loss
  • Merging two Forgejo databases is not safely supported

I then tried Various Git-based backup options:

  • git clone --mirror
  • git bundle
  • direct filesystem copying

While these successfully preserved Git history, they did not solve the core issue:

Forgejo does not automatically register repositories that exist on disk.

As a result, repositories did not appear in the web interface after transfer.


While I tried to find help on Mastodon (directly from Forgejo team) and on XMPP, the responses I received either:

  • Referred back to full database migration guides
  • Suggested rebuilding repositories manually
  • Did not account for the “existing instance + filesystem-only source” scenario

I was honestly stuck.


I finally found this approach:

  • Filesystem-level repository transfer
  • Forgejo’s built-in repository adoption feature
  • Preservation of the existing database on the new server

This allowed both systems to be merged safely.


Stop Forgejo on the source server

To ensure consistency, Forgejo was stopped before copying repositories:

```bash id="s1" sudo systemctl stop forgejo


--- Backup repositories from the source server Repositories are stored as bare Git repositories in: ```id="s2" /var/lib/forgejo/data/forgejo-repositories

They were archived using:

```bash id="s3" tar czf forgejo-repositories.tar.gz /var/lib/forgejo/data/forgejo-repositories


This preserves full Git history, branches, and tags. --- Transfer to the new server The archive was copied to the new server: ```bash id="s4" scp forgejo-repositories.tar.gz user@new-server:/root/

Extract into a staging directory (You can copy directly to the prod folder as well)

To avoid disrupting existing repositories on the new instance, the archive was extracted safely:

```bash id="s5" mkdir -p /root/forgejo-import tar xzf forgejo-repositories.tar.gz -C /root/forgejo-import


--- Merge repositories into Forgejo storage The repositories were then merged into the active Forgejo repository directory: ```bash id="s6" rsync -a /root/forgejo-import/var/lib/forgejo/data/forgejo-repositories/ \ /var/lib/forgejo/data/forgejo-repositories/

Correct ownership was applied (I applied to only the updated repo folders and files):

```bash id="s7" sudo chown -R git:git /var/lib/forgejo/data/forgejo-repositories


--- Restart Forgejo Forgejo was restarted: ```bash id="s8" sudo systemctl start forgejo

At this moment, the repositories existed on disk but were not yet visible in the web interface.

This is expected behaviour because Forgejo relies on its database for repository registration.


Using “Unadopted Repositories”

Forgejo provides a built-in mechanism for handling this situation.

In the web interface:

  1. Log in as an administrator
  2. Navigate to Site Administration
  3. Open Repositories
  4. Select Unadopted Repositories
  5. Click the scan icon (magnifying glass)

Forgejo scanned the repository directory and listed all repositories that existed on disk but were not yet registered in the database.


Adopting repositories

Each repository was then:

  • Selected individually
  • Assigned to a user or organisation
  • Adopted into Forgejo

For my instance, I had separate user wise repositories listed for me.

Once adopted, Forgejo automatically:

  • Created the required database entries
  • Linked repository metadata to the filesystem
  • Made the repositories visible in the UI

Verifying the details

  • All repositories appeared in the interface
  • Branches and commit histories were intact
  • Git cloning worked via HTTPS and SSH
  • Existing repositories on the new server remained unaffected

I have written a steps only blog too, since I am sure several people will face this or maybe facing it already.

Upgrade Forgejo

- Posted in Linux/Unix by

Forgejo is the best when it comes to hosting your own stuff over a git. Rest all for me have been dull, and I get the pain for setting up any sort of app/software.

Anyhow, what I love about the binaries is, forgejo for one is the simplest to setup. Here is how I do it:


systemctl stop forgejo.service && wget https://codeberg.org/forgejo/forgejo/releases/download/vX.X.X/forgejo-X.X.X-linux-amd64 && chmod +x forgejo-X.X.X-linux-amd64 && cp forgejo-X.X.X-linux-amd64 /usr/local/bin/forgejo && chmod 755 /usr/local/bin/forgejo && systemctl start forgejo.service && rm forgejo-X.X.X-linux-amd64 && systemctl status forgejo.service

Simply replace the X.X.X with the version you are installing. Example: 11.0.9 or 13.0.4 (latest ones).

So something like:

systemctl stop forgejo.service && wget https://codeberg.org/forgejo/forgejo/releases/download/v13.0.4/forgejo-13.0.4-linux-amd64 && chmod +x forgejo-13.0.4-linux-amd64 && cp forgejo-13.0.4-linux-amd64 /usr/local/bin/forgejo && chmod 755 /usr/local/bin/forgejo && systemctl start forgejo.service && rm forgejo-13.0.4-linux-amd64 && systemctl status forgejo.service

or for the LTS:

systemctl stop forgejo.service && wget https://codeberg.org/forgejo/forgejo/releases/download/v11.0.9/forgejo-11.0.9-linux-amd64 && chmod +x forgejo-11.0.9-linux-amd64 && cp forgejo-11.0.9-linux-amd64 /usr/local/bin/forgejo && chmod 755 /usr/local/bin/forgejo && systemctl start forgejo.service && rm forgejo-11.0.9-linux-amd64 && systemctl status forgejo.service

[Guide]Let's Encrypt SSL/HTTPS Certificate for a unique port with HestiaCP

- Posted in Guides by

Introduction

In this tutorial, I will guide you through the process of setting up a let's encrypt ssl/https certificate (reverse proxy) on a unique port other than 80/443, example port:4545 on the root server for hosting using Hestia Control Panel (See installation URL given under prerequisites below). Hestia Control Panel is a popular open source web server control panel that simplifies the management of your website, email accounts, databases, and other hosting-related tasks. This tutorial is compatible with both VPS and Root Server offerings by netcup.

Assumptions:

  • You already have a sub-domain setup and the requisite service installed at the specified http port (example - http://sd1.domain.tld:4545).
  • You have the sub-domain setup with SSL/HTTPS (443) setup (example - https://sd1.domain.tld)
  • You have bare minimum knowledge of terminal, web servers, vhosts, reverse proxy.

The reading time of this tutorial is about 35 minutes; implementation will take approximately 60-70 minutes.

Background

The objective of Let’s Encrypt and the ACME protocol is to make it possible to set up an HTTPS server and have it automatically obtain browser-trusted certificates without any human intervention. This is accomplished by running an ACME client on a web server. To know more, visit Let's Encrypt. This also forms a part for use in Nginx reverse proxy configuration.

Forgejo is a self-hosted lightweight software forge (simple software project management). Easy to install and low maintenance, it just does the job.

In the world of open-source software, the story of how a project is governed is often as important as the code itself. Forgejo is a powerful testament to this fact. It is a “soft fork” of Gitea, created by a community of users and contributors to ensure that the project’s future remains in the hands of a non-profit, community-driven organization.

Born out of concerns following the creation of a for-profit company to manage Gitea, Forgejo’s mission is to be a truly free and open-source software (FOSS) forge, managed under the stewardship of the Codeberg e.V. non-profit. It is technically very similar to Gitea, but philosophically, it represents a commitment to community ownership and non-commercial governance.

Since Forgejo by default/design runs on port 4545 and many other projects also default to port 4545, I chose a different port (example 4545 here). This helps me keep it running in the background without conflicting with other applications. This was necessary for 2 more reasons:

  • Clean url everytime Example instead having to type or visit https://git.example.com:4545 every time, I will have a cleaner url as https://git.example.com.
  • Issue an HTTPS/SSL/TLS enabled URL and enjoy the higher level of security. Visitors & users of my site would also know they are safe.

Prerequisites

  • A server from netcup with latest Ubuntu 20.04/22.04/LTS; Debian 10/11/12/LTS or later installed (see the below URL) - use minimal mode of installation, also called clean installation. Installation Tutorial or the blog guide here.
  • A registered domain name
  • Access to your server

Step 1: Update your system

Before we begin, it's essential to ensure that your system is up-to-date. Log in to your server via SSH as the root user and run the following command:

For Ubuntu/Debian:

apt update && apt upgrade -y

Step 2: Add the necessary changes to the service (example git)

username@serverip:port

I created a normal subdomain at normal 80/443 ports with LE SSL generated. Then in the git app.ini (/etc/git/app.in) file, added this under [server]

nano /etc/git/app.ini
--------------
[server]
ENABLE_ACME = enable
HTTPS_PORT = 4545 ssl
ROOT_URL = https://git.domain.tld
-------------- **(save changes to the file by typing CTRL+X simultaneously)**
CTRL+X
Y
Enter

Then under nginx.conf ($HESTIADATA\conf\web\git.domain.tld\nginx.conf) I added

nano /$HESTIADATA\conf\web\git.domain.tld\nginx.conf
--------------
 location / {
     client_max_body_size 4096M;
     proxy_pass http://localhost:4545;
     proxy_set_header Connection $http_connection;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Host $host;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-Forwarded-Proto $scheme;
-------------- **(save via)**
CTRL+X
Y
Enter

Then under apache2.conf ($HESTIADATA\conf\web\git.domain.tld\apach2.conf) I added

nano /$HESTIADATA\conf\web\git.domain.tld\apache2.conf
--------------
     ProxyPreserveHost On
     ProxyRequests off
     AllowEncodedSlashes NoDecode
     ProxyPass / http://localhost:4545/ nocanon
-------------- **(save via)**
CTRL+X
Y
Enter

Then under apache2.ssl.conf ($HESTIADATA\conf\web\git.domain.tld\apache2.ssl.conf) I added

nano /$HESTIADATA\conf\web\git.domain.tld\apach2.ssl.conf
--------------
 < VirtualHost git.domain.tld:8443 https >
*****************************
*****************************
    ProxyPreserveHost On
     ProxyRequests off
     AllowEncodedSlashes NoDecode
     ProxyPass / http://localhost:4545/ nocanon
-------------- **(save via)**
CTRL+X
Y
Enter

I also enabled the following to ensure the proxy works:

 a2enmod proxy
 a2enmod proxy_http
 a2enmod proxy_balancer
 a2enmod proxy_wstunnel
 systemctl restart apache2

Then I restarted all services

 systemctl restart apache2
 systemctl restart nginx
 systemctl start git.service

I got the help from these:

APache SSL long record rrror

Let's Encrypt SSL certificate

Gitea reverse proxy - Apache HTTPD

Gitea reverse proxy - general conf

Gitea reverse proxy - NGINX

Someone's personal Forgejo guide

Conclusion

Awesome! You've successfully set up a let's encrypt certificate on a unique port other than the usual 443/8443.