added Gitea
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
# Copy to .env and adjust. .env is git-ignored; this file is not.
|
||||||
|
# Every value here has a default in compose.yaml, so a fresh clone runs
|
||||||
|
# with no .env at all.
|
||||||
|
|
||||||
|
# ─── Identity ───────────────────────────────────────────────────────
|
||||||
|
# Become USER_UID / USER_GID in the container, which is how Gitea's `git`
|
||||||
|
# user is made to match the owner of the bind-mounted data directory.
|
||||||
|
# Wrong values mean Gitea cannot write its own data.
|
||||||
|
#
|
||||||
|
# id -u ; id -g
|
||||||
|
#
|
||||||
|
#PUID=1000
|
||||||
|
#PGID=1000
|
||||||
|
|
||||||
|
# ─── Paths ──────────────────────────────────────────────────────────
|
||||||
|
# Repositories, the SQLite database and conf/app.ini. This is the whole
|
||||||
|
# backup -- nothing in it regenerates.
|
||||||
|
#DATA_PATH=./data
|
||||||
|
|
||||||
|
# ─── Ports ──────────────────────────────────────────────────────────
|
||||||
|
#PORT=3000
|
||||||
|
|
||||||
|
# Host port for SSH clone; the container always listens on 22. Port 22 on
|
||||||
|
# the host belongs to the host's own sshd, which is why this isn't 22.
|
||||||
|
#
|
||||||
|
# If you change it, also uncomment GITEA__server__SSH_PORT in compose.yaml
|
||||||
|
# so the clone URLs Gitea advertises match -- otherwise it hands out
|
||||||
|
# port 22 and clients land on the host's sshd instead.
|
||||||
|
#SSH_PORT=222
|
||||||
|
|
||||||
|
# ─── Timezone ───────────────────────────────────────────────────────
|
||||||
|
# There is no TZ variable here on purpose: compose.yaml mounts the host's
|
||||||
|
# /etc/timezone and /etc/localtime read-only, so the container follows the
|
||||||
|
# host automatically.
|
||||||
+129
@@ -0,0 +1,129 @@
|
|||||||
|
# Gitea
|
||||||
|
|
||||||
|
Self-hosted Git with a web UI, issues and pull requests. A few hundred MB of Go
|
||||||
|
that starts in a second, where the alternative is a JVM and a shopping list of
|
||||||
|
services.
|
||||||
|
|
||||||
|
This is the stack the rest of this repo is developed against — the compose files
|
||||||
|
you're reading live in a Gitea instance, and GitHub is the mirror.
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
$EDITOR .env # PUID/PGID must match the owner of ./gitea
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://<host>:3000`. You get Gitea's **install wizard**, not a login page —
|
||||||
|
it writes `app.ini` from what you enter and that's the moment the instance is
|
||||||
|
configured. Two things to settle there rather than later:
|
||||||
|
|
||||||
|
1. **Server and Third-Party Service Settings → Base URL.** Set it to the URL
|
||||||
|
people will actually use. Wrong here means every clone URL it hands out is
|
||||||
|
wrong.
|
||||||
|
2. **Create the admin account** at the bottom of the wizard. If you skip it,
|
||||||
|
*the first user to register becomes the administrator* — which is fine on a
|
||||||
|
LAN and not fine on anything reachable.
|
||||||
|
|
||||||
|
## Ports
|
||||||
|
|
||||||
|
| Port | Proto | Purpose |
|
||||||
|
|------|-------|---------|
|
||||||
|
| 3000 | http | Web UI and the HTTP(S) clone endpoint |
|
||||||
|
| 222 | ssh | SSH clone endpoint (container listens on 22) |
|
||||||
|
|
||||||
|
## Why it looks like this
|
||||||
|
|
||||||
|
**It started as upstream's example** —
|
||||||
|
[Install with Docker](https://docs.gitea.com/installation/install-with-docker/)
|
||||||
|
— with four changes to bring it in line with the rest of this repo, listed at
|
||||||
|
the end of this section. Everything else is upstream's, and what follows is what
|
||||||
|
those choices actually mean.
|
||||||
|
|
||||||
|
**SQLite by default.** There's no database container here, and none is needed:
|
||||||
|
with no `GITEA__database__DB_TYPE` set, Gitea uses SQLite inside `/data`. For one
|
||||||
|
person or a small team that is genuinely the right answer — one less container,
|
||||||
|
one less backup, and the performance ceiling is far above what a personal
|
||||||
|
instance reaches. Upstream documents MySQL and PostgreSQL variants using
|
||||||
|
`GITEA__database__DB_TYPE=mysql` / `postgres`; switch if you outgrow it, and do
|
||||||
|
it before there's data to migrate.
|
||||||
|
|
||||||
|
**`USER_UID` / `USER_GID` exist because of the bind mount.** `./gitea:/data` is a
|
||||||
|
host directory, so the `git` user inside the container has to match whoever owns
|
||||||
|
it. Upstream notes that named volumes avoid the problem entirely — Docker manages
|
||||||
|
ownership — at the cost of your data being somewhere less obvious.
|
||||||
|
|
||||||
|
**SSH is on 222, not 22**, because 22 on the host belongs to the host's own sshd.
|
||||||
|
This is the source of the most common Gitea confusion: see the gotchas.
|
||||||
|
|
||||||
|
**Environment variables map to `app.ini` sections** with the pattern
|
||||||
|
`GITEA__section__KEY`. So `GITEA__server__ROOT_URL` sets `ROOT_URL` under
|
||||||
|
`[server]`. Useful to know, because the wizard only exposes a fraction of what
|
||||||
|
Gitea can be told.
|
||||||
|
|
||||||
|
### What was changed from upstream's example
|
||||||
|
|
||||||
|
Four things, all for the same reason — this file is published, and a fresh clone
|
||||||
|
has to work:
|
||||||
|
|
||||||
|
- **`${PUID:-1000}` / `${PGID:-1000}` instead of bare `${PUID}`.** Compose
|
||||||
|
interpolates an unset variable to an *empty string* and starts the container
|
||||||
|
anyway, so upstream's version hands Gitea `USER_UID=` on any clone without a
|
||||||
|
`.env`. Defaults are the convention here for exactly this reason.
|
||||||
|
- **`restart: unless-stopped` instead of `always`**, so a deliberate stop
|
||||||
|
survives a reboot.
|
||||||
|
- **`${DATA_PATH:-./data}` instead of `./gitea`**, which also stops the data
|
||||||
|
landing at the slightly comic `gitea/gitea/`.
|
||||||
|
- **Pinned to `1.27.3` instead of `:latest`**, because Gitea runs schema
|
||||||
|
migrations between releases.
|
||||||
|
|
||||||
|
Two settings are also present but commented out —
|
||||||
|
`GITEA__server__SSH_PORT` and `GITEA__server__ROOT_URL` — because both are
|
||||||
|
things you will need the moment you publish this beyond localhost. See the
|
||||||
|
gotchas.
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- **SSH clone URLs advertise the wrong port by default.** Gitea knows it listens
|
||||||
|
on 22 *inside* the container; it has no idea you published it on 222. So it
|
||||||
|
offers `git@host:user/repo.git`, which sends the client to port 22 — the host's
|
||||||
|
sshd — and the failure looks like a key problem rather than a port problem.
|
||||||
|
Uncomment `GITEA__server__SSH_PORT` in `compose.yaml` (it tracks `SSH_PORT`,
|
||||||
|
so the two can't drift), or set the SSH port in the wizard.
|
||||||
|
- **Behind a reverse proxy, `ROOT_URL` is the setting that matters.** Get it
|
||||||
|
wrong and the UI works fine while every clone URL, webhook and OAuth redirect
|
||||||
|
points somewhere else. See [reverse proxy](../docs/reverse-proxy.md), which
|
||||||
|
already lists Gitea as a service needing this.
|
||||||
|
- **The install wizard runs once.** After it writes `app.ini`, that file wins —
|
||||||
|
changing an environment variable afterwards does *not* change a setting the
|
||||||
|
wizard already recorded. Edit `gitea/gitea/conf/app.ini` (or delete it and
|
||||||
|
reinstall) if you need to change course.
|
||||||
|
- **First registered user becomes admin** if you didn't create an admin in the
|
||||||
|
wizard. Disable registration once your accounts exist:
|
||||||
|
`GITEA__service__DISABLE_REGISTRATION=true`.
|
||||||
|
- **Back up `./gitea`.** It holds every repository, the SQLite database, and
|
||||||
|
`conf/app.ini`. There is nothing else to back up, and nothing in it
|
||||||
|
regenerates.
|
||||||
|
- **Mirror pushes need credentials that outlive your session.** If you push from
|
||||||
|
here to GitHub, that's an access token or deploy key stored in Gitea, not your
|
||||||
|
laptop's agent.
|
||||||
|
|
||||||
|
## Exposing it
|
||||||
|
|
||||||
|
Publishes plain HTTP; TLS belongs at the proxy.
|
||||||
|
|
||||||
|
- [Reverse proxy with Caddy](../docs/reverse-proxy.md) — **needs `ROOT_URL`**,
|
||||||
|
see above. HTTP clone and the web UI both go through it.
|
||||||
|
- [Cloudflare Tunnel](../cloudflare-tunnel/) — works for the web UI and HTTP
|
||||||
|
clone, but **SSH clone won't pass** and the ~100 MB body cap will meet you at
|
||||||
|
the first large push. Fine for browsing, awkward as your only route.
|
||||||
|
- [Single sign-on with Authentik](../docs/authentik-sso.md) — Gitea speaks OIDC
|
||||||
|
natively, so use that rather than forward auth, which would break `git` over
|
||||||
|
HTTP as surely as it breaks any other non-browser client.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Install with Docker: <https://docs.gitea.com/installation/install-with-docker/>
|
||||||
|
- Configuration cheat sheet: <https://docs.gitea.com/administration/config-cheat-sheet>
|
||||||
|
- Image: <https://hub.docker.com/r/gitea/gitea>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
networks:
|
||||||
|
gitea:
|
||||||
|
external: false
|
||||||
|
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
# Pinned. Gitea runs schema migrations between releases, so an unattended
|
||||||
|
# pull picking up a new minor is not something to meet by surprise.
|
||||||
|
image: docker.gitea.com/gitea:1.27.3
|
||||||
|
container_name: gitea
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- gitea
|
||||||
|
|
||||||
|
environment:
|
||||||
|
# Gitea's `git` user is made to match the owner of the bind-mounted data
|
||||||
|
# directory. Defaults so a fresh clone runs with no .env at all -- bare
|
||||||
|
# ${PUID} would interpolate to an empty string and start anyway.
|
||||||
|
- USER_UID=${PUID:-1000}
|
||||||
|
- USER_GID=${PGID:-1000}
|
||||||
|
# Gitea knows it listens on 22 inside the container and has no idea it is
|
||||||
|
# published on 222, so the SSH clone URLs it hands out send clients to the
|
||||||
|
# host's own sshd. Uncomment to match the published port below.
|
||||||
|
#- GITEA__server__SSH_PORT=${SSH_PORT:-222}
|
||||||
|
# Set this once you're behind a proxy, or every clone URL, webhook and
|
||||||
|
# OAuth redirect points at the wrong host.
|
||||||
|
#- GITEA__server__ROOT_URL=https://git.example.com/
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
# Every repository, the SQLite database and conf/app.ini. Back this up --
|
||||||
|
# nothing in it regenerates.
|
||||||
|
- ${DATA_PATH:-./data}:/data
|
||||||
|
# Timezone comes from the host rather than a TZ variable.
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "${PORT:-3000}:3000"
|
||||||
|
# 22 on the host belongs to the host's own sshd, hence 222.
|
||||||
|
- "${SSH_PORT:-222}:22"
|
||||||
Reference in New Issue
Block a user