Skip to content

Gitea

Run Gitea — self-hosted Git service — as a managed container, with a no-wizard install and an auto-generated web login.

pg addon install gitea runs Gitea — the lightweight self-hosted Git service — as a managed container from the official upstream image (docker.io/gitea/gitea, rootful build). Like Grafana it is a top-level addon: it is not attached to any one PostgreSQL instance — it fronts none, though it can use one as its metadata database (see --dsn below). One container serves the web UI, the Git HTTP traffic, and git-over-ssh on the image’s OpenSSH sshd (see Git SSH — that sshd runs on every instance whether or not --ssh-port is set; the flag only makes it the live clone endpoint).

The install is fully non-interactive: INSTALL_LOCK=true skips Gitea’s web setup wizard, and the admin account is created afterwards via the in-container gitea admin user create CLI. The web login password is generated on first install, printed once, and stored in pg.yaml; retrieve it later with pg addon password gitea. Listen defaults to 0.0.0.0 — a Git host is cloned from other machines — and the exposure is guarded by the generated strong password plus closed self-registration; pass --listen 127.0.0.1 for loopback-only access.

Platform: Linux is the tested platform. The design supports macOS (the image is multi-arch; the container runs under the podman machine VM on the pgcli-net bridge with the web port — and, when enabled, the SSH port — published), but it has not been validated there yet.

Parameters

