init: project structure, .gitignore, .env.example, runners.conf.example
- .gitignore: excludes .env, runners.conf, certs, temp files, editor files - .env.example: all configuration variables with sections and descriptions - runners.conf.example: dynamic runner definition format (pipe-delimited) - PLAN.md: comprehensive implementation plan with DoD for all 18 milestones - CLAUDE.md: project conventions and instructions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
5
.claude/settings.json
Normal file
5
.claude/settings.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": ["Bash(*)"]
|
||||||
|
}
|
||||||
|
}
|
||||||
124
.env.example
Normal file
124
.env.example
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# .env.example — Gitea Migration Configuration
|
||||||
|
# Copy to .env and populate all PRE-POPULATED values before running preflight
|
||||||
|
# AUTO-POPULATED values will be filled in by scripts during execution
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# UNRAID SERVER
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
UNRAID_IP= # Static IP of Unraid server
|
||||||
|
UNRAID_SSH_USER= # SSH username for Unraid
|
||||||
|
UNRAID_SSH_PORT=22 # SSH port (default 22)
|
||||||
|
UNRAID_GITEA_PORT=3000 # Port Gitea web UI will listen on
|
||||||
|
UNRAID_GITEA_SSH_PORT=2222 # Port for git-over-SSH (host 22 is taken by SSH server)
|
||||||
|
UNRAID_GITEA_DATA_PATH= # Absolute path on NVMe for Gitea data (e.g. /mnt/nvme/gitea)
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# FEDORA SERVER
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
FEDORA_IP= # Static IP of Fedora server
|
||||||
|
FEDORA_SSH_USER= # SSH username for Fedora
|
||||||
|
FEDORA_SSH_PORT=22 # SSH port (default 22)
|
||||||
|
FEDORA_GITEA_PORT=3000 # Port Gitea web UI will listen on
|
||||||
|
FEDORA_GITEA_SSH_PORT=2222 # Port for git-over-SSH (host 22 is taken by SSH server)
|
||||||
|
FEDORA_GITEA_DATA_PATH= # Absolute path on NVMe for Gitea data (e.g. /mnt/nvme/gitea)
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# GITEA — SHARED CREDENTIALS (used on both Unraid + Fedora instances)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
GITEA_ADMIN_USER= # Admin username (same on both instances)
|
||||||
|
GITEA_ADMIN_PASSWORD= # Admin password (min 8 chars, same on both instances)
|
||||||
|
GITEA_ADMIN_EMAIL= # Admin email (same on both instances)
|
||||||
|
GITEA_ORG_NAME= # Organization name to create (e.g. mifi-llc)
|
||||||
|
GITEA_INSTANCE_NAME= # Display name for the Gitea instance (e.g. MIFI Git)
|
||||||
|
GITEA_DB_TYPE=sqlite3 # Database type — sqlite3 is sufficient for your scale
|
||||||
|
GITEA_VERSION=1.23 # Gitea Docker image tag (e.g. 1.23, 1.23.1, latest)
|
||||||
|
ACT_RUNNER_VERSION=0.2.11 # act_runner version for all runners (e.g. 0.2.11, latest)
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# GITEA — PRIMARY INSTANCE (Unraid)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
GITEA_DOMAIN= # Public domain/subdomain pointing to Unraid (e.g. git.yourdomain.com)
|
||||||
|
GITEA_INTERNAL_URL= # Internal URL (e.g. http://UNRAID_IP:3000) used by scripts
|
||||||
|
# AUTO-POPULATED by phase1 scripts:
|
||||||
|
GITEA_ADMIN_TOKEN= # API token for primary instance — do not fill manually
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# GITEA — BACKUP INSTANCE (Fedora)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
GITEA_BACKUP_INTERNAL_URL= # Internal URL of Fedora Gitea (e.g. http://FEDORA_IP:3000)
|
||||||
|
GITEA_BACKUP_MIRROR_INTERVAL=8h # How often Fedora pulls from Unraid (e.g. 8h, 24h)
|
||||||
|
BACKUP_STORAGE_PATH= # Absolute path on Fedora to store gitea dump archives (e.g. /mnt/nvme/gitea-backups)
|
||||||
|
BACKUP_RETENTION_COUNT=5 # Number of backup archives to keep (older ones are pruned)
|
||||||
|
# AUTO-POPULATED by phase2 scripts:
|
||||||
|
GITEA_BACKUP_ADMIN_TOKEN= # API token for backup instance — do not fill manually
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# RUNNERS
|
||||||
|
# Runner definitions live in runners.conf (see runners.conf.example)
|
||||||
|
# Use manage_runner.sh to add/remove runners at any time
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# AUTO-POPULATED by phase1 scripts — do not fill manually:
|
||||||
|
GITEA_RUNNER_REGISTRATION_TOKEN= # Retrieved from Gitea admin panel via API
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# REPOSITORIES
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# GitHub source repos (for migration import)
|
||||||
|
GITHUB_USERNAME= # GitHub username or org name
|
||||||
|
GITHUB_TOKEN= # GitHub personal access token (needs repo read scope)
|
||||||
|
|
||||||
|
# Repo names — must match exactly as they appear on GitHub
|
||||||
|
REPO_1_NAME= # e.g. android-kotlin-app
|
||||||
|
REPO_2_NAME= # e.g. ios-swiftui-app
|
||||||
|
REPO_3_NAME= # e.g. go-cli-tool
|
||||||
|
|
||||||
|
# Migration options (true/false)
|
||||||
|
MIGRATE_ISSUES=false # Migrate GitHub issues to Gitea
|
||||||
|
MIGRATE_LABELS=true # Migrate GitHub labels
|
||||||
|
MIGRATE_MILESTONES=false # Migrate GitHub milestones
|
||||||
|
MIGRATE_WIKI=false # Migrate GitHub wiki
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# GITHUB MIRROR (offsite backup)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
GITHUB_MIRROR_TOKEN= # GitHub PAT with repo write scope (for push mirroring)
|
||||||
|
# Can be same as GITHUB_TOKEN if it has write scope
|
||||||
|
GITHUB_MIRROR_INTERVAL=8h # How often Gitea pushes to GitHub
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# NGINX REVERSE PROXY (existing Docker container on Unraid)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
NGINX_CONTAINER_NAME= # Name of existing Nginx Docker container (e.g. nginx, swag)
|
||||||
|
NGINX_CONF_PATH= # Host path to Nginx conf.d directory (e.g. /mnt/user/appdata/nginx/conf.d)
|
||||||
|
SSL_MODE=letsencrypt # SSL mode: "letsencrypt" (auto-provision via Certbot) or "existing" (provide cert paths)
|
||||||
|
SSL_EMAIL= # Email for Let's Encrypt (only if SSL_MODE=letsencrypt)
|
||||||
|
SSL_CERT_PATH= # Absolute path to SSL cert on Unraid (only if SSL_MODE=existing)
|
||||||
|
SSL_KEY_PATH= # Absolute path to SSL key on Unraid (only if SSL_MODE=existing)
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# BRANCH PROTECTION
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
PROTECTED_BRANCH=main # Branch to protect across all repos
|
||||||
|
REQUIRE_PR_REVIEW=false # Require PR review before merge (true/false)
|
||||||
|
REQUIRED_APPROVALS=1 # Number of approvals required if above is true
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# SECURITY (Phase 9 — post-migration)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
SEMGREP_VERSION=latest # Semgrep OSS version to pin
|
||||||
|
TRIVY_VERSION=latest # Trivy version to pin
|
||||||
|
GITLEAKS_VERSION=latest # Gitleaks version to pin
|
||||||
|
SECURITY_FAIL_ON_ERROR=true # Block PR merge if security scan fails (true/false)
|
||||||
22
.gitignore
vendored
Normal file
22
.gitignore
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Secrets — never commit
|
||||||
|
.env
|
||||||
|
runners.conf
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
*.crt
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Temp files from script runs
|
||||||
|
/tmp/
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Backup archives
|
||||||
|
*.zip
|
||||||
|
|
||||||
|
# Editor / IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*~
|
||||||
46
CLAUDE.md
Normal file
46
CLAUDE.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Gitea Migration Toolkit
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
Bash-based automation toolkit for migrating 3 GitHub repos to self-hosted Gitea. All scripts run from MacBook, SSHing into Unraid (primary) and Fedora (backup mirror). GitHub serves as offsite push mirror.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
- **Control plane**: MacBook runs all scripts locally, SSHs into remotes
|
||||||
|
- **Primary Gitea**: Docker Compose on Unraid
|
||||||
|
- **Backup Gitea**: Docker Compose on Fedora (pull mirrors)
|
||||||
|
- **Runners**: Docker on Unraid/Fedora, native binary + launchd on MacBook
|
||||||
|
- **HTTPS**: Nginx reverse proxy + Certbot on Unraid
|
||||||
|
|
||||||
|
## Script Conventions
|
||||||
|
- All `.sh` files MUST start with `set -euo pipefail`
|
||||||
|
- All scripts source `lib/common.sh` for shared functions
|
||||||
|
- All scripts MUST pass `shellcheck` with zero warnings
|
||||||
|
- All scripts MUST pass `bash -n` syntax check
|
||||||
|
- Configuration via `.env` file (never hardcode values)
|
||||||
|
- Templates use `.tpl` extension and `envsubst` for rendering
|
||||||
|
- Every phase has: main script + post_check + teardown
|
||||||
|
|
||||||
|
## Idempotency
|
||||||
|
Every create/deploy operation checks state first and skips if already done. Running any script twice produces the same result with no errors.
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
```
|
||||||
|
.env.example # Template — copy to .env and fill in
|
||||||
|
runners.conf.example # Template — copy to runners.conf
|
||||||
|
lib/common.sh # Shared functions (source this in every script)
|
||||||
|
setup/ # Machine setup + .env wizard
|
||||||
|
templates/ # Config templates (.tpl files)
|
||||||
|
contracts/ # API endpoint documentation
|
||||||
|
backup/ # Backup and restore scripts
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Commands
|
||||||
|
- `setup/configure_env.sh` — Interactive .env setup wizard
|
||||||
|
- `preflight.sh` — Validate everything before running phases
|
||||||
|
- `run_all.sh` — Execute all phases sequentially
|
||||||
|
- `teardown_all.sh` — Reverse teardown
|
||||||
|
- `manage_runner.sh add|remove|list` — Dynamic runner management
|
||||||
|
|
||||||
|
## Sensitive Files (never commit)
|
||||||
|
- `.env` — contains passwords, tokens, IPs
|
||||||
|
- `runners.conf` — contains server IPs and paths
|
||||||
|
- `*.pem`, `*.key`, `*.crt` — SSL certificates
|
||||||
20
runners.conf.example
Normal file
20
runners.conf.example
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# runners.conf — Gitea Actions Runner Definitions
|
||||||
|
# Copy to runners.conf and edit. One runner per line.
|
||||||
|
# Use manage_runner.sh to add/remove runners dynamically.
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# FORMAT: name|ssh_host|ssh_user|ssh_port|data_path|labels|type
|
||||||
|
#
|
||||||
|
# name — Display name in Gitea admin panel
|
||||||
|
# ssh_host — IP address or hostname (for local machine, use "local")
|
||||||
|
# ssh_user — SSH username (ignored if ssh_host is "local")
|
||||||
|
# ssh_port — SSH port (ignored if ssh_host is "local")
|
||||||
|
# data_path — Absolute path for runner binary + data on that machine
|
||||||
|
# labels — Comma-separated runner labels (used in workflow runs-on)
|
||||||
|
# type — "docker" (Linux, runs jobs in containers) or "native" (macOS, runs jobs on host)
|
||||||
|
#
|
||||||
|
# EXAMPLES:
|
||||||
|
unraid-runner|192.168.1.10|root|22|/mnt/nvme/gitea-runner|linux|docker
|
||||||
|
fedora-runner|192.168.1.20|user|22|/mnt/nvme/gitea-runner|linux|docker
|
||||||
|
macbook-runner|local|_|_|~/gitea-runner|macos|native
|
||||||
Reference in New Issue
Block a user