Why Self-Hosting Your Git Repository Makes Sense
GitHub is convenient until it isn’t. Rate limits, storage restrictions, mandatory account creation for collaborators, and the lingering question of who actually controls your code are all friction points that eventually push serious developers toward self-hosting. Forgejo – a community-driven fork of Gitea – gives you a full Git hosting platform that runs on your own hardware, answers only to you, and costs nothing beyond the server it sits on.
Forgejo supports repositories, issues, pull requests, CI/CD through Forgejo Actions, SSH and HTTPS cloning, webhooks, user management, and organization-level permissions. The interface is clean and deliberately familiar to anyone coming from GitHub. Setup takes under an hour on a modest VPS or a Raspberry Pi sitting in a home lab. This guide walks through a production-ready Docker Compose installation with a PostgreSQL database and optional HTTPS via a reverse proxy.

Prerequisites and Server Requirements
You need a Linux server with Docker and Docker Compose installed. A 1GB RAM machine will run Forgejo without complaint for small teams. For anything beyond a dozen active users with large repositories, 2GB is a safer baseline. A domain name pointed at your server’s IP is strongly recommended if you plan to expose the instance to the internet – you’ll want HTTPS for SSH key management and webhook security to work correctly. If you’re running this locally only, a local IP address works fine for personal use.
Open ports 3000 (Forgejo’s web interface) and 2222 (SSH, remapped to avoid conflict with the host’s own SSH daemon) on your firewall before starting. If you’re using a cloud provider, adjust your security group or firewall rules accordingly. Create a directory to hold your Compose file and persistent data volumes before writing a single line of configuration.
Writing the Docker Compose File
Create a working directory and open a new docker-compose.yml file. The stack requires two services: a PostgreSQL container for the database and the Forgejo container itself. Start with the database block:
- Image: postgres:16
- Environment variables: POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB set to values of your choice
- A named volume mapped to /var/lib/postgresql/data for persistence
- Restart policy: always
Below the database service, define the Forgejo service using the image codeberg.org/forgejo/forgejo:latest. Set the environment variable USER_UID to 1000 and USER_GID to 1000 to match standard Linux user permissions. Map port 3000:3000 for the web interface and 2222:22 for SSH. Add a named volume pointing to /data inside the container – this is where repositories, configuration, and all user data live. Use depends_on to tell Compose to start the database first.
The full environment block for the Forgejo service should also include database connection details. Forgejo reads these during initial setup and can pre-fill the installer form. Set FORGEJO__database__DB_TYPE to postgres, FORGEJO__database__HOST to the name of your PostgreSQL service followed by :5432, and the user, password, and database name to match what you defined in the PostgreSQL service. This naming convention – double underscores as section separators – is Forgejo’s environment-based configuration syntax and it applies to every setting in the app.ini file.
Once the file is written, run docker compose up -d from the same directory. Docker will pull both images, create the volumes, and start the containers. Give it thirty seconds, then open your browser and navigate to http://your-server-ip:3000. The Forgejo installation wizard will load.

Running the Installation Wizard
The installer presents a single long form. Most fields will be pre-filled if you set the environment variables correctly. Verify the database connection section matches your PostgreSQL credentials, then scroll to the general settings. Set the site title, the base URL – using your actual domain if you have one – and the administrator username, email, and password. This is the only time you can create the admin account through the UI; keep the credentials somewhere safe.
Click install. Forgejo writes its configuration to /data/gitea/conf/app.ini inside the container volume and restarts its internal services. The redirect to the dashboard usually takes five to ten seconds. Log in with the admin credentials you just set and you’ll land on a fully functional Git hosting dashboard.
Configuring SSH, HTTPS, and Ongoing Settings
SSH cloning works out of the box on port 2222. Users add their SSH keys under Settings – SSH Keys in the Forgejo interface, exactly as they would on GitHub. When cloning, they specify the port explicitly: git clone ssh://git@your-domain:2222/username/repo.git. You can document this in a pinned announcement on the instance to save support questions.
For HTTPS, putting Nginx or Caddy in front of Forgejo as a reverse proxy is the standard approach. Caddy handles TLS certificate provisioning automatically via Let’s Encrypt with minimal configuration – point it at localhost:3000 and set your domain, and it manages renewal without cron jobs or certbot scripts. If you already run a reverse proxy for other services – for instance, if you’re using a setup similar to Portainer to manage your Docker containers visually – Forgejo drops into that existing infrastructure without additional complexity.
Post-install configuration happens in two places: the app.ini file at /data/gitea/conf/app.ini inside the volume, and the Site Administration panel in the UI. The admin panel covers user registration settings, email (SMTP), storage backends, and webhook allow lists. The app.ini gives you lower-level control over rate limiting, repository size caps, attachment limits, and federation settings. After editing app.ini directly, restart the container with docker compose restart forgejo for changes to take effect. Federation support – allowing Forgejo instances to interact through ActivityPub – is still maturing, but the groundwork is already present in recent releases.
Frequently Asked Questions
Is Forgejo compatible with GitHub’s Git workflow?
Yes. Forgejo supports standard Git over SSH and HTTPS, pull requests, issues, and webhooks, so existing Git workflows transfer without changes.
Can I migrate repositories from GitHub to Forgejo?
Forgejo includes a built-in migration tool that imports repositories, issues, and pull requests directly from GitHub, GitLab, and other sources.





