diff --git a/.gitignore b/.gitignore index adf84d2..6ddd18e 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,7 @@ myProx_template_ssh_key.txt more_dev_work.txt audit.md proxpanel-report.md +gitvotcloud_repo_credentials.txt +*_repo_credentials.txt +*credentials*.txt +*token*.txt diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 21f0348..b8cecb5 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -96,3 +96,34 @@ Then confirm: - Use a dedicated Proxmox API user/token with least privileges. - Keep backend bound to localhost (`127.0.0.1`) and expose only frontend port. - Enable off-host backups for DB and app config. + +## 5) PAT-Only Git Update Workflow (No Password Auth) + +Use Personal Access Token (PAT) authentication only. Do not use account passwords for Git pull/push. + +### A. Create PAT (Git server) +1. Sign in to your Git server user settings. +2. Create a PAT with minimum required scopes (`repo:read` for pull; add write only if needed). +3. Save it securely (password manager/secret vault). + +### B. Update app on server with PAT (no credential persistence) +Run this on the server: + +```bash +cd /opt/proxpanel +chmod +x infra/deploy/git-pat-sync.sh +export GIT_USERNAME="your_git_username" +export GIT_PAT="your_personal_access_token" +bash infra/deploy/git-pat-sync.sh \ + --repo-dir /opt/proxpanel \ + --branch main \ + --repo-url https://git.votcloud.com/austindebest/proxpanel.git +unset GIT_PAT +``` + +Then deploy: + +```bash +cd /opt/proxpanel +docker compose --env-file .env.production -f infra/deploy/docker-compose.production.yml up -d --build +``` diff --git a/infra/deploy/git-pat-sync.sh b/infra/deploy/git-pat-sync.sh new file mode 100644 index 0000000..efd3603 --- /dev/null +++ b/infra/deploy/git-pat-sync.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# Pulls latest code using PAT auth without persisting password credentials. +# Required env vars: +# GIT_USERNAME +# GIT_PAT +# +# Example: +# export GIT_USERNAME="austindebest" +# export GIT_PAT="***" +# bash infra/deploy/git-pat-sync.sh --repo-dir /opt/proxpanel --branch main + +REPO_DIR="/opt/proxpanel" +BRANCH="main" +REMOTE="origin" +REPO_URL="" + +die() { + printf '\n[ERROR] %s\n' "$*" >&2 + exit 1 +} + +usage() { + cat <<'EOF' +Usage: + bash infra/deploy/git-pat-sync.sh [options] + +Options: + --repo-dir Repository directory (default: /opt/proxpanel) + --branch Branch to pull (default: main) + --remote Remote to use (default: origin) + --repo-url Optional URL to set on remote before sync + -h, --help Show this help + +Required environment variables: + GIT_USERNAME Git username + GIT_PAT Personal Access Token +EOF +} + +parse_args() { + while [[ $# -gt 0 ]]; do + case "$1" in + --repo-dir) + REPO_DIR="${2:-}" + shift 2 + ;; + --branch) + BRANCH="${2:-}" + shift 2 + ;; + --remote) + REMOTE="${2:-}" + shift 2 + ;; + --repo-url) + REPO_URL="${2:-}" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + die "Unknown argument: $1" + ;; + esac + done +} + +require_env() { + [[ -n "${GIT_USERNAME:-}" ]] || die "GIT_USERNAME is required." + [[ -n "${GIT_PAT:-}" ]] || die "GIT_PAT is required." +} + +build_auth_header() { + local pair + pair="${GIT_USERNAME}:${GIT_PAT}" + printf 'Authorization: Basic %s' "$(printf '%s' "${pair}" | base64 | tr -d '\n')" +} + +sync_repo() { + [[ -d "${REPO_DIR}/.git" ]] || die "Not a git repo: ${REPO_DIR}" + + local auth_header + auth_header="$(build_auth_header)" + + if [[ -n "${REPO_URL}" ]]; then + git -C "${REPO_DIR}" remote set-url "${REMOTE}" "${REPO_URL}" + fi + + git -c http.extraHeader="${auth_header}" -C "${REPO_DIR}" fetch "${REMOTE}" --prune + git -C "${REPO_DIR}" checkout "${BRANCH}" + git -c http.extraHeader="${auth_header}" -C "${REPO_DIR}" pull --ff-only "${REMOTE}" "${BRANCH}" +} + +main() { + parse_args "$@" + require_env + sync_repo + echo "Repository synced successfully: ${REPO_DIR} (${BRANCH})" +} + +main "$@"