Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f99525612 | |||
| 8e707d9c4d | |||
| 418c825b01 | |||
| 75f29af27f | |||
| 4467fe629a | |||
| 1912feffe5 | |||
| 9077b3dad6 | |||
| d09ac51c5b | |||
| 9d7975721d | |||
| 667d62b456 | |||
| 90b1ca8de3 | |||
| 17d824d718 | |||
| 06a8636aee | |||
| 4bf08c1fc3 | |||
| 7e721c54d0 | |||
| e6aa5a1dd2 | |||
| bbe18e1413 |
@@ -0,0 +1,140 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build-and-release:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: code.foss.global/host.today/ht-docker-node:latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Deno
|
||||
uses: denoland/setup-deno@v1
|
||||
with:
|
||||
deno-version: v2.x
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- name: Enable corepack
|
||||
run: corepack enable
|
||||
|
||||
- name: Configure pnpm registry
|
||||
run: pnpm config set registry https://verdaccio.lossless.digital/
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Get version from tag
|
||||
id: version
|
||||
run: |
|
||||
VERSION=${GITHUB_REF#refs/tags/}
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "version_number=${VERSION#v}" >> $GITHUB_OUTPUT
|
||||
echo "Building version: $VERSION"
|
||||
|
||||
- name: Verify package.json version matches tag
|
||||
run: |
|
||||
PACKAGE_VERSION=$(node -p "JSON.parse(require('fs').readFileSync('package.json', 'utf8')).version")
|
||||
TAG_VERSION="${{ steps.version.outputs.version_number }}"
|
||||
echo "package.json version: $PACKAGE_VERSION"
|
||||
echo "Tag version: $TAG_VERSION"
|
||||
if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then
|
||||
echo "ERROR: Version mismatch!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Test package
|
||||
run: pnpm test
|
||||
|
||||
- name: Build binary artifacts
|
||||
run: pnpm run build:binary
|
||||
|
||||
- name: Generate SHA256 checksums
|
||||
run: |
|
||||
cd dist/binaries
|
||||
sha256sum * > SHA256SUMS.txt
|
||||
cat SHA256SUMS.txt
|
||||
cd ../..
|
||||
|
||||
- name: Pack npm artifact
|
||||
run: |
|
||||
mkdir -p dist/package
|
||||
pnpm pack --pack-destination dist/package
|
||||
ls -lh dist/package
|
||||
|
||||
- name: Extract changelog for this version
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
if [ -f changelog.md ]; then
|
||||
awk "/## $VERSION/,/## /" changelog.md | sed '$d' > /tmp/release_notes.md || true
|
||||
fi
|
||||
if [ ! -s /tmp/release_notes.md ]; then
|
||||
cat > /tmp/release_notes.md << EOF
|
||||
## DcRouter $VERSION
|
||||
|
||||
NodeNext package build plus self-extracting Linux binaries.
|
||||
|
||||
### Artifacts
|
||||
|
||||
- npm package tarball
|
||||
- dcrouter-linux-x64
|
||||
- dcrouter-linux-arm64
|
||||
- SHA256SUMS.txt
|
||||
EOF
|
||||
fi
|
||||
|
||||
- name: Delete existing release if it exists
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
EXISTING_RELEASE_ID=$(curl -s \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
"https://code.foss.global/api/v1/repos/serve.zone/dcrouter/releases/tags/$VERSION" \
|
||||
| jq -r '.id // empty')
|
||||
if [ -n "$EXISTING_RELEASE_ID" ]; then
|
||||
curl -X DELETE -s \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
"https://code.foss.global/api/v1/repos/serve.zone/dcrouter/releases/$EXISTING_RELEASE_ID"
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
- name: Create Gitea Release
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
RELEASE_ID=$(curl -X POST -s \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"https://code.foss.global/api/v1/repos/serve.zone/dcrouter/releases" \
|
||||
-d "{
|
||||
\"tag_name\": \"$VERSION\",
|
||||
\"name\": \"DcRouter $VERSION\",
|
||||
\"body\": $(jq -Rs . /tmp/release_notes.md),
|
||||
\"draft\": false,
|
||||
\"prerelease\": false
|
||||
}" | jq -r '.id')
|
||||
for artifact in dist/package/* dist/binaries/*; do
|
||||
[ -f "$artifact" ] || continue
|
||||
filename=$(basename "$artifact")
|
||||
curl -X POST -s \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary "@$artifact" \
|
||||
"https://code.foss.global/api/v1/repos/serve.zone/dcrouter/releases/$RELEASE_ID/assets?name=$filename"
|
||||
done
|
||||
|
||||
- name: Release Summary
|
||||
run: |
|
||||
echo "Release ${{ steps.version.outputs.version }} complete"
|
||||
ls -lh dist/package
|
||||
ls -lh dist/binaries
|
||||
+23
-1
@@ -29,6 +29,28 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"@git.zone/tsdeno": {
|
||||
"compileTargets": [
|
||||
{
|
||||
"name": "dcrouter-linux-x64",
|
||||
"entryPoint": "binary/dcrouter.ts",
|
||||
"outDir": "dist/binaries",
|
||||
"target": "x86_64-unknown-linux-gnu",
|
||||
"permissions": ["--allow-all"],
|
||||
"noCheck": true,
|
||||
"selfExtracting": true
|
||||
},
|
||||
{
|
||||
"name": "dcrouter-linux-arm64",
|
||||
"entryPoint": "binary/dcrouter.ts",
|
||||
"outDir": "dist/binaries",
|
||||
"target": "aarch64-unknown-linux-gnu",
|
||||
"permissions": ["--allow-all"],
|
||||
"noCheck": true,
|
||||
"selfExtracting": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"@git.zone/cli": {
|
||||
"schemaVersion": 2,
|
||||
"projectType": "service",
|
||||
@@ -96,4 +118,4 @@
|
||||
]
|
||||
},
|
||||
"@ship.zone/szci": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
process.env.CLI_CALL = 'true';
|
||||
|
||||
const cliTool = await import('../dist_ts/index.js');
|
||||
await cliTool.runCli();
|
||||
@@ -3,6 +3,75 @@
|
||||
## Pending
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 2026-05-30 - 13.38.2
|
||||
|
||||
### Fixes
|
||||
|
||||
- bump @serve.zone/remoteingress to ^4.21.1 (deps)
|
||||
- Updated @serve.zone/remoteingress in package.json and deno.json from ^4.21.0 to ^4.21.1.
|
||||
|
||||
## 2026-05-30 - 13.38.1
|
||||
|
||||
### Fixes
|
||||
|
||||
- bump @serve.zone/remoteingress to ^4.21.0 (deps)
|
||||
- Updates @serve.zone/remoteingress from ^4.18.0 to ^4.21.0.
|
||||
- update @serve.zone/remoteingress to ^4.21.0 (deps)
|
||||
- Updates the Deno import mapping for @serve.zone/remoteingress from ^4.18.0 to ^4.21.0.
|
||||
|
||||
## 2026-05-29 - 13.38.0
|
||||
|
||||
### Features
|
||||
|
||||
- support explicit DNS bind interface configuration (dns)
|
||||
- Add a dnsBindInterface option to override the embedded DNS UDP bind address.
|
||||
- Read DCROUTER_DNS_BIND_INTERFACE from OCI container configuration and document it in CLI help.
|
||||
- Add test coverage for explicit DNS bind interface handling in OCI config.
|
||||
|
||||
## 2026-05-29 - 13.37.2
|
||||
|
||||
### Fixes
|
||||
|
||||
- exclude assets from compiled and published artifacts (packaging)
|
||||
- Removed assets from the Deno compile include list.
|
||||
- Removed assets from the npm package files list.
|
||||
|
||||
## 2026-05-29 - 13.37.1
|
||||
|
||||
### Fixes
|
||||
|
||||
- configure pnpm registry for release workflow (release)
|
||||
- Sets the pnpm registry before dependency installation so release builds resolve packages from the configured registry.
|
||||
|
||||
## 2026-05-29 - 13.37.0
|
||||
|
||||
### Features
|
||||
|
||||
- add CLI binary distribution (distribution)
|
||||
- Add dcrouter bin entry, Deno compile targets, binary entrypoint, and tag-driven release workflow for Linux artifacts.
|
||||
- Add --version and --help handling to the CLI for safe package and binary smoke tests.
|
||||
- Keep the Deno binary import map aligned with the current SmartDNS and SmartProxy runtime dependencies.
|
||||
- add one-line installer and Docker distribution docs (distribution)
|
||||
- Add an install.sh flow that installs Linux x64 and arm64 release binaries by default with a NodeNext source-build fallback.
|
||||
- Document installer modes, binary artifact names, and the published multi-arch Docker image.
|
||||
|
||||
## 2026-05-29 - 13.36.3
|
||||
|
||||
### Fixes
|
||||
|
||||
- update SmartProxy to keep idle WebSocket tunnels on dedicated lifecycle timeouts
|
||||
- Bump @push.rocks/smartproxy to ^27.11.1.
|
||||
- Prevent public gateway WebSocket routes from inheriting the HTTP socket timeout.
|
||||
- bump smartproxy to keep idle WebSocket tunnels on dedicated lifecycle timeouts (deps)
|
||||
- Bump @push.rocks/smartproxy to ^27.11.1.
|
||||
- Prevent public gateway WebSocket routes from inheriting the HTTP socket timeout.
|
||||
|
||||
## 2026-05-29 - 13.36.2
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "@serve.zone/dcrouter",
|
||||
"version": "13.38.2",
|
||||
"exports": "./binary/dcrouter.ts",
|
||||
"compile": {
|
||||
"include": [
|
||||
"dist_serve"
|
||||
]
|
||||
},
|
||||
"imports": {
|
||||
"@api.global/typedrequest": "npm:@api.global/typedrequest@^3.3.1",
|
||||
"@api.global/typedrequest-interfaces": "npm:@api.global/typedrequest-interfaces@^3.0.19",
|
||||
"@api.global/typedserver": "npm:@api.global/typedserver@^8.4.6",
|
||||
"@api.global/typedsocket": "npm:@api.global/typedsocket@^4.1.3",
|
||||
"@apiclient.xyz/cloudflare": "npm:@apiclient.xyz/cloudflare@^7.1.0",
|
||||
"@idp.global/sdk/server": "npm:@idp.global/sdk@^1.3.1/server",
|
||||
"@push.rocks/lik": "npm:@push.rocks/lik@^6.4.1",
|
||||
"@push.rocks/projectinfo": "npm:@push.rocks/projectinfo@^5.1.0",
|
||||
"@push.rocks/qenv": "npm:@push.rocks/qenv@^6.1.4",
|
||||
"@push.rocks/smartacme": "npm:@push.rocks/smartacme@^9.5.0",
|
||||
"@push.rocks/smartdata": "npm:@push.rocks/smartdata@^7.1.7",
|
||||
"@push.rocks/smartdb": "npm:@push.rocks/smartdb@^2.10.1",
|
||||
"@push.rocks/smartdns": "npm:@push.rocks/smartdns@^7.9.3",
|
||||
"@push.rocks/smartfs": "npm:@push.rocks/smartfs@^1.5.1",
|
||||
"@push.rocks/smartguard": "npm:@push.rocks/smartguard@^3.1.0",
|
||||
"@push.rocks/smartjwt": "npm:@push.rocks/smartjwt@^2.2.2",
|
||||
"@push.rocks/smartlog": "npm:@push.rocks/smartlog@^3.2.2",
|
||||
"@push.rocks/smartmetrics": "npm:@push.rocks/smartmetrics@^3.0.3",
|
||||
"@push.rocks/smartmigration": "npm:@push.rocks/smartmigration@1.4.1",
|
||||
"@push.rocks/smartmta": "npm:@push.rocks/smartmta@^5.3.3",
|
||||
"@push.rocks/smartnetwork": "npm:@push.rocks/smartnetwork@^4.7.2",
|
||||
"@push.rocks/smartpath": "npm:@push.rocks/smartpath@^6.0.0",
|
||||
"@push.rocks/smartpromise": "npm:@push.rocks/smartpromise@^4.2.4",
|
||||
"@push.rocks/smartproxy": "npm:@push.rocks/smartproxy@^27.11.1",
|
||||
"@push.rocks/smartradius": "npm:@push.rocks/smartradius@^1.1.2",
|
||||
"@push.rocks/smartrequest": "npm:@push.rocks/smartrequest@^5.0.3",
|
||||
"@push.rocks/smartrx": "npm:@push.rocks/smartrx@^3.0.10",
|
||||
"@push.rocks/smartstate": "npm:@push.rocks/smartstate@^2.3.1",
|
||||
"@push.rocks/smartunique": "npm:@push.rocks/smartunique@^3.0.9",
|
||||
"@push.rocks/smartvpn": "npm:@push.rocks/smartvpn@1.20.0",
|
||||
"@push.rocks/taskbuffer": "npm:@push.rocks/taskbuffer@^8.0.2",
|
||||
"@serve.zone/interfaces": "npm:@serve.zone/interfaces@^5.8.0",
|
||||
"@serve.zone/remoteingress": "npm:@serve.zone/remoteingress@^4.21.1",
|
||||
"@tsclass/tsclass": "npm:@tsclass/tsclass@^9.5.1",
|
||||
"lru-cache": "npm:lru-cache@^11.4.0",
|
||||
"qrcode": "npm:qrcode@^1.5.4",
|
||||
"uuid": "npm:uuid@^14.0.0"
|
||||
}
|
||||
}
|
||||
Executable
+359
@@ -0,0 +1,359 @@
|
||||
#!/bin/bash
|
||||
|
||||
# DcRouter Installer Script
|
||||
# Installs the self-extracting Linux binary by default, or builds the NodeNext
|
||||
# source package when --source is specified.
|
||||
#
|
||||
# Usage:
|
||||
# Binary install:
|
||||
# curl -sSL https://code.foss.global/serve.zone/dcrouter/raw/branch/main/install.sh | sudo bash
|
||||
#
|
||||
# Source install:
|
||||
# curl -sSL https://code.foss.global/serve.zone/dcrouter/raw/branch/main/install.sh | sudo bash -s -- --source
|
||||
#
|
||||
# Options:
|
||||
# -h, --help Show this help message
|
||||
# --version VERSION Install a specific tag/version (e.g. vX.Y.Z)
|
||||
# --install-dir DIR Installation directory (default: /opt/dcrouter)
|
||||
# --binary Install release binary (default)
|
||||
# --source Clone the tag and build the NodeNext package locally
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SHOW_HELP=0
|
||||
SPECIFIED_VERSION=""
|
||||
INSTALL_DIR="/opt/dcrouter"
|
||||
INSTALL_MODE="binary"
|
||||
GITEA_BASE_URL="https://code.foss.global"
|
||||
GITEA_REPO="serve.zone/dcrouter"
|
||||
SERVICE_NAME="dcrouter"
|
||||
BIN_DIR="/usr/local/bin"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
SHOW_HELP=1
|
||||
shift
|
||||
;;
|
||||
--version)
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Error: --version requires a value"
|
||||
exit 1
|
||||
fi
|
||||
SPECIFIED_VERSION="$2"
|
||||
shift 2
|
||||
;;
|
||||
--install-dir)
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Error: --install-dir requires a value"
|
||||
exit 1
|
||||
fi
|
||||
INSTALL_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
--binary)
|
||||
INSTALL_MODE="binary"
|
||||
shift
|
||||
;;
|
||||
--source)
|
||||
INSTALL_MODE="source"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
echo "Use -h or --help for usage information"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $SHOW_HELP -eq 1 ]]; then
|
||||
echo "DcRouter Installer Script"
|
||||
echo "Installs DcRouter as a self-extracting binary or NodeNext source build."
|
||||
echo ""
|
||||
echo "Usage: $0 [options]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -h, --help Show this help message"
|
||||
echo " --version VERSION Install a specific tag/version (e.g. vX.Y.Z)"
|
||||
echo " --install-dir DIR Installation directory (default: /opt/dcrouter)"
|
||||
echo " --binary Install release binary (default)"
|
||||
echo " --source Clone the tag and build the NodeNext package locally"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " curl -sSL https://code.foss.global/serve.zone/dcrouter/raw/branch/main/install.sh | sudo bash"
|
||||
echo " curl -sSL https://code.foss.global/serve.zone/dcrouter/raw/branch/main/install.sh | sudo bash -s -- --source"
|
||||
echo " curl -sSL https://code.foss.global/serve.zone/dcrouter/raw/branch/main/install.sh | sudo bash -s -- --version vX.Y.Z"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$EUID" -ne 0 ]]; then
|
||||
echo "Please run as root (sudo bash install.sh or pipe to sudo bash)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$INSTALL_DIR" in
|
||||
""|"/")
|
||||
echo "Error: unsafe install directory: $INSTALL_DIR"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
require_command() {
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
echo "Error: required command not found: $1"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_pnpm() {
|
||||
if command -v pnpm >/dev/null 2>&1; then
|
||||
return
|
||||
fi
|
||||
if command -v corepack >/dev/null 2>&1; then
|
||||
corepack enable
|
||||
fi
|
||||
if ! command -v pnpm >/dev/null 2>&1; then
|
||||
echo "Error: pnpm is required for --source installs. Install Node.js with corepack/pnpm first."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
make_executable_if_present() {
|
||||
if [[ -f "$1" ]]; then
|
||||
chmod 0755 "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
get_latest_version() {
|
||||
echo "Fetching latest release version from Gitea..." >&2
|
||||
|
||||
local api_url="${GITEA_BASE_URL}/api/v1/repos/${GITEA_REPO}/releases/latest"
|
||||
local response
|
||||
if ! response=$(curl -fsSL "$api_url" 2>/dev/null); then
|
||||
echo "Error: Failed to fetch latest release information from Gitea API" >&2
|
||||
echo "URL: $api_url" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local version
|
||||
version=$(printf '%s' "$response" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
|
||||
if [[ -z "$version" ]]; then
|
||||
echo "Error: Could not determine latest version from API response" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$version"
|
||||
}
|
||||
|
||||
detect_binary_name() {
|
||||
local os
|
||||
local arch
|
||||
os=$(uname -s)
|
||||
arch=$(uname -m)
|
||||
|
||||
if [[ "$os" != "Linux" ]]; then
|
||||
echo "Error: binary installer currently supports Linux only. Use --source for this platform." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$arch" in
|
||||
x86_64|amd64)
|
||||
echo "dcrouter-linux-x64"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
echo "dcrouter-linux-arm64"
|
||||
;;
|
||||
*)
|
||||
echo "Error: unsupported architecture for binary install: $arch. Use --source." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
echo "================================================"
|
||||
echo " DcRouter Installation Script"
|
||||
echo "================================================"
|
||||
echo ""
|
||||
|
||||
require_command curl
|
||||
require_command sed
|
||||
|
||||
if [[ -n "$SPECIFIED_VERSION" ]]; then
|
||||
VERSION="$SPECIFIED_VERSION"
|
||||
echo "Installing specified version: $VERSION"
|
||||
else
|
||||
VERSION=$(get_latest_version)
|
||||
echo "Installing latest version: $VERSION"
|
||||
fi
|
||||
echo "Install mode: $INSTALL_MODE"
|
||||
echo ""
|
||||
|
||||
SOURCE_REF="$VERSION"
|
||||
REPO_URL="${GITEA_BASE_URL}/${GITEA_REPO}.git"
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
SOURCE_DIR="$TEMP_DIR/source"
|
||||
BACKUP_DIR=""
|
||||
SERVICE_WAS_RUNNING=0
|
||||
SERVICE_STOPPED=0
|
||||
SYSTEMD_AVAILABLE=0
|
||||
|
||||
cleanup_temp() {
|
||||
rm -rf "$TEMP_DIR"
|
||||
}
|
||||
trap cleanup_temp EXIT
|
||||
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
SYSTEMD_AVAILABLE=1
|
||||
if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
|
||||
SERVICE_WAS_RUNNING=1
|
||||
fi
|
||||
fi
|
||||
|
||||
restore_previous_installation() {
|
||||
if [[ -n "$BACKUP_DIR" && -d "$BACKUP_DIR" ]]; then
|
||||
echo "Restoring previous installation from $BACKUP_DIR..."
|
||||
rm -rf "$INSTALL_DIR" || true
|
||||
mv "$BACKUP_DIR" "$INSTALL_DIR" || true
|
||||
if [[ -f "$INSTALL_DIR/dcrouter" ]]; then
|
||||
mkdir -p "$BIN_DIR" || true
|
||||
ln -sf "$INSTALL_DIR/dcrouter" "$BIN_DIR/dcrouter" || true
|
||||
elif [[ -f "$INSTALL_DIR/cli.js" ]]; then
|
||||
mkdir -p "$BIN_DIR" || true
|
||||
ln -sf "$INSTALL_DIR/cli.js" "$BIN_DIR/dcrouter" || true
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
restart_previous_service_on_error() {
|
||||
if [[ $SERVICE_STOPPED -eq 1 && $SYSTEMD_AVAILABLE -eq 1 ]]; then
|
||||
echo "Installation failed after stopping DcRouter; restarting previous service..."
|
||||
systemctl start "$SERVICE_NAME" || true
|
||||
fi
|
||||
}
|
||||
|
||||
handle_install_error() {
|
||||
trap - ERR
|
||||
restore_previous_installation
|
||||
restart_previous_service_on_error
|
||||
}
|
||||
trap handle_install_error ERR
|
||||
|
||||
stop_service_if_running() {
|
||||
if [[ $SERVICE_WAS_RUNNING -eq 1 && $SYSTEMD_AVAILABLE -eq 1 ]] && systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
|
||||
echo "Stopping DcRouter service..."
|
||||
systemctl stop "$SERVICE_NAME"
|
||||
SERVICE_STOPPED=1
|
||||
fi
|
||||
}
|
||||
|
||||
move_previous_installation() {
|
||||
mkdir -p "$(dirname "$INSTALL_DIR")"
|
||||
if [[ -d "$INSTALL_DIR" ]]; then
|
||||
BACKUP_DIR="${INSTALL_DIR}.previous.$$"
|
||||
echo "Moving previous installation to $BACKUP_DIR"
|
||||
mv "$INSTALL_DIR" "$BACKUP_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
install_source_build() {
|
||||
require_command git
|
||||
require_command node
|
||||
ensure_pnpm
|
||||
|
||||
echo "Cloning DcRouter source from $REPO_URL ($SOURCE_REF)..."
|
||||
git clone --depth 1 --branch "$SOURCE_REF" "$REPO_URL" "$SOURCE_DIR"
|
||||
|
||||
echo "Installing dependencies..."
|
||||
pnpm --dir "$SOURCE_DIR" install --frozen-lockfile
|
||||
|
||||
echo "Building DcRouter..."
|
||||
pnpm --dir "$SOURCE_DIR" run build
|
||||
|
||||
echo "Validating built CLI..."
|
||||
node "$SOURCE_DIR/cli.js" --version >/dev/null
|
||||
|
||||
stop_service_if_running
|
||||
move_previous_installation
|
||||
|
||||
echo "Installing source build to $INSTALL_DIR"
|
||||
mv "$SOURCE_DIR" "$INSTALL_DIR"
|
||||
make_executable_if_present "$INSTALL_DIR/cli.js"
|
||||
make_executable_if_present "$INSTALL_DIR/cli.ts.js"
|
||||
make_executable_if_present "$INSTALL_DIR/cli.child.js"
|
||||
|
||||
mkdir -p "$BIN_DIR"
|
||||
ln -sf "$INSTALL_DIR/cli.js" "$BIN_DIR/dcrouter"
|
||||
}
|
||||
|
||||
install_release_binary() {
|
||||
local binary_name
|
||||
local download_url
|
||||
local temp_file
|
||||
|
||||
binary_name=$(detect_binary_name)
|
||||
download_url="${GITEA_BASE_URL}/${GITEA_REPO}/releases/download/${VERSION}/${binary_name}"
|
||||
temp_file="$TEMP_DIR/$binary_name"
|
||||
|
||||
echo "Downloading DcRouter binary: $download_url"
|
||||
curl -fSL "$download_url" -o "$temp_file"
|
||||
chmod 0755 "$temp_file"
|
||||
|
||||
echo "Validating downloaded binary..."
|
||||
"$temp_file" --version >/dev/null
|
||||
|
||||
stop_service_if_running
|
||||
move_previous_installation
|
||||
|
||||
echo "Installing binary to $INSTALL_DIR"
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
install -m 0755 "$temp_file" "$INSTALL_DIR/dcrouter"
|
||||
|
||||
mkdir -p "$BIN_DIR"
|
||||
ln -sf "$INSTALL_DIR/dcrouter" "$BIN_DIR/dcrouter"
|
||||
}
|
||||
|
||||
if [[ "$INSTALL_MODE" == "source" ]]; then
|
||||
install_source_build
|
||||
else
|
||||
install_release_binary
|
||||
fi
|
||||
|
||||
echo "Symlink created: $BIN_DIR/dcrouter"
|
||||
|
||||
if ! "$BIN_DIR/dcrouter" --version >/dev/null; then
|
||||
echo "Error: Installed DcRouter CLI failed validation"
|
||||
restore_previous_installation
|
||||
restart_previous_service_on_error
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$BACKUP_DIR" && -d "$BACKUP_DIR" ]]; then
|
||||
rm -rf "$BACKUP_DIR"
|
||||
fi
|
||||
|
||||
if [[ $SERVICE_WAS_RUNNING -eq 1 && $SYSTEMD_AVAILABLE -eq 1 ]]; then
|
||||
echo "Restarting DcRouter service..."
|
||||
systemctl restart "$SERVICE_NAME"
|
||||
SERVICE_STOPPED=0
|
||||
echo "Service restarted successfully."
|
||||
echo ""
|
||||
fi
|
||||
|
||||
trap - ERR
|
||||
|
||||
echo "================================================"
|
||||
echo " DcRouter Installation Complete!"
|
||||
echo "================================================"
|
||||
echo ""
|
||||
echo "Installation details:"
|
||||
echo " Install directory: $INSTALL_DIR"
|
||||
echo " Symlink location: $BIN_DIR/dcrouter"
|
||||
echo " Version: $VERSION"
|
||||
echo " Mode: $INSTALL_MODE"
|
||||
echo ""
|
||||
echo "Get started:"
|
||||
echo ""
|
||||
echo " dcrouter --version"
|
||||
echo " dcrouter --help"
|
||||
echo ""
|
||||
+16
-14
@@ -1,9 +1,12 @@
|
||||
{
|
||||
"name": "@serve.zone/dcrouter",
|
||||
"private": false,
|
||||
"version": "13.36.2",
|
||||
"version": "13.38.2",
|
||||
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"dcrouter": "./cli.js"
|
||||
},
|
||||
"exports": {
|
||||
".": "./dist_ts/index.js",
|
||||
"./interfaces": "./dist_ts_interfaces/index.js",
|
||||
@@ -15,7 +18,8 @@
|
||||
"test": "(tstest test/ --verbose --logfile --timeout 60)",
|
||||
"start": "(node ./cli.js)",
|
||||
"startTs": "(node cli.ts.js)",
|
||||
"build": "(tsbuild tsfolders --allowimplicitany && npm run bundle)",
|
||||
"build": "(tsbuild tsfolders --allowimplicitany && pnpm run bundle)",
|
||||
"build:binary": "(pnpm run build && tsdeno compile)",
|
||||
"build:docker": "tsdocker build --verbose",
|
||||
"release:docker": "tsdocker push --verbose",
|
||||
"bundle": "(tsbundle)",
|
||||
@@ -25,6 +29,7 @@
|
||||
"@git.zone/tsbuild": "^4.4.2",
|
||||
"@git.zone/tsbundle": "^2.10.4",
|
||||
"@git.zone/tsdocker": "^2.4.0",
|
||||
"@git.zone/tsdeno": "^1.4.0",
|
||||
"@git.zone/tsrun": "^2.0.4",
|
||||
"@git.zone/tstest": "^3.6.6",
|
||||
"@git.zone/tswatch": "^3.3.5",
|
||||
@@ -36,7 +41,7 @@
|
||||
"@api.global/typedserver": "^8.4.6",
|
||||
"@api.global/typedsocket": "^4.1.3",
|
||||
"@apiclient.xyz/cloudflare": "^7.1.0",
|
||||
"@design.estate/dees-catalog": "^3.81.0",
|
||||
"@design.estate/dees-catalog": "^3.83.0",
|
||||
"@design.estate/dees-element": "^2.2.4",
|
||||
"@idp.global/sdk": "^1.3.1",
|
||||
"@push.rocks/lik": "^6.4.1",
|
||||
@@ -56,7 +61,7 @@
|
||||
"@push.rocks/smartnetwork": "^4.7.2",
|
||||
"@push.rocks/smartpath": "^6.0.0",
|
||||
"@push.rocks/smartpromise": "^4.2.4",
|
||||
"@push.rocks/smartproxy": "^27.11.0",
|
||||
"@push.rocks/smartproxy": "^27.11.1",
|
||||
"@push.rocks/smartradius": "^1.1.2",
|
||||
"@push.rocks/smartrequest": "^5.0.3",
|
||||
"@push.rocks/smartrx": "^3.0.10",
|
||||
@@ -66,7 +71,7 @@
|
||||
"@push.rocks/taskbuffer": "^8.0.2",
|
||||
"@serve.zone/catalog": "^2.12.4",
|
||||
"@serve.zone/interfaces": "^5.8.0",
|
||||
"@serve.zone/remoteingress": "^4.18.0",
|
||||
"@serve.zone/remoteingress": "^4.21.1",
|
||||
"@tsclass/tsclass": "^9.5.1",
|
||||
"@types/qrcode": "^1.5.6",
|
||||
"lru-cache": "^11.4.0",
|
||||
@@ -99,25 +104,22 @@
|
||||
"VLAN assignment",
|
||||
"MAC authentication"
|
||||
],
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild",
|
||||
"mongodb-memory-server",
|
||||
"puppeteer"
|
||||
]
|
||||
},
|
||||
"packageManager": "pnpm@10.11.0",
|
||||
"files": [
|
||||
"ts/**/*",
|
||||
"binary/**/*",
|
||||
"ts_web/**/*",
|
||||
"ts_apiclient/**/*",
|
||||
"dist/**/*",
|
||||
"dist_*/**/*",
|
||||
"dist_ts/**/*",
|
||||
"dist_ts_web/**/*",
|
||||
"dist_ts_apiclient/**/*",
|
||||
"assets/**/*",
|
||||
"cli.js",
|
||||
"cli.ts.js",
|
||||
"cli.child.js",
|
||||
"cli.child.ts",
|
||||
"deno.json",
|
||||
"tsconfig.json",
|
||||
".smartconfig.json",
|
||||
"readme.md"
|
||||
]
|
||||
|
||||
Generated
+38
-17
@@ -24,8 +24,8 @@ importers:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
'@design.estate/dees-catalog':
|
||||
specifier: ^3.81.0
|
||||
version: 3.81.0(@tiptap/pm@2.27.2)
|
||||
specifier: ^3.83.0
|
||||
version: 3.83.0(@tiptap/pm@2.27.2)
|
||||
'@design.estate/dees-element':
|
||||
specifier: ^2.2.4
|
||||
version: 2.2.4
|
||||
@@ -84,8 +84,8 @@ importers:
|
||||
specifier: ^4.2.4
|
||||
version: 4.2.4
|
||||
'@push.rocks/smartproxy':
|
||||
specifier: ^27.11.0
|
||||
version: 27.11.0
|
||||
specifier: ^27.11.1
|
||||
version: 27.11.1
|
||||
'@push.rocks/smartradius':
|
||||
specifier: ^1.1.2
|
||||
version: 1.1.2
|
||||
@@ -114,8 +114,8 @@ importers:
|
||||
specifier: ^5.8.0
|
||||
version: 5.8.0
|
||||
'@serve.zone/remoteingress':
|
||||
specifier: ^4.18.0
|
||||
version: 4.18.0
|
||||
specifier: ^4.21.1
|
||||
version: 4.21.1
|
||||
'@tsclass/tsclass':
|
||||
specifier: ^9.5.1
|
||||
version: 9.5.1
|
||||
@@ -138,6 +138,9 @@ importers:
|
||||
'@git.zone/tsbundle':
|
||||
specifier: ^2.10.4
|
||||
version: 2.10.4
|
||||
'@git.zone/tsdeno':
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
'@git.zone/tsdocker':
|
||||
specifier: ^2.4.0
|
||||
version: 2.4.0
|
||||
@@ -362,8 +365,8 @@ packages:
|
||||
'@configvault.io/interfaces@1.0.17':
|
||||
resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==}
|
||||
|
||||
'@design.estate/dees-catalog@3.81.0':
|
||||
resolution: {integrity: sha512-N7ocwSKVdjDQWmVV2XWiyg3dotGEuxP4/jhyB6duH8zJ3k63wmGm8+FeoP+LzRc8/U0Bl8w7UZrewlkIEMstUA==}
|
||||
'@design.estate/dees-catalog@3.83.0':
|
||||
resolution: {integrity: sha512-Ia4fwZ5ndziJkSE000nCro83rD8Rujki7ASHBQhL6ZDflZRJRlfuc13azVnQC2sazKlo/bWSgiiLcpc3V2IYrw==}
|
||||
|
||||
'@design.estate/dees-comms@1.0.30':
|
||||
resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==}
|
||||
@@ -726,6 +729,10 @@ packages:
|
||||
resolution: {integrity: sha512-/xWOGrnuMaJ/Xo/EasaF9N3N9w1J9LDywZaRTa0UTtzbEtfJP7F2NJ9l4tWCwS+vTKpnqApX7ZueRh1h5MrwPQ==}
|
||||
hasBin: true
|
||||
|
||||
'@git.zone/tsdeno@1.4.0':
|
||||
resolution: {integrity: sha512-84kFa/uKPTlzeLxtHoFxefk6O9khsWWQ2PCWNbCNYIUqWHUvN9COpGq0GXWtsoxLWPhTTIeHsOX4+O55uT2MPw==}
|
||||
hasBin: true
|
||||
|
||||
'@git.zone/tsdocker@2.4.0':
|
||||
resolution: {integrity: sha512-GFE93RxFm8HDrSm5Ulggy4se7heb4GaNQgaWV6Mds6lhkm6GouO91xZYlmXVH9glzBoFJNG63pFXYHW6nrqf5A==}
|
||||
hasBin: true
|
||||
@@ -1422,8 +1429,8 @@ packages:
|
||||
'@push.rocks/smartpromise@4.2.4':
|
||||
resolution: {integrity: sha512-8FUyYt94hOIY9mqHjitn4h69u0jbEtTF2RKKw2DpiTVFjpDTk9gXbVHZ/V+xEcBrN4mrzdQES0OiDmkNPoddEQ==}
|
||||
|
||||
'@push.rocks/smartproxy@27.11.0':
|
||||
resolution: {integrity: sha512-ruyUMbrk28BTtrhcZpB5fX35FRQyyhJgVd7snPFa3Zttw0N8ahYrwKXpKfuagvOcaIpORMQoyR5WSv0C2ATFVA==}
|
||||
'@push.rocks/smartproxy@27.11.1':
|
||||
resolution: {integrity: sha512-29THhFUTr9NtU1/UBqqOgcbsHcUMHj7Dhh2XfXp6NP/rfDGUFiFFmCNcAdC3OJ0n6BgwTBOtOzo+4rJbrGJRpw==}
|
||||
|
||||
'@push.rocks/smartpuppeteer@2.0.6':
|
||||
resolution: {integrity: sha512-G+8cyDERvbXQcb9Sd8lnYdWYz8b3Mv2LfFf1ULmucDqQhcRHvxrWX/dKsvBZrwKPR4Wg+795Dyd+E1iOOh3tHw==}
|
||||
@@ -1712,8 +1719,9 @@ packages:
|
||||
'@serve.zone/interfaces@5.8.0':
|
||||
resolution: {integrity: sha512-0ekSKUL/b44wmmzuCRANzrjaJRAHtkqiL8cPiMASEs7UJBDqbJCrgtrlJK84pz5dxBz3jTcdznNd5qjB8c6H0A==}
|
||||
|
||||
'@serve.zone/remoteingress@4.18.0':
|
||||
resolution: {integrity: sha512-/cW9wb/e57u9+715RzV5d8HCezWtR88LcpistTNSl7GACi5ai+C2tPy7ZQprnnrNhqjfgzWiAH4bKZafwONntg==}
|
||||
'@serve.zone/remoteingress@4.21.1':
|
||||
resolution: {integrity: sha512-e/1wRYYkN2QKaxoLgzW6zEyKwzpG05liaRymTSVvS2Hah9J9e/0/fROO9VHl6QjhkUjtG9fckzcdnQriYI/h8g==}
|
||||
hasBin: true
|
||||
|
||||
'@smithy/chunked-blob-reader-native@4.2.3':
|
||||
resolution: {integrity: sha512-jA5k5Udn7Y5717L86h4EIv06wIr3xn8GM1qHRi/Nf31annXcXHJjBKvgztnbn2TxH3xWrPBfgwHsOwZf0UmQWw==}
|
||||
@@ -4376,7 +4384,7 @@ snapshots:
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@api.global/typedsocket': 4.1.3(@push.rocks/smartserve@2.0.4)
|
||||
'@cloudflare/workers-types': 4.20260507.1
|
||||
'@design.estate/dees-catalog': 3.81.0(@tiptap/pm@2.27.2)
|
||||
'@design.estate/dees-catalog': 3.83.0(@tiptap/pm@2.27.2)
|
||||
'@design.estate/dees-comms': 1.0.30
|
||||
'@push.rocks/lik': 6.4.1
|
||||
'@push.rocks/smartdelay': 3.1.0
|
||||
@@ -4910,7 +4918,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
|
||||
'@design.estate/dees-catalog@3.81.0(@tiptap/pm@2.27.2)':
|
||||
'@design.estate/dees-catalog@3.83.0(@tiptap/pm@2.27.2)':
|
||||
dependencies:
|
||||
'@design.estate/dees-domtools': 2.5.6
|
||||
'@design.estate/dees-element': 2.2.4
|
||||
@@ -5243,6 +5251,19 @@ snapshots:
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
'@git.zone/tsdeno@1.4.0':
|
||||
dependencies:
|
||||
'@push.rocks/early': 4.0.4
|
||||
'@push.rocks/smartcli': 4.0.21
|
||||
'@push.rocks/smartconfig': 6.1.1
|
||||
'@push.rocks/smartfs': 1.5.1
|
||||
'@push.rocks/smartshell': 3.3.8
|
||||
transitivePeerDependencies:
|
||||
- '@nuxt/kit'
|
||||
- react
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
'@git.zone/tsdocker@2.4.0':
|
||||
dependencies:
|
||||
'@push.rocks/lik': 6.4.1
|
||||
@@ -6675,7 +6696,7 @@ snapshots:
|
||||
|
||||
'@push.rocks/smartpromise@4.2.4': {}
|
||||
|
||||
'@push.rocks/smartproxy@27.11.0':
|
||||
'@push.rocks/smartproxy@27.11.1':
|
||||
dependencies:
|
||||
'@push.rocks/smartcrypto': 2.0.4
|
||||
'@push.rocks/smartlog': 3.2.2
|
||||
@@ -7047,7 +7068,7 @@ snapshots:
|
||||
|
||||
'@serve.zone/catalog@2.12.4(@tiptap/pm@2.27.2)':
|
||||
dependencies:
|
||||
'@design.estate/dees-catalog': 3.81.0(@tiptap/pm@2.27.2)
|
||||
'@design.estate/dees-catalog': 3.83.0(@tiptap/pm@2.27.2)
|
||||
'@design.estate/dees-domtools': 2.5.6
|
||||
'@design.estate/dees-element': 2.2.4
|
||||
'@design.estate/dees-wcctools': 3.9.0
|
||||
@@ -7064,7 +7085,7 @@ snapshots:
|
||||
'@push.rocks/smartlog-interfaces': 3.0.2
|
||||
'@tsclass/tsclass': 9.5.1
|
||||
|
||||
'@serve.zone/remoteingress@4.18.0':
|
||||
'@serve.zone/remoteingress@4.21.1':
|
||||
dependencies:
|
||||
'@push.rocks/qenv': 6.1.4
|
||||
'@push.rocks/smartnftables': 1.2.0
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
allowBuilds:
|
||||
esbuild: true
|
||||
mongodb-memory-server: true
|
||||
puppeteer: true
|
||||
@@ -34,6 +34,20 @@ Highlights:
|
||||
|
||||
## Install
|
||||
|
||||
Install the CLI/runtime on a Linux gateway host with the released self-extracting binary:
|
||||
|
||||
```bash
|
||||
curl -sSL https://code.foss.global/serve.zone/dcrouter/raw/branch/main/install.sh | sudo bash
|
||||
```
|
||||
|
||||
The installer downloads `dcrouter-linux-x64` or `dcrouter-linux-arm64` from the latest Gitea release, installs it under `/opt/dcrouter`, and links `/usr/local/bin/dcrouter`. Use `--version vX.Y.Z` to pin a release, `--install-dir /path` to change the target directory, or `--source` to clone the tag and build the NodeNext package locally.
|
||||
|
||||
```bash
|
||||
curl -sSL https://code.foss.global/serve.zone/dcrouter/raw/branch/main/install.sh | sudo bash -s -- --source
|
||||
```
|
||||
|
||||
Use the package as a TypeScript library:
|
||||
|
||||
```bash
|
||||
pnpm add @serve.zone/dcrouter
|
||||
```
|
||||
@@ -260,6 +274,21 @@ Supported environment overrides include:
|
||||
| `DCROUTER_CACHE_ENABLED` | Enables or disables DB-backed persistence. |
|
||||
| `DCROUTER_MAX_CONNECTIONS`, `DCROUTER_MAX_CONNECTIONS_PER_IP`, `DCROUTER_CONNECTION_RATE_LIMIT` | SmartProxy capacity and rate-limit overrides. |
|
||||
|
||||
## Docker Image
|
||||
|
||||
Release builds publish a multi-arch OCI image at `code.foss.global/serve.zone/dcrouter:latest` for `linux/amd64` and `linux/arm64`. The image sets `DCROUTER_MODE=OCI_CONTAINER` and starts `node ./cli.js`.
|
||||
|
||||
```bash
|
||||
docker run --rm --name dcrouter \
|
||||
--network host \
|
||||
-v dcrouter-data:/data \
|
||||
-e DCROUTER_BASE_DIR=/data \
|
||||
-e DCROUTER_TLS_EMAIL=ops@example.com \
|
||||
code.foss.global/serve.zone/dcrouter:latest
|
||||
```
|
||||
|
||||
Host networking is the simplest container mode for a gateway that owns HTTP/S, SMTP, DNS, RADIUS, remote ingress, and dynamic proxy ports. For narrower deployments, publish only the ports you enable in `IDcRouterOptions` or via the `DCROUTER_*` environment overrides.
|
||||
|
||||
## Published Modules
|
||||
|
||||
This repository intentionally publishes multiple module boundaries from one codebase.
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||
import { getOciContainerConfig } from '../ts_oci_container/index.js';
|
||||
|
||||
tap.test('OCI config should accept explicit DNS bind interface', async () => {
|
||||
const previousValue = process.env.DCROUTER_DNS_BIND_INTERFACE;
|
||||
process.env.DCROUTER_DNS_BIND_INTERFACE = '192.168.190.3';
|
||||
|
||||
try {
|
||||
const config = getOciContainerConfig();
|
||||
expect(config.dnsBindInterface).toEqual('192.168.190.3');
|
||||
} finally {
|
||||
if (previousValue === undefined) {
|
||||
delete process.env.DCROUTER_DNS_BIND_INTERFACE;
|
||||
} else {
|
||||
process.env.DCROUTER_DNS_BIND_INTERFACE = previousValue;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default tap.start();
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/dcrouter',
|
||||
version: '13.36.2',
|
||||
version: '13.38.2',
|
||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||
}
|
||||
|
||||
+18
-10
@@ -93,6 +93,9 @@ export interface IDcRouterOptions {
|
||||
* Email domains with `internal-dns` mode must be included here
|
||||
*/
|
||||
dnsScopes?: string[];
|
||||
|
||||
/** Explicit UDP bind address for the embedded DNS server. Defaults to auto-detection. */
|
||||
dnsBindInterface?: string;
|
||||
|
||||
/**
|
||||
* IPs of proxies that forward traffic to your server (optional)
|
||||
@@ -1875,16 +1878,21 @@ export class DcRouter {
|
||||
logger.log('info', `Setting up DNS server with primary nameserver: ${primaryNameserver}`);
|
||||
|
||||
// Get VM IP address for UDP binding
|
||||
const networkInterfaces = plugins.os.networkInterfaces();
|
||||
let vmIpAddress = '0.0.0.0'; // Default to all interfaces
|
||||
|
||||
// Try to find the VM's internal IP address
|
||||
for (const [_name, interfaces] of Object.entries(networkInterfaces)) {
|
||||
if (interfaces) {
|
||||
for (const iface of interfaces) {
|
||||
if (!iface.internal && iface.family === 'IPv4') {
|
||||
vmIpAddress = iface.address;
|
||||
break;
|
||||
const networkInterfaces = plugins.os.networkInterfaces() as Record<
|
||||
string,
|
||||
Array<{ internal: boolean; family: string; address: string }> | undefined
|
||||
>;
|
||||
let vmIpAddress = this.options.dnsBindInterface || '0.0.0.0'; // Default to all interfaces
|
||||
|
||||
// Try to find the VM's internal IP address when no explicit bind address is configured.
|
||||
if (!this.options.dnsBindInterface) {
|
||||
interfaceLoop: for (const [_name, interfaces] of Object.entries(networkInterfaces)) {
|
||||
if (interfaces) {
|
||||
for (const iface of interfaces) {
|
||||
if (!iface.internal && iface.family === 'IPv4') {
|
||||
vmIpAddress = iface.address;
|
||||
break interfaceLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
@@ -1,3 +1,4 @@
|
||||
import { commitinfo } from './00_commitinfo_data.js';
|
||||
export * from './00_commitinfo_data.js';
|
||||
|
||||
// Re-export smartmta (excluding commitinfo to avoid naming conflict)
|
||||
@@ -18,6 +19,29 @@ export * from './remoteingress/index.js';
|
||||
export type { IHttp3Config } from './http3/index.js';
|
||||
|
||||
export const runCli = async () => {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
if (args.includes('--version') || args.includes('version')) {
|
||||
console.log(commitinfo.version);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.includes('--help') || args.includes('-h') || args.includes('help')) {
|
||||
console.log(`dcrouter ${commitinfo.version}
|
||||
|
||||
Usage:
|
||||
dcrouter
|
||||
dcrouter --version
|
||||
dcrouter --help
|
||||
|
||||
Environment:
|
||||
DCROUTER_MODE=OCI_CONTAINER Start with OCI container configuration
|
||||
DCROUTER_DNS_BIND_INTERFACE Override the embedded DNS UDP bind address
|
||||
DATA_DIR=<path> Override the writable dcrouter data directory
|
||||
`);
|
||||
return;
|
||||
}
|
||||
|
||||
let options: import('./classes.dcrouter.js').IDcRouterOptions = {};
|
||||
|
||||
if (process.env.DCROUTER_MODE === 'OCI_CONTAINER') {
|
||||
|
||||
+9
-9
@@ -1,13 +1,13 @@
|
||||
// node native
|
||||
import * as dns from 'dns';
|
||||
import * as fs from 'fs';
|
||||
import * as crypto from 'crypto';
|
||||
import * as http from 'http';
|
||||
import * as net from 'net';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as tls from 'tls';
|
||||
import * as util from 'util';
|
||||
import * as dns from 'node:dns';
|
||||
import * as fs from 'node:fs';
|
||||
import * as crypto from 'node:crypto';
|
||||
import * as http from 'node:http';
|
||||
import * as net from 'node:net';
|
||||
import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
import * as tls from 'node:tls';
|
||||
import * as util from 'node:util';
|
||||
|
||||
export {
|
||||
dns,
|
||||
|
||||
@@ -74,6 +74,10 @@ export function getOciContainerConfig(): IDcRouterOptions {
|
||||
options.dnsScopes = dnsScopes;
|
||||
}
|
||||
|
||||
if (process.env.DCROUTER_DNS_BIND_INTERFACE) {
|
||||
options.dnsBindInterface = process.env.DCROUTER_DNS_BIND_INTERFACE;
|
||||
}
|
||||
|
||||
// Email config
|
||||
const emailHostname = process.env.DCROUTER_EMAIL_HOSTNAME;
|
||||
const emailPorts = parseCommaSeparatedNumbers(process.env.DCROUTER_EMAIL_PORTS);
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/dcrouter',
|
||||
version: '13.36.2',
|
||||
version: '13.38.2',
|
||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user