diff --git a/gitea/SETUP.md b/gitea/SETUP.md new file mode 100644 index 0000000..3ac50b7 --- /dev/null +++ b/gitea/SETUP.md @@ -0,0 +1,42 @@ +# Service Setup Guide: Gitea + +Gitea is a painless self-hosted Git service covering the entire software development lifecycle. + +## 1. Pre-Setup (Manual) +### Create Service User +- [ ] **Manual**: Create a local user named `svc-gitea` in Synology DSM (Control Panel > User & Group). +- [ ] **Manual**: Give this user read/write access to the `docker` shared folder. + +### Get User IDs +- [ ] **Manual**: SSH into your NAS and run `sudo synouser --get svc-gitea`. +- [ ] **Confirmed IDs**: Locate the `User ID` (PUID) and `Group ID` (PGID). +- [ ] **Action**: Open `create_gitea_folders.sh` and update the `USER_ID="[PUID]:[PGID]"` line. +- [ ] **Action**: Open `stack.env` and update the `USER_UID` and `USER_GID` variables. + +## 2. Infrastructure Setup +### Run Setup Script +- [ ] **Action**: Run the setup script in Dry-Run mode to verify changes: + ```bash + sudo bash create_gitea_folders.sh + ``` +- [ ] **Action**: Apply the folder creation and ownership settings: + ```bash + sudo bash create_gitea_folders.sh --run + ``` + +## 3. Portainer Deployment +### Environment Variables +- [ ] **Action**: Review `stack.env`. Ensure `DOMAIN` and `ROOT_URL` exactly match the Cloudflare configuration (e.g., `gitea.chengs.uk`) to prevent the mismatch security error. + +### Deploy Stack +- [ ] **Action**: Create a new stack named `gitea-stack`. +- [ ] **Action**: Upload or paste the environment variables from `stack.env`. +- [ ] **Action**: Paste the content of `docker-compose.portainer.yml` and deploy. +- [ ] **Verification**: Access the Gitea web interface at `http://[NAS_IP]:3001` (or whatever HTTP port you defined). + +## 4. Troubleshooting +### ROOT_URL Error Mismatch +If you ever see the error: +`Your ROOT_URL in app.ini is "http://...", it's unlikely matching the site you are visiting.` + +This means Gitea's security system noticed you are accessing it from a different URL than it was configured for. Ensure the `GITEA__server__DOMAIN` and `GITEA__server__ROOT_URL` environment variables exactly match the public address you use (like a Cloudflare Tunnel domain). This is already permanently fixed via the environment variables in the provided `docker-compose.portainer.yml` file. diff --git a/gitea/create_gitea_folders.sh b/gitea/create_gitea_folders.sh new file mode 100644 index 0000000..1faf1cf --- /dev/null +++ b/gitea/create_gitea_folders.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# Default to dry-run mode +DRY_RUN=true +if [[ "$1" == "--run" || "$1" == "-r" ]]; then DRY_RUN=false; fi + +if [ "$DRY_RUN" = "true" ]; then + echo "--- DRY RUN MODE ---" + echo "To apply changes, run: sudo bash $0 --run" + echo "--------------------" +fi + +# Configuration +BASE="/volume1/docker/gitea" +# Replace with your actual Synology PUID/PGID for the svc-gitea user +# Using 1033 as requested by user +USER_ID="1033:65538" # svc-gitea + +# Helper functions +run_mkdir() { + local path=$1 + if [ -d "$path" ]; then + echo "[OK] Folder exists, no changes will be made: $path" + else + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CREATE] Folder: $path" + else + echo "[EXECUTE] Creating folder: $path" + mkdir -p "$path" + fi + fi +} + +run_chown_recursive() { + local owner=$1; local path=$2 + local uid=${owner%%:*}; local gid=${owner#*:} + + # Check if folder exists first + if [ ! -d "$path" ]; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL SET] Owner to $owner upon creation: $path" + else + echo "[EXECUTE] Setting owner to $owner (recursive): $path" + chown -R "$owner" "$path" + fi + return + fi + + # Check if any file/folder inside diverges from the target ownership + if find "$path" \( ! -uid "$uid" -o ! -gid "$gid" \) | grep -q .; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CHANGE] Owner to $owner (recursive): $path" + else + echo "[EXECUTE] Setting owner to $owner (recursive): $path" + chown -R "$owner" "$path" + fi + else + echo "[OK] Owner is $owner, no changes will be made: $path" + fi +} + +run_chmod_recursive() { + local mode=$1; local path=$2 + + # Check if folder exists first + if [ ! -d "$path" ]; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL SET] Permissions to $mode upon creation: $path" + else + echo "[EXECUTE] Setting permissions to $mode (recursive): $path" + chmod -R "$mode" "$path" + fi + return + fi + + # Check if any file/folder inside diverges from the target permissions + if find "$path" ! -perm -"$mode" | grep -q .; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CHANGE] Permissions to $mode (recursive): $path" + else + echo "[EXECUTE] Setting permissions to $mode (recursive): $path" + chmod -R "$mode" "$path" + fi + else + echo "[OK] Permissions are $mode, no changes will be made: $path" + fi +} + +# Run tasks +run_mkdir "${BASE}/data" +run_mkdir "${BASE}/config" +run_chown_recursive "$USER_ID" "${BASE}" +run_chmod_recursive 750 "${BASE}" + +if [ "$DRY_RUN" = "false" ]; then + echo "Done." +fi diff --git a/gitea/docker-compose.portainer.yml b/gitea/docker-compose.portainer.yml new file mode 100644 index 0000000..c8d6934 --- /dev/null +++ b/gitea/docker-compose.portainer.yml @@ -0,0 +1,32 @@ +version: "3" + +networks: + gitea: + external: false + +services: + server: + image: gitea/gitea:latest + container_name: gitea + environment: + - USER_UID=${USER_UID} + - USER_GID=${USER_GID} + - TZ=${TZ} + + # Fix for ROOT_URL Domain Check Error + - GITEA__server__DOMAIN=${DOMAIN} + - GITEA__server__ROOT_URL=${ROOT_URL} + - GITEA__server__SSH_PORT=${SSH_PORT} + - GITEA__server__HTTP_PORT=3000 + restart: always + networks: + - gitea + volumes: + - /volume1/docker/gitea/data:/data + - /volume1/docker/gitea/config:/etc/gitea + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + ports: + # Map the local NAS port to the container's internal 3000 port + - "${HTTP_PORT}:3000" + - "${SSH_PORT}:22" diff --git a/gitea/stack.env b/gitea/stack.env new file mode 100644 index 0000000..12e20ee --- /dev/null +++ b/gitea/stack.env @@ -0,0 +1,15 @@ +# Synology Execution User +# Change these to match the svc-gitea user IDs +USER_UID=1033 +USER_GID=65538 +TZ=America/Toronto + +# Gitea Configuration +# Ensure this matches your exact Cloudflare tunnel URL +DOMAIN=gitea.chengs.uk +ROOT_URL=https://gitea.chengs.uk/ + +# Local NAS Ports +# Set the HTTP port (e.g. 3001 if that's what you were using before) +HTTP_PORT=3001 +SSH_PORT=2222