Flag Default Description
--name gitea Instance name (map key)
--image docker.io/gitea/gitea:28.1.0 Image override (rootful build only — see Known limitations)
--port auto (base 3080) Host web port; auto-allocated from gitea_start_port
--ssh-port unset Make the always-running sshd the live git-over-ssh endpoint on this host port (see Git SSH). A port is allocated from gitea_ssh_start_port (base 2222) for every instance to park sshd off 22, SSH on or off; --ssh-port 0 disables live cloning but keeps the reservation
--listen 0.0.0.0 Bind address — defaults to every interface; use 127.0.0.1 for loopback-only. Also the host Gitea renders into clone URLs
--admin-user gitea Web login user (deliberately not git — that is the container’s OS user ssh:// clones authenticate as)
--password auto-generated Web login password (applied only when the admin account does not yet exist — see below)
--dsn empty postgres://user:pass@host:port/db to keep Gitea’s metadata in an external PostgreSQL instead of the embedded SQLite; the database must already exist
--allow-registration false Open self-service signup (the web UI shows a Register entry). Closed by default — see Listening and exposure
--data-dir auto Data directory override (default under the base dir)
--force false Recreate even when running — to apply changed ports, credentials, dsn, listen address or the registration toggle

Install

pg addon install gitea

The command pulls the image if needed, creates and starts the container, waits for Gitea’s first-boot migrations to finish, creates the admin account, and prints:

✓ Gitea installed: "gitea"
  Container:  pgcli-gitea-gitea
  Image:      docker.io/gitea/gitea:28.1.0
  Data:       /home/you/.pgcli/addon/gitea/gitea/data
  Web URL:    http://localhost:3080/
  Git SSH:    disabled (HTTP clone/push only; enable with --ssh-port N --force)

  Login user:     gitea
  Login password: <auto-generated>

Open the URL, sign in with the printed credentials, and create your first org/repo in the web UI. Clone over HTTP with the same login:

git clone http://127.0.0.1:3080/<owner>/<repo>.git

The data directory and /data

Everything Gitea owns lives in one bind-mounted directory: the repositories, the rendered /data/gitea/conf/app.ini, the SQLite metadata database (/data/gitea/gitea.db — absent with --dsn), the SSH host keys, and logs. It survives pg addon remove (delete it with --clean-data), so reinstalling under the same name revives everything.

The image’s rootful build runs as the git user — uid/gid 1000, pinned via USER_UID/USER_GID so the host-side pre-chown and the container process can never drift apart — and its entrypoint only chowns what it creates itself, so pgcli chowns the data dir on the host before creating the container: via podman unshare chown 1000:1000 under rootless podman, or a direct recursive chown when pgcli runs as root on a rootful host.

pgcli never injects SECRET_KEY or INTERNAL_TOKEN. Gitea folds every GITEA__<section>__<KEY> environment variable into the persisted app.ini on each boot; if pgcli regenerated and injected crypto secrets, a reinstall over a kept data dir would re-key the persisted app.ini while the surviving database still holds 2FA seeds and OAuth client secrets encrypted under the old key — a silent, unlogged lockout. So those keys belong to the volume: Gitea generates them itself on first boot, and pgcli owns only the admin login password.

The admin password takes effect only when the admin account does not exist in the database — it is created with gitea admin user create, never reset. Reinstalling over a kept data dir (or a kept --dsn database) keeps the original login; the printed password is then inert (install says so explicitly). To change the login of an existing store, run gitea admin user change-password inside the container (pg exec <instance> -- ... style: podman exec -it <container> gitea admin user change-password ...), or remove with --clean-data and reinstall (SQLite mode — a --dsn database also has to be dropped by hand).

Re-running install reuses a running container and starts a stopped one — config changes only apply after a remove + reinstall or --force.

Database: SQLite or --dsn

By default Gitea uses its embedded SQLite database inside /data — zero dependencies, one file, revived with the data dir. For anything shared or long-lived, point the metadata at PostgreSQL:

pg addon install gitea --name git1 --dsn "postgres://gitea:secret@127.0.0.1:35432/gitea"

pgcli validates the DSN before writing anything and renders it into GITEA__database__DB_TYPE=postgres plus HOST/NAME/USER/PASSWD. The install summary and pg addon list echo it back with the credentials hidden (host:port/db). Same contract as PostgREST’s --dsn: the database must already exist (create it on a managed instance with pg exec <instance> -c 'CREATE DATABASE gitea ...' or any other way); Gitea creates its own schema on first boot. pg addon remove gitea — even with --clean-data — never touches the external database; it only holds Gitea’s tables.

Git SSH (optional)

Every Gitea instance runs an OpenSSH sshd — the official image’s s6 openssh service is unconditional (its run script execs sshd; no GITEA__server__* env turns it off). What --ssh-port actually toggles is whether that sshd is the live git-over-ssh clone endpoint or just an idle listener. --ssh-port takes a host port from gitea_ssh_start_port (base 2222) for every instance — SSH on or off — precisely so the always-on sshd is parked off 22: on the host network, leaving it on 22 would race the host’s own sshd and the log would fill with Bind to port 22 … Address in use forever. pgcli moves it by setting the image’s bare SSH_LISTEN_PORT / SSH_PORT env (those are what the rendered sshd_config’s Port line actually consumes — GITEA__server__SSH_LISTEN_PORT alone only changes what Gitea believes the port is, not what sshd binds).

  • SSH off (default, no --ssh-port): DISABLE_SSH=true so Gitea neither writes the git user’s authorized_keys nor advertises ssh:// clone URLs. The s6 sshd is still running, parked on a pool port, and no client will ever reach it. The pool reservation stays — nothing frees it.
  • SSH on (--ssh-port N, N>0): git-over-ssh rides that same s6 sshd — the image’s native route. DISABLE_SSH=false makes Gitea populate the git user’s authorized_keys (which sshd reads via AuthorizedKeysFile pointed into /data/gitea/ssh/); Gitea’s own built-in Go SSH listener is pinned off with START_SSH_LISTENER=false so it does not double-bind the same port in the same netns; and SSH_DOMAIN / SSH_PORT render the ssh://git@<host>:N/<owner>/<repo>.git clone URL.
pg addon install gitea --name git1 --ssh-port 2222   # explicit, or omit for pool

Auth is the git account’s SSH keys added through the web UI (the OS user is git; the web admin is gitea). Host keys live under <data>/ssh/, so they survive reinstalls — if you remove with --clean-data, clients see a new-host-key warning the next time.

Under the macOS bridge the SSH port is additionally published, but only when SSH is on — a parked sshd is unreachable by design, so it gets no -p. Not passing --ssh-port on a later install keeps the stored setting; --ssh-port 0 disables live cloning (the port reservation stays — only the DISABLE_SSH flip and the clone-URL change take effect, with a --force recreate).

Listening and exposure

Gitea’s Listen defaults to 0.0.0.0: the container shares the host’s network namespace, so the web UI and Git HTTP are reachable on every interface at the assigned port. This is deliberate — a Git host is cloned from other machines — and is protected by the generated strong admin password plus DISABLE_REGISTRATION=true (self-service account creation is off; create accounts with pg addon gitea user create). For a loopback-only deployment pass --listen 127.0.0.1 (recreate with --force).

--allow-registration flips that second guard: pg addon install gitea --name <n> --allow-registration --force renders DISABLE_REGISTRATION=false and the web UI grows a Register entry. Close it again with --allow-registration=false --force — the toggle is a stored config value gated on the flag being passed, so a plain re-install (or one without the flag) keeps whatever state is stored, and only --force pushes a change into the live container. What opens up is account spam, not takeover: a field test confirmed the register form creates a NORMAL user (IsAdmin=false) — Gitea has no way to make signup produce an admin; elevation is exclusively pg addon gitea user create --admin or the admin panel, independent of how the account was born. Companion Gitea-side hardening for an open-registration site lives in the same service section (REGISTER_EMAIL_CONFIRM, CAPTCHA, REQUIRE_SIGNIN_VIEW) — outside pgcli’s rendered env set, so it stays Gitea-side configuration.

--listen is also what displayed clone URLs use: a wildcard bind is not a connectable address, so it is echoed as localhost, and any explicit host/IP appears verbatim in ROOT_URL and the ssh:// URLs. When Gitea sits behind a reverse proxy that forwards X-Forwarded-Proto and Host — which pgcli’s nginx template does by default — Gitea rewrites the displayed clone URL to match the incoming request, so the code button on the repo page reads https://<proxy-host>/<owner>/<repo>.git correctly (scheme from X-Forwarded-Proto, host from Host, standard port dropped). pgcli’s rendered ROOT_URL stays http://<host>:<web-port>/ because there is no config face to advertise https/the proxy port — but that only governs webhook/redirect URLs generated server-side; interactive clone URLs follow the request. For TLS, see HTTPS via nginx.

HTTPS via nginx

Gitea serves plaintext HTTP; to reach it over https:// you front it with the nginx addon, which terminates TLS and proxies to the Gitea web port. Two things to get right: bring your own certificate (or let pgcli mint a self-signed one), and use nginx’s custom --conf-file mode — the template’s default client_max_body_size (1 MiB) rejects any larger git push with HTTP 413.

# 1. a self-signed leaf whose SAN covers the host you clone by (IP and/or DNS)
pg cert --host 10.0.0.9,git.internal \
        --cert-file /srv/gitea.crt --key-file /srv/gitea.key

Write the proxy config as /srv/gitea-nginx.conf — the parts that matter for Git are client_max_body_size 10m (nginx’s built-in default is 1 MiB, and without raising it a larger git push dies with HTTP 413 before reaching Gitea) and the long proxy_*_timeout (streaming git push outlives the 60s default). The same file as a generic template also lives in the nginx docs (“Git HTTP push with client_max_body_size”):

worker_processes auto;
pid /tmp/nginx.pid;

events {
    worker_connections 1024;
}

http {
    # Lift nginx's request-body cap so git pushes aren't rejected. nginx's
    # built-in default is 1 MiB — anything larger dies with HTTP 413 before
    # reaching Gitea. 10m covers typical pushes; raise it (or use 0 for no
    # limit) if you commit larger binaries.
    client_max_body_size 10m;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;

    upstream gitea {
        server 127.0.0.1:3080;    # the Gitea web port pgcli allocated
    }

    server {
        listen 0.0.0.0:80;
        location / {
            return 308 https://$host$request_uri;   # force HTTPS (308 keeps method+body,
        }                                           # so git push survives the redirect)
    }

    server {
        listen 0.0.0.0:443 ssl;
        # pgcli bind-mounts the --tls-cert / --tls-key files at these paths:
        ssl_certificate     /etc/nginx/certs/public.crt;
        ssl_certificate_key /etc/nginx/certs/private.key;
        ssl_protocols TLSv1.2 TLSv1.3;

        location / {
            proxy_pass http://gitea;
            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;   # what makes the displayed
        }                                                 # clone URL read https://…
    }
}
# 2. install the proxy on that file (recreate anytime with --force)
pg addon install nginx --name proxy --conf-file /srv/gitea-nginx.conf \
  --tls --tls-cert /srv/gitea.crt --tls-key /srv/gitea.key \
  --http-port 80 --https-port 443 --listen 0.0.0.0

The nginx proxy now serves https://10.0.0.9/ and forwards to Gitea’s 127.0.0.1:3080. Clone and push over the proxy URL (hand clients the .crt as their CA so the self-signed cert verifies):

git clone https://10.0.0.9/<owner>/<repo>.git        # over the TLS proxy
git -c http.sslCAInfo=/srv/gitea.crt push ...        # trust the self-signed leaf

Notes:

  • The Gitea web port (3080) is still open directly; the proxy does not hide it. For an origin that only nginx may reach, reinstall Gitea with --listen 127.0.0.1 so it binds loopback only, and point the proxy’s backend at 127.0.0.1:3080 (same host) — works because both run on the host network.
  • pg addon nginx reload will not pick up an external edit to the mounted nginx.conf (the bind mount pins the original inode, so a sed -i/editor rewrite is invisible until the container restarts). Reload only applies changes pgcli itself wrote. After hand-editing the conf, restart with pg addon stop nginx --name proxy && pg addon start nginx --name proxy, or reinstall with --force.
  • A real CA cert (Let’s Encrypt / ZeroSSL / corporate) is the right choice in production — see Production domain + a real CA below; it drops the --cacert hand-off entirely, browsers and git trust it out of the box.
  • git-over-ssh (--ssh-port) is independent of this; TLS here only fronts the web UI and Git-over-HTTP.

Production domain + a real CA (Let’s Encrypt / corporate)

For anything facing the internet, don’t ship a pg cert self-signed leaf — point a real domain at the host (e.g. git.example.com → 203.0.113.7) and get a CA-signed certificate for it. How you obtain that certificate is outside pgcli’s scope — any CA and any tool you like; all that matters is ending up with a PEM cert (including its intermediate chain) and its private key.

Then create the nginx proxy exactly as in the steps above, only swapping the certificate paths for your domain cert — the same --conf-file, ports and --tls are unchanged:

pg addon install nginx --name proxy --conf-file /srv/gitea-nginx.conf \
  --tls \
  --tls-cert /etc/ssl/git.example.com/fullchain.pem \
  --tls-key  /etc/ssl/git.example.com/privkey.pem \
  --http-port 80 --https-port 443 --listen 0.0.0.0

Set --listen git.example.com on the Gitea install too (with --force), so ROOT_URL and any ssh:// hints carry the real hostname. Once it’s up, users clone https://git.example.com/<owner>/<repo>.git with no CA hand-off — browsers and git trust public CAs by default.

Remember to replace the certificate before it expires. pgcli copies the BYO pair into the addon’s TLS dir (<base>/addon/nginx/<name>/tls/ as public.crt / private.key) at install, and that directory is bind-mounted into the container — so renewal is: overwrite those two files, then

pg addon nginx reload --name proxy

(Verified: the served certificate changes immediately after the reload. This works because the TLS dir is mounted as a directory; unlike the single-file nginx.conf mount, new contents are visible to the running container.)

Retrieving the web login

The login is Gitea’s web/Git-HTTP sign-in, unrelated to any PostgreSQL role (even with --dsn). Re-read the password at any time:

pg addon password gitea              # bare password on stdout
pg addon password gitea --file ./pw  # or write it to a 0600 file

It is also stored in pg.yaml (addons.gitea.<name>.password).

Managing accounts (members and admins)

Self-registration is closed, so every account beyond the install admin is created by an admin. pg addon gitea user wraps the in-container gitea admin user … CLI (run as the git uid automatically) so you manage accounts from the host without a manual podman exec. The instance must be running.

# a member, generated password (printed once, NOT stored in pg.yaml)
pg addon gitea user create --username alice --email alice@corp.example
# a member, pinned password
pg addon gitea user create --username bob   --password 'B0b-pin-pass'
# a second site admin
pg addon gitea user create --username carol --admin
# list everyone
pg addon gitea user list
# remove an account (must own nothing, or use --purge) ...
pg addon gitea user delete --username bob
# ... or drop everything the account owns
pg addon gitea user delete --username bob --purge
flag (create) default meaning
--username (required) the account name
--email <username>@localhost pass a real address when the user should get notifications / password resets
--password generated pin the login, or let pgcli generate a strong one and print it once
--admin false create a site admin instead of a normal member
--must-change-password false Gitea’s own default is true for every account after the first; that forces a change on first login and, until it happens, returns 403 for HTTP clone/push and API basic-auth. pgcli sends =false explicitly so a member can clone immediately — set it true only to hand out a one-time password

These logins are Gitea’s own accounts, not pgcli-managed, so a generated password is printed once and is not written to pg.yaml — record it at creation. (Only the install admin’s login is stored; that one you retrieve with pg addon password gitea.) To change an existing account’s password, run gitea admin user change-password inside the container.

delete refuses to remove the install admin (it is pgcli’s stored login). A plain delete only succeeds for an account that owns nothing; if it still owns repositories Gitea refuses with user still has ownership of repositories — pass --purge to remove the account and everything it owns (repos, orgs, comments).

Ports

Each Gitea instance takes one port for the web UI, allocated from a pool with base gitea_start_port (default 3080 — Gitea’s conventional 3000 is the Grafana pool’s base in pgcli, so Gitea starts one pool over; still recognizably “the Gitea port”). Every instance also takes a port from a second pool (gitea_ssh_start_port, default 2222 — the conventional Gitea SSH mapping) to park the image’s always-running sshd off 22; whether SSH is on or off only decides whether that port is a live clone endpoint or an idle listener, so the reservation is held either way. Both pools skip ports already taken by any managed container or the used_ports list, and the allocations are written into pg.yaml:

pg addon install gitea --name git2                 # second instance: next free web port
pg addon install gitea --name git3 --port 3100     # explicit port still wins
pg addon install gitea --name git4 --ssh-port 0    # SSH disabled: parked sshd keeps its pool port

The two pools’ bases (3080 / 2222) are disjoint from every other addon’s pool.

Configuration

addons:
  gitea:
    git1:
      name: git1
      image_tag: docker.io/gitea/gitea:28.1.0
      host_port: 3080
      listen: 0.0.0.0
      admin_user: gitea
      password: <generated>
      ssh: true
      ssh_port: 2222
      dsn: postgres://gitea:secret@127.0.0.1:35432/gitea
      autostart: false
      # data_dir: /srv/gitea-data    # optional, overrides the default location

Config is env-only (GITEA__<section>__<KEY> plus two bare SSH_LISTEN_PORT / SSH_PORT vars — those are what the image’s always-running sshd actually binds; the GITEA__server__* copy only drives Gitea’s own SSH-aware clone-URL rendering), folded by the image into app.ini on every boot; the app.ini inside /data is rewritten from these variables, so hand-editing it is not a supported configuration path (settings pgcli does not set survive the rewrite, but changing one of pgcli’s own keys by hand just gets undone on the next boot). The variables pgcli sets are: the wizard skip (INSTALL_LOCK), the listener (HTTP_PORT/HTTP_ADDR), the display URL (ROOT_URL), the registration gate (DISABLE_REGISTRATION, rendered in both states — true by default, false with --allow-registration, since Gitea’s own default is open and an omitted line could not override a persisted one), the always-emitted bare SSH_LISTEN_PORT/SSH_PORT pair that parks the s6 sshd off 22, DISABLE_SSH=true when SSH is off (Gitea then also does not write authorized_keys or show ssh:// URLs) or — when SSH is on — DISABLE_SSH=false plus the URL-rendering trio SSH_LISTEN_PORT/SSH_PORT/SSH_DOMAIN under GITEA__server__ and START_SSH_LISTENER=false so Gitea’s own Go listener does not double-bind the same port, the optional database block, and the process uid pin (USER_UID/USER_GID).

List

pg addon list
Web add-ons (gitea):
  gitea (name: git1)
    Status:      running
    Web URL:     http://localhost:3080/
    Git SSH:     ssh://git@localhost:2222/
    Database:    external PostgreSQL (127.0.0.1:35432/gitea)
    Login user:  gitea
    Data:        /home/you/.pgcli/addon/gitea/git1/data
    Image:       docker.io/gitea/gitea:28.1.0
    Container:   pgcli-gitea-git1

Passwords are hidden by default to keep the listing paste-safe; pg addon list --show-password reveals the plaintext value, and pg addon password gitea prints a single one bare for scripting.

Start and stop

Containers run with podman’s unless-stopped restart policy, so they come back automatically with the podman service after a host reboot. start/stop manage them explicitly:

pg addon stop gitea
pg addon start gitea

Auto-start on Boot

To have a Gitea instance started automatically on host boot, enable it:

pg autostart enable --gitea --name git1

This flags the instance in pg.yaml and installs/refreshes a boot service (a systemd --user unit on Linux, a LaunchAgent on macOS) that runs pg start --autostart. A boot-time start only brings the container up — the data dir was already chowned to uid 1000 at create time, so it needs no host privileges beyond podman itself. With --dsn, the external PostgreSQL must be up too: a managed instance with its own autostart starts earlier in the same pass; any other endpoint just needs to be reachable. See Autostart for the full mechanism, status and disabling.

Remove

pg addon remove gitea              # keeps the data dir — repos and login survive a reinstall
pg addon remove gitea --clean-data # deletes the data dir too (repositories are gone)

Under rootless podman, --clean-data deletes the data dir through podman unshare rm — Gitea writes as the container’s git uid (1000), which maps to a subordinate uid the host user cannot rm directly. With --dsn the external database is never touched either way — drop it yourself if you really want the data gone.

Logs

pg logs addon gitea            # show recent console output
pg logs addon gitea -f         # follow
pg logs addon gitea -n 200     # last 200 lines (also -i / --tail)

Troubleshooting

  • install fails with a chown diagnostic — the image runs as uid 1000 and never fixes ownership of an existing mount, so pgcli chowns the host data dir before creating the container: through podman unshare chown under rootless podman, or a direct recursive chown when pgcli itself runs as root on a rootful host. The manager shells out to the plain podman CLI, so this only fails outside those two cases — e.g. a non-root pg explicitly pointed at someone else’s rootful daemon. Run the install as root, or switch to rootless podman; a manual sudo chown -R 1000:1000 <data-dir> alone does not clear it, since pgcli re-checks ownership on every install attempt.
  • The login password doesn’t work after a reinstall — the admin account is created, never reset. On an existing store (kept /data or --dsn database) use gitea admin user change-password inside the container, or wipe and start over (--clean-data, and drop the external DB by hand in dsn mode).
  • Clone URLs show localhost even though Gitea is on a server — a wildcard --listen 0.0.0.0 collapses to localhost in displayed URLs because 0.0.0.0 is not connectable. Pass --listen <host-or-ip> (with --force) to make clone URLs real.
  • ssh:// clone says connection refused / wrong port — live cloning is off unless the instance was installed with --ssh-port (the s6 sshd is running but parked, so it is not a clone endpoint). And pgcli keeps SSH_PORT (what URLs show), the Gitea-side SSH_LISTEN_PORT, and the bare SSH_LISTEN_PORT (what the s6 sshd actually binds) all equal — a hand-mismatched config breaks exactly this way.
  • Log line Bind to port 22 … Address in use — the sshd’s park port has somehow reverted to 22 (an app.ini edit survived a boot, or bare env was stripped). A fresh install never hits this: pgcli always emits bare SSH_LISTEN_PORT=<pool port> for every instance, SSH on or off.
  • git push over HTTP asks for a password and rejects the web one — Gitea asks for the account’s credentials; if the account has 2FA on, HTTP push needs a personal access token or an SSH key instead of the password.
  • Port already allocated — the assigned ports are held in pg.yaml and skipped for later instances; free them with pg addon remove first, or pick others with --port / --ssh-port.

Known limitations

  • The image must be pinned to a version tag and upgraded by changing --image (Gitea migrates its database forward on first boot of the newer image — there is no downgrade path). Rootful and rootless builds have mutually incompatible data layouts: pgcli pins the rootful build and an -rootless tag will not read the existing /data (or the data written by another rootless deployment).
  • Plaintext HTTP: TLS termination and real hostnames are the nginx addon’s job — front Gitea with it in custom --conf-file mode (the template’s 1 MiB client_max_body_size default breaks larger git push). Gitea rewrites the on-page clone URL from X-Forwarded-Proto + Host, so behind nginx’s default proxy headers the copy button reads https://<proxy>/… correctly. pgcli renders ROOT_URL as http://<host>:<web-port>/ and v1 exposes no knob to change that — the only visible effect so far is anything Gitea generates from ROOT_URL directly (rather than from the request) keeps the internal http origin.
  • v1 sets no OAuth, SMTP, webhook-tuning, or repository-storage (MinFS) options — everything beyond the table above is Gitea-side configuration pgcli deliberately leaves alone. Self-registration is closed; create users with pg addon gitea user create.
  • On macOS the container runs inside the podman machine; it has been validated on Linux only.