Tailscale With Progress Bar #40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Tailscale With Progress Bar | |
| on: | |
| workflow_dispatch: {} # Manual trigger | |
| schedule: | |
| - cron: "30 1 * * *" # 7:00 AM IST (1:30 UTC) | |
| #on: | |
| #schedule: | |
| # - cron: "30 1 * * *" #7 AM IST | |
| # - cron: "30 6 * * *" #12 PM | |
| # - cron: "30 11 * * *" #5 PM | |
| # - cron: "30 16 * * *" #10 PM | |
| jobs: | |
| run-tailscale: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Install Tailscale + jq | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y curl jq | |
| curl -fsSL https://tailscale.com/install.sh | sh | |
| - name: Enable IP Forwarding | |
| run: | | |
| sudo sysctl -w net.ipv4.ip_forward=1 | |
| sudo sysctl -w net.ipv6.conf.all.forwarding=1 | |
| - name: Get Runner Hostname (Unique for Tailscale) | |
| id: runner_info | |
| run: | | |
| BASE_HOSTNAME=$(hostname) | |
| UNIQUE_HOSTNAME="${BASE_HOSTNAME}-${GITHUB_RUN_ID}" | |
| echo "runner_hostname=$UNIQUE_HOSTNAME" >> $GITHUB_ENV | |
| echo "runner_hostname=$UNIQUE_HOSTNAME" >> $GITHUB_OUTPUT | |
| - name: Start Tailscale Exit Node | |
| run: | | |
| sudo tailscale up \ | |
| --authkey ${{ secrets.TAILSCALE_PREAUTHKEY }} \ | |
| --ssh \ | |
| --advertise-exit-node \ | |
| --hostname ${{ steps.runner_info.outputs.runner_hostname }} \ | |
| --reset | |
| env: | |
| TS_SOCKET: /tmp/tailscaled.sock | |
| - name: Auto-Approve Exit Node via API | |
| run: | | |
| NODE_ID=$(sudo tailscale status --json | jq -r '.Self.ID') | |
| curl -X POST "https://api.tailscale.com/api/v2/node/$NODE_ID/attributes" \ | |
| -u "${{ secrets.TS_API_KEY }}:" \ | |
| --data-binary '{"attr":"exit-node", "value": true}' | |
| - name: Save Start Time | |
| run: | | |
| START_TIME=$(date +%s) | |
| echo "START_TIME=$START_TIME" >> $GITHUB_ENV | |
| - name: Get Tailscale & Public IP | |
| id: get_ips | |
| run: | | |
| TAILSCALE_IP=$(sudo tailscale ip -4) | |
| PUBLIC_IP=$(curl -s ifconfig.me) | |
| LOCATION_JSON=$(curl -s http://ip-api.com/json/$PUBLIC_IP) | |
| CITY=$(echo $LOCATION_JSON | jq -r '.city // "Unknown City"') | |
| COUNTRY=$(echo $LOCATION_JSON | jq -r '.country // "Unknown Country"') | |
| CC=$(echo $LOCATION_JSON | jq -r '.countryCode // ""') | |
| ISP=$(echo $LOCATION_JSON | jq -r '.isp // "Unknown ISP"') | |
| FLAG="" | |
| for (( i=0; i<${#CC}; i++ )); do | |
| c=${CC:i:1} | |
| code=$(( $(printf '%d' "'$c") - 65 + 0x1F1E6 )) | |
| FLAG+=$(printf "\\U%08X" $code) | |
| done | |
| FLAG=$(echo -e $FLAG) | |
| echo "TAILSCALE_IP=$TAILSCALE_IP" >> $GITHUB_ENV | |
| echo "PUBLIC_IP=$PUBLIC_IP" >> $GITHUB_ENV | |
| echo "CITY=$CITY" >> $GITHUB_ENV | |
| echo "COUNTRY=$COUNTRY" >> $GITHUB_ENV | |
| echo "FLAG=$FLAG" >> $GITHUB_ENV | |
| echo "ISP=$ISP" >> $GITHUB_ENV | |
| echo "ts_ip=$TAILSCALE_IP" >> $GITHUB_OUTPUT | |
| echo "pub_ip=$PUBLIC_IP" >> $GITHUB_OUTPUT | |
| - name: Live Telegram Notification | |
| run: | | |
| START_TIME=${{ env.START_TIME }} | |
| UTC_HOUR=$(date -u +%H) | |
| NEXT_RUN_HOUR=$(( ( (10#$UTC_HOUR / 6 + 1) * 6 ) % 24 )) | |
| NEXT_RUN_IST=$(date -d "today ${NEXT_RUN_HOUR}:00 UTC +5 hours 30 minutes" +"%I:%M %p") | |
| MSG="🚀 Tailscale Node Online%0A🖥️ Runner: ${{ steps.runner_info.outputs.runner_hostname }}%0A🌐 Tailscale IP: ${{ steps.get_ips.outputs.ts_ip }}%0A🌍 Public IP: ${{ steps.get_ips.outputs.pub_ip }}%0A📍 Location: ${{ env.CITY }}, ${{ env.COUNTRY }} ${{ env.FLAG }}%0A🏢 ISP: ${{ env.ISP }}%0A⏱️ Running since: 00:00:00%0A⏰ Next workflow (IST): $NEXT_RUN_IST%0A%0AProgress: ▱▱▱▱▱▱▱▱▱▱ 0%" | |
| RESPONSE=$(curl -s -X POST "https://api.telegram.org/bot${{ secrets.TG_BOT_TOKEN }}/sendMessage" \ | |
| -d chat_id=${{ secrets.TG_CHAT_ID }} \ | |
| -d text="$MSG") | |
| MESSAGE_ID=$(echo $RESPONSE | jq -r '.result.message_id') | |
| while [ $(($(date +%s) - $START_TIME)) -lt 21600 ]; do | |
| ELAPSED=$(($(date +%s) - $START_TIME)) | |
| HOURS=$(printf "%02d" $((ELAPSED/3600))) | |
| MINUTES=$(printf "%02d" $(((ELAPSED%3600)/60))) | |
| SECONDS=$(printf "%02d" $((ELAPSED%60))) | |
| # progress calculation | |
| PERCENT=$((ELAPSED * 100 / 21600)) | |
| FILLED=$((PERCENT / 10)) | |
| EMPTY=$((10 - FILLED)) | |
| BAR=$(printf "%0.s▰" $(seq 1 $FILLED)) | |
| BAR+=$(printf "%0.s▱" $(seq 1 $EMPTY)) | |
| PUBLIC_IP=$(curl -s ifconfig.me) | |
| LOCATION_JSON=$(curl -s http://ip-api.com/json/$PUBLIC_IP) | |
| CITY=$(echo $LOCATION_JSON | jq -r '.city // "Unknown City"') | |
| COUNTRY=$(echo $LOCATION_JSON | jq -r '.country // "Unknown Country"') | |
| CC=$(echo $LOCATION_JSON | jq -r '.countryCode // ""') | |
| ISP=$(echo $LOCATION_JSON | jq -r '.isp // "Unknown ISP"') | |
| FLAG="" | |
| for (( i=0; i<${#CC}; i++ )); do | |
| c=${CC:i:1} | |
| code=$(( $(printf '%d' "'$c") - 65 + 0x1F1E6 )) | |
| FLAG+=$(printf "\\U%08X" $code) | |
| done | |
| FLAG=$(echo -e $FLAG) | |
| UTC_HOUR=$(date -u +%H) | |
| NEXT_RUN_HOUR=$(( ( (10#$UTC_HOUR / 6 + 1) * 6 ) % 24 )) | |
| NEXT_RUN_IST=$(date -d "today ${NEXT_RUN_HOUR}:00 UTC +5 hours 30 minutes" +"%I:%M %p") | |
| MSG="🚀 Tailscale Node Online%0A🖥️ Runner: ${{ steps.runner_info.outputs.runner_hostname }}%0A🌐 Tailscale IP: ${{ steps.get_ips.outputs.ts_ip }}%0A🌍 Public IP: $PUBLIC_IP%0A📍 Location: $CITY, $COUNTRY $FLAG%0A🏢 ISP: $ISP%0A⏱️ Running since: ${HOURS}:${MINUTES}:${SECONDS}%0A⏰ Next workflow (IST): $NEXT_RUN_IST%0A%0AProgress: $BAR $PERCENT%" | |
| curl -s -X POST "https://api.telegram.org/bot${{ secrets.TG_BOT_TOKEN }}/editMessageText" \ | |
| -d chat_id=${{ secrets.TG_CHAT_ID }} \ | |
| -d message_id=$MESSAGE_ID \ | |
| -d text="$MSG" | |
| sleep 30 | |
| done | |
| - name: Cleanup Exit Node | |
| if: always() | |
| run: | | |
| sudo tailscale down | |
| - name: Send Telegram Stop Notification | |
| if: always() | |
| run: | | |
| END_TIME=$(date +%s) | |
| DURATION=$((END_TIME - ${{ env.START_TIME }})) | |
| HOURS=$(printf "%02d" $((DURATION/3600))) | |
| MINUTES=$(printf "%02d" $(((DURATION%3600)/60))) | |
| SECONDS=$(printf "%02d" $((DURATION%60))) | |
| CC=$(curl -s http://ip-api.com/json/${{ steps.get_ips.outputs.pub_ip }} | jq -r '.countryCode // ""') | |
| FLAG="" | |
| for (( i=0; i<${#CC}; i++ )); do | |
| c=${CC:i:1} | |
| code=$(( $(printf '%d' "'$c") - 65 + 0x1F1E6 )) | |
| FLAG+=$(printf "\\U%08X" $code) | |
| done | |
| FLAG=$(echo -e $FLAG) | |
| MSG="🛑 Tailscale Node Stopped%0A🖥️ Runner: ${{ steps.runner_info.outputs.runner_hostname }}%0A🌐 Tailscale IP was: ${{ steps.get_ips.outputs.ts_ip }}%0A🌍 Public IP was: ${{ steps.get_ips.outputs.pub_ip }}%0A📍 Location was: ${{ env.CITY }}, ${{ env.COUNTRY }} $FLAG%0A🏢 ISP: ${{ env.ISP }}%0A⏱️ Active Duration: ${HOURS}:${MINUTES}:${SECONDS}" | |
| curl -s -X POST "https://api.telegram.org/bot${{ secrets.TG_BOT_TOKEN }}/sendMessage" \ | |
| -d chat_id=${{ secrets.TG_CHAT_ID }} \ | |
| -d text="$MSG" |