219 lines
7.0 KiB
Bash
Executable File
219 lines
7.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ==============================================================================
|
|
# Gitea Deployment Script (Docker Compose + Traefik)
|
|
# ==============================================================================
|
|
# Deploys Gitea + PostgreSQL behind the shared Traefik reverse proxy.
|
|
#
|
|
# Usage: deploy-docker-gitea.sh
|
|
# deploy-docker-gitea.sh --domain git.us.an2.io
|
|
# deploy-docker-gitea.sh --remove [--purge] [--yes]
|
|
# ==============================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "${SCRIPT_DIR}/common.sh"
|
|
|
|
# --- Parse arguments ---
|
|
parse_args "$@"
|
|
|
|
# --- Service config ---
|
|
SERVICE_NAME="gitea"
|
|
BASE_DIR="/opt/${SERVICE_NAME}"
|
|
CONFIG_NAME="${SERVICE_NAME}"
|
|
UNIT_NAME="${SERVICE_NAME}-docker"
|
|
SSH_PORT="${SSH_PORT:-222}"
|
|
|
|
# --- Handle --remove ---
|
|
if [[ "$ARG_REMOVE" == "1" ]]; then
|
|
require_root
|
|
do_remove "$SERVICE_NAME" "$CONFIG_NAME" "$UNIT_NAME" "$BASE_DIR"
|
|
exit 0
|
|
fi
|
|
|
|
# --- Domain resolution: --domain > existing .env > default ---
|
|
# Read domain from .env without sourcing (avoids clobbering other vars)
|
|
if [[ -n "$ARG_DOMAIN" ]]; then
|
|
DOMAIN="$ARG_DOMAIN"
|
|
elif [[ -f "${BASE_DIR}/.env" ]] && grep -q '^DOMAIN=' "${BASE_DIR}/.env"; then
|
|
DOMAIN="$(grep '^DOMAIN=' "${BASE_DIR}/.env" | cut -d= -f2)"
|
|
else
|
|
DOMAIN="git.an2.io"
|
|
fi
|
|
|
|
# --- Detect current state for banner ---
|
|
traefik_status="Not found — will deploy"
|
|
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q '^traefik$'; then
|
|
traefik_status="Running"
|
|
elif [[ -f "${TRAEFIK_DIR}/docker-compose.yml" ]]; then
|
|
traefik_status="Stopped — will start"
|
|
fi
|
|
|
|
install_mode="Fresh install"
|
|
if [[ -f "${BASE_DIR}/.env" ]]; then
|
|
install_mode="Re-run (preserving data)"
|
|
fi
|
|
|
|
# --- Print deployment plan ---
|
|
echo ""
|
|
echo -e "${CYAN}══════════════════════════════════════════════${NC}"
|
|
echo -e "${CYAN} Deploying Gitea (Docker)${NC}"
|
|
echo -e "${CYAN}══════════════════════════════════════════════${NC}"
|
|
echo -e " Domain: ${DOMAIN}"
|
|
echo -e " Data: ${BASE_DIR}"
|
|
echo -e " SSH Port: ${SSH_PORT}"
|
|
echo -e " Traefik: ${traefik_status}"
|
|
echo -e " Mode: ${install_mode}"
|
|
echo -e "${CYAN}══════════════════════════════════════════════${NC}"
|
|
echo ""
|
|
|
|
# --- Check if already deployed and running ---
|
|
if [[ -f "${BASE_DIR}/docker-compose.yml" ]] && \
|
|
docker ps --format '{{.Names}}' 2>/dev/null | grep -q '^gitea$'; then
|
|
echo -e "${GREEN} Gitea is already running — nothing to do.${NC}"
|
|
echo ""
|
|
echo -e " Logs: docker logs -f gitea"
|
|
echo -e " Backup: ${SCRIPT_DIR}/backup-gitea.sh"
|
|
echo -e " Remove: $0 --remove [--purge]"
|
|
echo ""
|
|
exit 0
|
|
fi
|
|
|
|
# --- Shared infrastructure ---
|
|
require_root
|
|
detect_os
|
|
install_prerequisites
|
|
ensure_docker_network
|
|
ensure_traefik
|
|
configure_firewall "${SSH_PORT}/tcp"
|
|
|
|
# --- Backup restore check ---
|
|
if check_and_restore_backup "$SERVICE_NAME"; then
|
|
# Backup restored — source .env for credentials, but keep our resolved domain
|
|
saved_domain="$DOMAIN"
|
|
# shellcheck source=/dev/null
|
|
source "${BASE_DIR}/.env"
|
|
DOMAIN="$saved_domain"
|
|
else
|
|
# --- Fresh install ---
|
|
|
|
# Preserve credentials from existing .env on re-run
|
|
if [[ -f "${BASE_DIR}/.env" ]]; then
|
|
saved_domain="$DOMAIN"
|
|
# shellcheck source=/dev/null
|
|
source "${BASE_DIR}/.env"
|
|
DOMAIN="$saved_domain"
|
|
else
|
|
POSTGRES_USER="gitea"
|
|
POSTGRES_PASSWORD="$(generate_password)"
|
|
POSTGRES_DB="gitea"
|
|
fi
|
|
|
|
info "Creating directory layout..."
|
|
mkdir -p "${BASE_DIR}"/{postgres/data,gitea/data}
|
|
|
|
# --- Generate .env ---
|
|
cat > "${BASE_DIR}/.env" <<DOTENV
|
|
# Generated by deploy-docker-gitea.sh on $(date -Iseconds)
|
|
DOMAIN=${DOMAIN}
|
|
SSH_PORT=${SSH_PORT}
|
|
POSTGRES_USER=${POSTGRES_USER}
|
|
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
|
POSTGRES_DB=${POSTGRES_DB}
|
|
DOTENV
|
|
chmod 600 "${BASE_DIR}/.env"
|
|
ok ".env written."
|
|
|
|
# --- Generate docker-compose.yml ---
|
|
cat > "${BASE_DIR}/docker-compose.yml" <<'COMPOSE'
|
|
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
container_name: gitea-postgres
|
|
restart: unless-stopped
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
mem_limit: 2G
|
|
read_only: true
|
|
tmpfs:
|
|
- /tmp
|
|
- /var/run/postgresql
|
|
volumes:
|
|
- ./postgres/data:/var/lib/postgresql/data
|
|
environment:
|
|
- POSTGRES_USER
|
|
- POSTGRES_PASSWORD
|
|
- POSTGRES_DB
|
|
networks:
|
|
- gitea-internal
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "5"
|
|
|
|
gitea:
|
|
image: docker.gitea.com/gitea:1.25.5
|
|
container_name: gitea
|
|
restart: unless-stopped
|
|
depends_on:
|
|
postgres:
|
|
condition: service_started
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
mem_limit: 2G
|
|
environment:
|
|
- USER_UID=1000
|
|
- USER_GID=1000
|
|
- GITEA__database__DB_TYPE=postgres
|
|
- GITEA__database__HOST=gitea-postgres:5432
|
|
- GITEA__database__NAME=${POSTGRES_DB}
|
|
- GITEA__database__USER=${POSTGRES_USER}
|
|
- GITEA__database__PASSWD=${POSTGRES_PASSWORD}
|
|
- GITEA__server__ROOT_URL=https://${DOMAIN}
|
|
- GITEA__server__SSH_DOMAIN=${DOMAIN}
|
|
- GITEA__server__SSH_PORT=${SSH_PORT}
|
|
volumes:
|
|
- ./gitea/data:/data
|
|
- /etc/timezone:/etc/timezone:ro
|
|
- /etc/localtime:/etc/localtime:ro
|
|
ports:
|
|
- "${SSH_PORT}:22"
|
|
networks:
|
|
- gitea-internal
|
|
- traefik-public
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "5"
|
|
|
|
networks:
|
|
gitea-internal:
|
|
driver: bridge
|
|
traefik-public:
|
|
external: true
|
|
COMPOSE
|
|
ok "docker-compose.yml written."
|
|
fi
|
|
|
|
# --- Always do these (fresh or restored) ---
|
|
write_traefik_dynamic_config "$CONFIG_NAME" "$DOMAIN" "http://gitea:3000"
|
|
install_systemd_unit "$UNIT_NAME" "$BASE_DIR"
|
|
(cd "$BASE_DIR" && docker compose up -d)
|
|
wait_for_healthy "gitea" "http://localhost:3000/" 120
|
|
|
|
# --- Summary ---
|
|
echo ""
|
|
echo -e "${GREEN}══════════════════════════════════════════════${NC}"
|
|
echo -e "${GREEN} Gitea deployed successfully${NC}"
|
|
echo -e "${GREEN}══════════════════════════════════════════════${NC}"
|
|
echo -e " URL: https://${DOMAIN}"
|
|
echo -e " SSH: ssh://git@${DOMAIN}:${SSH_PORT}"
|
|
echo -e " Data: ${BASE_DIR}/"
|
|
echo -e " Traefik: ${TRAEFIK_DYNAMIC_DIR}/${CONFIG_NAME}.yml"
|
|
echo -e " Systemd: systemctl status ${UNIT_NAME}"
|
|
echo -e " Logs: docker logs -f gitea"
|
|
echo -e "${GREEN}══════════════════════════════════════════════${NC}"
|
|
echo ""
|