Enable WireGuard service, change HTTPFetchClient to use wireguard proxy, and add required env vars
All checks were successful
Build And Deploy / build-and-deploy (push) Successful in 1m22s

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
This commit is contained in:
badblocks 2026-02-05 10:27:26 -08:00
parent 3b64839cbd
commit 1fbcbf772a
No known key found for this signature in database
10 changed files with 106 additions and 57 deletions

View file

@ -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}

View file

@ -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

View file

@ -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",

BIN
bun.lockb

Binary file not shown.

View file

@ -1,4 +1,5 @@
#!/bin/bash
set -eu
#######################
# VARIABLES #

View file

@ -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 <<EOF
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}
@ -32,6 +33,10 @@ Host ${SSH_HOST}
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#*/}/"

View file

@ -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:

View file

@ -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": {

View file

@ -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<string, string>) => {
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<string, string>) => {
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<string, string>) => {
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<string, string>) => {
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<string, string>) => {
const response = await fetch(url, {
const response = await ofetch(url, {
method: "DELETE",
headers,
dispatcher: wireguardDispatcher,
});
return response.json();

View file

@ -4,13 +4,16 @@ export const prerender = false;
export const POST: APIRoute = async () => {
try {
return new Response(
JSON.stringify(await cap.createChallenge({ challengeDifficulty: 4 })),
{
return new Response(JSON.stringify(await cap.createChallenge()), {
status: 200,
},
});
} catch (error) {
return new Response(
JSON.stringify({
success: false,
error: error instanceof Error ? error.message : String(error),
}),
{ status: 400 },
);
} catch {
return new Response(JSON.stringify({ success: false }), { status: 400 });
}
};