From 1fbcbf772a60b9cf1f7123c615b20a081ad67670 Mon Sep 17 00:00:00 2001 From: badbl0cks <4161747+badbl0cks@users.noreply.github.com> Date: Thu, 5 Feb 2026 10:27:26 -0800 Subject: [PATCH] Enable WireGuard service, change HTTPFetchClient to use wireguard proxy, and add required env vars Add WireGuard-related env variables to .env.example (addresses, keys, endpoint, DNS) Resolve WIREGUARD_ENDPOINT_HOST to WIREGUARD_ENDPOINT_IP in cicd/scripts/deploy.sh and write it to .env, failing if unresolved Un-comment and enable the wireguard service in docker-compose.yml Remove an obsolete commented workflow snippet --- .env.example | 13 ++++++ .forgejo/workflows/build-and-deploy.yml | 59 +++++++++++++++--------- astro.config.mjs | 3 +- bun.lockb | Bin 238804 -> 239169 bytes cicd/scripts/build.sh | 1 + cicd/scripts/deploy.sh | 7 ++- deploy/docker-compose.yml | 43 ++++++++--------- package.json | 2 + src/lib/HttpFetchClient.ts | 20 ++++++-- src/pages/cap/challenge.ts | 15 +++--- 10 files changed, 106 insertions(+), 57 deletions(-) diff --git a/.env.example b/.env.example index 93f995b..b8a0b73 100644 --- a/.env.example +++ b/.env.example @@ -16,3 +16,16 @@ SSH_PORT=${SSH_PORT} SSH_HOST=${SSH_HOST} SSH_KEY="${SSH_KEY}" SSH_KNOWN_HOST="${SSH_KNOWN_HOST}" +WIREGUARD_ALLOWED_IPS=${WIREGUARD_ALLOWED_IPS} +DNS_SERVER=${DNS_SERVER} +DNS_ADDRESS=${DNS_ADDRESS} +WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY} +WIREGUARD_ADDRESSES=${WIREGUARD_ADDRESSES} +WIREGUARD_PUBLIC_KEY=${WIREGUARD_PUBLIC_KEY} +WIREGUARD_ENDPOINT_HOST=${WIREGUARD_ENDPOINT_HOST} +WIREGUARD_ENDPOINT_PORT=${WIREGUARD_ENDPOINT_PORT} +WIREGUARD_ENDPOINT_IP=${WIREGUARD_ENDPOINT_IP} +HEALTH_TARGET_ADDRESSES=${HEALTH_TARGET_ADDRESSES} +HEALTH_ICMP_TARGET_IPS=${HEALTH_ICMP_TARGET_IPS} +VERSION_INFORMATION=${VERSION_INFORMATION} +PUBLICIP_ENABLED=${PUBLICIP_ENABLED} diff --git a/.forgejo/workflows/build-and-deploy.yml b/.forgejo/workflows/build-and-deploy.yml index 7396a1f..274e94a 100644 --- a/.forgejo/workflows/build-and-deploy.yml +++ b/.forgejo/workflows/build-and-deploy.yml @@ -10,43 +10,56 @@ jobs: steps: - name: Install dependencies run: | - apt-get update && apt-get install gettext -y + apt-get update && apt-get install gettext dnsutils iputils-ping -y - name: Check out repository uses: actions/checkout@v4 - # - name: Expose repo secrets and vars as shell variables - # env: - # SECRETS_CONTEXT: ${{ toJSON(secrets) }} - # VARS_CONTEXT: ${{ toJSON(vars) }} - # run: | - # # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable - # # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings - # # # EOF randomness is to account for empty secrets and vars - # 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: Substitute environment variables in .env.example and write to .env env: CERTBOT_EMAIL: ${{secrets.CERTBOT_EMAIL}} CLOUDFLARE_API_TOKEN: ${{secrets.CLOUDFLARE_API_TOKEN}} - DOMAIN: ${{secrets.DOMAIN}} - PUBLIC_IP: ${{secrets.PUBLIC_IP}} - ANDROID_SMS_GATEWAY_IP: ${{secrets.ANDROID_SMS_GATEWAY_IP}} - ANDROID_SMS_GATEWAY_URL: ${{secrets.ANDROID_SMS_GATEWAY_URL}} 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}} - ASTRO_DB_REMOTE_URL: ${{secrets.ASTRO_DB_REMOTE_URL}} OTP_SUPER_SECRET_SALT: ${{secrets.OTP_SUPER_SECRET_SALT}} - IMAGE_FILENAME: ${{secrets.IMAGE_FILENAME}} - IMAGE_NAME: ${{secrets.IMAGE_NAME}} SSH_USER: ${{secrets.SSH_USER}} - SSH_PORT: ${{secrets.SSH_PORT}} - SSH_HOST: ${{secrets.SSH_HOST}} - SSH_KEY: ${{secrets.SSH_KEY}} 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 diff --git a/astro.config.mjs b/astro.config.mjs index e98b414..427afd4 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -18,12 +18,13 @@ export default defineConfig({ }), // adapter: bun(), // output: "static", + compressHTML: false, devToolbar: { enabled: false }, prefetch: { prefetchAll: true, }, security: { - checkOrigin: true, + checkOrigin: false, }, session: { driver: "lru-cache", diff --git a/bun.lockb b/bun.lockb index 0cc7456c869a9d9b52e6ede651be4c1453e145ca..a4e562ffdbc309128415d8fc9a9e2a5d187ca9ef 100755 GIT binary patch delta 44316 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 delta 44012 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 G-S!{rw7Zi4 diff --git a/cicd/scripts/build.sh b/cicd/scripts/build.sh index 3dedac4..8c105a4 100755 --- a/cicd/scripts/build.sh +++ b/cicd/scripts/build.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -eu ####################### # VARIABLES # diff --git a/cicd/scripts/deploy.sh b/cicd/scripts/deploy.sh index 350fa0a..2dec7ad 100755 --- a/cicd/scripts/deploy.sh +++ b/cicd/scripts/deploy.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -eu ####################### # VARIABLES # @@ -16,7 +17,7 @@ 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 || cat >> ${HOME}/.ssh/config <&1 1>/dev/null || cat >> ${HOME}/.ssh/config <&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#*/}/" diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index b5dd6a4..ab1a62f 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -3,8 +3,8 @@ services: image: ${IMAGE_NAME}:latest restart: always container_name: badblocks-personal-site - ports: - - "4321:4321" + volumes: + - /srv/badblocks-personal-site/db:/db networks: - proxynet env_file: @@ -24,32 +24,33 @@ services: # timeout: 15s # retries: 3 # start_period: 120s - # wireguard: - # image: qmcgaw/gluetun - # cap_add: - # - NET_ADMIN - # container_name: wireguard - # environment: - # - VPN_SERVICE_PROVIDER=custom - # - VPN_TYPE=wireguard - # - HTTPPROXY=on - # expose: - # - "8888" - # env_file: - # - .env - # devices: - # - /dev/net/tun:/dev/net/tun - # restart: unless-stopped - # networks: - # - proxynet + wireguard: + image: qmcgaw/gluetun + cap_add: + - NET_ADMIN + container_name: wireguard + environment: + - VPN_SERVICE_PROVIDER=custom + - VPN_TYPE=wireguard + - HTTPPROXY=on + expose: + - "8888" + env_file: + - .env + devices: + - /dev/net/tun:/dev/net/tun + restart: unless-stopped + networks: + - proxynet # healthcheck: - # test: ss["CMD", "ping", "-c", "1", "-W", "3", "$$ANDROID_SMS_GATEWAY_IP"] + # test: ["CMD", "ping", "-c", "1", "-W", "3", "$$ANDROID_SMS_GATEWAY_IP"] # interval: 30s # timeout: 15s # retries: 3 # start_period: 60s certbot: image: serversideup/certbot-dns-cloudflare + container_name: certbot volumes: - ./certs:/etc/letsencrypt environment: diff --git a/package.json b/package.json index ea5cbff..b99ae72 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,10 @@ "astro-htmx": "^1.0.6", "htmx.org": "^2.0.8", "iconify-icon": "^3.0.2", + "ofetch": "^1.5.1", "otplib": "^12.0.1", "typescript": "^5.9.3", + "undici": "^7.21.0", "validator": "^13.15.26" }, "devDependencies": { diff --git a/src/lib/HttpFetchClient.ts b/src/lib/HttpFetchClient.ts index 54e637c..0b3e7f1 100644 --- a/src/lib/HttpFetchClient.ts +++ b/src/lib/HttpFetchClient.ts @@ -1,43 +1,53 @@ +import { ofetch } from "ofetch"; +import { ProxyAgent } from "undici"; + +const wireguardDispatcher = new ProxyAgent("http://wireguard:8888"); + const httpFetchClient = { get: async (url: string, headers: Record) => { - const response = await fetch(url, { + const response = await ofetch(url, { method: "GET", headers, + dispatcher: wireguardDispatcher, }); return response.json(); }, post: async (url: string, body: JSON, headers: Record) => { - const response = await fetch(url, { + const response = await ofetch(url, { method: "POST", headers, body: JSON.stringify(body), + dispatcher: wireguardDispatcher, }); return response.json(); }, put: async (url: string, body: JSON, headers: Record) => { - const response = await fetch(url, { + const response = await ofetch(url, { method: "PUT", headers, body: JSON.stringify(body), + dispatcher: wireguardDispatcher, }); return response.json(); }, patch: async (url: string, body: JSON, headers: Record) => { - const response = await fetch(url, { + const response = await ofetch(url, { method: "PATCH", headers, body: JSON.stringify(body), + dispatcher: wireguardDispatcher, }); return response.json(); }, delete: async (url: string, headers: Record) => { - const response = await fetch(url, { + const response = await ofetch(url, { method: "DELETE", headers, + dispatcher: wireguardDispatcher, }); return response.json(); diff --git a/src/pages/cap/challenge.ts b/src/pages/cap/challenge.ts index 35151b2..3dde79a 100644 --- a/src/pages/cap/challenge.ts +++ b/src/pages/cap/challenge.ts @@ -4,13 +4,16 @@ export const prerender = false; export const POST: APIRoute = async () => { try { + return new Response(JSON.stringify(await cap.createChallenge()), { + status: 200, + }); + } catch (error) { return new Response( - JSON.stringify(await cap.createChallenge({ challengeDifficulty: 4 })), - { - status: 200, - }, + JSON.stringify({ + success: false, + error: error instanceof Error ? error.message : String(error), + }), + { status: 400 }, ); - } catch { - return new Response(JSON.stringify({ success: false }), { status: 400 }); } };