New releases
Recipe version compared with the latest known upstream release. A version number, not a reading of what changed.
Gitea hosts Git repositories, pull requests, issues, wikis, and package registries on your own server. This recipe uses the official image and PostgreSQL, disables open registration, and binds web and SSH to localhost.
Gitea is an open-source Git service for small teams and personal projects. It combines repositories, code review, issues, projects, wikis, releases, package registries, and built-in CI/CD support without handing code to an external platform.
This recipe runs the pinned official Gitea 1.27.3 image with PostgreSQL 17.11. The web UI and built-in SSH server bind to localhost, and open registration is disabled. Gitea Actions and a runner are intentionally out of scope.
The full smoke test has passed on amd64 and arm64; backup and restore remain
untested in practice. Public web access requires an HTTPS reverse proxy. Only expose
SSH after configuring the administrator, keys, and firewall. Repositories,
attachments, and configuration live under /data; PostgreSQL stores the
database separately.
These are stored results of separate checks, not real-time data. An unknown status means the check has not been performed yet.
Recipe version compared with the latest known upstream release. A version number, not a reading of what changed.
Result of a dedicated Docker image scan, not a Compose configuration check.
A new major version is found by comparing version numbers. A compatibility verdict is entered by hand after reading the release notes and the migration steps.
Upstream Compose changes relative to the verified recipe.
Pinned image tags checked for newer versions.
From observation to action
The recipe already pins the latest known release. The steps below show the evidence retained for that version.
1.27.31.27.3Open this release on GitHub ↗ The link is evidence to review, not proof of compatibility.
The version numbers do not cross a major compatibility boundary. No compatibility verdict has been recorded.
No image-tag change is currently planned.
Manual steps after the pull. Release-specific migration steps still come from the release notes and installation guide.
No version change is currently planned. The recipe includes a backup procedure. Restore has not been tested.
An exact Fully verified check for this target was recorded on 2026-09-03.
The status shows how fully the published recipe meets each level's requirements.
A minimal setup for a local network or access through a VPN.
You still need to add: single server, local access, minimum components.
A public deployment with protected access and backups.
You still need to add: domain, https via reverse proxy, off-server backup.
A setup designed for predictable operations and observability.
You still need to add: external monitoring, cpu and memory limits.
Tailored to your server
Answer five questions and download a ready-to-run Gitea bundle.
Screenshots have not been added yet.
Read the full guide first: it explains external access, backups, and data locations.
cp .env.example .envdocker compose up -ddocker compose psUse Ubuntu 22.04+ or Debian 12+ with Docker Engine and Compose v2.24+. Allocate at least 1 CPU, 512 MB RAM, and 5 GB disk; 1 GB RAM plus space for repositories, packages, and backups is recommended.
docker --version
docker compose version
mkdir -p ~/services/gitea
cd ~/services/gitea
cp .env.example .env
chmod 600 .env
openssl rand -base64 36
Put the generated value in POSTGRES_PASSWORD, replace git.example.com, and
never publish .env. GITEA_HTTP_PORT and GITEA_SSH_PORT select local ports;
GITEA_DOMAIN, GITEA_SSH_DOMAIN, and GITEA_ROOT_URL define public addresses;
the POSTGRES_* variables configure the database; the volume variables name
persistent storage; GITEA_BACKUP_DIR selects backup storage.
docker compose config
docker compose pull
docker compose up -d --wait
curl --fail http://127.0.0.1:3000/api/healthz
read -rsp 'Administrator password: ' GITEA_ADMIN_PASSWORD
docker compose exec gitea gitea admin user create --admin --must-change-password --username admin --email admin@example.com --password "$GITEA_ADMIN_PASSWORD"
unset GITEA_ADMIN_PASSWORD
The password is not stored in shell history, but is briefly passed to the
process inside the container; change it immediately in the UI. Open registration
is disabled. Gitea persists its data under /data.
Keep both bindings on 127.0.0.1 and expose web only through HTTPS. Test SSH
through ssh -L 2222:127.0.0.1:2222 user@server, then ssh -p 2222 git@localhost.
To expose Git over SSH publicly, change only its Compose binding to a specific
VPS address such as ${SERVER_IP}:${GITEA_SSH_PORT}:22, document SERVER_IP in
.env, and allow that TCP port through the firewall. Keep port 3000 local.
Prefer a VPN or SSH tunnel. If the proxy runs on another LAN host, bind web to a
specific private server address and allow only the proxy through the firewall.
Do not use 0.0.0.0 without network restrictions.
Replace the domain in .env and one file under proxy/. Caddy obtains a
certificate, Nginx expects Certbot files, and Traefik uses the letsencrypt
resolver. The proxy must preserve the URI and forward Host,
X-Forwarded-Proto, and the client address. A containerized Traefik needs a
reachable host gateway instead of 127.0.0.1.
chmod +x backup.sh restore.sh
./backup.sh
The script stops Gitea, runs a native pg_dump, archives the complete data
volume, and starts the service again. Stopping is required: the repositories on
disk and the database rows describing them are consistent with each other only
while nothing writes. The archive lands in GITEA_BACKUP_DIR. Encrypt it
because it contains private code, keys, and configuration. Keep an off-server
copy and test restores regularly.
Restore irreversibly replaces the data volume and database. The script takes an
emergency copy of the current state before replacing it. Use the same Gitea
version, check .env, then:
./restore.sh ./backups/gitea-YYYYMMDDTHHMMSSZ.tar
docker compose ps
curl --fail http://127.0.0.1:3000/api/healthz
The script finishes with gitea admin regenerate hooks: hook scripts embed
absolute paths and the binary version, so they must be rewritten after the data
directory is replaced. The procedure has not passed a practical restore test;
test it on a separate server first.
Back up first and read the release notes and upgrade guide. The image is pinned
in compose.yaml: replace 1.27.3 with a reviewed exact version, update the
exact PostgreSQL tag if needed, then run
docker compose pull && docker compose up -d --wait. Do not switch between
rootful and rootless images because their data layouts are incompatible.
Never run an old image over a migrated database. Restore the previous exact Gitea and PostgreSQL tags, then restore the entire pre-update directory using the procedure above. Rolling back migrations without a synchronized file and database backup is unsafe.
docker compose down preserves data. After verifying an external backup, remove
all data with:
docker compose down
docker volume rm gitea-data gitea-database
rm -rf ~/services/gitea
Sources: official Docker installation, backup and restore, reverse proxies, and upgrades.
docker compose ps
docker compose logs --tail=200 gitea database
docker inspect --format '{{json .State.Health}}' "$(docker compose ps -q gitea)"
Check the database password, free disk space, and volume access. /api/healthz
must return HTTP 200.
/dataThe official rootful container uses the git user with UID/GID 1000 for
persistent data. Do not change USER_UID or USER_GID without migrating
ownership. Run chown -R 1000:1000 before using a bind mount.
Check GITEA_ROOT_URL, GITEA_DOMAIN, GITEA_SSH_DOMAIN, and
GITEA_SSH_PORT, then run docker compose up -d --force-recreate.
This is the safe default: SSH binds to localhost. Test through a tunnel first.
For public access, follow the VPS section, change only the SSH binding, inspect
the firewall, and diagnose with ssh -vvv -p 2222 git@git.example.com.
Check curl http://127.0.0.1:3000/api/healthz, the upstream address, and whether
the proxy can reach host localhost. A containerized proxy has a different
localhost namespace.
Inspect the logs and regenerate Git hooks:
docker compose exec gitea gitea admin regenerate hooks
docker compose exec gitea gitea doctor check --all
Fossary is an independent informational catalog and is not affiliated with the developers of the listed applications. We collect information from public sources and verify published recipes, but we do not develop, distribute, or control these applications.
A listing or validation status is not a requirement, endorsement, or personal recommendation to use an application. You decide whether it is suitable and use it at your own risk. We do not warrant an application's security, availability, or fitness for purpose and, to the extent permitted by law, are not liable for resulting loss or damage. Review its license, security settings, data processing, and backup procedures before installation.