Raja's Exocortex

Gitea

Gitea is published via Traefik HTTPS and SSH. The Traefik router is configured to permit access from the LAN and the Internet. The SSH router is configured to permit access from the LAN and Tailscale.

Deploy behind traefik.

File: Docker Compose

# Filename: /srv/gitea.example.com/docker-compose.yaml
# docker-compose file to start up gitea in https://gitea.example.com
#
# Create 2 traefik routers - for http LAN/Internet and ssh clients LAN/tailscale
#  1. LAN (Internal) users: no Google SSO auth in Traefik, else webhooks don't work
#  2. SSH users: blocked in iptables firewall, so only internal access is available

name: gitea-example.com

services:
  gitea:
    image: gitea/gitea
    container_name: gitea.example.com
    restart: always
    user: nobody

    mem_limit: 2G

    volumes:
      - ./data:/var/lib/gitea
      - ./config:/etc/gitea
      - /etc/timezone:/etc/timezone:ro

    labels:
      - com.centurylinklabs.watchtower.enable=true
      - traefik.enable=true

      # Permit for internal LAN users only
#     - traefik.http.routers.gitea.rule=Host(`gitea.example.com`) && ClientIP(`127.0.0.0/8`, `10.0.0.0/8`, `100.64.0.0/10`, `172.16.0.0/12`, `192.168.0.0/16`)

      - traefik.http.routers.gitea.rule=Host(`gitea.example.com`)
      - traefik.http.routers.gitea.tls=true
      - traefik.http.routers.gitea.tls.certresolver=lets-encrypt
      - traefik.http.routers.gitea.service=gitea
      - traefik.http.services.gitea.loadbalancer.server.port=3000

      # Access gitea via ssh, iptables fireawll permits only private IPs and tailscale
      - traefik.tcp.routers.gitea-ssh.rule=HostSNI(`*`)
      - traefik.tcp.routers.gitea-ssh.entrypoints=ssh
      - traefik.tcp.routers.gitea-ssh.service=gitea-ssh
      - traefik.tcp.services.gitea-ssh.loadbalancer.server.port=2222

File: Gitea app.ini

; Filename: app.ini
; Gitea configuration file
; 
; Ref: https://docs.gitea.io/en-us/config-cheat-sheet/
APP_NAME = Gitea: Git with a cup of tea
RUN_USER = nobody
RUN_MODE = prod
WORK_PATH = /var/lib/gitea

[repository]
ROOT = /var/lib/gitea/git/repositories

[repository.local]
LOCAL_COPY_PATH = /tmp/gitea/local-repo

[repository.upload]
TEMP_PATH = /tmp/gitea/uploads

[server]
APP_DATA_PATH = /var/lib/gitea
SSH_DOMAIN = TODO_TAILSCALE_IP
HTTP_PORT = 3000
ROOT_URL = https://gitea.example.com
DISABLE_SSH = false
; In rootless gitea container only internal ssh server is supported
START_SSH_SERVER = true
SSH_PORT = 2222
SSH_LISTEN_PORT = 2222
BUILTIN_SSH_SERVER_USER = git
LFS_START_SERVER = true
DOMAIN = gitea.example.com
LFS_JWT_SECRET = TODO_RANDOM_LFS_JWT_SECRET
OFFLINE_MODE = false

[lfs]
PATH = /var/lib/gitea/git/lfs

[database]
PATH = /var/lib/gitea/data/gitea.db
DB_TYPE = sqlite3
LOG_SQL = false

[session]
PROVIDER_CONFIG = /var/lib/gitea/data/sessions
PROVIDER = file

[picture]
AVATAR_UPLOAD_PATH = /var/lib/gitea/data/avatars
REPOSITORY_AVATAR_UPLOAD_PATH = /var/lib/gitea/data/gitea/repo-avatars
DISABLE_GRAVATAR = false
ENABLE_FEDERATED_AVATAR = true

[attachment]
PATH = /var/lib/gitea/data/attachments

[log]
ROOT_PATH = %(GITEA_WORK_DIR)/log
MODE = console
LEVEL = Warn
STACKTRACE_LEVEL = None
logger.router.MODE = ,
logger.xorm.MODE = ,
logger.access.MODE =

; this is the config options of "console" mode (used by MODE=console above)
[log.console]
MODE = console
FLAGS = stdflags
PREFIX =
COLORIZE = true

[security]
INSTALL_LOCK = true
SECRET_KEY = TODO_RANDOM_SECRET_KEY
INTERNAL_TOKEN = TODO_RANDOM_INTERNAL_TOKEN

[service]
DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW = true
REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL = false
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
ENABLE_CAPTCHA = false
DEFAULT_KEEP_EMAIL_PRIVATE = false
DEFAULT_ALLOW_CREATE_ORGANIZATION = false
DEFAULT_ENABLE_TIMETRACKING = false
NO_REPLY_ADDRESS = 
EMAIL_DOMAIN_ALLOWLIST = @gmail.com

; Auto create Google SSO users from @domain.com
; Gitea username will be the username part of the email (eg {username}@domain.com)
[oauth2_client]
ENABLE_AUTO_REGISTRATION = false
ACCOUNT_LINKING = disabled
REGISTER_EMAIL_CONFIRM = false
UPDATE_AVATAR = true
USERNAME = email

[oauth2]
JWT_SECRET = TODO_RANDOM_SECRET

[ui]
DEFAULT_THEME = dark-arc
THEMES = gitea,arc-green,dark-arc

[mailer]
ENABLED = true
FROM = noreply-gitea@example.com
PROTOCOL = smtp+starttls
SMTP_ADDR = in-v3.mailjet.com
SMTP_PORT = 587
USER = TODO_USER
PASSWD = TODO_PASSWORD

[openid]
ENABLE_OPENID_SIGNIN = false
ENABLE_OPENID_SIGNUP = false

[webhook]
ALLOWED_HOST_LIST = *

See Also:

  1. Gitea ACT Runner setup gitea-act-runner
  2. ACT Runner workflow for Gemini-CLI gemini-pr-review
  3. ACT Runner workflow for Kingfisher secrets scanning kingfisher-secrets-scan
  4. #TODO Laravel CI workflows -- Pint, Larastan, run migrations
  5. #TODO React CI workflows -- Biome
  6. #TODO Java CI workflows -- maven PMD, Spotless
  7. #TODO Renovate BOT -- SBOM update checker