Files
docker/git/Gemini.md

284 lines
13 KiB
Markdown

Okay, let's switch gears to run Gitea using Docker and Docker Compose. This is generally the recommended approach as it isolates Gitea and its dependencies.
We'll still create a user on the *host* system to own the data volumes, ensuring correct permissions *outside* the container. The Gitea container itself runs internally as a user (usually `git`, UID/GID 1000 by default in the official image), and Docker maps the volume permissions.
**Key Components:**
1. **`docker-compose.yml`:** Defines the Gitea service and potentially a database service (e.g., PostgreSQL).
2. **Host Directory Structure:** Directories on the host machine to store persistent Gitea data (repos, config, database files, logs).
3. **Host User (`git`):** A user on the host system to own these directories, matching the UID/GID used inside the container.
4. **`app.ini`:** The Gitea configuration file, placed in the host directory structure to be mounted into the container.
**Steps:**
**1. Create Host User and Group (if they don't exist)**
We need a user and group on the host machine. We'll use the standard non-privileged UID/GID `1000`, which the official Gitea Docker image typically uses internally for its `git` user.
```bash
# Run these commands with sudo
sudo groupadd --gid 1000 git || echo "Group git (GID 1000) likely already exists."
sudo useradd --system --uid 1010 --gid 1010 --comment "Gitea Docker User" --shell /usr/sbin/nologin --home /opt/gitea git || echo "User git (UID 1010) likely already exists."
# Verify (optional)
id git
```
* If UID/GID 1000 is already taken on your system, choose another (e.g., 1001) and make sure to specify it in the `docker-compose.yml` using `user: UID:GID`. However, sticking to 1000 is often simplest if possible.
* `--shell /usr/sbin/nologin` prevents this user from being used for interactive logins.
* `--home /opt/gitea` sets a nominal home directory, though we won't rely on it directly.
**2. Create Host Directory Structure and Initial `app.ini`**
We'll create a directory (e.g., `/opt/gitea`) on the host to hold all persistent data and configuration.
```bash
#!/bin/bash
# Exit immediately if a command exits with a non-zero status.
set -e
# --- Configuration ---
HOST_GITEA_ROOT="/opt/gitea" # Or choose another location like /srv/gitea
HOST_GITEA_DATA_DIR="${HOST_GITEA_ROOT}/data"
HOST_GITEA_CONFIG_DIR="${HOST_GITEA_ROOT}/config" # Gitea image expects config in /data/gitea/conf
HOST_GITEA_LOG_DIR="${HOST_GITEA_ROOT}/log" # We'll mount this separately for clarity
HOST_USER_UID=1010 # Must match the UID used inside the container (or specified in docker-compose)
HOST_USER_GID=1010 # Must match the GID used inside the container (or specified in docker-compose)
# --- Pre-checks ---
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root (or using sudo)"
exit 1
fi
if ! getent passwd "${HOST_USER_UID}" > /dev/null 2>&1; then
echo "ERROR: User with UID ${HOST_USER_UID} does not exist. Please create it first."
exit 1
fi
if ! getent group "${HOST_USER_GID}" > /dev/null 2>&1; then
echo "ERROR: Group with GID ${HOST_USER_GID} does not exist. Please create it first."
exit 1
fi
echo "--- Gitea Docker Host Setup ---"
# --- Create Directories ---
echo "[1/3] Creating host directories in ${HOST_GITEA_ROOT}..."
mkdir -pv "${HOST_GITEA_DATA_DIR}"
mkdir -pv "${HOST_GITEA_CONFIG_DIR}"
mkdir -pv "${HOST_GITEA_LOG_DIR}"
echo "Host directories created."
# --- Create Minimal app.ini ---
# Note: Gitea container expects app.ini at /data/gitea/conf/app.ini
# We will mount HOST_GITEA_CONFIG_DIR to /etc/gitea for easier access,
# but Gitea might ignore it if /data/gitea/conf/app.ini exists from the volume mount.
# A safer approach is often to let Gitea create the first config inside the /data mount
# and then modify it, or mount the specific file. Let's mount the dir /etc/gitea for now.
GITEA_CONF_FILE="${HOST_GITEA_CONFIG_DIR}/app.ini"
echo "[2/3] Creating minimal configuration file: ${GITEA_CONF_FILE}..."
cat << EOF > "${GITEA_CONF_FILE}"
; Example Gitea Configuration File for Docker
; Paths here usually refer to locations INSIDE the container.
; For details, see: https://docs.gitea.com/administration/config-cheat-sheet
APP_NAME = Gitea Docker
RUN_USER = git ; User inside the container
RUN_MODE = prod
[server]
DOMAIN = git.ptrwd.com ; CHANGE THIS to your actual domain/IP
HTTP_PORT = 3000 ; Port inside the container
ROOT_URL = http://git.ptrwd.com:3000/ ; CHANGE THIS along with DOMAIN
DISABLE_SSH = false
SSH_DOMAIN = %(DOMAIN)s ; Use value from DOMAIN
SSH_PORT = 22 ; Port inside the container (we map 2222 to this externally)
SSH_LISTEN_PORT = 22 ; Make built-in SSH listen on port 22 inside the container
START_SSH_SERVER = true ; Use the built-in SSH server
LFS_START_SERVER = true
LFS_CONTENT_PATH = /data/gitea/lfs ; Path inside the container
[repository]
ROOT = /data/git/gitea-repositories ; Path inside the container
[log]
ROOT_PATH = /data/log ; Path inside container (maps to HOST_GITEA_LOG_DIR)
MODE = console,file ; Log to console (for docker logs) and file
LEVEL = Info
[database]
; === IMPORTANT: Configure your database ===
; Option 1: SQLite3 (Simplest, place DB inside the data volume)
DB_TYPE = sqlite3
PATH = /data/gitea/gitea.db ; Path inside the container
;
; Option 2: PostgreSQL (Recommended for production, use docker-compose service name as host)
; DB_TYPE = postgres
; HOST = db:5432 ; 'db' is the service name in docker-compose.yml
; NAME = gitea
; USER = gitea
; PASSWD = 'YOUR_POSTGRES_PASSWORD' ; Use secrets or env vars in real setup
; SSL_MODE = disable
;
; Option 3: MySQL
; DB_TYPE = mysql
; HOST = db:3306 ; 'db' is the service name in docker-compose.yml
; NAME = gitea
; USER = gitea
; PASSWD = 'YOUR_MYSQL_PASSWORD' ; Use secrets or env vars in real setup
; CHARSET = utf8mb4
[service]
REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL = false
DISABLE_REGISTRATION = false
ENABLE_CAPTCHA = false
REQUIRE_SIGNIN_VIEW = false
[security]
INSTALL_LOCK = true ; Set to true AFTER first install via web UI
SECRET_KEY = PLEASE_CHANGE_ME_SECRET_KEY_! ; CHANGE THIS! Generate with 'docker exec <container_name> gitea generate secret SECRET_KEY'
INTERNAL_TOKEN = PLEASE_CHANGE_ME_INTERNAL_TOKEN_! ; CHANGE THIS! Generate with 'docker exec <container_name> gitea generate secret INTERNAL_TOKEN'
PASSWORD_HASH_ALGO = pbkdf2 ; Default and recommended
[session]
PROVIDER = file
PROVIDER_CONFIG = /data/sessions ; Path inside the container
[picture]
AVATAR_UPLOAD_PATH = /data/gitea/avatars ; Path inside the container
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars ; Path inside the container
[attachment]
PATH = /data/gitea/attachments ; Path inside the container
EOF
echo "Minimal ${GITEA_CONF_FILE} created."
echo " >> IMPORTANT: Review and edit ${GITEA_CONF_FILE} with your specific settings (DOMAIN, ROOT_URL, Database, Secret Keys)!"
# --- Set Ownership ---
echo "[3/3] Setting ownership for ${HOST_GITEA_ROOT} to ${HOST_USER_UID}:${HOST_USER_GID}..."
chown -R "${HOST_USER_UID}":"${HOST_USER_GID}" "${HOST_GITEA_ROOT}"
# Set permissions (optional, ownership is key for docker volumes)
# chmod -R u+rwX,go= "${HOST_GITEA_ROOT}" # Give owner full control, deny group/others
chmod 750 "${HOST_GITEA_ROOT}" # Owner rwx, group rx, others ---
find "${HOST_GITEA_ROOT}" -type d -exec chmod 750 {} \; # Dirs: owner rwx, group rx
find "${HOST_GITEA_ROOT}" -type f -exec chmod 640 {} \; # Files: owner rw, group r
echo "Ownership and basic permissions set."
echo "--- Host Setup Complete ---"
echo "Next steps:"
echo "1. **CRITICAL:** Edit ${GITEA_CONF_FILE} for your specific needs (Domain, Database, Secrets!)."
echo "2. Create the docker-compose.yml file."
echo "3. Run 'docker compose up -d' in the directory containing docker-compose.yml."
```
**How to use the script:**
1. Save the script (e.g., `setup_docker_gitea_host.sh`).
2. Make it executable: `chmod +x setup_docker_gitea_host.sh`.
3. Run with sudo: `sudo ./setup_docker_gitea_host.sh`.
4. **Crucially, edit the generated `/opt/gitea/config/app.ini` file** with your actual domain, database choice, and generate/set real secret keys *before* starting the container.
**3. Create `docker-compose.yml`**
Create this file in a convenient location (e.g., in `/opt/gitea` or a dedicated project directory). This example uses PostgreSQL, which is recommended for production.
```yaml
# /opt/gitea/docker-compose.yml
# or ~/gitea-docker/docker-compose.yml
networks:
gitea-net:
external: false
services:
gitea:
image: gitea/gitea:latest # Use a specific version tag in production, e.g., :1.21.5
container_name: gitea
restart: always
environment:
# All config is primarily done via app.ini now, but you could pass some simpler ones here
- USER_UID=1010 # Matches the host user created
- USER_GID=1010 # Matches the host group created
- GITEA__database__DB_TYPE=postgres # Example: Overriding app.ini via env var if needed
- GITEA__database__HOST=db:5432 # Using double underscore convention
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea_password # CHANGE THIS! Use docker secrets ideally
networks:
- gitea-net
volumes:
# Mount the main data directory from the host
- ./data:/data # Maps host's ./data (relative to compose file) to container's /data
# Mount the config directory separately (optional, but explicit)
- ./config:/etc/gitea # Maps host's ./config to container's /etc/gitea
# Mount log directory
- ./log:/data/log # Maps host's ./log to container's /data/log (matches app.ini)
# Timezone consistency
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000" # Map host port 3000 to container port 3000 (HTTP)
- "2222:22" # Map host port 2222 to container port 22 (SSH)
depends_on:
db:
condition: service_healthy # Wait for postgres to be healthy
db:
image: postgres:15 # Use a specific version
container_name: gitea-db
restart: always
environment:
- POSTGRES_USER=gitea # CHANGE THIS if needed
- POSTGRES_PASSWORD=gitea_password # CHANGE THIS! Must match GITEA__database__PASSWD
- POSTGRES_DB=gitea # CHANGE THIS if needed
networks:
- gitea-net
volumes:
# Persist postgres data on the host - create a 'postgres' dir next to 'data', 'config', 'log'
- ./postgres:/var/lib/postgresql/data
healthcheck:
# Basic check to see if postgres is ready to accept connections
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 5
volumes:
gitea_data:
gitea_config:
postgres_data:
```
**Explanation:**
* **`user: "1000:1000"` (Optional but good practice):** You can explicitly add this under the `gitea:` service definition to force the container process to run as UID/GID 1000, ensuring it matches the host directory ownership. The official image usually handles this, but being explicit can prevent permission issues.
* **Volumes (`./data:/data`, etc.):** We use *bind mounts*. This maps the directories we created on the host (`/opt/gitea/data`, `/opt/gitea/config`, etc.) directly into the specified paths inside the container. Docker uses the ownership we set on the host directories (`chown 1000:1000`).
* **`app.ini` Location:** The Gitea image typically looks for `app.ini` within its data directory (`/data/gitea/conf/app.ini`). By mounting `./config:/etc/gitea` and `./data:/data`, the container *should* find the config. If you have issues, you might need to adjust the volume mount for config or ensure the `app.ini` is placed at `/opt/gitea/data/gitea/conf/app.ini` on the host *before* starting. Mounting `/etc/gitea` is often cleaner if the image respects `GITEA_CUSTOM`. For simplicity, the setup script places it in `./config`, matching the volume mount. Adjust if Gitea doesn't pick it up.
* **Database:** The `db` service uses the official Postgres image. Its data is persisted in `./postgres` on the host. The Gitea container connects to it using the service name `db` as the hostname. **Change the default passwords!**
* **Ports:** `3000:3000` maps the web UI port. `2222:22` maps host port 2222 to the container's SSH port 22 (make sure your host's firewall allows port 2222).
* **Networks:** A dedicated network `gitea-net` allows the containers to communicate easily using service names (`gitea`, `db`).
* **Healthcheck:** Ensures Gitea only starts *after* PostgreSQL is ready.
**4. Running Gitea**
1. Navigate to the directory where you saved `docker-compose.yml` (e.g., `/opt/gitea`).
2. Ensure you have edited `/opt/gitea/config/app.ini` appropriately (Domain, DB, **Secrets**). Generate secrets using `docker run --rm gitea/gitea:latest gitea generate secret SECRET_KEY` etc., if needed.
3. Start the services in detached mode:
```bash
cd /opt/gitea
docker compose up -d
```
4. Check the logs:
```bash
docker compose logs -f gitea
docker compose logs -f db
```
5. Access Gitea in your browser at `http://<your-host-ip-or-domain>:3000`.
6. Clone via SSH using `ssh://git@<your-host-ip-or-domain>:2222/user/repo.git`.
This Docker setup provides isolation, easier dependency management (database), and uses host volumes with correct permissions managed by the `git` (UID/GID 1000) user on the host.