> ## Documentation Index
> Fetch the complete documentation index at: https://help.freakhosting.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Self-Host a Git Server with Forgejo and Docker

> Self-host a Git server with Forgejo and Docker: run codeberg.org/forgejo/forgejo:17 with PostgreSQL, add HTTPS with Nginx and clone over SSH on port 222.

To self-host a Git server with Forgejo, run the `codeberg.org/forgejo/forgejo:17` image and a `postgres:14` database with Docker Compose. Publish the web interface on `127.0.0.1:3000` behind Nginx with HTTPS, and Git over SSH on port `222`. Open `https://git.example.com`, complete the initial configuration and create the administrator account.

| Difficulty | Time | Works on | Needs |
| - | - | - | - |
| Intermediate | 30 minutes | Ubuntu 22.04 / 24.04, Debian 12 / 13, AlmaLinux / Rocky 9 / 10 | [Docker](https://help.freakhosting.com/portals/other/how-to-install-docker.md) 20.10.6 or newer, a domain, ports 80, 443 and 222 |

## What is Forgejo?

Forgejo is a free, self-hosted Git service, similar to GitHub or GitLab: repositories, issues, pull requests, packages and CI (Forgejo Actions) in one web app. It started as a fork of Gitea and is developed under the Codeberg umbrella.

## Before you start

* [Install Docker](https://help.freakhosting.com/portals/other/how-to-install-docker.md). Forgejo's upgrade guide asks for Docker 20.10.6 or newer.
* Point `git.example.com` at your server. See [point a domain to your server](https://help.freakhosting.com/portals/other/how-to-point-a-domain-to-your-server.md).
* [Install Nginx](https://help.freakhosting.com/portals/other/how-to-install-nginx.md) for HTTPS. The commands use `sudo`; leave it out if you are `root`.
* Your server's own SSH keeps port 22. Forgejo's SSH listens on port 222 so the two don't clash.

## How to install Forgejo with Docker Compose

**1. Create a folder and a database password**

```bash theme={null}
mkdir -p ~/forgejo && cd ~/forgejo
echo "DB_PASSWORD=$(openssl rand -hex 24)" > .env
chmod 600 .env
```

**2. Create compose.yaml**

This is the PostgreSQL example from the [Forgejo Docker guide](https://forgejo.org/docs/latest/admin/installation/docker/), with the password moved to `.env`, the web port bound to `127.0.0.1` and the SSH port shown in clone URLs set to 222:

```yaml theme={null}
networks:
  forgejo:
    external: false

services:
  server:
    image: codeberg.org/forgejo/forgejo:17
    container_name: forgejo
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - FORGEJO__database__DB_TYPE=postgres
      - FORGEJO__database__HOST=db:5432
      - FORGEJO__database__NAME=forgejo
      - FORGEJO__database__USER=forgejo
      - FORGEJO__database__PASSWD=${DB_PASSWORD}
      - FORGEJO__server__SSH_PORT=222
    restart: always
    networks:
      - forgejo
    volumes:
      - ./forgejo:/data
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "127.0.0.1:3000:3000"
      - "222:22"
    depends_on:
      - db

  db:
    image: postgres:14
    restart: always
    environment:
      - POSTGRES_USER=forgejo
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=forgejo
    networks:
      - forgejo
    volumes:
      - ./postgres:/var/lib/postgresql/data
```

`FORGEJO__section__KEY` variables write settings into Forgejo's `app.ini`. The `:17` tag follows the Forgejo 17 series; moving to the next major version is a deliberate tag change.

**3. Start it**

```bash theme={null}
sudo docker compose up -d
```

If `codeberg.org` is unreachable, the Forgejo docs say you can use `data.forgejo.org/forgejo/forgejo:17` instead.

## How to serve Forgejo over HTTPS with Nginx

**1. Create the Nginx site**

Create `/etc/nginx/sites-available/git.example.com` (Ubuntu / Debian) or `/etc/nginx/conf.d/git.example.com.conf` (AlmaLinux / Rocky):

```nginx theme={null}
server {
    listen 80;
    listen [::]:80;
    server_name git.example.com;

    client_max_body_size 512M;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}
```

`client_max_body_size` allows large pushes over HTTPS; raise it if you push bigger repositories.

**2. Enable, test and reload**

```bash theme={null}
sudo ln -s /etc/nginx/sites-available/git.example.com /etc/nginx/sites-enabled/   # Ubuntu / Debian only
sudo nginx -t
sudo systemctl reload nginx
```

On AlmaLinux / Rocky, also run `sudo setsebool -P httpd_can_network_connect 1`.

**3. Get a certificate**

```bash theme={null}
sudo certbot --nginx -d git.example.com
```

## How to complete the initial configuration

**1. Open the setup page**

Open `https://git.example.com`. Forgejo shows its initial configuration page. The database settings are already filled in from `compose.yaml`.

**2. Set the domain and URL**

Set **Server Domain** to `git.example.com` and **Forgejo Base URL** to `https://git.example.com/`.

**3. Create the administrator account**

In the optional administrator account section, enter a username, email and strong password, then click the install button at the bottom of the page. The Forgejo docs recommend creating the administrator here, especially if you will disable self-registration.

**4. Decide who can register**

For a private server, disable self-registration. Add this line to the `environment` list of the `server` service and run `sudo docker compose up -d`:

```yaml theme={null}
      - FORGEJO__service__DISABLE_REGISTRATION=true
```

Only administrators can then create accounts.

> [!WARNING]
>
> Complete the initial configuration as soon as the site is reachable. Until you do, whoever opens the page first can configure the server.

## How to check it worked

Log in, add your public SSH key in your user settings and create a test repository called `project`. Then clone it from your computer:

```bash theme={null}
git clone ssh://git@git.example.com:222/alex/project.git
```

The clone succeeds without asking for a password. If port 222 times out, allow TCP 222 in any firewall in front of the server; see [check if a port is open from outside](https://help.freakhosting.com/portals/other/how-to-check-if-a-port-is-open-from-outside.md).

## How to back up Forgejo

Forgejo recommends stopping it during a backup so files and database match. Back up the database with `pg_dump` and the `./forgejo` folder, which holds repositories and `app.ini` (including the secret keys).

```bash theme={null}
cd ~/forgejo
sudo docker compose stop server
sudo docker compose exec -T db pg_dump -U forgejo forgejo > forgejo-db.sql
sudo tar -czf forgejo-data.tar.gz forgejo
sudo docker compose start server
```

See the [Forgejo backup guide](https://forgejo.org/docs/latest/admin/setup/backup/) and [back up Docker volumes](https://help.freakhosting.com/portals/other/how-to-back-up-docker-volumes.md).

## How to update Forgejo

Minor and patch releases arrive when you pull the same major tag:

```bash theme={null}
cd ~/forgejo
sudo docker compose pull
sudo docker compose up -d
```

For a new major version (for example 17 to 18), back up first, read the release notes' upgrade section, then change the tag in `compose.yaml` and run the same two commands. The [upgrade guide](https://forgejo.org/docs/latest/admin/upgrade/) recommends going straight to the latest release and checking the result with `forgejo doctor check --all`.

## Frequently asked questions

### Forgejo or Gitea: which should I use?

Both run the same way in Docker. Forgejo is community-governed under Codeberg. If you are moving from Gitea, the Forgejo docs say to upgrade to Forgejo 10.0.x first, then to later versions.

### Can I use SQLite instead of PostgreSQL?

Yes. If you leave out the database settings, Forgejo uses SQLite, which is fine for a few users. PostgreSQL suits larger or busier servers.

### Why do clone URLs show port 22?

`SSH_PORT` sets the port shown in clone URLs. Check that `FORGEJO__server__SSH_PORT=222` is in `compose.yaml` and recreate the container.

### Can I run CI pipelines?

Yes, with Forgejo Actions. It needs a separate Forgejo Runner; see the [Forgejo Actions docs](https://forgejo.org/docs/latest/admin/actions/).

## Related guides

> [card] [VPS and dedicated server guides](https://help.freakhosting.com/portals/other/vps-and-dedicated-server-guides.md)
>
> Every guide in this section.

> [card] [Create and use SSH keys](https://help.freakhosting.com/portals/other/how-to-create-and-use-ssh-keys.md)
>
> Make the key you add to Forgejo.

> [card] [Nginx reverse proxy](https://help.freakhosting.com/portals/other/how-to-set-up-nginx-as-a-reverse-proxy.md)
>
> How proxying to a local port works.

> [card] [Update Docker containers](https://help.freakhosting.com/portals/other/how-to-update-docker-containers.md)
>
> Pull new images safely.

> [card] [Set up a firewall with UFW](https://help.freakhosting.com/portals/other/how-to-set-up-a-firewall-with-ufw.md)
>
> Allow ports 80, 443 and 222.

***

> [!NOTE]
>
> **Checked against the official [Forgejo documentation](https://forgejo.org/docs/latest/admin/installation/docker/)** on 4 November 2026 (image `codeberg.org/forgejo/forgejo:17`); `compose.yaml` validated with `docker compose config` and the Nginx configuration syntax-tested on Ubuntu 24.04 LTS. Settings can change between Forgejo major versions.

> [!NOTE]
>
> ### Need Extra Help?
>
> If you encounter any issues, our support team is ready to assist:
>
> * **Live Chat:** Quick assistance via our website.
> * **Support Ticket:** [Open a Ticket](https://freakhosting.com/clientarea/submitticket.php)
> * **Discord:** [Join our Community](https://discord.gg/freakhosting)
> * **Email:** [support@freakhosting.com](mailto:support@freakhosting.com)

> [!TIP]
>
> ### Save on Your Hosting
>
> Ready to upgrade your hosting? Use code **KB20** at checkout for **20% off** your first order!

***

**Last Updated:** November 2026


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.