From 110f67c56751c6bcc91c2ab6b5f2487bead6c378 Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Sun, 22 Mar 2026 18:39:05 -0400 Subject: [PATCH] fix: add Gitea hardening config and script to disable registration + require sign-in Adds deploy/gitea/app.ini with hardened [service] settings and scripts/harden_gitea.sh to apply them on the server. The script backs up the existing config, patches the four required settings, restarts Gitea, and verifies the changes. Settings applied: - DISABLE_REGISTRATION = true - ALLOW_ONLY_EXTERNAL_REGISTRATION = false - SHOW_REGISTRATION_BUTTON = false - REQUIRE_SIGNIN_VIEW = true Fixes #988 Co-Authored-By: Claude Opus 4.6 --- deploy/gitea/app.ini | 21 +++++ scripts/harden_gitea.sh | 169 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 deploy/gitea/app.ini create mode 100755 scripts/harden_gitea.sh diff --git a/deploy/gitea/app.ini b/deploy/gitea/app.ini new file mode 100644 index 00000000..976a19db --- /dev/null +++ b/deploy/gitea/app.ini @@ -0,0 +1,21 @@ +; ── Gitea Hardening — Security Overrides ───────────────────────────────────── +; +; Merge these settings into your Gitea custom/conf/app.ini. +; +; On a default Gitea install (Docker or bare-metal): +; /path/to/gitea/custom/conf/app.ini +; +; After editing, restart Gitea: +; systemctl restart gitea # bare-metal +; docker restart # Docker +; +; See also: scripts/harden_gitea.sh (automated version) + +[service] +; Disable public registration — only admins can create accounts +DISABLE_REGISTRATION = true +ALLOW_ONLY_EXTERNAL_REGISTRATION = false +SHOW_REGISTRATION_BUTTON = false + +; Require sign-in to view any content (repos, explore, etc.) +REQUIRE_SIGNIN_VIEW = true diff --git a/scripts/harden_gitea.sh b/scripts/harden_gitea.sh new file mode 100755 index 00000000..2ea031ba --- /dev/null +++ b/scripts/harden_gitea.sh @@ -0,0 +1,169 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ── Gitea Hardening Script ────────────────────────────────────────────────── +# +# Disables public registration and requires sign-in to view content. +# Refs: Issue #988 +# +# Usage (on the Gitea server): +# sudo bash scripts/harden_gitea.sh +# sudo bash scripts/harden_gitea.sh --config /path/to/custom/conf/app.ini +# sudo bash scripts/harden_gitea.sh --docker gitea # restart via docker +# +# What it does: +# 1. Patches [service] section in app.ini +# 2. Restarts Gitea so changes take effect +# 3. Verifies the changes are active + +BOLD='\033[1m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +info() { echo -e "${GREEN}[+]${NC} $1"; } +warn() { echo -e "${YELLOW}[!]${NC} $1"; } +error() { echo -e "${RED}[x]${NC} $1"; } + +# ── Defaults ──────────────────────────────────────────────────────────────── + +# Common Gitea config paths (checked in order) +SEARCH_PATHS=( + "/etc/gitea/app.ini" + "/opt/gitea/custom/conf/app.ini" + "/data/gitea/conf/app.ini" + "/app/gitea/conf/app.ini" +) + +CONFIG_PATH="" +DOCKER_CONTAINER="" +SYSTEMD_SERVICE="gitea" + +# ── Parse arguments ───────────────────────────────────────────────────────── + +while [[ $# -gt 0 ]]; do + case $1 in + --config) CONFIG_PATH="$2"; shift 2 ;; + --docker) DOCKER_CONTAINER="$2"; shift 2 ;; + --service) SYSTEMD_SERVICE="$2"; shift 2 ;; + -h|--help) + echo "Usage: $0 [--config /path/to/app.ini] [--docker container] [--service name]" + exit 0 + ;; + *) error "Unknown option: $1"; exit 1 ;; + esac +done + +# ── Find config ───────────────────────────────────────────────────────────── + +if [ -z "$CONFIG_PATH" ]; then + for path in "${SEARCH_PATHS[@]}"; do + if [ -f "$path" ]; then + CONFIG_PATH="$path" + break + fi + done +fi + +# If using Docker, try to find config inside the container +if [ -z "$CONFIG_PATH" ] && [ -n "$DOCKER_CONTAINER" ]; then + for path in "${SEARCH_PATHS[@]}"; do + if docker exec "$DOCKER_CONTAINER" test -f "$path" 2>/dev/null; then + CONFIG_PATH="$path" + info "Found config inside container at $path" + break + fi + done +fi + +if [ -z "$CONFIG_PATH" ]; then + error "Could not find Gitea app.ini. Use --config to specify the path." + exit 1 +fi + +info "Using config: $CONFIG_PATH" + +# ── Backup ────────────────────────────────────────────────────────────────── + +BACKUP="${CONFIG_PATH}.bak.$(date +%Y%m%d%H%M%S)" + +if [ -n "$DOCKER_CONTAINER" ]; then + docker exec "$DOCKER_CONTAINER" cp "$CONFIG_PATH" "$BACKUP" +else + cp "$CONFIG_PATH" "$BACKUP" +fi +info "Backup saved to $BACKUP" + +# ── Apply settings ────────────────────────────────────────────────────────── + +apply_setting() { + local key="$1" + local value="$2" + local file="$3" + + if [ -n "$DOCKER_CONTAINER" ]; then + # Check if key exists (commented or not) and update, otherwise append to [service] + if docker exec "$DOCKER_CONTAINER" grep -qE "^;?\s*${key}\s*=" "$file" 2>/dev/null; then + docker exec "$DOCKER_CONTAINER" sed -i "s|^;*\s*${key}\s*=.*|${key} = ${value}|" "$file" + else + # Append after [service] section header + docker exec "$DOCKER_CONTAINER" sed -i "/^\[service\]/a ${key} = ${value}" "$file" + fi + else + if grep -qE "^;?\s*${key}\s*=" "$file" 2>/dev/null; then + sed -i "s|^;*\s*${key}\s*=.*|${key} = ${value}|" "$file" + else + # Ensure [service] section exists, then append + if ! grep -q '^\[service\]' "$file"; then + printf '\n[service]\n' >> "$file" + fi + sed -i "/^\[service\]/a ${key} = ${value}" "$file" + fi + fi +} + +info "Applying hardening settings..." + +apply_setting "DISABLE_REGISTRATION" "true" "$CONFIG_PATH" +apply_setting "ALLOW_ONLY_EXTERNAL_REGISTRATION" "false" "$CONFIG_PATH" +apply_setting "SHOW_REGISTRATION_BUTTON" "false" "$CONFIG_PATH" +apply_setting "REQUIRE_SIGNIN_VIEW" "true" "$CONFIG_PATH" + +info "Settings applied:" +info " DISABLE_REGISTRATION = true" +info " ALLOW_ONLY_EXTERNAL_REGISTRATION = false" +info " SHOW_REGISTRATION_BUTTON = false" +info " REQUIRE_SIGNIN_VIEW = true" + +# ── Restart Gitea ─────────────────────────────────────────────────────────── + +echo "" +if [ -n "$DOCKER_CONTAINER" ]; then + info "Restarting Gitea container: $DOCKER_CONTAINER" + docker restart "$DOCKER_CONTAINER" +elif systemctl is-active --quiet "$SYSTEMD_SERVICE" 2>/dev/null; then + info "Restarting Gitea via systemd: $SYSTEMD_SERVICE" + systemctl restart "$SYSTEMD_SERVICE" +else + warn "Could not detect Gitea service. Restart Gitea manually to apply changes." +fi + +# ── Verify ────────────────────────────────────────────────────────────────── + +echo "" +info "Verification — current [service] settings:" +if [ -n "$DOCKER_CONTAINER" ]; then + docker exec "$DOCKER_CONTAINER" grep -A 20 '^\[service\]' "$CONFIG_PATH" | head -25 +else + grep -A 20 '^\[service\]' "$CONFIG_PATH" | head -25 +fi + +echo "" +echo -e "${GREEN}${BOLD} Gitea hardening complete.${NC}" +echo "" +echo " Registration: DISABLED" +echo " Sign-in required to view: YES" +echo "" +echo " Backup: $BACKUP" +echo "" -- 2.43.0