Remove CI/CD stuffs from being directly in project (migrated to separate
CI/CD infrastructure)
This commit is contained in:
parent
da4925753d
commit
27417f6806
7 changed files with 2 additions and 418 deletions
|
|
@ -1,72 +0,0 @@
|
||||||
name: Build And Deploy
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
apt-get update && apt-get install gettext dnsutils iputils-ping -y
|
|
||||||
- name: Check out repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Substitute environment variables in .env.example and write to .env
|
|
||||||
env:
|
|
||||||
CERTBOT_EMAIL: ${{secrets.CERTBOT_EMAIL}}
|
|
||||||
CLOUDFLARE_API_TOKEN: ${{secrets.CLOUDFLARE_API_TOKEN}}
|
|
||||||
ANDROID_SMS_GATEWAY_LOGIN: ${{secrets.ANDROID_SMS_GATEWAY_LOGIN}}
|
|
||||||
ANDROID_SMS_GATEWAY_PASSWORD: ${{secrets.ANDROID_SMS_GATEWAY_PASSWORD}}
|
|
||||||
ANDROID_SMS_GATEWAY_RECIPIENT_PHONE: ${{secrets.ANDROID_SMS_GATEWAY_RECIPIENT_PHONE}}
|
|
||||||
OTP_SUPER_SECRET_SALT: ${{secrets.OTP_SUPER_SECRET_SALT}}
|
|
||||||
SSH_USER: ${{secrets.SSH_USER}}
|
|
||||||
SSH_KNOWN_HOST: ${{secrets.SSH_KNOWN_HOST}}
|
|
||||||
ASTRO_DB_REMOTE_URL: ${{secrets.ASTRO_DB_REMOTE_URL}}
|
|
||||||
SSH_KEY: ${{secrets.SSH_KEY}}
|
|
||||||
WIREGUARD_PRIVATE_KEY: ${{secrets.WIREGUARD_PRIVATE_KEY}}
|
|
||||||
WIREGUARD_PUBLIC_KEY: ${{secrets.WIREGUARD_PUBLIC_KEY}}
|
|
||||||
DNS_SERVER: ${{vars.DNS_SERVER}}
|
|
||||||
DNS_ADDRESS: ${{vars.DNS_ADDRESS}}
|
|
||||||
DOMAIN: ${{vars.DOMAIN}}
|
|
||||||
PUBLIC_IP: ${{vars.PUBLIC_IP}}
|
|
||||||
ANDROID_SMS_GATEWAY_IP: ${{vars.ANDROID_SMS_GATEWAY_IP}}
|
|
||||||
ANDROID_SMS_GATEWAY_URL: ${{vars.ANDROID_SMS_GATEWAY_URL}}
|
|
||||||
IMAGE_FILENAME: ${{vars.IMAGE_FILENAME}}
|
|
||||||
IMAGE_NAME: ${{vars.IMAGE_NAME}}
|
|
||||||
SSH_PORT: ${{vars.SSH_PORT}}
|
|
||||||
SSH_HOST: ${{vars.SSH_HOST}}
|
|
||||||
WIREGUARD_ALLOWED_IPS: ${{vars.WIREGUARD_ALLOWED_IPS}}
|
|
||||||
WIREGUARD_ADDRESSES: ${{vars.WIREGUARD_ADDRESSES}}
|
|
||||||
WIREGUARD_ENDPOINT_HOST: ${{vars.WIREGUARD_ENDPOINT_HOST}}
|
|
||||||
WIREGUARD_ENDPOINT_PORT: ${{vars.WIREGUARD_ENDPOINT_PORT}}
|
|
||||||
HEALTH_TARGET_ADDRESSES: ${{vars.HEALTH_TARGET_ADDRESSES}}
|
|
||||||
HEALTH_ICMP_TARGET_IPS: ${{vars.HEALTH_ICMP_TARGET_IPS}}
|
|
||||||
VERSION_INFORMATION: ${{vars.VERSION_INFORMATION}}
|
|
||||||
PUBLICIP_ENABLED: ${{vars.PUBLICIP_ENABLED}}
|
|
||||||
run: |
|
|
||||||
envsubst < .env.example > .env
|
|
||||||
# - name: Export secrets and variables to $GITHUB_ENV
|
|
||||||
# env:
|
|
||||||
# SECRETS_CONTEXT: ${{ toJSON(secrets) }}
|
|
||||||
# VARS_CONTEXT: ${{ toJSON(vars) }}
|
|
||||||
# run: |
|
|
||||||
# EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
|
|
||||||
# to_envs() { jq -r "to_entries[] | \"\(.key)<<$EOF\n\(.value)\n$EOF\n\""; }
|
|
||||||
# echo "$VARS_CONTEXT" | to_envs >> $GITHUB_ENV
|
|
||||||
# echo "$SECRETS_CONTEXT" | to_envs >> $GITHUB_ENV
|
|
||||||
# - name: Update .env with secrets and variables
|
|
||||||
# run: |
|
|
||||||
# envsubst < .env.example > .env
|
|
||||||
# cat .env
|
|
||||||
- name: Run build script
|
|
||||||
run: |
|
|
||||||
cd cicd/scripts
|
|
||||||
chmod +x ./build.sh
|
|
||||||
./build.sh
|
|
||||||
- name: Run deploy script
|
|
||||||
run: |
|
|
||||||
cd cicd/scripts
|
|
||||||
chmod +x ./deploy.sh
|
|
||||||
./deploy.sh
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
#######################
|
|
||||||
# VARIABLES #
|
|
||||||
#######################
|
|
||||||
ROOT_DIR=$(dirname $(dirname $(dirname $(realpath $0))))
|
|
||||||
GIT_REF=${GIT_REF:-main}
|
|
||||||
|
|
||||||
### NO EDITS BELOW THIS LINE ###
|
|
||||||
cd ${ROOT_DIR}
|
|
||||||
source .env
|
|
||||||
git checkout ${GIT_REF}
|
|
||||||
GIT_SHA=$(git rev-parse --short HEAD)
|
|
||||||
|
|
||||||
if [[ "${GIT_REF}" =~ ^refs/tags/v([0-9]+\.[0-9]+\.[0-9]+)(-.*)?$ ]]; then
|
|
||||||
VERSION="${BASH_REMATCH[1]}"
|
|
||||||
if [[ -n "${BASH_REMATCH[2]}" ]]; then
|
|
||||||
VERSION="${VERSION}${BASH_REMATCH[2]}"
|
|
||||||
fi
|
|
||||||
echo "Using git tag version: ${VERSION}"
|
|
||||||
else
|
|
||||||
VERSION=$(node -p "require('./package.json').version || '0.0.0'")
|
|
||||||
GIT_SHA_SHORT="${GIT_SHA:0:7}"
|
|
||||||
VERSION="${VERSION}-${GIT_SHA_SHORT}"
|
|
||||||
echo "Using package.json + SHA version: ${VERSION}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker build -t ${IMAGE_NAME}:latest -t ${IMAGE_NAME}:v${VERSION} --build-arg VERSION=${VERSION} .
|
|
||||||
docker save -o ${IMAGE_FILENAME} ${IMAGE_NAME}:latest
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
#######################
|
|
||||||
# VARIABLES #
|
|
||||||
#######################
|
|
||||||
ROOT_DIR=$(dirname $(dirname $(dirname $(realpath $0))))
|
|
||||||
|
|
||||||
### NO EDITS BELOW THIS LINE ###
|
|
||||||
cd ${ROOT_DIR}
|
|
||||||
source .env
|
|
||||||
|
|
||||||
mkdir -p ${HOME}/.ssh
|
|
||||||
chmod 700 ${HOME}/.ssh
|
|
||||||
echo "${SSH_KEY}" > ${HOME}/.ssh/id_ed25519-${SSH_HOST//./_}
|
|
||||||
echo "${SSH_KNOWN_HOST}" > ${HOME}/.ssh/known_hosts-${SSH_HOST//./_}
|
|
||||||
chmod -R 600 ${HOME}/.ssh/
|
|
||||||
chmod 700 ${HOME}/.ssh
|
|
||||||
|
|
||||||
grep -q "Host ${SSH_HOST}" ${HOME}/.ssh/config 2>&1 1>/dev/null || cat >> ${HOME}/.ssh/config <<EOF
|
|
||||||
Host ${SSH_HOST}
|
|
||||||
HostName ${SSH_HOST}
|
|
||||||
User ${SSH_USER}
|
|
||||||
Port ${SSH_PORT}
|
|
||||||
IdentityFile ${HOME}/.ssh/id_ed25519-${SSH_HOST//./_}
|
|
||||||
UserKnownHostsFile ${HOME}/.ssh/known_hosts-${SSH_HOST//./_}
|
|
||||||
StrictHostKeyChecking yes
|
|
||||||
ControlMaster auto
|
|
||||||
ControlPath ~/.ssh/control-%C
|
|
||||||
ControlPersist yes
|
|
||||||
ConnectionAttempts 3
|
|
||||||
ConnectTimeout 10
|
|
||||||
ServerAliveInterval 10
|
|
||||||
EOF
|
|
||||||
|
|
||||||
WIREGUARD_ENDPOINT_IP=$(dig +short $WIREGUARD_ENDPOINT_HOST | tail -n1)
|
|
||||||
[[ -z ${WIREGUARD_ENDPOINT_IP} ]] && echo "Failed to resolve IP address for WIREGUARD_ENDPOINT_HOST" >&2 && exit 1
|
|
||||||
echo "WIREGUARD_ENDPOINT_IP=${WIREGUARD_ENDPOINT_IP}" >> .env
|
|
||||||
|
|
||||||
DOCKER_HOST=ssh://${SSH_HOST} docker load -i ${IMAGE_FILENAME}
|
|
||||||
|
|
||||||
ssh ${SSH_HOST} "mkdir -p /srv/${IMAGE_NAME#*/}/"
|
|
||||||
ssh ${SSH_HOST} "cd /srv/${IMAGE_NAME#*/}/ && docker compose down"
|
|
||||||
scp .env ${SSH_HOST}:/srv/${IMAGE_NAME#*/}/.env
|
|
||||||
cd deploy
|
|
||||||
scp -r . ${SSH_HOST}:/srv/${IMAGE_NAME#*/}/
|
|
||||||
ssh ${SSH_HOST} "cd /srv/${IMAGE_NAME#*/}/ && docker compose up -d"
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
cat /etc/letsencrypt/live/badblocks.dev/fullchain.pem /etc/letsencrypt/live/badblocks.dev/privkey.pem > /etc/letsencrypt/fullcert.pem
|
|
||||||
chmod 755 /etc/letsencrypt/
|
|
||||||
chmod 644 /etc/letsencrypt/fullcert.pem
|
|
||||||
|
|
@ -5,8 +5,6 @@ services:
|
||||||
container_name: badblocks-personal-site
|
container_name: badblocks-personal-site
|
||||||
volumes:
|
volumes:
|
||||||
- ./db:/db
|
- ./db:/db
|
||||||
networks:
|
|
||||||
- proxynet
|
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
# healthcheck:
|
# healthcheck:
|
||||||
|
|
@ -41,46 +39,13 @@ services:
|
||||||
devices:
|
devices:
|
||||||
- /dev/net/tun:/dev/net/tun
|
- /dev/net/tun:/dev/net/tun
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
|
||||||
- proxynet
|
|
||||||
# healthcheck:
|
# healthcheck:
|
||||||
# test: ["CMD", "ping", "-c", "1", "-W", "3", "$$ANDROID_SMS_GATEWAY_IP"]
|
# test: ["CMD", "ping", "-c", "1", "-W", "3", "$$ANDROID_SMS_GATEWAY_IP"]
|
||||||
# interval: 30s
|
# interval: 30s
|
||||||
# timeout: 15s
|
# timeout: 15s
|
||||||
# retries: 3
|
# retries: 3
|
||||||
# start_period: 60s
|
# start_period: 60s
|
||||||
certbot:
|
|
||||||
image: serversideup/certbot-dns-cloudflare
|
|
||||||
container_name: certbot
|
|
||||||
volumes:
|
|
||||||
- ./certs:/etc/letsencrypt
|
|
||||||
environment:
|
|
||||||
CLOUDFLARE_API_TOKEN: "${CLOUDFLARE_API_TOKEN}"
|
|
||||||
CERTBOT_EMAIL: "${CERTBOT_EMAIL}"
|
|
||||||
CERTBOT_DOMAINS: "${DOMAIN}"
|
|
||||||
haproxy:
|
|
||||||
image: haproxy:3.2
|
|
||||||
stop_signal: SIGTERM
|
|
||||||
container_name: haproxy
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
command: ["haproxy", "-f", "/usr/local/etc/haproxy"]
|
|
||||||
ports:
|
|
||||||
- "${PUBLIC_IP}:80:80"
|
|
||||||
- "${PUBLIC_IP}:443:443"
|
|
||||||
- "${PUBLIC_IP}:8404:8404"
|
|
||||||
volumes:
|
|
||||||
- ./haproxy:/usr/local/etc/haproxy:ro
|
|
||||||
- ./certs:/certs:ro
|
|
||||||
restart: always
|
|
||||||
networks:
|
networks:
|
||||||
- proxynet
|
default:
|
||||||
# healthcheck:
|
|
||||||
# test: ["CMD", "haproxy", "-c", "-f", "/usr/local/etc/haproxy"]
|
|
||||||
# interval: 30s
|
|
||||||
# timeout: 10s
|
|
||||||
# retries: 3
|
|
||||||
networks:
|
|
||||||
proxynet:
|
|
||||||
name: proxynet
|
name: proxynet
|
||||||
driver: bridge
|
external: true
|
||||||
|
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<meta name="viewport" content="width=device-width" />
|
|
||||||
<title>Challenge Accepted!</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background: #ddd;
|
|
||||||
color: #000;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
#progress {
|
|
||||||
position: absolute;
|
|
||||||
margin: 0;
|
|
||||||
top: 50%%;
|
|
||||||
left: 50%%;
|
|
||||||
transform: translate(-50%%, -50%%);
|
|
||||||
text-align: center;
|
|
||||||
font-size: 125%%;
|
|
||||||
}
|
|
||||||
#progressBar {
|
|
||||||
font-size: 250%%;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
#progressBar.done {
|
|
||||||
transition:
|
|
||||||
font-size 2s linear,
|
|
||||||
opacity 2s linear;
|
|
||||||
font-size: 1000%%;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
.animate {
|
|
||||||
animation: spin 2s infinite linear;
|
|
||||||
}
|
|
||||||
@keyframes spin {
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iframe {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
footer {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 4px;
|
|
||||||
width: 100%%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<form method="post" target="post" action="/_challenge" name="challenge">
|
|
||||||
<input type="hidden" name="ip" value="%[src]" />
|
|
||||||
<input type="hidden" name="ts" value="%[date]" />
|
|
||||||
<input type="hidden" name="diff" value="4" />
|
|
||||||
<input type="hidden" name="tries" value="" />
|
|
||||||
</form>
|
|
||||||
<div id="progress">
|
|
||||||
<span id="progressText"></span>
|
|
||||||
<div id="progressBar"></div>
|
|
||||||
</div>
|
|
||||||
<iframe srcdoc="" src="about:blank" name="post"></iframe>
|
|
||||||
<script>
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
async function challenge(diff, ip, ts) {
|
|
||||||
let te = new TextEncoder();
|
|
||||||
let tries = 0;
|
|
||||||
progressText.innerText = "✋ Checking connection, please wait";
|
|
||||||
progressBar.innerText = "🌀";
|
|
||||||
progressBar.className = "animate";
|
|
||||||
for (; tries < 10_000_000; tries++) {
|
|
||||||
let hash = await crypto.subtle.digest(
|
|
||||||
"SHA-256",
|
|
||||||
te.encode([ip, location.hostname, ts, tries].join(";")),
|
|
||||||
);
|
|
||||||
let y = new Uint8Array(hash);
|
|
||||||
let i = 0;
|
|
||||||
while (i < diff / 2) {
|
|
||||||
if (y[i] > 0x0f) break;
|
|
||||||
if (i * 2 + 1 >= diff) return tries;
|
|
||||||
if (y[i++] > 0) break;
|
|
||||||
if (i * 2 >= diff) return tries;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function startChallenge(form) {
|
|
||||||
if (!("subtle" in window.crypto)) {
|
|
||||||
if (location.protocol !== "https:") {
|
|
||||||
progress.innerText =
|
|
||||||
"No WebCrypto support. This must be served over a HTTPS connection.";
|
|
||||||
} else {
|
|
||||||
progress.innerText =
|
|
||||||
"No WebCrypto support in your browser. " +
|
|
||||||
"This is required to pass the challenge.";
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let backoff = 0;
|
|
||||||
let tryOnce = (_) => {
|
|
||||||
if (backoff > 8) {
|
|
||||||
progressText.innerText =
|
|
||||||
"Failed to submit after several tries. Try reloading.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setTimeout(
|
|
||||||
async (_) => submitAnswer(form),
|
|
||||||
1000 * (Math.pow(2, backoff++) - 1),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
form.addEventListener("error", tryOnce);
|
|
||||||
let iframe = document.querySelector("iframe");
|
|
||||||
iframe.addEventListener("load", (_) =>
|
|
||||||
location.hash.length ? location.reload() : location.replace(location),
|
|
||||||
);
|
|
||||||
tryOnce();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function submitAnswer(form) {
|
|
||||||
let start = new Date();
|
|
||||||
let tries = await challenge(form.diff.value, form.ip.value, form.ts.value);
|
|
||||||
if (tries === undefined) {
|
|
||||||
progressText.innerText =
|
|
||||||
"Unable to calculate challenge. Try reloading or a different browser.";
|
|
||||||
progressBar.innerText = "🤯";
|
|
||||||
progressBar.className = "error";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
form.tries.value = tries;
|
|
||||||
progressText.innerText = "Took " + (new Date() - start) + "ms";
|
|
||||||
console.log(`${tries} tries.\n${progressText.innerText}`);
|
|
||||||
progressBar.className = "done";
|
|
||||||
progressBar.innerText = "✅";
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("load", (_) =>
|
|
||||||
startChallenge(document.forms.challenge),
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
<noscript
|
|
||||||
>Malicious scrapers break the web. To continue, you'll need JavaScript
|
|
||||||
enabled.</noscript
|
|
||||||
>
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
global
|
|
||||||
daemon
|
|
||||||
log stdout format raw local0 info
|
|
||||||
maxconn 2000
|
|
||||||
# For normalize-uri
|
|
||||||
expose-experimental-directives
|
|
||||||
|
|
||||||
defaults
|
|
||||||
mode http
|
|
||||||
log global
|
|
||||||
timeout connect 5s
|
|
||||||
timeout client 30s
|
|
||||||
timeout server 30s
|
|
||||||
timeout check 5s
|
|
||||||
retries 3
|
|
||||||
option httplog
|
|
||||||
option dontlognull
|
|
||||||
option redispatch
|
|
||||||
|
|
||||||
frontend http
|
|
||||||
bind :80
|
|
||||||
mode http
|
|
||||||
|
|
||||||
http-request redirect scheme https unless { ssl_fc }
|
|
||||||
|
|
||||||
frontend www
|
|
||||||
bind :443 ssl crt /certs/fullcert.pem
|
|
||||||
|
|
||||||
# 2 general purpose tags in this stick-table (name defaults to frontend name, i.e. www)
|
|
||||||
stick-table type ipv6 size 1m expire 2d store gpt(2)
|
|
||||||
http-request track-sc0 src
|
|
||||||
http-request normalize-uri path-merge-slashes
|
|
||||||
http-request normalize-uri path-strip-dot
|
|
||||||
http-request normalize-uri path-strip-dotdot
|
|
||||||
|
|
||||||
# Drop the connection immediately if the requester previously requested the honeypot path)
|
|
||||||
http-request silent-drop if { sc_get_gpt(0,0) gt 0 }
|
|
||||||
|
|
||||||
# Protect all paths except /robots.txt, /.well-known/*, and /favicon.ico
|
|
||||||
acl unprotected_path path -m reg ^/(robots.txt|\.well-known/.*|favicon\.ico|_challenge)$
|
|
||||||
# Matches the default config of anubis of triggering on "Mozilla"
|
|
||||||
acl protected_ua hdr(User-Agent) -m beg Mozilla/
|
|
||||||
# Set stick table index 0 to 1 if request is for honeypot path
|
|
||||||
http-request sc-set-gpt(0,0) 1 if { path -m beg /blokmeplz/ }
|
|
||||||
http-request silent-drop if { path -m beg /blokmeplz/ }
|
|
||||||
|
|
||||||
acl accepted sc_get_gpt(1,0) gt 0
|
|
||||||
http-request return status 200 content-type "text/html; charset=UTF-8" hdr "Cache-control" "max-age=0, no-cache" lf-file /usr/local/etc/haproxy/challenge.html if !unprotected_path protected_ua !accepted
|
|
||||||
use_backend challenge if { path -m beg /_challenge }
|
|
||||||
|
|
||||||
http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;"
|
|
||||||
default_backend main
|
|
||||||
|
|
||||||
backend challenge
|
|
||||||
mode http
|
|
||||||
option http-buffer-request
|
|
||||||
# The parameter to table must match the stick table used in the frontend.
|
|
||||||
http-request track-sc0 src table www
|
|
||||||
acl challenge_req method POST
|
|
||||||
http-request set-var(txn.tries) req.body_param(tries)
|
|
||||||
http-request set-var(txn.ts) req.body_param(ts)
|
|
||||||
http-request set-var(txn.host) hdr(Host),host_only
|
|
||||||
http-request set-var(txn.hash) src,concat(;,txn.host,),concat(;,txn.ts,),concat(;,txn.tries),sha2,hex
|
|
||||||
acl ts_recent date,neg,add(txn.ts) ge -60
|
|
||||||
# 4 is the difficulty, should match "diff" in challenge.html.
|
|
||||||
acl hash_good var(txn.hash) -m reg 0{4}.*
|
|
||||||
http-request sc-set-gpt(1,0) 1 if challenge_req ts_recent hash_good
|
|
||||||
http-request return status 200 if challenge_req hash_good
|
|
||||||
http-request return status 400 content-type "text/html; charset=UTF-8" hdr "Cache-control" "max-age=0" string "Bad request" if !challenge_req OR !hash_good
|
|
||||||
|
|
||||||
backend main
|
|
||||||
mode http
|
|
||||||
balance leastconn
|
|
||||||
option httpchk GET /health
|
|
||||||
http-check expect status 200
|
|
||||||
|
|
||||||
server badblocks-personal-site badblocks-personal-site:4321 check resolvers docker resolve-prefer ipv4 init-addr none
|
|
||||||
|
|
||||||
resolvers docker
|
|
||||||
nameserver dns1 127.0.0.11:53
|
|
||||||
resolve_retries 3
|
|
||||||
timeout resolve 1s
|
|
||||||
timeout retry 1s
|
|
||||||
hold valid 10s
|
|
||||||
hold obsolete 30s
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue