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
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:
parent
3b64839cbd
commit
1fbcbf772a
10 changed files with 106 additions and 57 deletions
13
.env.example
13
.env.example
|
|
@ -16,3 +16,16 @@ SSH_PORT=${SSH_PORT}
|
||||||
SSH_HOST=${SSH_HOST}
|
SSH_HOST=${SSH_HOST}
|
||||||
SSH_KEY="${SSH_KEY}"
|
SSH_KEY="${SSH_KEY}"
|
||||||
SSH_KNOWN_HOST="${SSH_KNOWN_HOST}"
|
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}
|
||||||
|
|
|
||||||
|
|
@ -10,43 +10,56 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
apt-get update && apt-get install gettext -y
|
apt-get update && apt-get install gettext dnsutils iputils-ping -y
|
||||||
- name: Check out repository
|
- name: Check out repository
|
||||||
uses: actions/checkout@v4
|
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
|
- name: Substitute environment variables in .env.example and write to .env
|
||||||
env:
|
env:
|
||||||
CERTBOT_EMAIL: ${{secrets.CERTBOT_EMAIL}}
|
CERTBOT_EMAIL: ${{secrets.CERTBOT_EMAIL}}
|
||||||
CLOUDFLARE_API_TOKEN: ${{secrets.CLOUDFLARE_API_TOKEN}}
|
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_LOGIN: ${{secrets.ANDROID_SMS_GATEWAY_LOGIN}}
|
||||||
ANDROID_SMS_GATEWAY_PASSWORD: ${{secrets.ANDROID_SMS_GATEWAY_PASSWORD}}
|
ANDROID_SMS_GATEWAY_PASSWORD: ${{secrets.ANDROID_SMS_GATEWAY_PASSWORD}}
|
||||||
ANDROID_SMS_GATEWAY_RECIPIENT_PHONE: ${{secrets.ANDROID_SMS_GATEWAY_RECIPIENT_PHONE}}
|
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}}
|
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_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}}
|
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: |
|
run: |
|
||||||
envsubst < .env.example > .env
|
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
|
- name: Run build script
|
||||||
run: |
|
run: |
|
||||||
cd cicd/scripts
|
cd cicd/scripts
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,13 @@ export default defineConfig({
|
||||||
}),
|
}),
|
||||||
// adapter: bun(),
|
// adapter: bun(),
|
||||||
// output: "static",
|
// output: "static",
|
||||||
|
compressHTML: false,
|
||||||
devToolbar: { enabled: false },
|
devToolbar: { enabled: false },
|
||||||
prefetch: {
|
prefetch: {
|
||||||
prefetchAll: true,
|
prefetchAll: true,
|
||||||
},
|
},
|
||||||
security: {
|
security: {
|
||||||
checkOrigin: true,
|
checkOrigin: false,
|
||||||
},
|
},
|
||||||
session: {
|
session: {
|
||||||
driver: "lru-cache",
|
driver: "lru-cache",
|
||||||
|
|
|
||||||
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# VARIABLES #
|
# VARIABLES #
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# VARIABLES #
|
# VARIABLES #
|
||||||
|
|
@ -16,7 +17,7 @@ echo "${SSH_KNOWN_HOST}" > ${HOME}/.ssh/known_hosts-${SSH_HOST//./_}
|
||||||
chmod -R 600 ${HOME}/.ssh/
|
chmod -R 600 ${HOME}/.ssh/
|
||||||
chmod 700 ${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}
|
Host ${SSH_HOST}
|
||||||
HostName ${SSH_HOST}
|
HostName ${SSH_HOST}
|
||||||
User ${SSH_USER}
|
User ${SSH_USER}
|
||||||
|
|
@ -32,6 +33,10 @@ Host ${SSH_HOST}
|
||||||
ServerAliveInterval 10
|
ServerAliveInterval 10
|
||||||
EOF
|
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}
|
DOCKER_HOST=ssh://${SSH_HOST} docker load -i ${IMAGE_FILENAME}
|
||||||
|
|
||||||
ssh ${SSH_HOST} "mkdir -p /srv/${IMAGE_NAME#*/}/"
|
ssh ${SSH_HOST} "mkdir -p /srv/${IMAGE_NAME#*/}/"
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ services:
|
||||||
image: ${IMAGE_NAME}:latest
|
image: ${IMAGE_NAME}:latest
|
||||||
restart: always
|
restart: always
|
||||||
container_name: badblocks-personal-site
|
container_name: badblocks-personal-site
|
||||||
ports:
|
volumes:
|
||||||
- "4321:4321"
|
- /srv/badblocks-personal-site/db:/db
|
||||||
networks:
|
networks:
|
||||||
- proxynet
|
- proxynet
|
||||||
env_file:
|
env_file:
|
||||||
|
|
@ -24,32 +24,33 @@ services:
|
||||||
# timeout: 15s
|
# timeout: 15s
|
||||||
# retries: 3
|
# retries: 3
|
||||||
# start_period: 120s
|
# start_period: 120s
|
||||||
# wireguard:
|
wireguard:
|
||||||
# image: qmcgaw/gluetun
|
image: qmcgaw/gluetun
|
||||||
# cap_add:
|
cap_add:
|
||||||
# - NET_ADMIN
|
- NET_ADMIN
|
||||||
# container_name: wireguard
|
container_name: wireguard
|
||||||
# environment:
|
environment:
|
||||||
# - VPN_SERVICE_PROVIDER=custom
|
- VPN_SERVICE_PROVIDER=custom
|
||||||
# - VPN_TYPE=wireguard
|
- VPN_TYPE=wireguard
|
||||||
# - HTTPPROXY=on
|
- HTTPPROXY=on
|
||||||
# expose:
|
expose:
|
||||||
# - "8888"
|
- "8888"
|
||||||
# env_file:
|
env_file:
|
||||||
# - .env
|
- .env
|
||||||
# devices:
|
devices:
|
||||||
# - /dev/net/tun:/dev/net/tun
|
- /dev/net/tun:/dev/net/tun
|
||||||
# restart: unless-stopped
|
restart: unless-stopped
|
||||||
# networks:
|
networks:
|
||||||
# - proxynet
|
- proxynet
|
||||||
# healthcheck:
|
# 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
|
# interval: 30s
|
||||||
# timeout: 15s
|
# timeout: 15s
|
||||||
# retries: 3
|
# retries: 3
|
||||||
# start_period: 60s
|
# start_period: 60s
|
||||||
certbot:
|
certbot:
|
||||||
image: serversideup/certbot-dns-cloudflare
|
image: serversideup/certbot-dns-cloudflare
|
||||||
|
container_name: certbot
|
||||||
volumes:
|
volumes:
|
||||||
- ./certs:/etc/letsencrypt
|
- ./certs:/etc/letsencrypt
|
||||||
environment:
|
environment:
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,10 @@
|
||||||
"astro-htmx": "^1.0.6",
|
"astro-htmx": "^1.0.6",
|
||||||
"htmx.org": "^2.0.8",
|
"htmx.org": "^2.0.8",
|
||||||
"iconify-icon": "^3.0.2",
|
"iconify-icon": "^3.0.2",
|
||||||
|
"ofetch": "^1.5.1",
|
||||||
"otplib": "^12.0.1",
|
"otplib": "^12.0.1",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
|
"undici": "^7.21.0",
|
||||||
"validator": "^13.15.26"
|
"validator": "^13.15.26"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,53 @@
|
||||||
|
import { ofetch } from "ofetch";
|
||||||
|
import { ProxyAgent } from "undici";
|
||||||
|
|
||||||
|
const wireguardDispatcher = new ProxyAgent("http://wireguard:8888");
|
||||||
|
|
||||||
const httpFetchClient = {
|
const httpFetchClient = {
|
||||||
get: async (url: string, headers: Record<string, string>) => {
|
get: async (url: string, headers: Record<string, string>) => {
|
||||||
const response = await fetch(url, {
|
const response = await ofetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers,
|
headers,
|
||||||
|
dispatcher: wireguardDispatcher,
|
||||||
});
|
});
|
||||||
|
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
post: async (url: string, body: JSON, headers: Record<string, string>) => {
|
post: async (url: string, body: JSON, headers: Record<string, string>) => {
|
||||||
const response = await fetch(url, {
|
const response = await ofetch(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers,
|
headers,
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
|
dispatcher: wireguardDispatcher,
|
||||||
});
|
});
|
||||||
|
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
put: async (url: string, body: JSON, headers: Record<string, string>) => {
|
put: async (url: string, body: JSON, headers: Record<string, string>) => {
|
||||||
const response = await fetch(url, {
|
const response = await ofetch(url, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers,
|
headers,
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
|
dispatcher: wireguardDispatcher,
|
||||||
});
|
});
|
||||||
|
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
patch: async (url: string, body: JSON, headers: Record<string, string>) => {
|
patch: async (url: string, body: JSON, headers: Record<string, string>) => {
|
||||||
const response = await fetch(url, {
|
const response = await ofetch(url, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers,
|
headers,
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
|
dispatcher: wireguardDispatcher,
|
||||||
});
|
});
|
||||||
|
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
delete: async (url: string, headers: Record<string, string>) => {
|
delete: async (url: string, headers: Record<string, string>) => {
|
||||||
const response = await fetch(url, {
|
const response = await ofetch(url, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers,
|
headers,
|
||||||
|
dispatcher: wireguardDispatcher,
|
||||||
});
|
});
|
||||||
|
|
||||||
return response.json();
|
return response.json();
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,16 @@ export const prerender = false;
|
||||||
|
|
||||||
export const POST: APIRoute = async () => {
|
export const POST: APIRoute = async () => {
|
||||||
try {
|
try {
|
||||||
return new Response(
|
return new Response(JSON.stringify(await cap.createChallenge()), {
|
||||||
JSON.stringify(await cap.createChallenge({ challengeDifficulty: 4 })),
|
|
||||||
{
|
|
||||||
status: 200,
|
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 });
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue