Compare commits
No commits in common. "74644e547cb58d070ff75a2a8f5e5efa56685e30" and "50013d8ede9996739387a35d3140fcc15bcb3d80" have entirely different histories.
74644e547c
...
50013d8ede
5 changed files with 123 additions and 434 deletions
|
|
@ -7,8 +7,6 @@
|
|||
function cmd::config::on_load() {
|
||||
flag::register --name
|
||||
flag::register --type
|
||||
flag::register --force
|
||||
flag::register --dry-run
|
||||
}
|
||||
|
||||
# ============================================
|
||||
|
|
@ -35,43 +33,27 @@ EOF
|
|||
# ============================================
|
||||
|
||||
function cmd::config::run() {
|
||||
local subcmd="${1:-show}"
|
||||
local name=""
|
||||
local type=""
|
||||
|
||||
# If first arg is a flag, treat as 'show' subcommand
|
||||
if [[ "$subcmd" == --* ]]; then
|
||||
subcmd="show"
|
||||
else
|
||||
shift || true
|
||||
fi
|
||||
|
||||
case "$subcmd" in
|
||||
show) cmd::config::_show "$@" ;;
|
||||
migrate) cmd::config::migrate "$@" ;;
|
||||
help) cmd::config::help ;;
|
||||
*)
|
||||
log::error "Unknown subcommand: '${subcmd}'"
|
||||
cmd::config::help
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Show
|
||||
# ============================================
|
||||
|
||||
function cmd::config::_show() {
|
||||
local name="" type=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--name) name="$2"; shift 2 ;;
|
||||
--type) type="$2"; shift 2 ;;
|
||||
--help) cmd::config::help; return ;;
|
||||
*) log::error "Unknown flag: $1"; return 1 ;;
|
||||
--name) name="$2"; shift 2 ;;
|
||||
--type) type="$2"; shift 2 ;;
|
||||
--help) cmd::config::help; return ;;
|
||||
*)
|
||||
log::error "Unknown flag: $1"
|
||||
cmd::config::help
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -z "$name" ]] && log::error "Missing required flag: --name" && return 1
|
||||
if [[ -z "$name" ]]; then
|
||||
log::error "Missing required flag: --name"
|
||||
return 1
|
||||
fi
|
||||
|
||||
name=$(peers::resolve_and_require "$name" "$type") || return 1
|
||||
|
||||
local conf
|
||||
|
|
@ -79,203 +61,4 @@ function cmd::config::_show() {
|
|||
|
||||
log::section "Client Config: ${name}"
|
||||
cat "$conf"
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Migrate
|
||||
# ============================================
|
||||
|
||||
function cmd::config::migrate() {
|
||||
local force=false dry_run=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--force) force=true; shift ;;
|
||||
--dry-run) dry_run=true; shift ;;
|
||||
--help) cmd::config::help; return ;;
|
||||
*) log::error "Unknown flag: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
local wgctl_dir
|
||||
wgctl_dir="$(ctx::wgctl)"
|
||||
local config_dir="${wgctl_dir}/config"
|
||||
local data_dir="${wgctl_dir}/data"
|
||||
local legacy_conf="${wgctl_dir}/wgctl.conf"
|
||||
local json_conf="${config_dir}/wgctl.json"
|
||||
|
||||
# Check if already migrated
|
||||
if [[ -f "$json_conf" && ! -f "$legacy_conf" ]]; then
|
||||
log::wg_warning "Already migrated to new config structure"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log::section "wgctl Config Migration"
|
||||
printf "\n"
|
||||
printf " This will:\n"
|
||||
printf " 1. Create %s/config/ and %s/data/\n" "$wgctl_dir" "$wgctl_dir"
|
||||
printf " 2. Convert wgctl.conf → wgctl.json\n"
|
||||
printf " 3. Move data files to data/\n\n"
|
||||
|
||||
if ! $force && ! $dry_run; then
|
||||
read -r -p " Proceed? [y/N] " confirm
|
||||
case "$confirm" in [yY]*) ;; *) log::info "Aborted"; return 0 ;; esac
|
||||
fi
|
||||
|
||||
local do=""
|
||||
$dry_run && do="echo [dry-run]"
|
||||
|
||||
# 1. Create directories
|
||||
$dry_run || mkdir -p "$config_dir" "$data_dir"
|
||||
$dry_run && printf " Would create: %s/config/\n" "$wgctl_dir"
|
||||
$dry_run && printf " Would create: %s/data/\n" "$wgctl_dir"
|
||||
|
||||
# 2. Convert wgctl.conf → wgctl.json
|
||||
if [[ -f "$legacy_conf" ]]; then
|
||||
if ! $dry_run; then
|
||||
config::_convert_to_json "$legacy_conf" "$json_conf"
|
||||
fi
|
||||
printf " %s wgctl.conf → config/wgctl.json\n" "$($dry_run && echo '[dry-run]' || echo '✓')"
|
||||
else
|
||||
log::wg_warning "No wgctl.conf found — creating default wgctl.json"
|
||||
$dry_run || config::_write_default_json "$json_conf"
|
||||
fi
|
||||
|
||||
# 3. Move data files
|
||||
local -a data_files=(
|
||||
"hosts.json"
|
||||
"services.json"
|
||||
"subnets.json"
|
||||
"policies.json"
|
||||
)
|
||||
local -a data_dirs=(
|
||||
"rules"
|
||||
"identities"
|
||||
"groups"
|
||||
"blocks"
|
||||
"meta"
|
||||
"peer-history"
|
||||
)
|
||||
|
||||
for f in "${data_files[@]}"; do
|
||||
if [[ -f "${wgctl_dir}/${f}" ]]; then
|
||||
$dry_run || mv "${wgctl_dir}/${f}" "${data_dir}/${f}"
|
||||
printf " %s %s → data/%s\n" \
|
||||
"$($dry_run && echo '[dry-run]' || echo '✓')" "$f" "$f"
|
||||
fi
|
||||
done
|
||||
|
||||
for d in "${data_dirs[@]}"; do
|
||||
if [[ -d "${wgctl_dir}/${d}" ]]; then
|
||||
$dry_run || mv "${wgctl_dir}/${d}" "${data_dir}/${d}"
|
||||
printf " %s %s/ → data/%s/\n" \
|
||||
"$($dry_run && echo '[dry-run]' || echo '✓')" "$d" "$d"
|
||||
fi
|
||||
done
|
||||
|
||||
# 4. Remove legacy conf after successful migration
|
||||
if ! $dry_run && [[ -f "$legacy_conf" ]]; then
|
||||
mv "$legacy_conf" "${legacy_conf}.bak"
|
||||
printf " ✓ wgctl.conf → wgctl.conf.bak (backup)\n"
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
$dry_run && log::wg_warning "Dry run — no changes made" \
|
||||
|| log::wg_success "Migration complete"
|
||||
}
|
||||
|
||||
function config::_convert_to_json() {
|
||||
local legacy_file="$1" output_file="$2"
|
||||
|
||||
# Read legacy conf into variables
|
||||
local wg_interface="wg0" wg_endpoint="" wg_dns="10.0.0.103"
|
||||
local wg_dns_fallback="" wg_port="51820" wg_subnet="10.1.0.0/16"
|
||||
local wg_lan="10.0.0.0/24" wg_hs_check="300" date_format="eu"
|
||||
|
||||
while IFS='=' read -r key value || [[ -n "$key" ]]; do
|
||||
[[ "$key" =~ ^[[:space:]]*# ]] && continue
|
||||
[[ -z "${key// }" ]] && continue
|
||||
key="${key// /}"
|
||||
value="${value// /}"
|
||||
case "$key" in
|
||||
WG_INTERFACE) wg_interface="$value" ;;
|
||||
WG_ENDPOINT) wg_endpoint="$value" ;;
|
||||
WG_DNS) wg_dns="$value" ;;
|
||||
WG_DNS_FALLBACK) wg_dns_fallback="$value" ;;
|
||||
WG_PORT) wg_port="$value" ;;
|
||||
WG_SUBNET) wg_subnet="$value" ;;
|
||||
WG_LAN) wg_lan="$value" ;;
|
||||
WG_HANDSHAKE_CHECK_TIME_SEC) wg_hs_check="$value" ;;
|
||||
DATE_FORMAT) date_format="$value" ;;
|
||||
esac
|
||||
done < "$legacy_file"
|
||||
|
||||
# Build fallback DNS array
|
||||
local dns_fallback_json="[]"
|
||||
if [[ -n "$wg_dns_fallback" ]]; then
|
||||
local fallback_array
|
||||
fallback_array=$(echo "$wg_dns_fallback" | tr ',' '\n' | \
|
||||
while IFS= read -r s; do
|
||||
s="${s// /}"
|
||||
[[ -n "$s" ]] && printf '"%s",' "$s"
|
||||
done | sed 's/,$//')
|
||||
dns_fallback_json="[${fallback_array}]"
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$output_file")"
|
||||
cat > "$output_file" << JSON
|
||||
{
|
||||
"wireguard": {
|
||||
"interface": "${wg_interface}",
|
||||
"endpoint": "${wg_endpoint}",
|
||||
"port": ${wg_port},
|
||||
"subnet": "${wg_subnet}",
|
||||
"lan": "${wg_lan}"
|
||||
},
|
||||
"dns": {
|
||||
"primary": "${wg_dns}",
|
||||
"fallback": ${dns_fallback_json}
|
||||
},
|
||||
"handshake": {
|
||||
"check_interval_sec": ${wg_hs_check}
|
||||
},
|
||||
"activity": {
|
||||
"total": {"low": 1000000, "medium": 10000000, "high": 100000000},
|
||||
"current": {"low": 1000000, "medium": 10000000, "high": 100000000}
|
||||
},
|
||||
"display": {
|
||||
"date_format": "${date_format}"
|
||||
}
|
||||
}
|
||||
JSON
|
||||
}
|
||||
|
||||
function config::_write_default_json() {
|
||||
local output_file="$1"
|
||||
mkdir -p "$(dirname "$output_file")"
|
||||
cat > "$output_file" << 'JSON'
|
||||
{
|
||||
"wireguard": {
|
||||
"interface": "wg0",
|
||||
"endpoint": "",
|
||||
"port": 51820,
|
||||
"subnet": "10.1.0.0/16",
|
||||
"lan": "10.0.0.0/24"
|
||||
},
|
||||
"dns": {
|
||||
"primary": "10.0.0.103",
|
||||
"fallback": []
|
||||
},
|
||||
"handshake": {
|
||||
"check_interval_sec": 300
|
||||
},
|
||||
"activity": {
|
||||
"total": {"low": 1000000, "medium": 10000000, "high": 100000000},
|
||||
"current": {"low": 1000000, "medium": 10000000, "high": 100000000}
|
||||
},
|
||||
"display": {
|
||||
"date_format": "eu"
|
||||
}
|
||||
}
|
||||
JSON
|
||||
}
|
||||
104
core/context.sh
104
core/context.sh
|
|
@ -10,88 +10,80 @@ _CTX_CORE="${_CTX_ROOT}/core"
|
|||
_CTX_MODULES="${_CTX_ROOT}/modules"
|
||||
_CTX_COMMANDS="${_CTX_ROOT}/commands"
|
||||
_CTX_CLIENTS="${_CTX_WG}/clients"
|
||||
_CTX_DATA="${_CTX_WG}/.wgctl"
|
||||
|
||||
# ── Directory layout ──────────────────────────────────
|
||||
# .wgctl/
|
||||
# config/ ← wgctl.json, display.json
|
||||
# data/ ← all persistent data (rules, identities, etc.)
|
||||
# daemon/ ← runtime files (logs, caches)
|
||||
# ============================================
|
||||
# Artifacts
|
||||
# ============================================
|
||||
|
||||
_CTX_WGCTL="${_CTX_WG}/.wgctl"
|
||||
_CTX_CONFIG="${_CTX_WGCTL}/config"
|
||||
_CTX_DATA="${_CTX_WGCTL}/data"
|
||||
_CTX_DAEMON="${_CTX_WGCTL}/daemon"
|
||||
|
||||
# ── Data subdirs ──────────────────────────────────────
|
||||
_CTX_RULES="${_CTX_DATA}/rules"
|
||||
_CTX_RULES_BASE="${_CTX_RULES}/base"
|
||||
_CTX_GROUPS="${_CTX_DATA}/groups"
|
||||
_CTX_BLOCKS="${_CTX_DATA}/blocks"
|
||||
_CTX_META="${_CTX_DATA}/meta"
|
||||
_CTX_IDENTITY="${_CTX_DATA}/identities"
|
||||
_CTX_PEER_HISTORY="${_CTX_DATA}/peer-history"
|
||||
|
||||
# ── Data files ────────────────────────────────────────
|
||||
_CTX_DAEMON="${_CTX_DATA}/daemon"
|
||||
_CTX_NET="${_CTX_DATA}/services.json"
|
||||
_CTX_HOSTS="${_CTX_DATA}/hosts.json"
|
||||
_CTX_SUBNETS="${_CTX_DATA}/subnets.json"
|
||||
_CTX_POLICIES="${_CTX_DATA}/policies.json"
|
||||
|
||||
# ── Config files ──────────────────────────────────────
|
||||
_CTX_CONFIG_FILE="${_CTX_CONFIG}/wgctl.json"
|
||||
|
||||
# ============================================
|
||||
# Accessors
|
||||
# ============================================
|
||||
|
||||
function ctx::root() { echo "$_CTX_ROOT"; }
|
||||
function ctx::core() { echo "$_CTX_CORE"; }
|
||||
function ctx::modules() { echo "$_CTX_MODULES"; }
|
||||
function ctx::commands() { echo "$_CTX_COMMANDS"; }
|
||||
function ctx::wg() { echo "$_CTX_WG"; }
|
||||
function ctx::clients() { echo "$_CTX_CLIENTS"; }
|
||||
|
||||
# Top-level dirs
|
||||
function ctx::wgctl() { echo "$_CTX_WGCTL"; }
|
||||
function ctx::config() { echo "$_CTX_CONFIG"; }
|
||||
function ctx::data() { echo "$_CTX_DATA"; }
|
||||
function ctx::daemon() { echo "$_CTX_DAEMON"; }
|
||||
|
||||
# Data subdirs
|
||||
function ctx::blocks() { echo "$_CTX_BLOCKS"; }
|
||||
function ctx::groups() { echo "$_CTX_GROUPS"; }
|
||||
function ctx::rules() { echo "$_CTX_RULES"; }
|
||||
function ctx::rules::base() { echo "$_CTX_RULES_BASE"; }
|
||||
function ctx::clients() { echo "$_CTX_CLIENTS"; }
|
||||
function ctx::wg() { echo "$_CTX_WG"; }
|
||||
function ctx::data() { echo "$_CTX_DATA"; }
|
||||
function ctx::rules() { echo "$_CTX_RULES"; }
|
||||
function ctx::groups() { echo "$_CTX_GROUPS"; }
|
||||
function ctx::blocks() { echo "$_CTX_BLOCKS"; }
|
||||
function ctx::meta() { echo "$_CTX_META"; }
|
||||
function ctx::identities() { echo "$_CTX_IDENTITY"; }
|
||||
function ctx::peer_history() { echo "$_CTX_PEER_HISTORY"; }
|
||||
|
||||
# Data files
|
||||
function ctx::daemon() { echo "$_CTX_DAEMON"; }
|
||||
function ctx::net() { echo "$_CTX_NET"; }
|
||||
function ctx::hosts() { echo "$_CTX_HOSTS"; }
|
||||
function ctx::subnets() { echo "$_CTX_SUBNETS"; }
|
||||
function ctx::policies() { echo "$_CTX_POLICIES"; }
|
||||
|
||||
# Config files
|
||||
function ctx::config_file() { echo "$_CTX_CONFIG_FILE"; }
|
||||
|
||||
# Daemon files
|
||||
function ctx::events_log() { echo "${_CTX_DAEMON}/events.log"; }
|
||||
function ctx::fw_events_log() { echo "${_CTX_DAEMON}/fw_events.log"; }
|
||||
function ctx::endpoint_cache() { echo "${_CTX_DAEMON}/endpoint_cache.json"; }
|
||||
|
||||
# Tool paths
|
||||
function ctx::identities() { echo "${_CTX_IDENTITY}"; }
|
||||
function ctx::policies() { echo "${_CTX_DATA}/policies.json"; }
|
||||
function ctx::subnets() { echo "${_CTX_DATA}/subnets.json"; }
|
||||
function ctx::hosts() { echo "${_CTX_DATA}/hosts.json"; }
|
||||
function ctx::events_log() { echo "$(ctx::daemon)/events.log"; }
|
||||
function ctx::fw_events_log() { echo "$(ctx::daemon)/fw_events.log"; }
|
||||
function ctx::json_helper() { echo "${_CTX_CORE}/json_helper.py"; }
|
||||
function ctx::monitor_script() { echo "${_CTX_ROOT}/daemon/wgctl-monitor.py"; }
|
||||
function ctx::lib() { echo "${_CTX_CORE}/lib"; }
|
||||
function ctx::endpoint_cache() { echo "${_CTX_DAEMON}/endpoint_cache.json"; }
|
||||
|
||||
# ============================================
|
||||
# Path Helpers
|
||||
# ============================================
|
||||
|
||||
function ctx::client::path() { local IFS="/"; echo "$_CTX_CLIENTS/$*"; }
|
||||
function ctx::meta::path() { local IFS="/"; echo "$_CTX_META/$*"; }
|
||||
function ctx::identity::path() { local IFS="/"; echo "$_CTX_IDENTITY/$*"; }
|
||||
function ctx::block::path() { local IFS="/"; echo "$_CTX_BLOCKS/$*"; }
|
||||
function ctx::group::path() { local IFS="/"; echo "$_CTX_GROUPS/$*"; }
|
||||
function ctx::rule::path() { local IFS="/"; echo "$_CTX_RULES/$*"; }
|
||||
function ctx::client::path() {
|
||||
local IFS="/"
|
||||
echo "$_CTX_CLIENTS/$*"
|
||||
}
|
||||
|
||||
function ctx::meta::path() {
|
||||
local IFS="/"
|
||||
echo "$_CTX_META/$*"
|
||||
}
|
||||
|
||||
function ctx::identity::path() {
|
||||
local IFS="/"
|
||||
echo "$_CTX_IDENTITY/$*"
|
||||
}
|
||||
|
||||
function ctx::block::path() {
|
||||
local IFS="/"
|
||||
echo "$_CTX_BLOCKS/$*"
|
||||
}
|
||||
|
||||
function ctx::group::path() {
|
||||
local IFS="/"
|
||||
echo "$_CTX_GROUPS/$*"
|
||||
}
|
||||
|
||||
function ctx::rule::path() {
|
||||
local IFS="/"
|
||||
echo "$_CTX_RULES/$*"
|
||||
}
|
||||
|
|
@ -144,10 +144,6 @@ function json::error_envelope() {
|
|||
"$command" "$error" "$ts"
|
||||
}
|
||||
|
||||
# Config
|
||||
|
||||
function json::config_load() { python3 "$JSON_HELPER" config_load "$1" </dev/null; }
|
||||
|
||||
function json::peer_transfer() {
|
||||
ACTIVITY_TOTAL_LOW="$(config::activity_total_low)" \
|
||||
ACTIVITY_TOTAL_MED="$(config::activity_total_med)" \
|
||||
|
|
|
|||
|
|
@ -1564,53 +1564,6 @@ def peer_history_lookup(history_dir, ip):
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def config_load(file):
|
||||
"""
|
||||
Load wgctl.json and output KEY=value pairs for all config fields.
|
||||
Automatically handles nested sections — add fields to JSON, they appear here.
|
||||
"""
|
||||
import os
|
||||
if not os.path.exists(file):
|
||||
return
|
||||
try:
|
||||
with open(file) as f:
|
||||
d = json.load(f)
|
||||
|
||||
def emit(key, val):
|
||||
if val is not None and val != '':
|
||||
print(f"{key}={val}")
|
||||
|
||||
wg = d.get('wireguard', {})
|
||||
dns = d.get('dns', {})
|
||||
hs = d.get('handshake', {})
|
||||
act = d.get('activity', {})
|
||||
dis = d.get('display', {})
|
||||
|
||||
emit('WG_INTERFACE', wg.get('interface'))
|
||||
emit('WG_ENDPOINT', wg.get('endpoint'))
|
||||
emit('WG_PORT', wg.get('port'))
|
||||
emit('WG_SUBNET', wg.get('subnet'))
|
||||
emit('WG_LAN', wg.get('lan'))
|
||||
emit('WG_DNS', dns.get('primary'))
|
||||
# fallback: join array to comma-separated string
|
||||
fb = dns.get('fallback', [])
|
||||
if fb: emit('WG_DNS_FALLBACK', ', '.join(str(x) for x in fb))
|
||||
emit('WG_HANDSHAKE_CHECK_TIME_SEC', hs.get('check_interval_sec'))
|
||||
emit('DATE_FORMAT', dis.get('date_format'))
|
||||
|
||||
atot = act.get('total', {})
|
||||
acur = act.get('current', {})
|
||||
emit('ACTIVITY_TOTAL_LOW_BYTES', atot.get('low'))
|
||||
emit('ACTIVITY_TOTAL_MED_BYTES', atot.get('medium'))
|
||||
emit('ACTIVITY_TOTAL_HIGH_BYTES', atot.get('high'))
|
||||
emit('ACTIVITY_CURRENT_LOW_BYTES', acur.get('low'))
|
||||
emit('ACTIVITY_CURRENT_MED_BYTES', acur.get('medium'))
|
||||
emit('ACTIVITY_CURRENT_HIGH_BYTES', acur.get('high'))
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# ======================================================
|
||||
|
||||
def _net_read(file):
|
||||
|
|
@ -1980,7 +1933,6 @@ commands = {
|
|||
'clean_handshakes': lambda args: clean_handshakes(args[0], args[1] if len(args) > 1 else '300'),
|
||||
'batch_resolve': lambda args: batch_resolve(args[0], args[1], *args[2:]),
|
||||
'peer_history_lookup': lambda args: peer_history_lookup(args[0], args[1]),
|
||||
'config_load': lambda args: config_load(args[0]),
|
||||
}
|
||||
|
||||
# ── Main ─────────────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -8,30 +8,32 @@ function config::on_load() {
|
|||
config::_init_defaults
|
||||
config::load
|
||||
config::validate
|
||||
fmt::set_date_format "${_FMT_DATE_FORMAT:-eu}"
|
||||
fmt::set_date_format "${_FMT_DATE_FORMAT:-iso}"
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Defaults
|
||||
# ============================================
|
||||
|
||||
# Activity thresholds
|
||||
declare -g _ACTIVITY_TOTAL_LOW_BYTES="${ACTIVITY_TOTAL_LOW_BYTES:-1000000}"
|
||||
declare -g _ACTIVITY_TOTAL_MED_BYTES="${ACTIVITY_TOTAL_MED_BYTES:-10000000}"
|
||||
declare -g _ACTIVITY_TOTAL_HIGH_BYTES="${ACTIVITY_TOTAL_HIGH_BYTES:-100000000}"
|
||||
|
||||
declare -g _ACTIVITY_CURRENT_LOW_BYTES="${ACTIVITY_CURRENT_LOW_BYTES:-1000000}"
|
||||
declare -g _ACTIVITY_CURRENT_MED_BYTES="${ACTIVITY_CURRENT_MED_BYTES:-10000000}"
|
||||
declare -g _ACTIVITY_CURRENT_HIGH_BYTES="${ACTIVITY_CURRENT_HIGH_BYTES:-100000000}"
|
||||
|
||||
|
||||
function config::_init_defaults() {
|
||||
_WG_INTERFACE="wg0"
|
||||
_WG_DNS="10.0.0.103"
|
||||
_WG_DNS_FALLBACK=""
|
||||
_WG_LAN="10.0.0.0/24"
|
||||
_WG_SUBNET="10.1.0.0/16"
|
||||
_WG_PORT="51820"
|
||||
_WG_ENDPOINT=""
|
||||
_WG_HANDSHAKE_CHECK_TIME_SEC="300"
|
||||
_FMT_DATE_FORMAT="eu"
|
||||
_WG_INTERFACE="${WG_INTERFACE:-wg0}"
|
||||
_WG_DNS="${WG_DNS:-10.0.0.103}"
|
||||
_WG_DNS_FALLBACK="${WG_DNS_FALLBACK:-}"
|
||||
_WG_LAN="${WG_LAN:-10.0.0.0/24}"
|
||||
_WG_SUBNET="${WG_SUBNET:-10.1.0.0/16}"
|
||||
_WG_PORT="${WG_PORT:-51820}"
|
||||
_WG_ENDPOINT="${WG_ENDPOINT:-}"
|
||||
_WG_HANDSHAKE_CHECK_TIME_SEC="${WG_HANDSHAKE_CHECK_TIME_SEC:-180}"
|
||||
|
||||
# Derived
|
||||
_WG_CONFIG="$(ctx::wg)/${_WG_INTERFACE}.conf"
|
||||
|
|
@ -42,89 +44,13 @@ function config::_init_defaults() {
|
|||
}
|
||||
|
||||
# ============================================
|
||||
# Load from wgctl.json
|
||||
# Falls back to wgctl.conf for migration period
|
||||
# ============================================
|
||||
|
||||
function config::load() {
|
||||
local json_conf
|
||||
json_conf="$(ctx::config_file)"
|
||||
|
||||
if [[ -f "$json_conf" ]]; then
|
||||
config::_load_json "$json_conf"
|
||||
else
|
||||
# Fallback: legacy wgctl.conf
|
||||
local legacy_conf
|
||||
legacy_conf="$(ctx::wgctl)/wgctl.conf"
|
||||
[[ -f "$legacy_conf" ]] && config::_load_legacy "$legacy_conf"
|
||||
fi
|
||||
|
||||
# Recompute derived values after overrides
|
||||
_WG_CONFIG="$(ctx::wg)/${_WG_INTERFACE}.conf"
|
||||
_WG_TUNNEL_SPLIT="${_WG_SUBNET}, ${_WG_LAN}"
|
||||
}
|
||||
|
||||
function config::_load_json() {
|
||||
local file="$1"
|
||||
[[ ! -f "$file" ]] && return 0
|
||||
|
||||
while IFS='=' read -r key value; do
|
||||
[[ -z "$key" ]] && continue
|
||||
case "$key" in
|
||||
WG_INTERFACE) _WG_INTERFACE="$value" ;;
|
||||
WG_ENDPOINT) _WG_ENDPOINT="$value" ;;
|
||||
WG_DNS) _WG_DNS="$value" ;;
|
||||
WG_DNS_FALLBACK) _WG_DNS_FALLBACK="$value" ;;
|
||||
WG_PORT) _WG_PORT="$value" ;;
|
||||
WG_SUBNET) _WG_SUBNET="$value" ;;
|
||||
WG_LAN) _WG_LAN="$value" ;;
|
||||
WG_HANDSHAKE_CHECK_TIME_SEC) _WG_HANDSHAKE_CHECK_TIME_SEC="$value" ;;
|
||||
DATE_FORMAT)
|
||||
_FMT_DATE_FORMAT="$value"
|
||||
fmt::set_date_format "$value"
|
||||
;;
|
||||
ACTIVITY_TOTAL_LOW_BYTES) _ACTIVITY_TOTAL_LOW_BYTES="$value" ;;
|
||||
ACTIVITY_TOTAL_MED_BYTES) _ACTIVITY_TOTAL_MED_BYTES="$value" ;;
|
||||
ACTIVITY_TOTAL_HIGH_BYTES) _ACTIVITY_TOTAL_HIGH_BYTES="$value" ;;
|
||||
ACTIVITY_CURRENT_LOW_BYTES) _ACTIVITY_CURRENT_LOW_BYTES="$value" ;;
|
||||
ACTIVITY_CURRENT_MED_BYTES) _ACTIVITY_CURRENT_MED_BYTES="$value" ;;
|
||||
ACTIVITY_CURRENT_HIGH_BYTES) _ACTIVITY_CURRENT_HIGH_BYTES="$value" ;;
|
||||
esac
|
||||
done < <(json::config_load "$file" 2>/dev/null)
|
||||
}
|
||||
|
||||
function config::_load_legacy() {
|
||||
local conf_file="$1"
|
||||
log::wg_warning "Using legacy wgctl.conf — run 'wgctl config migrate' to upgrade"
|
||||
while IFS='=' read -r key value || [[ -n "$key" ]]; do
|
||||
[[ "$key" =~ ^[[:space:]]*# ]] && continue
|
||||
[[ -z "${key// }" ]] && continue
|
||||
key="${key// /}"
|
||||
value="${value// /}"
|
||||
case "$key" in
|
||||
WG_INTERFACE) _WG_INTERFACE="$value" ;;
|
||||
WG_ENDPOINT) _WG_ENDPOINT="$value" ;;
|
||||
WG_DNS) _WG_DNS="$value" ;;
|
||||
WG_DNS_FALLBACK) _WG_DNS_FALLBACK="$value" ;;
|
||||
WG_PORT) _WG_PORT="$value" ;;
|
||||
WG_SUBNET) _WG_SUBNET="$value" ;;
|
||||
WG_LAN) _WG_LAN="$value" ;;
|
||||
WG_HANDSHAKE_CHECK_TIME_SEC) _WG_HANDSHAKE_CHECK_TIME_SEC="$value" ;;
|
||||
DATE_FORMAT)
|
||||
_FMT_DATE_FORMAT="$value"
|
||||
fmt::set_date_format "$value"
|
||||
;;
|
||||
esac
|
||||
done < "$conf_file"
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Validation (unchanged)
|
||||
# Validation
|
||||
# ============================================
|
||||
|
||||
function config::validate() {
|
||||
local errors=()
|
||||
|
||||
# Server key and config files
|
||||
if [[ ! -f "$_WG_SERVER_PUBLIC_KEY_FILE" ]]; then
|
||||
errors+=("Server public key not found: ${_WG_SERVER_PUBLIC_KEY_FILE}")
|
||||
fi
|
||||
|
|
@ -135,6 +61,7 @@ function config::validate() {
|
|||
errors+=("WireGuard config not found: ${_WG_CONFIG}")
|
||||
fi
|
||||
|
||||
# Required config values
|
||||
local endpoint
|
||||
endpoint=$(config::endpoint)
|
||||
if [[ -z "$endpoint" ]]; then
|
||||
|
|
@ -165,6 +92,7 @@ function config::validate() {
|
|||
errors+=("WG_SUBNET is not set — required for IP allocation")
|
||||
fi
|
||||
|
||||
# Warn-only
|
||||
local lan
|
||||
lan=$(config::lan)
|
||||
if [[ -z "$lan" ]]; then
|
||||
|
|
@ -176,7 +104,7 @@ function config::validate() {
|
|||
for err in "${errors[@]}"; do
|
||||
printf " ✗ %s\n" "$err" >&2
|
||||
done
|
||||
printf "\n Edit %s to fix these issues.\n\n" "$(ctx::config_file)" >&2
|
||||
printf "\n Edit /etc/wireguard/.wgctl/wgctl.conf to fix these issues.\n\n" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
|
@ -184,7 +112,44 @@ function config::validate() {
|
|||
}
|
||||
|
||||
# ============================================
|
||||
# Accessors (unchanged)
|
||||
# Load overrides from .wgctl/wgctl.conf
|
||||
# ============================================
|
||||
|
||||
function config::load() {
|
||||
local conf_file
|
||||
conf_file="$(ctx::data)/wgctl.conf"
|
||||
[[ ! -f "$conf_file" ]] && return 0
|
||||
while IFS='=' read -r key value || [[ -n "$key" ]]; do
|
||||
[[ "$key" =~ ^[[:space:]]*# ]] && continue
|
||||
[[ -z "${key// }" ]] && continue
|
||||
key="${key// /}"
|
||||
value="${value// /}"
|
||||
case "$key" in
|
||||
WG_INTERFACE) _WG_INTERFACE="$value" ;;
|
||||
WG_ENDPOINT) _WG_ENDPOINT="$value" ;;
|
||||
WG_DNS) _WG_DNS="$value" ;;
|
||||
WG_DNS_FALLBACK) _WG_DNS_FALLBACK="$value" ;;
|
||||
WG_PORT) _WG_PORT="$value" ;;
|
||||
WG_SUBNET) _WG_SUBNET="$value" ;;
|
||||
WG_LAN) _WG_LAN="$value" ;;
|
||||
WG_HANDSHAKE_CHECK_TIME_SEC) _WG_HANDSHAKE_CHECK_TIME_SEC="$value" ;;
|
||||
ACTIVITY_LOW_BYTES) _ACTIVITY_LOW_BYTES="$value" ;;
|
||||
ACTIVITY_MED_BYTES) _ACTIVITY_MED_BYTES="$value" ;;
|
||||
ACTIVITY_HIGH_BYTES) _ACTIVITY_HIGH_BYTES="$value" ;;
|
||||
DATE_FORMAT)
|
||||
_FMT_DATE_FORMAT="$value"
|
||||
fmt::set_date_format "$value"
|
||||
;;
|
||||
esac
|
||||
done < "$conf_file"
|
||||
|
||||
# Recompute derived values after overrides
|
||||
_WG_CONFIG="$(ctx::wg)/${_WG_INTERFACE}.conf"
|
||||
_WG_TUNNEL_SPLIT="${_WG_SUBNET}, ${_WG_LAN}"
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Accessors
|
||||
# ============================================
|
||||
|
||||
function config::interface() { echo "$_WG_INTERFACE"; }
|
||||
|
|
@ -201,9 +166,9 @@ function config::handshake_time_sec() { echo "$_WG_HANDSHAKE_CHECK_TIME_SEC"
|
|||
function config::activity_total_low() { echo "$_ACTIVITY_TOTAL_LOW_BYTES"; }
|
||||
function config::activity_total_med() { echo "$_ACTIVITY_TOTAL_MED_BYTES"; }
|
||||
function config::activity_total_high() { echo "$_ACTIVITY_TOTAL_HIGH_BYTES"; }
|
||||
function config::activity_current_low() { echo "$_ACTIVITY_CURRENT_LOW_BYTES"; }
|
||||
function config::activity_current_med() { echo "$_ACTIVITY_CURRENT_MED_BYTES"; }
|
||||
function config::activity_current_high() { echo "$_ACTIVITY_CURRENT_HIGH_BYTES"; }
|
||||
function config::activity_current_low() { echo "$_ACTIVITY_TOTAL_LOW_BYTES"; }
|
||||
function config::activity_current_med() { echo "$_ACTIVITY_TOTAL_MED_BYTES"; }
|
||||
function config::activity_current_high() { echo "$_ACTIVITY_TOTAL_HIGH_BYTES"; }
|
||||
function config::server_public_key() { cat "$_WG_SERVER_PUBLIC_KEY_FILE"; }
|
||||
|
||||
function config::allowed_ips_for() {
|
||||
|
|
@ -226,4 +191,5 @@ function config::dns_string() {
|
|||
else
|
||||
echo "$(config::dns)"
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Reference in a new issue