Skip to content

Commit 2d99ace

Browse files
author
thibeaum
committed
Server side updates
1 parent e9bcb49 commit 2d99ace

3 files changed

Lines changed: 110 additions & 6 deletions

File tree

.github/workflows/update.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
name: Update proxy list
22

3+
# The scheduled cron was removed in favor of a server-side cron driving
4+
# scripts/update-and-push.sh (see README "Server cron setup"). GitHub
5+
# Actions' scheduler is too unreliable at the documented 5-minute minimum —
6+
# in practice we saw first-run delays of 30–60+ minutes and uneven cadence
7+
# afterward. The manual dispatch and push triggers remain as a fallback so
8+
# the workflow can still be invoked from the GitHub UI if the server cron
9+
# is down.
310
on:
4-
schedule:
5-
# Every 5 minutes. GitHub may delay scheduled workflows under load — the
6-
# real upstream cadence is "every minute" on the API, this mirror is a
7-
# 5-minute snapshot.
8-
- cron: "*/5 * * * *"
911
workflow_dispatch:
1012
push:
1113
branches: [main]

README.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,14 +197,49 @@ curl 'https://api.proxyscrape.com/v4/free-proxy-list/get?request=display_proxies
197197
4. Shards by protocol and country and writes `data.{txt,json,csv}` for each
198198
5. Writes `proxies/stats.json` with the summary
199199

200-
The [`.github/workflows/update.yml`](.github/workflows/update.yml) action runs the script on a 5-minute cron, commits any changes, and pushes. Run it locally too:
200+
A 5-minute cron on a ProxyScrape-controlled server drives [`scripts/update-and-push.sh`](scripts/update-and-push.sh), which pulls, runs the updater, commits, and pushes. The [GitHub Actions workflow](.github/workflows/update.yml) keeps `workflow_dispatch` and push triggers for manual / emergency runs, but the scheduled cron there is disabled — GitHub's scheduler is too unreliable at 5-minute cadence (we saw 30–60+ minute first-run delays and uneven cadence afterwards).
201+
202+
Run the updater locally:
201203

202204
```bash
203205
python3 scripts/update.py
204206
```
205207

206208
No dependencies — Python 3.10+, stdlib only.
207209

210+
### Server cron setup
211+
212+
If you want to mirror this dataset yourself or run a fork, the wrapper is drop-in:
213+
214+
```bash
215+
# 1. Clone the repo on the server
216+
git clone https://github.com/proxyscrape/free-proxy-list.git /srv/free-proxy-list
217+
cd /srv/free-proxy-list
218+
219+
# 2. Verify the wrapper runs end-to-end (no commit if there are no changes)
220+
./scripts/update-and-push.sh
221+
222+
# 3. Install the cron — every 5 minutes
223+
crontab -e
224+
```
225+
226+
Add this line:
227+
228+
```cron
229+
*/5 * * * * /srv/free-proxy-list/scripts/update-and-push.sh >> /var/log/free-proxy-list.log 2>&1
230+
```
231+
232+
The wrapper:
233+
- Resolves the repo root from its own location, so `REPO_DIR` is only needed if you symlink the script elsewhere
234+
- Uses `flock` so a slow tick can't collide with the next one — overlapping crontab firings safely skip
235+
- Pulls with `--rebase --autostash` first, so concurrent edits (by humans or other servers) stay compatible
236+
- Only commits + pushes if `proxies/` actually changed
237+
- Exits non-zero on real failures so cron's `MAILTO` surfaces them
238+
239+
Git push needs credentials available to the cron user. Two common patterns:
240+
- **Deploy key**: generate an SSH key, add the public half to the repo's Deploy keys (with write access), point the `origin` remote at `git@github.com:proxyscrape/free-proxy-list.git`
241+
- **Fine-grained PAT**: store in `~/.git-credentials` for the cron user, use HTTPS remote
242+
208243
## Other free tools from ProxyScrape
209244

210245
If you're working with proxies, you probably want more than just a list. These are all free, no account required:

scripts/update-and-push.sh

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Cron-friendly wrapper around scripts/update.py:
4+
# 1. Pull any new remote commits (rebase, autostash safety net)
5+
# 2. Run the Python updater to refresh the proxies/ tree
6+
# 3. Commit + push only if anything actually changed
7+
#
8+
# Designed to be invoked from a crontab — see the "Server cron setup"
9+
# section in README.md for installation steps.
10+
#
11+
# Exits non-zero on any failure so cron's MAILTO surfaces it.
12+
13+
set -euo pipefail
14+
15+
# Resolve the repo root from this script's location so the wrapper works no
16+
# matter where you put the checkout. Override with REPO_DIR=... if you need
17+
# to point at a different working tree.
18+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19+
REPO_DIR="${REPO_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
20+
21+
cd "$REPO_DIR"
22+
23+
# Author for the bot commits. Override at the cron call site if you want a
24+
# different identity (e.g. a dedicated service account).
25+
GIT_USER_NAME="${GIT_USER_NAME:-proxyscrape-mirror-bot}"
26+
GIT_USER_EMAIL="${GIT_USER_EMAIL:-support@proxyscrape.com}"
27+
28+
# Lock to prevent overlapping runs. A long network stall on one tick should
29+
# never collide with the next. flock returns 1 immediately when the lock is
30+
# held; that's the correct behavior for a 5-min cron — skip this tick.
31+
LOCKFILE="${TMPDIR:-/tmp}/free-proxy-list-mirror.lock"
32+
exec 9>"$LOCKFILE"
33+
if ! flock -n 9; then
34+
echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] Another instance is running; skipping tick" >&2
35+
exit 0
36+
fi
37+
38+
log() {
39+
echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] $*"
40+
}
41+
42+
log "Starting update in $REPO_DIR"
43+
44+
# Pull remote updates first — anyone editing the repo (humans, other servers)
45+
# stays compatible. --autostash protects against any stray local changes.
46+
git pull --rebase --autostash --quiet origin main
47+
48+
# Run the updater. Failures here propagate (set -e).
49+
python3 scripts/update.py
50+
51+
# Stage only the data we publish. The script also writes stats.json under
52+
# proxies/, so a single `git add proxies/` covers everything we care about.
53+
git add proxies/
54+
55+
if git diff --cached --quiet; then
56+
log "No changes — upstream list is unchanged this tick"
57+
exit 0
58+
fi
59+
60+
TS=$(date -u +"%Y-%m-%d %H:%M:%S UTC")
61+
git -c user.name="$GIT_USER_NAME" -c user.email="$GIT_USER_EMAIL" \
62+
commit --quiet -m "chore(data): automatic update — $TS"
63+
64+
# `--quiet` suppresses progress; stderr still surfaces auth/network errors.
65+
git push --quiet
66+
67+
log "Pushed update"

0 commit comments

Comments
 (0)