Compare commits

...
5 Commits
7 changed files with 432 additions and 30 deletions
+268 -1
View File
@@ -1 +1,268 @@
build.sh ##############################
# Operating System Files
##############################
.DS_Store
.AppleDouble
.LSOverride
Thumbs.db
ehthumbs.db
Desktop.ini
Icon?
$RECYCLE.BIN/
.Spotlight-V100/
.Trashes/
.fseventsd
##############################
# IDEs
##############################
.vscode/
.idea/
*.iml
*.ipr
*.iws
##############################
# VS Code
##############################
.history/
*.code-workspace
##############################
# Vim
##############################
*.swp
*.swo
Session.vim
##############################
# Sublime
##############################
*.sublime-workspace
*.sublime-project
##############################
# Temporary Files
##############################
*.tmp
*.temp
*.bak
*.old
*.orig
*.rej
*.save
##############################
# Logs
##############################
*.log
logs/
log/
*.out
*.err
*.trace
##############################
# Runtime
##############################
*.pid
*.seed
*.pid.lock
##############################
# Secrets
##############################
.env
.env.*
!.env.example
*.pem
*.key
*.crt
*.cer
*.p12
*.pfx
*.kdbx
*.secret
*.token
##############################
# SSH
##############################
.ssh/
##############################
# Docker
##############################
docker-compose.override.yml
docker-compose.local.yml
##############################
# VM Storage
##############################
storage/
windows/
downloads/
##############################
# Disk Images
##############################
*.qcow2
*.qcow
*.vhd
*.vhdx
*.vdi
*.raw
*.img
*.iso
*.bin
##############################
# QEMU
##############################
*.nvram
*.fd
*.efi
*.sock
*.monitor
*.serial
##############################
# Samba
##############################
shared/
share/
##############################
# Backups
##############################
backup/
backups/
*.backup
##############################
# Cache
##############################
.cache/
.cache-loader/
.tmp/
temp/
tmp/
##############################
# Python
##############################
__pycache__/
*.py[cod]
.pytest_cache/
.mypy_cache/
.venv/
venv/
##############################
# Node
##############################
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
##############################
# Build
##############################
dist/
build/
out/
release/
##############################
# Coverage
##############################
coverage/
.coverage
coverage.xml
##############################
# Archives
##############################
*.zip
*.tar
*.tar.gz
*.tgz
*.7z
*.rar
##############################
# Generated Config
##############################
config.local.*
settings.local.*
local.env
##############################
# Test Files
##############################
test-output/
playwright-report/
##############################
# macOS
##############################
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
##############################
# Linux
##############################
*~
.nfs*
##############################
# Windows
##############################
*.stackdump
##############################
# Misc
##############################
*.cache
*.lock
*.lock.json
*.bak.*
##############################
# Keep Examples
##############################
!.gitkeep
!.env.example
+5 -5
View File
@@ -8,8 +8,8 @@ An empty default means the variable is unset and its value is determined automat
| Variable | Default | Description | | Variable | Default | Description |
|---|---|---| |---|---|---|
| `URL` | | URL or local path to the DSM `.pat` installation file. Downloads the default Virtual DSM image automatically when unset. | | `URL` | | URL or local path to a custom `.pat` installation file. |
| `COUNTRY` | | Country code used to select the Synology download mirror. Detected automatically when unset. | | `COUNTRY` | | Country code used to select the Synology download mirror. |
| `HOST_MAC` | | MAC address reported to DSM. | | `HOST_MAC` | | MAC address reported to DSM. |
| `HOST_MODEL` | | Synology host model reported to DSM. | | `HOST_MODEL` | | Synology host model reported to DSM. |
| `HOST_SERIAL` | | Synology host serial number reported to DSM. | | `HOST_SERIAL` | | Synology host serial number reported to DSM. |
@@ -47,14 +47,14 @@ An empty default means the variable is unset and its value is determined automat
| Variable | Default | Description | | Variable | Default | Description |
|---|---|---| |---|---|---|
| `NETWORK` | | Network mode, such as `nat`, `user`, or `N` to disable networking. | | `NETWORK` | | Network mode, such as `nat`, `user`, or `N` to disable networking. |
| `DHCP` | `N` | Enables macvtap networking so DSM receives an address from the external LAN through DHCP. | | `DHCP` | `N` | Enables macvtap networking so DSM receives a DHCP address. |
| `HOST` | `VirtualDSM` | Hostname assigned to DSM. | | `HOST` | | Hostname assigned to the machine on the network. |
| `IP` | | Overrides the automatically selected guest IPv4 address. | | `IP` | | Overrides the automatically selected guest IPv4 address. |
| `MAC` | | Guest network adapter MAC address. | | `MAC` | | Guest network adapter MAC address. |
| `ADAPTER` | `virtio-net-pci` | QEMU network adapter model. | | `ADAPTER` | `virtio-net-pci` | QEMU network adapter model. |
| `DEV` | `eth0` | Container network interface used as the uplink. | | `DEV` | `eth0` | Container network interface used as the uplink. |
| `MTU` | | MTU assigned to the guest network interface. | | `MTU` | | MTU assigned to the guest network interface. |
| `MASK` | `255.255.255.0` | IPv4 netmask. | | `MASK` | `255.255.255.0` | IPv4 netmask for guest network. |
| `TAP` | `dsm` | TAP or macvtap interface name. | | `TAP` | `dsm` | TAP or macvtap interface name. |
| `BRIDGE` | `docker` | Bridge name used for NAT networking. | | `BRIDGE` | `docker` | Bridge name used for NAT networking. |
| `HOST_PORTS` | | Ports excluded from guest forwarding. | | `HOST_PORTS` | | Ports excluded from guest forwarding. |
+64 -5
View File
@@ -2,6 +2,7 @@
set -Eeuo pipefail set -Eeuo pipefail
info="/run/shm/msg.html" info="/run/shm/msg.html"
info_tmp="${info}.${BASHPID}.tmp"
escape() { escape() {
@@ -17,6 +18,23 @@ escape() {
return 0 return 0
} }
writeInfo() {
local content="$1"
if ! printf '%s\n' "$content" > "$info_tmp"; then
rm -f -- "$info_tmp"
return 1
fi
if ! mv -f -- "$info_tmp" "$info"; then
rm -f -- "$info_tmp"
return 1
fi
return 0
}
getBytes() { getBytes() {
local path="$1" local path="$1"
@@ -48,6 +66,24 @@ getBytes() {
return 0 return 0
} }
getStatus() {
local file="$1"
local bytes total extra=""
[ -r "$file" ] || return 1
read -r bytes total extra < "$file" || return 1
if [[ ! "$bytes" =~ ^[0-9]+$ ||
! "$total" =~ ^[0-9]+$ ||
-n "$extra" ]]; then
return 1
fi
printf '%s %s\n' "$bytes" "$total"
return 0
}
formatSize() { formatSize() {
local bytes="$1" local bytes="$1"
@@ -117,7 +153,9 @@ printSizeProgress() {
return 0 return 0
} }
finishLogProgress() { finishProgress() {
rm -f -- "$info_tmp"
if [[ "$output" == "log" && "$printed" == "Y" ]]; then if [[ "$output" == "log" && "$printed" == "Y" ]]; then
printf '\n' printf '\n'
@@ -132,6 +170,7 @@ body=$(escape "$3")
output="${4:-}" output="${4:-}"
step_bytes="${5:-536870912}" step_bytes="${5:-536870912}"
mode="${6:-apparent}" mode="${6:-apparent}"
status_file="${7:-}"
if [[ -n "$total" && ! "$total" =~ ^(0|[1-9][0-9]*)$ ]]; then if [[ -n "$total" && ! "$total" =~ ^(0|[1-9][0-9]*)$ ]]; then
printf 'Invalid total size: %s\n' "$total" >&2 printf 'Invalid total size: %s\n' "$total" >&2
@@ -168,7 +207,7 @@ if [ -z "$total" ] || [[ "$total" == "0" ]]; then
log_mode="size" log_mode="size"
fi fi
trap finishLogProgress EXIT trap finishProgress EXIT
trap 'exit 0' HUP INT QUIT TERM trap 'exit 0' HUP INT QUIT TERM
if [[ "$body" == *"..." ]]; then if [[ "$body" == *"..." ]]; then
@@ -178,12 +217,32 @@ fi
while true; do while true; do
bytes=$(getBytes "$path" "$mode") bytes=$(getBytes "$path" "$mode")
effective_total="$total"
if [ -n "$status_file" ] && status=$(getStatus "$status_file"); then
read -r status_bytes status_total <<< "$status"
bytes="$status_bytes"
if (( status_total > 0 )); then
effective_total="$status_total"
fi
fi
# A real total may become available shortly after aria2 starts.
if [[ "$log_mode" == "size" &&
"$printed" == "N" &&
-n "$effective_total" &&
"$effective_total" != "0" ]]; then
log_mode="percent"
fi
if (( bytes > 4096 )); then if (( bytes > 4096 )); then
write_html="Y" write_html="Y"
if [ -z "$total" ] || [[ "$total" == "0" ]] || (( bytes > total )); then if [ -z "$effective_total" ] ||
[[ "$effective_total" == "0" ]] ||
(( bytes > effective_total )); then
size=$(formatSize "$bytes") size=$(formatSize "$bytes")
if [[ "$output" == "log" ]]; then if [[ "$output" == "log" ]]; then
@@ -197,7 +256,7 @@ while true; do
fi fi
else else
# Truncate to one decimal so progress is never reported early. # Truncate to one decimal so progress is never reported early.
progress=$((bytes * 1000 / total)) progress=$((bytes * 1000 / effective_total))
(( progress > 1000 )) && progress=1000 (( progress > 1000 )) && progress=1000
percent=$((progress / 10)) percent=$((progress / 10))
@@ -219,7 +278,7 @@ while true; do
fi fi
if [[ "$write_html" == "Y" ]]; then if [[ "$write_html" == "Y" ]]; then
printf '%s\n' "${body//(\[P\])/($size)}" > "$info" writeInfo "${body//(\[P\])/($size)}"
fi fi
fi fi
+15 -4
View File
@@ -22,17 +22,28 @@ prepareWebFiles() {
configureWebPorts() { configureWebPorts() {
sed -i "s/listen 5000 default_server;/listen $WEB_PORT default_server;/g" /etc/nginx/sites-enabled/web.conf if ! sed -i \
sed -i "s/proxy_pass http:\/\/127.0.0.1:8004\/;/proxy_pass http:\/\/127.0.0.1:$WSD_PORT\/;/g" /etc/nginx/sites-enabled/web.conf -e "s|listen 5000 default_server;|listen $WEB_PORT default_server;|g" \
-e "s|proxy_pass http://127.0.0.1:8004/;|proxy_pass http://127.0.0.1:$WSD_PORT/;|g" \
/etc/nginx/sites-enabled/web.conf; then
error "Failed to configure webserver ports!"
return 1
fi
return 0 return 0
} }
configureIpv6Listen() { configureIpv6Listen() {
# shellcheck disable=SC2143
if [ -f /proc/net/if_inet6 ] && [[ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null)" != "1" ]]; then if [ -f /proc/net/if_inet6 ] && [[ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null)" != "1" ]]; then
sed -i "s/listen $WEB_PORT default_server;/listen [::]:$WEB_PORT default_server ipv6only=off;/g" /etc/nginx/sites-enabled/web.conf
if ! sed -i \
"s/listen $WEB_PORT default_server;/listen [::]:$WEB_PORT default_server ipv6only=off;/g" \
/etc/nginx/sites-enabled/web.conf; then
error "Failed to configure IPv6 webserver listener!"
return 1
fi
fi fi
return 0 return 0
+18 -5
View File
@@ -3,6 +3,8 @@ set -Eeuo pipefail
lastmsg="" lastmsg=""
path="/run/shm/msg.html" path="/run/shm/msg.html"
dir=$(dirname -- "$path")
name=$(basename -- "$path")
refresh() { refresh() {
@@ -17,15 +19,26 @@ refresh() {
lastmsg="$msg" lastmsg="$msg"
echo "s: $msg" echo "s: $msg"
return 0 return 0
} }
refresh refresh
inotifywait -m "$path" | inotifywait \
while read -r fp event fn; do -m -q \
-e close_write,moved_to,delete \
--format '%e %f' \
"$dir" |
while read -r event file; do
[[ "$file" == "$name" ]] || continue
case "${event,,}" in case "${event,,}" in
"modify"* ) refresh ;; "delete"* )
"delete_self" ) echo "c: vnc" ;; echo "c: vnc" ;;
esac "close_write"* | "moved_to"* )
refresh ;;
esac
done done
+21 -2
View File
@@ -300,6 +300,25 @@ writeFile() {
return 0 return 0
} }
writeAtomic() {
local path="$1"
local content="$2"
local tmp="${path}.${BASHPID}.tmp"
if ! printf '%s\n' "$content" > "$tmp"; then
rm -f -- "$tmp"
return 1
fi
if ! mv -f -- "$tmp" "$path"; then
rm -f -- "$tmp"
return 1
fi
return 0
}
readFile() { readFile() {
local path="$1" local path="$1"
@@ -411,8 +430,8 @@ html() {
HTML="${HTML/\[4\]/$footer}" HTML="${HTML/\[4\]/$footer}"
HTML="${HTML/\[5\]/$FOOTER2}" HTML="${HTML/\[5\]/$FOOTER2}"
echo "$HTML" > "$PAGE" || return 1 writeAtomic "$PAGE" "$HTML" || return 1
echo "$body" > "$INFO" || return 1 writeAtomic "$INFO" "$body" || return 1
return 0 return 0
} }
+41 -8
View File
@@ -1,15 +1,27 @@
var timer;
var request; var request;
var booting = false; var booting = false;
var interval = 1000; var interval = 1000;
function abortRequest() {
if (!request) {
return false;
}
request.onreadystatechange = null;
request.abort();
request = null;
return true;
}
function getInfo() { function getInfo() {
var url = "msg.html"; var url = "msg.html";
try { try {
if (request) { abortRequest();
request.abort();
}
if (window.XMLHttpRequest) { if (window.XMLHttpRequest) {
request = new XMLHttpRequest(); request = new XMLHttpRequest();
@@ -56,7 +68,10 @@ function processInfo() {
return true; return true;
} }
var msg = request.responseText; var response = request;
request = null;
var msg = response.responseText;
if (msg == null || msg.length == 0) { if (msg == null || msg.length == 0) {
if (booting) { if (booting) {
@@ -68,9 +83,9 @@ function processInfo() {
return false; return false;
} }
var notFound = (request.status == 404); var notFound = (response.status == 404);
if (request.status == 200) { if (response.status == 200) {
if (msg.toLowerCase().indexOf("<html>") !== -1) { if (msg.toLowerCase().indexOf("<html>") !== -1) {
notFound = true; notFound = true;
} else { } else {
@@ -88,7 +103,7 @@ function processInfo() {
return true; return true;
} }
setError("Error: Received statuscode " + request.status); setError("Error: Received statuscode " + response.status);
return false; return false;
} catch (e) { } catch (e) {
@@ -157,7 +172,9 @@ function setError(text) {
} }
function schedule() { function schedule() {
setTimeout(getInfo, interval);
clearTimeout(timer);
timer = setTimeout(getInfo, interval);
} }
function reload() { function reload() {
@@ -179,11 +196,27 @@ function connect() {
switch (cmd) { switch (cmd) {
case "s": case "s":
var aborted = abortRequest();
processMsg(msg); processMsg(msg);
if (aborted &&
msg.toLowerCase().indexOf("href=") == -1) {
schedule();
}
break; break;
case "e": case "e":
if (abortRequest()) {
schedule();
}
setError(msg); setError(msg);
break; break;
default: default:
console.warn("Unknown event: " + cmd); console.warn("Unknown event: " + cmd);
break; break;