diff --git a/Dockerfile b/Dockerfile index afe8116..119f480 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ RUN if [ "$TARGETPLATFORM" != "linux/amd64" ]; then extra="qemu-user"; fi \ wget \ fdisk \ unzip \ - socat \ + nginx \ procps \ xz-utils \ iptables \ @@ -39,11 +39,16 @@ RUN if [ "$TARGETPLATFORM" != "linux/amd64" ]; then extra="qemu-user"; fi \ qemu-system-x86 \ "$extra" \ && apt-get clean \ + && unlink /etc/nginx/sites-enabled/default \ + && sed -i 's/^worker_processes.*/worker_processes 1;/' /etc/nginx/nginx.conf \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* COPY ./src /run/ +COPY ./web /var/www/ COPY --from=builder /qemu-host.bin /run/host.bin + RUN chmod +x /run/*.sh && chmod +x /run/*.bin +RUN mv /var/www/nginx.conf /etc/nginx/sites-enabled/web.conf VOLUME /storage EXPOSE 22 139 445 5000 diff --git a/src/disk.sh b/src/disk.sh index 25d90b3..9427352 100644 --- a/src/disk.sh +++ b/src/disk.sh @@ -61,8 +61,8 @@ getSize() { local DISK_FILE=$1 local DISK_EXT DISK_FMT - DISK_EXT="$(echo "${DISK_FILE//*./}" | sed 's/^.*\.//')" - DISK_FMT="$(ext2fmt "$DISK_EXT")" + DISK_EXT=$(echo "${DISK_FILE//*./}" | sed 's/^.*\.//') + DISK_FMT=$(ext2fmt "$DISK_EXT") case "${DISK_FMT,,}" in raw) @@ -112,7 +112,9 @@ createDisk() { fi fi - info "Creating a $DISK_TYPE $DISK_DESC image in $DISK_FMT format with a size of $DISK_SPACE..." + MSG="Creating a $DISK_TYPE $DISK_DESC image in $DISK_FMT format with a size of $DISK_SPACE..." + info "$MSG" && html "$MSG" + local FAIL="Could not create a $DISK_TYPE $DISK_FMT $DISK_DESC image of $DISK_SPACE ($DISK_FILE)" case "${DISK_FMT,,}" in @@ -195,7 +197,9 @@ resizeDisk() { fi local GB=$(( (CUR_SIZE + 1073741823)/1073741824 )) - info "Resizing $DISK_DESC from ${GB}G to $DISK_SPACE..." + MSG="Resizing $DISK_DESC from ${GB}G to $DISK_SPACE..." + info "$MSG" && html "$MSG" + local FAIL="Could not resize the $DISK_TYPE $DISK_FMT $DISK_DESC image from ${GB}G to $DISK_SPACE ($DISK_FILE)" case "${DISK_FMT,,}" in @@ -262,7 +266,8 @@ convertDisk() { fi fi - info "Converting $DISK_DESC to $DST_FMT, please wait until completed..." + MSG="Converting $DISK_DESC to $DST_FMT, please wait until completed..." + info "$MSG" && html "$MSG" local CONV_FLAGS="-p" local DISK_PARAM="$DISK_ALLOC" @@ -301,7 +306,8 @@ convertDisk() { fi fi - info "Conversion of $DISK_DESC to $DST_FMT completed succesfully!" + MSG="Conversion of $DISK_DESC to $DST_FMT completed succesfully!" + info "$MSG" && html "$MSG" return 0 } @@ -372,7 +378,7 @@ addDisk () { else PREV_FMT="qcow2" fi - PREV_EXT="$(fmt2ext "$PREV_FMT")" + PREV_EXT=$(fmt2ext "$PREV_FMT") if [ -f "$DISK_BASE.$PREV_EXT" ] ; then convertDisk "$DISK_BASE.$PREV_EXT" "$PREV_FMT" "$DISK_FILE" "$DISK_FMT" "$DISK_BASE" "$DISK_DESC" "$FS" || exit $? @@ -420,7 +426,9 @@ addDevice () { return 0 } -DISK_EXT="$(fmt2ext "$DISK_FMT")" || exit $? +html "Initializing disks..." + +DISK_EXT=$(fmt2ext "$DISK_FMT") if [ -z "$ALLOCATE" ]; then if [[ "${DISK_FMT,,}" == "raw" ]]; then @@ -505,4 +513,5 @@ else addDisk "userdata4" "$DISK4_FILE" "$DISK_EXT" "disk4" "$DISK4_SIZE" "6" "0xf" "$DISK_FMT" || exit $? fi +html "Initialized disks successfully..." return 0 diff --git a/src/entry.sh b/src/entry.sh index fb85d1c..be29d5d 100755 --- a/src/entry.sh +++ b/src/entry.sh @@ -1,9 +1,8 @@ #!/usr/bin/env bash set -Eeuo pipefail -echo "❯ Starting Virtual DSM for Docker v$(/dev/null 2>&1; then @@ -221,7 +223,9 @@ else fi rm -rf /run/extract -info "Install: Preparing system partition..." + +MSG="Preparing system partition..." +info "Install: $MSG" && html "$MSG" BOOT=$(find "$TMP" -name "*.bin.zip") [ ! -f "$BOOT" ] && error "The PAT file contains no boot image." && exit 67 @@ -277,7 +281,8 @@ sfdisk -q "$SYSTEM" < "$PART" MOUNT="$TMP/system" rm -rf "$MOUNT" && mkdir -p "$MOUNT" -info "Install: Extracting system partition..." +MSG="Extracting system partition..." +info "Install: $MSG" && html "$MSG" HDA="$TMP/hda1" IDB="$TMP/indexdb" @@ -301,12 +306,13 @@ fi LABEL="1.44.1-42218" OFFSET="1048576" # 2048 * 512 NUMBLOCKS="622560" # (4980480 * 512) / 4096 +MSG="Installing system partition..." if [[ "$ROOT" != [Nn]* ]]; then tar xpfJ "$HDA.txz" --absolute-names --skip-old-files -C "$MOUNT/" - info "Install: Installing system partition..." + info "Install: $MSG" && html "$MSG" mke2fs -q -t ext4 -b 4096 -d "$MOUNT/" -L "$LABEL" -F -E "offset=$OFFSET" "$SYSTEM" "$NUMBLOCKS" @@ -314,7 +320,7 @@ else fakeroot -- bash -c "set -Eeu;\ tar xpfJ $HDA.txz --absolute-names --skip-old-files -C $MOUNT/;\ - printf '%b%s%b' '\E[1;34m❯ \E[1;36m' 'Install: Installing system partition...' '\E[0m\n';\ + printf '%b%s%b' '\E[1;34m❯ \E[1;36m' 'Install: $MSG' '\E[0m\n';\ mke2fs -q -t ext4 -b 4096 -d $MOUNT/ -L $LABEL -F -E offset=$OFFSET $SYSTEM $NUMBLOCKS" fi @@ -334,4 +340,5 @@ rm -rf "$TMP" { set +x; } 2>/dev/null [[ "$DEBUG" == [Yy1]* ]] && echo +html "Installation finished successfully..." return 0 diff --git a/src/network.sh b/src/network.sh index 314542d..601694d 100644 --- a/src/network.sh +++ b/src/network.sh @@ -173,14 +173,17 @@ closeNetwork() { if [[ "$DHCP" == [Yy1]* ]]; then - fKill "server.sh" + # Shutdown nginx + nginx -s stop 2> /dev/null + fWait "nginx" ip link set "$VM_NET_TAP" down || true ip link delete "$VM_NET_TAP" || true else - fKill "dnsmasq" + local pid="/var/run/dnsmasq.pid" + [ -f "$pid" ] && pKill "$(<"$pid")" ip link set "$VM_NET_TAP" down promisc off || true ip link delete "$VM_NET_TAP" || true @@ -227,8 +230,6 @@ getInfo() { # Configure Network # ###################################### -fKill "server.sh" - if [ ! -c /dev/vhost-net ]; then if mknod /dev/vhost-net c 10 238; then chmod 660 /dev/vhost-net @@ -236,6 +237,7 @@ if [ ! -c /dev/vhost-net ]; then fi getInfo +html "Initializing network..." if [[ "$DEBUG" == [Yy1]* ]]; then info "Container IP is $IP with gateway $GATEWAY on interface $VM_NET_DEV" && echo @@ -252,11 +254,15 @@ if [[ "$DHCP" == [Yy1]* ]]; then # Configuration for DHCP IP configureDHCP - # Display IP on port 80 and 5000 - /run/server.sh 5000 /run/ip.sh & + MSG="Please wait while discovering IP..." + html "$MSG" "2000" else + # Shutdown nginx + nginx -s stop 2> /dev/null + fWait "nginx" + # Configuration for static IP configureNAT diff --git a/src/print.sh b/src/print.sh index 95d7b9e..d2ddd1a 100644 --- a/src/print.sh +++ b/src/print.sh @@ -7,8 +7,10 @@ info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "$1" "\E[0m\n" >&2; } error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: $1" "\E[0m\n" >&2; } file="/run/shm/dsm.url" +page="/run/shm/index.html" address="/run/shm/qemu.ip" shutdown="/run/shm/qemu.end" +template="/var/www/index.html" url="http://127.0.0.1:2210/read?command=10" resp_err="Guest returned an invalid response:" @@ -66,6 +68,18 @@ location=$(<"$file") if [[ "$location" != "20.20"* ]]; then msg="http://$location" + title="Virtual DSM" + body="The location of DSM is http://$location" + script="" + + HTML=$(<"$template") + HTML="${HTML/\[1\]/$title}" + HTML="${HTML/\[2\]/$script}" + HTML="${HTML/\[3\]/$body}" + HTML="${HTML/\[4\]/}" + HTML="${HTML/\[5\]/}" + + echo "$HTML" > "$page" else diff --git a/src/reset.sh b/src/reset.sh index 60e8086..f385ca0 100644 --- a/src/reset.sh +++ b/src/reset.sh @@ -10,6 +10,10 @@ trap 'error "Status $? while: $BASH_COMMAND (line $LINENO/$BASH_LINENO)"' ERR [ ! -f "/run/entry.sh" ] && error "Script must run inside Docker container!" && exit 11 [ "$(id -u)" -ne "0" ] && error "Script must be executed with root privileges." && exit 12 +echo "❯ Starting $APP for Docker v$(/dev/null while isAlive "$pid"; do - sleep 0.1 + sleep 0.2 + done + + return 0 +} + +fWait() { + local name=$1 + + while pgrep -f -l "$name" >/dev/null; do + sleep 0.2 done return 0 @@ -81,14 +99,54 @@ fKill() { local name=$1 { pkill -f "$name" || true; } 2>/dev/null - - while pgrep -f -l "$name" >/dev/null; do - sleep 0.1 - done + fWait "$name" return 0 } +escape () { + local s + s=${1//&/\&} + s=${s///\>} + s=${s//'"'/\"} + printf -- %s "$s" + return 0 +} + +html() +{ + local title + local body + local footer + + title=$(escape "$APP") + title="$title" + footer=$(escape "$FOOTER1") + + body=$(escape "$1") + if [[ "$body" == *"..." ]]; then + body="

${body/.../}

" + fi + + local timeout="4999" + [ -n "${2:-}" ] && timeout="$2" + local script="" + [[ "$timeout" == "0" ]] && script="" + + local HTML + HTML=$(<"$TEMPLATE") + HTML="${HTML/\[1\]/$title}" + HTML="${HTML/\[2\]/$script}" + HTML="${HTML/\[3\]/$body}" + HTML="${HTML/\[4\]/$footer}" + HTML="${HTML/\[5\]/$FOOTER2}" + + echo "$HTML" > "$PAGE" + + return 0 +} + getCountry() { local url=$1 local query=$2 @@ -134,7 +192,8 @@ addPackage() { return 0 fi - info "Installing $desc..." + MSG="Installing $desc..." + info "$MSG" && html "$MSG" [ -z "$COUNTRY" ] && setCountry @@ -148,4 +207,9 @@ addPackage() { return 0 } +# Start webserver +cp -r /var/www/* /run/shm +html "Starting $APP for Docker..." +nginx -e stderr + return 0 diff --git a/src/server.sh b/src/server.sh deleted file mode 100644 index 95f25d5..0000000 --- a/src/server.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash -set -eu - -TMP_FILE=$(mktemp -q /tmp/server.XXXXXX) - -stop() { - trap - SIGINT EXIT - { pkill -f socat || true; } 2>/dev/null - [ -f "$TMP_FILE" ] && rm -f "$TMP_FILE" -} - -trap 'stop' EXIT SIGINT SIGTERM SIGHUP - -html() -{ - local h="VirtualDSM" - h="$h" - h="$h

$1

" - - echo "$h" -} - -if [[ "$2" != "/"* ]]; then - - BODY="$2" - - if [[ "$BODY" == "install" ]]; then - BODY="Please wait while Virtual DSM is being installed..." - BODY="$BODY" - fi - - HTML=$(html "$BODY") - printf '%b' "HTTP/1.1 200 OK\nContent-Length: ${#HTML}\nConnection: close\n\n$HTML" > "$TMP_FILE" - - socat TCP4-LISTEN:80,reuseaddr,fork,crlf SYSTEM:"cat $TMP_FILE" 2> /dev/null & - socat TCP4-LISTEN:"${1:-5000}",reuseaddr,fork,crlf SYSTEM:"cat $TMP_FILE" 2> /dev/null & wait $! - - exit - -fi - -if [[ "$2" != "/run/ip.sh" ]]; then - - cp "$2" "$TMP_FILE" - -else - - BODY="The location of DSM is http://\$LOCATION" - WAIT="Please wait while discovering IP..." - - HTML=$(html "xxx") - - { echo "#!/bin/bash" - echo "[ -f \"/run/shm/dsm.url\" ] && LOCATION=\$( "$TMP_FILE" - -fi - -chmod +x "$TMP_FILE" - -socat TCP4-LISTEN:80,reuseaddr,fork,crlf SYSTEM:"$TMP_FILE" 2> /dev/null & -socat TCP4-LISTEN:"${1:-5000}",reuseaddr,fork,crlf SYSTEM:"$TMP_FILE" 2> /dev/null & wait $! diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..10a9faa --- /dev/null +++ b/web/index.html @@ -0,0 +1,26 @@ + + + + + [1] + + + + [2] + + + +
+
+

[3]

+
+
+
+ +
+ + + diff --git a/web/nginx.conf b/web/nginx.conf new file mode 100644 index 0000000..a405c56 --- /dev/null +++ b/web/nginx.conf @@ -0,0 +1,33 @@ +server { + listen 80; + listen [::]:80; + listen 5000 default_server; + listen [::]:5000 default_server; + + autoindex on; + tcp_nodelay on; + server_tokens off; + absolute_redirect off; + + error_log /dev/null; + access_log /dev/null; + + include /etc/nginx/mime.types; + + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 5; + gzip_min_length 500; + gzip_disable "msie6"; + gzip_types text/css text/javascript text/xml text/plain text/x-component application/javascript application/json application/xml application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml; + + add_header Cache-Control "no-cache"; + + location / { + + root /run/shm; + index index.html; + + } +} diff --git a/web/style.css b/web/style.css new file mode 100644 index 0000000..def18b7 --- /dev/null +++ b/web/style.css @@ -0,0 +1,59 @@ +body { + color: white; + background-color: #125bdb; + font-family: Verdana, Arial, sans-serif; +} + +#content-wrap { + text-align: center; + padding: 20px; + margin-top: 100px; +} + +#footer { + width: 98%; + position: fixed; + bottom: 0px; + height: 40px; + text-align: center; +} + +#empty-space { + height: 40px; + /* Same height as footer */ +} + +a, +a:hover, +a:active, +a:visited { + color: white; +} + +.loading:after { + content: " ."; + animation: dots 1s steps(5, end) infinite; +} + +@keyframes dots { + + 0%, + 20% { + color: rgba(0, 0, 0, 0); + text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0); + } + + 40% { + color: white; + text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0); + } + + 60% { + text-shadow: 0.25em 0 0 white, 0.5em 0 0 rgba(0, 0, 0, 0); + } + + 80%, + 100% { + text-shadow: 0.25em 0 0 white, 0.5em 0 0 white; + } +}