diff --git a/.gitea/workflows/backup-volumes.yml b/.gitea/workflows/backup-volumes.yml index 0e22935..19f1fe1 100644 --- a/.gitea/workflows/backup-volumes.yml +++ b/.gitea/workflows/backup-volumes.yml @@ -14,7 +14,7 @@ jobs: - name: devops host: 10.0.0.175 user: lars - exclude_volumes: "41b0fdd5c39b8a598f4e5f6960ac0661a1fe6e60c055d4ceaa1fcfcde6ef1206" # Optional: Komma-separierte Liste zum Ausschließen + exclude_volumes: "41b0fdd5c39b8a598f4e5f6960ac0661a1fe6e60c055d4ceaa1fcfcde6ef1206,homelab_minio-data" # Optional: Komma-separierte Liste zum Ausschließen # Weitere Server können hier hinzugefügt werden: # - name: production # host: 10.0.0.180 @@ -28,15 +28,26 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Setup SSH + - name: Set server context for ${{ matrix.server.name }} + run: | + echo "SERVER_NAME=${{ matrix.server.name }}" >> $GITHUB_ENV + echo "SERVER_HOST=${{ matrix.server.host }}" >> $GITHUB_ENV + echo "SERVER_USER=${{ matrix.server.user }}" >> $GITHUB_ENV + echo "EXCLUDE_VOLUMES=${{ matrix.server.exclude_volumes }}" >> $GITHUB_ENV + echo "=== Starting backup for server: ${{ matrix.server.name }} ===" + echo "Host: ${{ matrix.server.host }}" + echo "User: ${{ matrix.server.user }}" + + - name: Setup SSH for ${{ matrix.server.name }} run: | mkdir -p ~/.ssh echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -H ${{ matrix.server.host }} >> ~/.ssh/known_hosts - - name: Upload backup script to server + - name: Upload backup script to ${{ matrix.server.name }} run: | + echo "Uploading backup script to ${{ matrix.server.name }}..." scp scripts/backup-servers/backup-docker-volumes.sh \ ${{ matrix.server.user }}@${{ matrix.server.host }}:/tmp/backup-docker-volumes.sh @@ -48,22 +59,22 @@ jobs: BACKUP_DATE=$(date +%Y%m%d_%H%M%S) echo "BACKUP_DATE=$BACKUP_DATE" >> $GITHUB_ENV - EXCLUDE_VOLUMES="${{ matrix.server.exclude_volumes }}" + echo "Creating backup on ${{ matrix.server.name }} at $BACKUP_DATE..." ssh ${{ matrix.server.user }}@${{ matrix.server.host }} \ - "BACKUP_DATE='$BACKUP_DATE' SERVER_NAME='${{ matrix.server.name }}' EXCLUDE_VOLUMES='$EXCLUDE_VOLUMES' /tmp/backup-docker-volumes.sh" + "BACKUP_DATE='$BACKUP_DATE' SERVER_NAME='${{ matrix.server.name }}' EXCLUDE_VOLUMES='${{ matrix.server.exclude_volumes }}' /tmp/backup-docker-volumes.sh" - name: Download backups from ${{ matrix.server.name }} run: | mkdir -p backups/${{ matrix.server.name }} echo "Downloading backups from ${{ matrix.server.name }}..." - scp -r ${{ matrix.server.user }}@${{ matrix.server.host }}:~/backups/${{ env.BACKUP_DATE }} \ + scp -r ${{ matrix.server.user }}@${{ matrix.server.host }}:~/backups/$BACKUP_DATE \ backups/${{ matrix.server.name }}/ echo "Downloaded files:" - ls -lh backups/${{ matrix.server.name }}/${{ env.BACKUP_DATE }}/ + ls -lh backups/${{ matrix.server.name }}/$BACKUP_DATE/ - - name: Upload backup artifacts + - name: Upload backup artifacts for ${{ matrix.server.name }} uses: actions/upload-artifact@v3 with: name: backup-${{ matrix.server.name }}-${{ env.BACKUP_DATE }} @@ -73,6 +84,7 @@ jobs: - name: Cleanup old backups on ${{ matrix.server.name }} (keep last 7 days) if: always() run: | + echo "Cleaning up old backups on ${{ matrix.server.name }}..." ssh ${{ matrix.server.user }}@${{ matrix.server.host }} << 'CLEANUP_EOF' # Lösche Backups älter als 7 Tage find ~/backups -maxdepth 1 -type d -name "????????_??????" -mtime +7 -exec rm -rf {} \; 2>/dev/null || true @@ -81,7 +93,8 @@ jobs: ls -lh ~/backups/ 2>/dev/null || echo "No backups found" CLEANUP_EOF - - name: Cleanup temporary files + - name: Cleanup temporary files on ${{ matrix.server.name }} if: always() run: | + echo "Cleaning up temporary files on ${{ matrix.server.name }}..." ssh ${{ matrix.server.user }}@${{ matrix.server.host }} "rm -f /tmp/backup-docker-volumes.sh" || true diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..4f646a2 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,225 @@ +name: Deploy Docker Compose + +on: + workflow_dispatch: + inputs: + server: + description: 'Target server to deploy' + required: true + type: choice + options: + - devops + - production + - staging + - all + service: + description: 'Service to deploy (leave empty for all)' + required: false + type: string + default: '' + action: + description: 'Docker Compose action' + required: true + type: choice + options: + - up + - restart + - pull-and-up + - down + - logs + default: 'pull-and-up' + detach: + description: 'Run in detached mode' + required: false + type: boolean + default: true + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set deployment context + id: context + run: | + echo "=== Deployment Configuration ===" + echo "Server: ${{ inputs.server }}" + echo "Service: ${{ inputs.service || 'all services' }}" + echo "Action: ${{ inputs.action }}" + echo "Detached: ${{ inputs.detach }}" + + # Git Repo URL (aus Gitea) + REPO_URL="https://git.hashdot.co/${{ github.repository }}.git" + echo "REPO_URL=$REPO_URL" >> $GITHUB_ENV + + # Server-Konfiguration setzen + case "${{ inputs.server }}" in + devops) + echo "HOST=10.0.0.175" >> $GITHUB_ENV + echo "USER=lars" >> $GITHUB_ENV + echo "COMPOSE_PATH=/home/lars/devops/servers/production/devops" >> $GITHUB_ENV + ;; + production) + echo "HOST=10.0.0.180" >> $GITHUB_ENV + echo "USER=lars" >> $GITHUB_ENV + echo "COMPOSE_PATH=/home/lars/production" >> $GITHUB_ENV + ;; + staging) + echo "HOST=10.0.0.185" >> $GITHUB_ENV + echo "USER=lars" >> $GITHUB_ENV + echo "COMPOSE_PATH=/home/lars/staging" >> $GITHUB_ENV + ;; + all) + echo "DEPLOY_ALL=true" >> $GITHUB_ENV + ;; + esac + + # Service-Parameter setzen + if [ -n "${{ inputs.service }}" ]; then + echo "SERVICE_ARG=${{ inputs.service }}" >> $GITHUB_ENV + else + echo "SERVICE_ARG=" >> $GITHUB_ENV + fi + + # Detach-Flag setzen + if [ "${{ inputs.detach }}" == "true" ]; then + echo "DETACH_FLAG=-d" >> $GITHUB_ENV + else + echo "DETACH_FLAG=" >> $GITHUB_ENV + fi + + - name: Setup SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + + # Füge alle möglichen Hosts hinzu + ssh-keyscan -H 10.0.0.175 >> ~/.ssh/known_hosts 2>/dev/null || true + ssh-keyscan -H 10.0.0.180 >> ~/.ssh/known_hosts 2>/dev/null || true + ssh-keyscan -H 10.0.0.185 >> ~/.ssh/known_hosts 2>/dev/null || true + + - name: Deploy to single server + if: inputs.server != 'all' + run: | + echo "=== Deploying to ${{ inputs.server }} ===" + + # Check ob Repo existiert, sonst clonen + ssh $USER@$HOST " + export COMPOSE_PATH='$COMPOSE_PATH' + export REPO_URL='$REPO_URL' + + if [ -d \"\$COMPOSE_PATH/.git\" ]; then + echo 'Repository already exists, pulling latest changes...' + cd \$COMPOSE_PATH && git pull + else + echo 'Repository not found, cloning...' + PARENT_DIR=\$(dirname \$COMPOSE_PATH) + mkdir -p \$PARENT_DIR + cd \$PARENT_DIR + git clone \$REPO_URL \homelab + echo 'Repository cloned successfully' + fi + " + + # Docker Compose Aktion ausführen + case "${{ inputs.action }}" in + up) + ssh $USER@$HOST "cd $COMPOSE_PATH && docker compose up $DETACH_FLAG $SERVICE_ARG" + ;; + restart) + ssh $USER@$HOST "cd $COMPOSE_PATH && docker compose restart $SERVICE_ARG" + ;; + pull-and-up) + ssh $USER@$HOST "cd $COMPOSE_PATH && docker compose pull $SERVICE_ARG && docker compose up $DETACH_FLAG $SERVICE_ARG" + ;; + down) + ssh $USER@$HOST "cd $COMPOSE_PATH && docker compose down $SERVICE_ARG" + ;; + logs) + ssh $USER@$HOST "cd $COMPOSE_PATH && docker compose logs --tail=100 $SERVICE_ARG" + ;; + esac + + - name: Deploy to all servers + if: inputs.server == 'all' + run: | + echo "=== Deploying to all servers ===" + + # Definiere alle Server + declare -A SERVERS=( + ["devops"]="lars@10.0.0.175:/home/lars/ghq/git.hashdot.co/lars/homelab/servers/production/devops" + ["production"]="lars@10.0.0.180:/home/lars/production" + ["staging"]="lars@10.0.0.185:/home/lars/staging" + ) + + for server in "${!SERVERS[@]}"; do + IFS=':' read -r user_host compose_path <<< "${SERVERS[$server]}" + + echo "" + echo ">>> Deploying to $server..." + + # Check ob Repo existiert, sonst clonen + ssh $user_host " + export COMPOSE_PATH='$compose_path' + export REPO_URL='$REPO_URL' + + if [ -d \"\$COMPOSE_PATH/.git\" ]; then + echo 'Repository already exists, pulling latest changes...' + cd \$COMPOSE_PATH && git pull + else + echo 'Repository not found, cloning...' + PARENT_DIR=\$(dirname \$COMPOSE_PATH) + mkdir -p \$PARENT_DIR + cd \$PARENT_DIR + git clone \$REPO_URL \$(basename \$COMPOSE_PATH) + echo 'Repository cloned successfully' + fi + " || { echo "Failed to setup git for $server"; continue; } + + # Docker Compose Aktion + case "${{ inputs.action }}" in + up) + ssh $user_host "cd $compose_path && docker compose up $DETACH_FLAG $SERVICE_ARG" + ;; + restart) + ssh $user_host "cd $compose_path && docker compose restart $SERVICE_ARG" + ;; + pull-and-up) + ssh $user_host "cd $compose_path && docker compose pull $SERVICE_ARG && docker compose up $DETACH_FLAG $SERVICE_ARG" + ;; + down) + ssh $user_host "cd $compose_path && docker compose down $SERVICE_ARG" + ;; + logs) + ssh $user_host "cd $compose_path && docker compose logs --tail=100 $SERVICE_ARG" + ;; + esac + + echo ">>> $server deployment completed" + done + + - name: Verify deployment + if: inputs.action != 'down' && inputs.action != 'logs' + run: | + echo "=== Verifying deployment ===" + + if [ "${{ inputs.server }}" != "all" ]; then + ssh $USER@$HOST "cd $COMPOSE_PATH && docker compose ps" + else + echo "Skipping verification for 'all' - check individual server logs" + fi + + - name: Deployment summary + if: always() + run: | + echo "=== Deployment Summary ===" + echo "Server: ${{ inputs.server }}" + echo "Service: ${{ inputs.service || 'all services' }}" + echo "Action: ${{ inputs.action }}" + echo "Status: ${{ job.status }}" + echo "" + echo "Deployment completed at $(date)"