--- name: gitea-deploy description: Automates deploying a self-hosted Gitea Git server on a VPS using Docker, then pushes the current project to it. Use when the user wants to self-host a Git server, set up Gitea on a VPS, push a project to a private Git server, or migrate away from GitHub/GitLab. Triggers on phrases like "deploy gitea", "self-host git", "setup git server", "push to my vps", "host my own git", "搭建git服务器", "自托管git", "部署gitea", "推送到vps". metadata: author: common-skills version: "1.0" compatibility: tools: - execute_bash requirements: - SSH access to a VPS (Linux) - Docker available or installable on VPS - git initialized in the local project --- # Gitea Deploy Automate deploying a self-hosted Gitea instance on a VPS and pushing the current project to it. ## Inputs Collect from the user before starting: | Field | Example | |---|---| | VPS host | `123.45.67.89` or `git.example.com` | | SSH user | `root` or `ubuntu` | | SSH private key path | `~/.ssh/id_rsa` | | Gitea admin username | `admin` | | Gitea admin password | (user provides, never log it) | | Gitea web port | `3000` (default) | | SSH port for Gitea | `2222` (default) | | Repository name | defaults to current directory name | If any field is missing, ask for it. Never guess credentials. ## Workflow ### 1. Validate Local Prerequisites ```bash git rev-parse --is-inside-work-tree # confirm we're in a git repo git status --short # show current state ``` If not a git repo, run `git init && git add -A && git commit -m "chore: initial commit"` after confirming with the user. ### 2. Test SSH Connectivity ```bash ssh -i -o StrictHostKeyChecking=no -o ConnectTimeout=10 @ "echo OK" ``` If this fails, stop and report the error. Do not proceed. ### 3. Check / Install Docker on VPS ```bash ssh -i @ "docker --version 2>/dev/null || (curl -fsSL https://get.docker.com | sh)" ``` Report the Docker version found or installed. ### 4. Deploy Gitea via Docker Compose Upload and run a `docker-compose.yml` on the VPS: ```bash ssh -i @ "mkdir -p ~/gitea" cat <<'EOF' | ssh -i @ "cat > ~/gitea/docker-compose.yml" services: gitea: image: gitea/gitea:latest restart: always environment: - USER_UID=1000 - USER_GID=1000 ports: - ":3000" - ":22" volumes: - ./data:/data EOF ssh -i @ "cd ~/gitea && docker compose up -d" ``` ### 5. Wait for Gitea to Be Ready Poll until the health endpoint responds (max 60 seconds): ```bash ssh -i @ \ "for i in \$(seq 1 12); do curl -sf http://localhost:/api/healthz && break || sleep 5; done" ``` If not ready after 60 s, show the container logs: ```bash ssh -i @ "docker logs gitea-gitea-1 --tail 30" ``` ### 6. Initialize Gitea via API Create the admin user and the target repository using the Gitea API: ```bash # Create admin user (first-time setup) ssh -i @ \ "docker exec gitea-gitea-1 gitea admin user create \ --username --password '' \ --email admin@localhost --admin --must-change-password=false" # Create repository curl -sf -X POST "http://:/api/v1/user/repos" \ -u ":" \ -H "Content-Type: application/json" \ -d "{\"name\":\"\",\"private\":true,\"auto_init\":false}" ``` If the admin user already exists, skip creation (exit code 1 is acceptable). ### 7. Configure Local Git Remote and Push ```bash # Add or update remote git remote remove gitea 2>/dev/null || true git remote add gitea "ssh://git@://.git" # Push all branches git push -u gitea --all git push gitea --tags ``` If push fails due to host key, add `-o StrictHostKeyChecking=no` to the SSH command used by git: ```bash GIT_SSH_COMMAND="ssh -i -o StrictHostKeyChecking=no" git push -u gitea --all ``` ### 8. Verify and Report ```bash curl -sf "http://:/api/v1/repos//" \ -u ":" | python3 -m json.tool ``` Report to the user: - Gitea web URL: `http://:` - Repository URL: `http://://` - SSH clone URL: `ssh://git@://.git` ## Edge Cases - **Docker already installed**: Step 3 detects and skips installation. - **Gitea already running**: Step 4 `docker compose up -d` is idempotent; existing containers are reused. - **Admin user already exists**: Step 6 catches the error and continues. - **Remote `gitea` already exists**: Step 7 removes and re-adds it. - **No commits yet**: Step 1 detects and offers to create an initial commit. ## Security Notes - Never print the admin password in command output. Reference it as ``. - Use `-o StrictHostKeyChecking=no` only for the initial setup; advise the user to remove it afterward. - Recommend the user change the admin password after first login. - For production use, suggest adding Nginx + Let's Encrypt for HTTPS.