Forgejo es una plataforma Git autoalojada y ligera, desarrollada por la comunidad bajo el paraguas de Codeberg e.V., con repositorios, incidencias, pull requests, registro de paquetes y CI/CD integrado con Forgejo Actions. En este tutorial desplegarás Forgejo en Ubuntu 24.04 con Docker Compose y PostgreSQL, lo publicarás con Nginx y un certificado de Let's Encrypt, habilitarás el acceso Git por SSH y registrarás un runner para ejecutar tu primer pipeline.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 2 GB de RAM (4 GB si el runner de CI va en el mismo servidor).
  • Un usuario no root con privilegios sudo.
  • Docker Engine y el plugin de Docker Compose instalados desde el repositorio oficial de Docker.
  • Un dominio con un registro DNS A que apunte a la IP del servidor. En la guía se usa git.your_domain.
  • UFW activo con SSH permitido.

Paso 1: Preparar el directorio y las contraseñas

Guarda todo el despliegue en /opt/forgejo:

sudo mkdir -p /opt/forgejo
sudo chown $USER: /opt/forgejo
cd /opt/forgejo

Genera una contraseña aleatoria para la base de datos y guárdala en un fichero .env, que Docker Compose lee automáticamente:

echo "POSTGRES_PASSWORD=$(openssl rand -hex 24)" > .env
chmod 600 .env

Paso 2: Crear el fichero de Docker Compose

Forgejo publica sus imágenes en el registro de Codeberg. Consulta la versión mayor estable actual en https://forgejo.org/releases/ y úsala en la etiqueta de la imagen; en el ejemplo es 15. Fijar la versión mayor evita saltos de versión inesperados al actualizar.

nano /opt/forgejo/compose.yaml
services:
  forgejo:
    image: codeberg.org/forgejo/forgejo:15
    container_name: forgejo
    restart: unless-stopped
    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=${POSTGRES_PASSWORD}
      - FORGEJO__server__DOMAIN=git.your_domain
      - FORGEJO__server__ROOT_URL=https://git.your_domain/
      - FORGEJO__server__SSH_DOMAIN=git.your_domain
      - FORGEJO__server__SSH_PORT=2222
      - FORGEJO__actions__ENABLED=true
    volumes:
      - ./data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "127.0.0.1:3000:3000"
      - "2222:22"
    depends_on:
      - db

  db:
    image: postgres:17
    container_name: forgejo-db
    restart: unless-stopped
    environment:
      - POSTGRES_USER=forgejo
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=forgejo
    volumes:
      - ./postgres:/var/lib/postgresql/data

Puntos clave de esta configuración:

  • Las variables FORGEJO__sección__CLAVE escriben directamente en el app.ini de Forgejo, así no tienes que editarlo a mano.
  • La interfaz web solo se publica en 127.0.0.1:3000: Nginx será el único punto de entrada HTTP. Esto importa porque los puertos que publica Docker no pasan por UFW.
  • El SSH del contenedor se expone en el puerto 2222 del servidor para no chocar con el SSH del sistema. SSH_PORT=2222 hace que las URL de clonado muestren ese puerto.
  • USER_UID y USER_GID fijan el usuario git del contenedor; 1000 suele ser el primer usuario de Ubuntu, que es el dueño de /opt/forgejo. Compruébalo con id -u.

Arranca los contenedores:

docker compose up -d
docker compose ps
NAME         IMAGE                             STATUS         PORTS
forgejo      codeberg.org/forgejo/forgejo:15   Up 8 seconds   127.0.0.1:3000->3000/tcp, 0.0.0.0:2222->22/tcp
forgejo-db   postgres:17                       Up 9 seconds   5432/tcp

Comprueba que Forgejo responde:

curl -sI http://127.0.0.1:3000 | head -n 1
HTTP/1.1 200 OK

Paso 3: Publicar Forgejo con Nginx y HTTPS

Instala Nginx y Certbot:

sudo apt update
sudo apt install nginx certbot python3-certbot-nginx

Abre HTTP, HTTPS y el puerto SSH de Forgejo en el cortafuegos:

sudo ufw allow 'Nginx Full'
sudo ufw allow 2222/tcp

Crea el bloque de servidor:

sudo nano /etc/nginx/sites-available/forgejo
server {
    listen 80;
    listen [::]:80;
    server_name git.your_domain;

    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 permite pushes por HTTPS y subidas de paquetes grandes; el valor por defecto de Nginx (1 MB) haría fallar casi cualquier push.

Activa el sitio y solicita el certificado. Certbot añadirá la configuración TLS y la redirección a HTTPS:

sudo ln -s /etc/nginx/sites-available/forgejo /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d git.your_domain
Successfully deployed certificate for git.your_domain to /etc/nginx/sites-enabled/forgejo
Congratulations! You have successfully enabled HTTPS on https://git.your_domain

Paso 4: Completar la instalación web

Abre https://git.your_domain. Forgejo muestra la página de configuración inicial con la base de datos y las URL ya rellenadas a partir de las variables de entorno. Revisa que URL base de Forgejo sea https://git.your_domain/.

Despliega la sección Configuración de la cuenta de administrador, crea tu usuario administrador con una contraseña segura y pulsa Instalar Forgejo. Tras unos segundos entrarás en el panel con esa cuenta.

Si la instancia es privada, desactiva el registro público. Añade esta línea a la lista environment del servicio forgejo en compose.yaml:

      - FORGEJO__service__DISABLE_REGISTRATION=true

Aplica el cambio recreando el contenedor:

cd /opt/forgejo
docker compose up -d

El enlace Registrarse desaparecerá de la cabecera. Los nuevos usuarios los crearás tú desde Administración del sitio > Cuentas de usuario.

Paso 5: Clonar por SSH

En tu equipo local, añade tu clave pública en Configuración > Claves SSH / GPG > Añadir clave. Crea un repositorio de prueba llamado prueba y comprueba la conexión SSH. Sustituye your_user por tu usuario de Forgejo:

ssh -T -p 2222 [email protected]_domain
Hi there, your_user! You've successfully authenticated with the key named mi-portatil, but Forgejo does not provide shell access.

Clona el repositorio con la URL que muestra la página del repositorio:

git clone ssh://[email protected]_domain:2222/your_user/prueba.git

Paso 6: Registrar un runner de Forgejo Actions

Forgejo Actions ejecuta workflows con sintaxis compatible con GitHub Actions, pero necesita un runner aparte. Lo instalarás en el propio servidor y ejecutará cada trabajo en un contenedor Docker.

Consulta la última versión en https://code.forgejo.org/forgejo/runner/releases, descarga el binario e instálalo:

RUNNER_VERSION=11.1.2
curl -fL -o forgejo-runner "https://code.forgejo.org/forgejo/runner/releases/download/v${RUNNER_VERSION}/forgejo-runner-${RUNNER_VERSION}-linux-amd64"
sudo install -m 0755 forgejo-runner /usr/local/bin/forgejo-runner
forgejo-runner --version

Crea un usuario de sistema para el runner, con acceso a Docker, y su configuración por defecto:

sudo useradd --system --create-home --home-dir /var/lib/forgejo-runner --shell /usr/sbin/nologin forgejo-runner
sudo usermod -aG docker forgejo-runner
sudo mkdir -p /etc/forgejo-runner
forgejo-runner generate-config | sudo tee /etc/forgejo-runner/config.yml > /dev/null

En Forgejo, ve a Administración del sitio > Actions > Runners > Crear nuevo runner y copia el token. Registra el runner como su usuario y desde su directorio, donde se guardará el fichero .runner con sus credenciales:

sudo -u forgejo-runner sh -c 'cd /var/lib/forgejo-runner && forgejo-runner register \
  --no-interactive \
  --config /etc/forgejo-runner/config.yml \
  --instance https://git.your_domain \
  --token your_registration_token \
  --name runner-01 \
  --labels docker:docker://node:22-bookworm'

La etiqueta docker:docker://node:22-bookworm hace que los trabajos con runs-on: docker se ejecuten en un contenedor Debian con Node.js, necesario para acciones como actions/checkout.

Crea el servicio de systemd:

sudo nano /etc/systemd/system/forgejo-runner.service
[Unit]
Description=Forgejo Actions runner
After=docker.service
Requires=docker.service

[Service]
ExecStart=/usr/local/bin/forgejo-runner daemon --config /etc/forgejo-runner/config.yml
WorkingDirectory=/var/lib/forgejo-runner
User=forgejo-runner
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now forgejo-runner
sudo journalctl -u forgejo-runner -n 10 --no-pager

En Administración del sitio > Actions > Runners, runner-01 debe aparecer como Idle.

Paso 7: Ejecutar el primer workflow

En el repositorio prueba, activa Actions en Configuración > Unidades > Actions si no aparece la pestaña. Después crea el fichero del workflow en tu copia local:

mkdir -p .forgejo/workflows
nano .forgejo/workflows/ci.yml
on: [push, pull_request]

jobs:
  prueba:
    runs-on: docker
    steps:
      - uses: actions/checkout@v4
      - name: Información del entorno
        run: |
          node --version
          ls -la

Súbelo:

git add .forgejo/workflows/ci.yml
git commit -m "Añadir workflow de CI"
git push

Abre la pestaña Actions del repositorio. La ejecución aparecerá en cola y, en unos segundos, en verde, con la versión de Node.js y el listado de ficheros en el registro del paso.

Paso 8: Actualizar Forgejo

Las actualizaciones dentro de la misma versión mayor solo requieren descargar la imagen y recrear el contenedor:

cd /opt/forgejo
docker compose pull
docker compose up -d

Antes de cambiar de versión mayor (por ejemplo de 15 a 16), lee las notas de la versión y haz una copia de seguridad. Forgejo incluye forgejo dump, que se ejecuta dentro del contenedor como el usuario git:

docker exec -u git -w /tmp forgejo forgejo dump --file /tmp/forgejo-dump.zip
docker cp forgejo:/tmp/forgejo-dump.zip ./forgejo-dump-$(date +%F).zip

Solución de problemas

Nginx devuelve 502 Bad Gateway. El contenedor no está en marcha o aún está arrancando. Revisa docker compose ps y docker compose logs forgejo --tail 50 en /opt/forgejo.

El push por HTTPS falla con 413 Request Entity Too Large. Falta client_max_body_size en el bloque HTTPS de Nginx o es demasiado pequeño. Ajústalo en /etc/nginx/sites-available/forgejo y recarga Nginx.

ssh -p 2222 pide contraseña o da Permission denied (publickey). Forgejo no reconoce la clave. Comprueba que añadiste la clave pública correcta en tu perfil y que el puerto 2222 está abierto con sudo ufw status.

Forgejo no arranca con errores de permisos en /data. USER_UID y USER_GID no coinciden con el dueño de /opt/forgejo/data. Compáralos con ls -ln /opt/forgejo y corrige uno de los dos.

Los trabajos se quedan en espera. El runs-on del workflow no coincide con ninguna etiqueta del runner. En este tutorial la etiqueta es docker.

Conclusión

Tienes Forgejo funcionando con Docker Compose y PostgreSQL, publicado con HTTPS detrás de Nginx, con acceso Git por SSH en el puerto 2222 y un runner de Forgejo Actions ejecutando workflows en contenedores. Como siguientes pasos, puedes configurar el envío de correo con las variables FORGEJO__mailer__*, programar forgejo dump a diario con un temporizador de systemd y copiar los resultados fuera del servidor, o usar el registro de paquetes integrado para publicar imágenes de contenedor desde tus workflows.