#!/usr/bin/env bash # setup-secrets-repo.sh # One-shot: creates a private encrypted secrets repo on Gitea using git-crypt. # Run as root on PD. set -euo pipefail # ── CONFIG ──────────────────────────────────────────────────────────────────── GITEA_HTTP_URL="http://10.5.30.6:3000" # ← local Gitea HTTP port (check TrueNAS app config) GITEA_SSH_PORT="2222" # ← Gitea SSH port GITEA_USER="fizzlepoof" GITEA_TOKEN="" # ← set this before use; regenerate with write:repository + write:user scopes REPO_NAME="homelab-secrets" LOCAL_PATH="/mnt/docker-ssd/docker/secrets" KEY_EXPORT_PATH="/root/.git-crypt-secrets.key" # back this up somewhere safe! # ───────────────────────────────────────────────────────────────────────────── RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' info() { echo -e "${GREEN}[+]${NC} $*"; } warn() { echo -e "${YELLOW}[!]${NC} $*"; } die() { echo -e "${RED}[✗]${NC} $*" >&2; exit 1; } [[ -z "$GITEA_TOKEN" ]] && die "GITEA_TOKEN is not set. Edit the CONFIG section and re-run." # ── 1. Dependencies ─────────────────────────────────────────────────────────── info "Checking dependencies..." command -v git &>/dev/null || die "git is not installed" command -v curl &>/dev/null || die "curl is not installed" if ! command -v git-crypt &>/dev/null; then info "git-crypt not found — installing via Docker (apt is blocked on TrueNAS)..." command -v docker &>/dev/null || die "docker is not installed" docker run --rm -v /tmp:/out debian:bookworm-slim \ bash -c "apt-get update -qq && apt-get install -y -qq git-crypt && cp /usr/bin/git-crypt /out/git-crypt" \ || die "Docker-based git-crypt install failed" mkdir -p /root/bin cp /tmp/git-crypt /root/bin/git-crypt chmod +x /root/bin/git-crypt export PATH="/root/bin:$PATH" info "git-crypt installed to /root/bin/git-crypt" fi # ── 2. Create private repo on Gitea ────────────────────────────────────────── info "Creating private repo '${REPO_NAME}' on Gitea..." HTTP_CODE=$(curl -s -o /tmp/gitea-create.json -w "%{http_code}" \ -X POST "${GITEA_HTTP_URL}/api/v1/user/repos" \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d "{ \"name\": \"${REPO_NAME}\", \"description\": \"Homelab secrets — git-crypt encrypted\", \"private\": true, \"auto_init\": false }") if [[ "$HTTP_CODE" == "201" ]]; then info "Repo created successfully." elif [[ "$HTTP_CODE" == "409" ]]; then warn "Repo already exists on Gitea — continuing." else cat /tmp/gitea-create.json die "Gitea API returned HTTP ${HTTP_CODE}. Check token and URL." fi REPO_URL="ssh://git@10.5.30.6:${GITEA_SSH_PORT}/${GITEA_USER}/${REPO_NAME}.git" # ── 3. Init local repo ──────────────────────────────────────────────────────── info "Setting up local repo at ${LOCAL_PATH}..." mkdir -p "$LOCAL_PATH" cd "$LOCAL_PATH" if [[ ! -d .git ]]; then git init git remote add origin "$REPO_URL" else warn ".git already exists — skipping init." git remote set-url origin "$REPO_URL" 2>/dev/null || true fi # ── 4. Init git-crypt ───────────────────────────────────────────────────────── if [[ ! -d .git-crypt ]]; then info "Initialising git-crypt..." git-crypt init else warn "git-crypt already initialised — skipping." fi # ── 5. Export symmetric key ─────────────────────────────────────────────────── info "Exporting symmetric key to ${KEY_EXPORT_PATH}..." git-crypt export-key "$KEY_EXPORT_PATH" chmod 600 "$KEY_EXPORT_PATH" warn "BACK THIS KEY UP. Without it you cannot decrypt the repo on another machine." warn " scp root@10.5.30.6:${KEY_EXPORT_PATH} /safe/location/" # ── 6. .gitattributes — encrypt everything except meta files ───────────────── info "Writing .gitattributes..." cat > .gitattributes << 'EOF' # Encrypt everything by default * filter=git-crypt diff=git-crypt # These stay plaintext .gitattributes !filter !diff README.md !filter !diff EOF # ── 7. Directory structure ──────────────────────────────────────────────────── info "Creating directory structure..." mkdir -p env keys certs tokens ssh cat > README.md << EOF # homelab-secrets Private secrets store for the homelab. All files except this README and .gitattributes are encrypted at rest with git-crypt. ## Unlock on a new machine \`\`\`bash git clone ${REPO_URL} cd ${REPO_NAME} git-crypt unlock /path/to/.git-crypt-secrets.key \`\`\` ## Structure | Directory | Contents | |-----------|----------| | \`env/\` | .env files for each stack | | \`keys/\` | API keys and tokens | | \`certs/\` | TLS certificates | | \`tokens/\`| Service tokens (Paperless, LiteLLM, etc.) | | \`ssh/\` | SSH private keys | ## Key location The symmetric key is stored at \`${KEY_EXPORT_PATH}\` on PD. Back it up to a password manager or USB drive. EOF # Placeholder files so dirs aren't empty for dir in env keys certs tokens ssh; do touch "${dir}/.gitkeep" done # ── 8. Initial commit and push ──────────────────────────────────────────────── info "Committing and pushing..." git add -A git -c user.name="Fizzlepoof" -c user.email="admin@paccoco.com" \ commit -m "chore: init encrypted secrets repo" git push -u origin main 2>/dev/null || git push -u origin master 2>/dev/null || \ die "Push failed. Check that Gitea credentials are configured (git credential store)." echo "" echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e "${GREEN} Done!${NC}" echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" echo " Repo: ${REPO_URL}" echo " Local: ${LOCAL_PATH}" echo " Key: ${KEY_EXPORT_PATH}" echo "" echo -e "${YELLOW} Next: back up the key, then start dropping .env files into ${LOCAL_PATH}/env/${NC}" echo ""