From ec48d9d53e8228c55092720f5d8e4e8d9c779a21 Mon Sep 17 00:00:00 2001 From: Retschga Date: Sun, 14 Nov 2021 17:56:29 +0100 Subject: [PATCH 1/5] Raspberry PI OS 32Bit Support --- Agent/Services/AppLauncherLinux.cs | 27 ++- Desktop.XPlat/Native/Linux/LibX11_32.cs | 38 ++++ Desktop.XPlat/Native/Linux/LibXtst_32.cs | 15 ++ .../Services/KeyboardMouseInputLinux.cs | 81 ++++++-- Desktop.XPlat/Services/ScreenCapturerLinux.cs | 37 +++- Server.Installer/Models/WebServerType.cs | 3 +- Server.Installer/Program.cs | 3 +- .../Resources/LinuxArm_Nginx_Install.sh | 174 ++++++++++++++++++ Server.Installer/Services/ServerInstaller.cs | 1 + Server/API/ClientDownloadsController.cs | 16 ++ Server/Pages/Downloads.razor | 29 +++ Server/wwwroot/Content/Install-arm.sh | 109 +++++++++++ Shared/Utilities/EnvironmentHelper.cs | 2 + Utilities/Publish.ps1 | 16 +- 14 files changed, 521 insertions(+), 30 deletions(-) create mode 100644 Desktop.XPlat/Native/Linux/LibX11_32.cs create mode 100644 Desktop.XPlat/Native/Linux/LibXtst_32.cs create mode 100644 Server.Installer/Resources/LinuxArm_Nginx_Install.sh create mode 100644 Server/wwwroot/Content/Install-arm.sh diff --git a/Agent/Services/AppLauncherLinux.cs b/Agent/Services/AppLauncherLinux.cs index 0f04ebcd0..23637e07d 100644 --- a/Agent/Services/AppLauncherLinux.cs +++ b/Agent/Services/AppLauncherLinux.cs @@ -126,13 +126,26 @@ private int StartLinuxDesktopApp(string args) { try { - var whoLine = whoString - .Split('\n', StringSplitOptions.RemoveEmptyEntries) - .First(); - - var whoSplit = whoLine.Split(' ', StringSplitOptions.RemoveEmptyEntries); - username = whoSplit[0]; - display = whoSplit.Last().TrimStart('(').TrimEnd(')'); + var whoLines = whoString + .Split('\n', StringSplitOptions.RemoveEmptyEntries); + + for(int i = 0; i < whoLines.Length; i++) + { + var whoLine = whoLines[i]; + var whoSplit = whoLine.Split(' ', StringSplitOptions.RemoveEmptyEntries); + + username = whoSplit[0]; + Logger.Write($"split last: {whoSplit.Last()}"); + + display = whoSplit.Last().TrimStart('(').TrimEnd(')'); + Logger.Write($"display: {display}"); + + if(display.Length >0 && display[0] == ':') + { + break; + } + + } xauthority = $"/home/{username}/.Xauthority"; args = $"-u {username} {args}"; } diff --git a/Desktop.XPlat/Native/Linux/LibX11_32.cs b/Desktop.XPlat/Native/Linux/LibX11_32.cs new file mode 100644 index 000000000..fd369db79 --- /dev/null +++ b/Desktop.XPlat/Native/Linux/LibX11_32.cs @@ -0,0 +1,38 @@ +/* + +Copyright 1985, 1986, 1987, 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +using System; +using System.Runtime.InteropServices; + +namespace Remotely.Desktop.XPlat.Native.Linux +{ + public static unsafe class LibX11_32 + { + + [DllImport("libX11")] + public static extern IntPtr XGetImage(IntPtr display, IntPtr drawable, int x, int y, int width, int height, uint plane_mask, int format); + } +} diff --git a/Desktop.XPlat/Native/Linux/LibXtst_32.cs b/Desktop.XPlat/Native/Linux/LibXtst_32.cs new file mode 100644 index 000000000..5c2cb2135 --- /dev/null +++ b/Desktop.XPlat/Native/Linux/LibXtst_32.cs @@ -0,0 +1,15 @@ +using System; +using System.Runtime.InteropServices; + +namespace Remotely.Desktop.XPlat.Native.Linux +{ + public class LibXtst_32 + { + [DllImport("libXtst")] + public static extern void XTestFakeKeyEvent(IntPtr display, uint keycode, bool is_press, uint delay); + [DllImport("libXtst")] + public static extern void XTestFakeButtonEvent(IntPtr display, uint button, bool is_press, uint delay); + [DllImport("libXtst")] + public static extern void XTestFakeMotionEvent(IntPtr display, int screen_number, int x, int y, uint delay); + } +} diff --git a/Desktop.XPlat/Services/KeyboardMouseInputLinux.cs b/Desktop.XPlat/Services/KeyboardMouseInputLinux.cs index 86f6046db..65bb2f6cc 100644 --- a/Desktop.XPlat/Services/KeyboardMouseInputLinux.cs +++ b/Desktop.XPlat/Services/KeyboardMouseInputLinux.cs @@ -32,7 +32,13 @@ public void SendKeyDown(string key) } var keyCode = LibX11.XKeysymToKeycode(Display, keySim); - LibXtst.XTestFakeKeyEvent(Display, keyCode, true, 0); + if(EnvironmentHelper.Is64) + { + LibXtst.XTestFakeKeyEvent(Display, keyCode, true, 0); + } + else{ + LibXtst_32.XTestFakeKeyEvent(Display, keyCode, true, 0); + } LibX11.XSync(Display, false); } catch (Exception ex) @@ -55,7 +61,13 @@ public void SendKeyUp(string key) } var keyCode = LibX11.XKeysymToKeycode(Display, keySim); - LibXtst.XTestFakeKeyEvent(Display, keyCode, false, 0); + if(EnvironmentHelper.Is64) + { + LibXtst.XTestFakeKeyEvent(Display, keyCode, false, 0); + } + else{ + LibXtst_32.XTestFakeKeyEvent(Display, keyCode, false, 0); + } LibX11.XSync(Display, false); } catch (Exception ex) @@ -75,8 +87,14 @@ public void SendMouseButtonAction(int button, ButtonAction buttonAction, double var mouseButton = (uint)(button + 1); InitDisplay(); - SendMouseMove(percentX, percentY, viewer); - LibXtst.XTestFakeButtonEvent(Display, mouseButton, isPressed, 0); + SendMouseMove(percentX, percentY, viewer); + if(EnvironmentHelper.Is64) + { + LibXtst.XTestFakeButtonEvent(Display, mouseButton, isPressed, 0); + } + else{ + LibXtst_32.XTestFakeButtonEvent(Display, mouseButton, isPressed, 0); + } LibX11.XSync(Display, false); } catch (Exception ex) @@ -92,11 +110,22 @@ public void SendMouseMove(double percentX, double percentY, Viewer viewer) InitDisplay(); var screenBounds = viewer.Capturer.CurrentScreenBounds; - LibXtst.XTestFakeMotionEvent(Display, - LibX11.XDefaultScreen(Display), - screenBounds.X + (int)(screenBounds.Width * percentX), - screenBounds.Y + (int)(screenBounds.Height * percentY), + if(EnvironmentHelper.Is64) + { + LibXtst.XTestFakeMotionEvent(Display, + LibX11.XDefaultScreen(Display), + screenBounds.X + (int)(screenBounds.Width * percentX), + screenBounds.Y + (int)(screenBounds.Height * percentY), + 0); + } + else{ + LibXtst_32.XTestFakeMotionEvent(Display, + LibX11.XDefaultScreen(Display), + screenBounds.X + (int)(screenBounds.Width * percentX), + screenBounds.Y + (int)(screenBounds.Height * percentY), 0); + } + LibX11.XSync(Display, false); } catch (Exception ex) @@ -114,11 +143,27 @@ public void SendMouseWheel(int deltaY) { LibXtst.XTestFakeButtonEvent(Display, 4, true, 0); LibXtst.XTestFakeButtonEvent(Display, 4, false, 0); + if(EnvironmentHelper.Is64) + { + LibXtst.XTestFakeButtonEvent(Display, 4, true, 0); + LibXtst.XTestFakeButtonEvent(Display, 4, false, 0); + } + else{ + LibXtst_32.XTestFakeButtonEvent(Display, 4, true, 0); + LibXtst_32.XTestFakeButtonEvent(Display, 4, false, 0); + } } else { - LibXtst.XTestFakeButtonEvent(Display, 5, true, 0); - LibXtst.XTestFakeButtonEvent(Display, 5, false, 0); + if(EnvironmentHelper.Is64) + { + LibXtst.XTestFakeButtonEvent(Display, 5, true, 0); + LibXtst.XTestFakeButtonEvent(Display, 5, false, 0); + } + else{ + LibXtst_32.XTestFakeButtonEvent(Display, 5, true, 0); + LibXtst_32.XTestFakeButtonEvent(Display, 5, false, 0); + } } LibX11.XSync(Display, false); } @@ -134,7 +179,13 @@ public void SendRightMouseDown(double percentX, double percentY, Viewer viewer) { InitDisplay(); SendMouseMove(percentX, percentY, viewer); - LibXtst.XTestFakeButtonEvent(Display, 3, true, 0); + if(EnvironmentHelper.Is64) + { + LibXtst.XTestFakeButtonEvent(Display, 3, true, 0); + } + else{ + LibXtst_32.XTestFakeButtonEvent(Display, 3, true, 0); + } LibX11.XSync(Display, false); } catch (Exception ex) @@ -149,7 +200,13 @@ public void SendRightMouseUp(double percentX, double percentY, Viewer viewer) { InitDisplay(); SendMouseMove(percentX, percentY, viewer); - LibXtst.XTestFakeButtonEvent(Display, 3, false, 0); + if(EnvironmentHelper.Is64) + { + LibXtst.XTestFakeButtonEvent(Display, 3, false, 0); + } + else{ + LibXtst_32.XTestFakeButtonEvent(Display, 3, false, 0); + } LibX11.XSync(Display, false); } catch (Exception ex) diff --git a/Desktop.XPlat/Services/ScreenCapturerLinux.cs b/Desktop.XPlat/Services/ScreenCapturerLinux.cs index 0adb07155..a46329469 100644 --- a/Desktop.XPlat/Services/ScreenCapturerLinux.cs +++ b/Desktop.XPlat/Services/ScreenCapturerLinux.cs @@ -146,14 +146,35 @@ private Bitmap GetX11Capture() var window = LibX11.XDefaultRootWindow(Display); - var imagePointer = LibX11.XGetImage(Display, - window, - CurrentScreenBounds.X, - CurrentScreenBounds.Y, - CurrentScreenBounds.Width, - CurrentScreenBounds.Height, - ~0, - 2); + IntPtr imagePointer = IntPtr.Zero; + + if(EnvironmentHelper.Is64) + { + imagePointer = LibX11.XGetImage(Display, + window, + CurrentScreenBounds.X, + CurrentScreenBounds.Y, + CurrentScreenBounds.Width, + CurrentScreenBounds.Height, + ~0, + 2); + } + else + { + imagePointer = LibX11_32.XGetImage(Display, + window, + CurrentScreenBounds.X, + CurrentScreenBounds.Y, + CurrentScreenBounds.Width, + CurrentScreenBounds.Height, + 0xffffffff, + 2); + } + + if(imagePointer == IntPtr.Zero) + { + Logger.Write($"libX11 XGetImage error"); + } var image = Marshal.PtrToStructure(imagePointer); diff --git a/Server.Installer/Models/WebServerType.cs b/Server.Installer/Models/WebServerType.cs index e7ad4db3a..23876cd51 100644 --- a/Server.Installer/Models/WebServerType.cs +++ b/Server.Installer/Models/WebServerType.cs @@ -14,6 +14,7 @@ public enum WebServerType UbuntuNginx, CentOsCaddy, CentOsNginx, - IisWindows + IisWindows3, + LinuxNginx } } diff --git a/Server.Installer/Program.cs b/Server.Installer/Program.cs index ca418323d..145fe0ffa 100644 --- a/Server.Installer/Program.cs +++ b/Server.Installer/Program.cs @@ -103,7 +103,8 @@ public static async Task Main(string[] args) "Nginx on Ubuntu", "Caddy on CentOS", "Nginx on CentOS", - "IIS on Windows Server 2016+"); + "IIS on Windows Server 2016+", + "Nginx on linux-arm"); if (Enum.TryParse(webServerType, out var result)) { diff --git a/Server.Installer/Resources/LinuxArm_Nginx_Install.sh b/Server.Installer/Resources/LinuxArm_Nginx_Install.sh new file mode 100644 index 000000000..6eae5b6cb --- /dev/null +++ b/Server.Installer/Resources/LinuxArm_Nginx_Install.sh @@ -0,0 +1,174 @@ +#!/bin/bash +echo "Thanks for trying Remotely!" +echo + +Args=( "$@" ) +ArgLength=${#Args[@]} + +for (( i=0; i<${ArgLength}; i+=2 )); +do + if [ "${Args[$i]}" = "--host" ]; then + HostName="${Args[$i+1]}" + elif [ "${Args[$i]}" = "--approot" ]; then + AppRoot="${Args[$i+1]}" + fi +done + +if [ -z "$AppRoot" ]; then + read -p "Enter path where the Remotely server files should be installed (typically /var/www/remotely): " AppRoot + if [ -z "$AppRoot" ]; then + AppRoot="/var/www/remotely" + fi +fi + +if [ -z "$HostName" ]; then + read -p "Enter server host (e.g. remotely.yourdomainname.com): " HostName +fi + +chmod +x "$AppRoot/Remotely_Server" + +echo "Using $AppRoot as the Remotely website's content directory." + +UbuntuVersion=$(lsb_release -r -s) + +apt-get -y install curl +apt-get -y install software-properties-common +apt-get -y install gnupg + +# Install .NET Core Runtime. +wget -q https://packages.microsoft.com/config/ubuntu/$UbuntuVersion/packages-microsoft-prod.deb +dpkg -i packages-microsoft-prod.deb +add-apt-repository universe +apt-get update +apt-get -y install apt-transport-https +apt-get -y install aspnetcore-runtime-5.0 +rm packages-microsoft-prod.deb + +curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin -c 5.0 + + + # Install other prerequisites. +apt-get -y install unzip +apt-get -y install acl +apt-get -y install libc6-dev +apt-get -y install libgdiplus + + +# Set permissions on Remotely files. +setfacl -R -m u:www-data:rwx $AppRoot +chown -R "$USER":www-data $AppRoot +chmod +x "$AppRoot/Remotely_Server" + + +# Install Nginx +apt-get update +apt-get -y install nginx + +systemctl start nginx + + +# Configure Nginx +nginxConfig=" + +server { + listen 80; + server_name $HostName *.$HostName; + location / { + proxy_pass http://localhost:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection keep-alive; + proxy_set_header Host \$host; + proxy_cache_bypass \$http_upgrade; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + } + + location /_blazor { + proxy_pass http://localhost:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection \"upgrade\"; + proxy_set_header Host \$host; + proxy_cache_bypass \$http_upgrade; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + } + location /AgentHub { + proxy_pass http://localhost:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection \"upgrade\"; + proxy_set_header Host \$host; + proxy_cache_bypass \$http_upgrade; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + } + location /ViewerHub { + proxy_pass http://localhost:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection \"upgrade\"; + proxy_set_header Host \$host; + proxy_cache_bypass \$http_upgrade; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + } + location /CasterHub { + proxy_pass http://localhost:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection \"upgrade\"; + proxy_set_header Host \$host; + proxy_cache_bypass \$http_upgrade; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + } +}" + +echo "$nginxConfig" > /etc/nginx/sites-available/remotely + +ln -s /etc/nginx/sites-available/remotely /etc/nginx/sites-enabled/remotely + +# Test config. +nginx -t + +# Reload. +nginx -s reload + + + + +# Create service. + +serviceConfig="[Unit] +Description=Remotely Server + +[Service] +WorkingDirectory=$AppRoot +ExecStart=/usr/bin/dotnet $AppRoot/Remotely_Server.dll +Restart=always +# Restart service after 10 seconds if the dotnet service crashes: +RestartSec=10 +SyslogIdentifier=remotely +User=www-data +Environment=ASPNETCORE_ENVIRONMENT=Production +Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false + +[Install] +WantedBy=multi-user.target" + +echo "$serviceConfig" > /etc/systemd/system/remotely.service + +chown -R www-data:www-data /var/www/remotely + +# Enable service. +systemctl enable remotely.service +# Start service. +systemctl restart remotely.service + + +# Install Certbot and get SSL cert. +apt-get -y install certbot python3-certbot-nginx + +certbot --nginx \ No newline at end of file diff --git a/Server.Installer/Services/ServerInstaller.cs b/Server.Installer/Services/ServerInstaller.cs index 5540530a7..51a963943 100644 --- a/Server.Installer/Services/ServerInstaller.cs +++ b/Server.Installer/Services/ServerInstaller.cs @@ -136,6 +136,7 @@ private async Task LaunchExternalInstaller(CliParams cliParams) WebServerType.CentOsCaddy => "CentOS_Caddy_Install.sh", WebServerType.CentOsNginx => "CentOS_Nginx_Install.sh", WebServerType.IisWindows => "IIS_Windows_Install.ps1", + WebServerType.LinuxNginx => "LinuxArm_Nginx_Install.ps1", _ => throw new Exception("Unrecognized reverse proxy type."), }; diff --git a/Server/API/ClientDownloadsController.cs b/Server/API/ClientDownloadsController.cs index 86e51f6fa..9c43b1585 100644 --- a/Server/API/ClientDownloadsController.cs +++ b/Server/API/ClientDownloadsController.cs @@ -50,6 +50,11 @@ public async Task GetDesktop(string platformID) var filePath = Path.Combine(_hostEnv.WebRootPath, "Content", "Linux-x64", "Remotely_Desktop"); return await GetDesktopFile(filePath); } + case "linux-arm": + { + var filePath = Path.Combine(_hostEnv.WebRootPath, "Content", "Linux-arm", "Remotely_Desktop"); + return await GetDesktopFile(filePath); + } case "MacOS-x64": { var filePath = Path.Combine(_hostEnv.WebRootPath, "Content", "MacOS-x64", "Remotely_Desktop"); @@ -86,6 +91,11 @@ public async Task GetDesktop(string platformId, string organizati var filePath = Path.Combine(_hostEnv.WebRootPath, "Content", "Linux-x64", "Remotely_Desktop"); return await GetDesktopFile(filePath, organizationId); } + case "linux-arm": + { + var filePath = Path.Combine(_hostEnv.WebRootPath, "Content", "Linux-arm", "Remotely_Desktop"); + return await GetDesktopFile(filePath, organizationId); + } case "MacOS-x64": { var filePath = Path.Combine(_hostEnv.WebRootPath, "Content", "MacOS-x64", "Remotely_Desktop"); @@ -190,6 +200,12 @@ private async Task GetInstallFile(string organizationId, string p { var fileName = "Install-Ubuntu-x64.sh"; + return await GetBashInstaller(fileName, organizationId); + } + case "armInstaller": + { + var fileName = "Install-arm.sh"; + return await GetBashInstaller(fileName, organizationId); } case "MacOSInstaller-x64": diff --git a/Server/Pages/Downloads.razor b/Server/Pages/Downloads.razor index 6e7efb13e..d86c0b661 100644 --- a/Server/Pages/Downloads.razor +++ b/Server/Pages/Downloads.razor @@ -32,6 +32,12 @@ Ubuntu Executable

+
+ Linux arm-32 +

+ Linux arm-32 Executable +

+
@*
macOS x64 (10.12 - 10.15)

@@ -176,6 +182,29 @@

+
+ Linux arm-32-Bit +

+ linux-arm-32bit Bash Installer + Linux Files Only +

+

+

Example Install:
+ + sudo [path]/Install-arm.sh +

+

+

Example Local Install:
+ + sudo [path]/Install-arm.sh --path [path]/Remotely-Linux.zip +

+

+

Uninstall:
+ + sudo [path]/Install-arm.sh --uninstall +

+
+
macOS x64 (10.12 - 10.15)

diff --git a/Server/wwwroot/Content/Install-arm.sh b/Server/wwwroot/Content/Install-arm.sh new file mode 100644 index 000000000..9cf039c90 --- /dev/null +++ b/Server/wwwroot/Content/Install-arm.sh @@ -0,0 +1,109 @@ +#!/bin/bash +HostName= +Organization= +GUID=$(cat /proc/sys/kernel/random/uuid) +UpdatePackagePath="" + + +Args=( "$@" ) +ArgLength=${#Args[@]} + +for (( i=0; i<${ArgLength}; i+=2 )); +do + if [ "${Args[$i]}" = "--uninstall" ]; then + systemctl stop remotely-agent + rm -r -f /usr/local/bin/Remotely + rm -f /etc/systemd/system/remotely-agent.service + systemctl daemon-reload + exit + elif [ "${Args[$i]}" = "--path" ]; then + UpdatePackagePath="${Args[$i+1]}" + fi +done + +UbuntuVersion=$(lsb_release -r -s) + +wget -q https://packages.microsoft.com/config/ubuntu/$UbuntuVersion/packages-microsoft-prod.deb -O packages-microsoft-prod.deb +dpkg -i packages-microsoft-prod.deb +apt-get update +apt-get -y install apt-transport-https +apt-get update +apt-get -y install dotnet-runtime-5.0 +rm packages-microsoft-prod.deb + +apt-get -y install libx11-dev +apt-get -y install libxrandr-dev +apt-get -y install unzip +apt-get -y install libc6-dev +apt-get -y install libgdiplus +apt-get -y install libxtst-dev +apt-get -y install xclip +apt-get -y install jq +apt-get -y install curl + +sudo curl -fsSL https://deb.nodesource.com/setup_17.x | bash - +sudo apt install nodejs + +curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin -c 5.0 + + +if [ -f "/usr/local/bin/Remotely/ConnectionInfo.json" ]; then + SavedGUID=`cat "/usr/local/bin/Remotely/ConnectionInfo.json" | jq -r '.DeviceID'` + if [[ "$SavedGUID" != "null" && -n "$SavedGUID" ]]; then + GUID="$SavedGUID" + fi +fi + +rm -r -f /usr/local/bin/Remotely +rm -f /etc/systemd/system/remotely-agent.service + +mkdir -p /usr/local/bin/Remotely/ +cd /usr/local/bin/Remotely/ + +if [ -z "$UpdatePackagePath" ]; then + echo "Downloading client..." >> /tmp/Remotely_Install.log + wget $HostName/Content/Remotely-Linux-arm.zip +else + echo "Copying install files..." >> /tmp/Remotely_Install.log + cp "$UpdatePackagePath" /usr/local/bin/Remotely/Remotely-Linux-arm.zip + rm -f "$UpdatePackagePath" +fi + +unzip ./Remotely-Linux-arm.zip +rm -f ./Remotely-Linux-arm.zip +chmod +x ./Remotely_Agent +chmod +x ./Desktop/Remotely_Desktop + + +connectionInfo="{ + \"DeviceID\":\"$GUID\", + \"Host\":\"$HostName\", + \"OrganizationID\": \"$Organization\", + \"ServerVerificationToken\":\"\" +}" + +echo "$connectionInfo" > ./ConnectionInfo.json + +curl --head $HostName/Content/Remotely-Linux.zip | grep -i "etag" | cut -d' ' -f 2 > ./etag.txt + +echo Creating service... >> /tmp/Remotely_Install.log + +serviceConfig="[Unit] +Description=The Remotely agent used for remote access. + +[Service] +WorkingDirectory=/usr/local/bin/Remotely/ +ExecStart=/usr/local/bin/Remotely/Remotely_Agent +Restart=always +StartLimitIntervalSec=0 +RestartSec=10 + +[Install] +WantedBy=graphical.target" + +echo "$serviceConfig" > /etc/systemd/system/remotely-agent.service + +systemctl enable remotely-agent +systemctl restart remotely-agent + +echo Install complete. >> /tmp/Remotely_Install.log diff --git a/Shared/Utilities/EnvironmentHelper.cs b/Shared/Utilities/EnvironmentHelper.cs index 66379c020..6ff1ce84f 100644 --- a/Shared/Utilities/EnvironmentHelper.cs +++ b/Shared/Utilities/EnvironmentHelper.cs @@ -60,6 +60,8 @@ public static bool IsDebug public static bool IsWindows => OperatingSystem.IsWindows(); + public static bool Is64 => Environment.Is64BitProcess; + public static Platform Platform { get diff --git a/Utilities/Publish.ps1 b/Utilities/Publish.ps1 index ea183974e..ba8d554d7 100644 --- a/Utilities/Publish.ps1 +++ b/Utilities/Publish.ps1 @@ -116,23 +116,30 @@ if ((Test-Path -Path "$Root\Agent\bin\Release\net5.0\win10-x86\publish" ) -eq $ if ((Test-Path -Path "$Root\Agent\bin\Release\net5.0\linux-x64\publish") -eq $true) { Get-ChildItem -Path "$Root\Agent\bin\Release\net5.0\linux-x64\publish" | Remove-Item -Force -Recurse } +if ((Test-Path -Path "$Root\Agent\bin\Release\net5.0\linux-arm\publish") -eq $true) { + Get-ChildItem -Path "$Root\Agent\bin\Release\net5.0\linux-arm\publish" | Remove-Item -Force -Recurse +} # Publish Core clients. dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime win10-x64 --configuration Release --output "$Root\Agent\bin\Release\net5.0\win10-x64\publish" "$Root\Agent" dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime linux-x64 --configuration Release --output "$Root\Agent\bin\Release\net5.0\linux-x64\publish" "$Root\Agent" dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime win10-x86 --configuration Release --output "$Root\Agent\bin\Release\net5.0\win10-x86\publish" "$Root\Agent" +dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime linux-arm --configuration Release --output "$Root\Agent\bin\Release\net5.0\win10-x86\publish" "$Root\Agent" New-Item -Path "$Root\Agent\bin\Release\net5.0\win10-x64\publish\Desktop\" -ItemType Directory -Force New-Item -Path "$Root\Agent\bin\Release\net5.0\win10-x86\publish\Desktop\" -ItemType Directory -Force New-Item -Path "$Root\Agent\bin\Release\net5.0\linux-x64\publish\Desktop\" -ItemType Directory -Force +New-Item -Path "$Root\Agent\bin\Release\net5.0\linux-arm\publish\Desktop\" -ItemType Directory -Force # Publish Linux ScreenCaster dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion -p:PublishProfile=packaged-linux-x64 --configuration Release "$Root\Desktop.XPlat\" +dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion -p:PublishProfile=packaged-linux-arm --configuration Release "$Root\Desktop.XPlat\" # Publish Linux GUI App dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion -p:PublishProfile=desktop-linux-x64 --configuration Release "$Root\Desktop.XPlat\" +dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion -p:PublishProfile=desktop-linux-arm --configuration Release "$Root\Desktop.XPlat\" # Publish Windows ScreenCaster (32-bit) @@ -159,7 +166,7 @@ if ($SignAssemblies) { &"$Root\Utilities\signtool.exe" sign /f "$CertificatePath" /p $CertificatePassword /t http://timestamp.digicert.com "$Root\Server\wwwroot\Content\Win-x86\Remotely_Desktop.exe" } -# Build installer. +# Build installer (Windows). &"$MSBuildPath" "$Root\Agent.Installer.Win" /t:Restore &"$MSBuildPath" "$Root\Agent.Installer.Win" /t:Build /p:Configuration=Release /p:Platform=AnyCPU /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion Copy-Item -Path "$Root\Agent.Installer.Win\bin\Release\Remotely_Installer.exe" -Destination "$Root\Server\wwwroot\Content\Remotely_Installer.exe" -Force @@ -189,6 +196,13 @@ while ((Test-Path -Path "$PublishDir\Remotely-Linux.zip") -eq $false){ } Move-Item -Path "$PublishDir\Remotely-Linux.zip" -Destination "$Root\Server\wwwroot\Content\Remotely-Linux.zip" -Force +$PublishDir = "$Root\Agent\bin\Release\net5.0\linux-arm\publish" +Compress-Archive -Path "$PublishDir\*" -DestinationPath "$PublishDir\Remotely-Linux-arm.zip" -Force +while ((Test-Path -Path "$PublishDir\Remotely-Linux-arm.zip") -eq $false){ + Start-Sleep -Seconds 1 +} +Move-Item -Path "$PublishDir\Remotely-Linux-arm.zip" -Destination "$Root\Server\wwwroot\Content\Remotely-Linux-arm.zip" -Force + if ($RID.Length -gt 0 -and $OutDir.Length -gt 0) { From 550013a6cfb5256dace770f2e1cf411fde698125 Mon Sep 17 00:00:00 2001 From: Retschga Date: Sat, 1 Jan 2022 23:46:48 +0100 Subject: [PATCH 2/5] build fork --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f90e03106..b8ce8deca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -109,7 +109,7 @@ jobs: with: # Comment out the below 'repository' line if you want to build from # your fork instead of the author's. - repository: lucent-sea/Remotely + # repository: lucent-sea/Remotely fetch-depth: 0 # Test the Server URL to make sure it's valid From 1a065c866633d4b216fbe0a6a14006d326190fe4 Mon Sep 17 00:00:00 2001 From: Retschga Date: Sun, 2 Jan 2022 12:51:03 +0100 Subject: [PATCH 3/5] rpi agent --- .../PublishProfiles/desktop-linux-arm.pubxml | 19 +++++++++++++++++++ .../PublishProfiles/packaged-linux-arm.pubxml | 17 +++++++++++++++++ Server.Installer/Models/WebServerType.cs | 2 +- .../Resources/LinuxArm_Nginx_Install.sh | 19 +++++++------------ Server.Installer/Services/ServerInstaller.cs | 2 +- Server/Pages/Downloads.razor | 4 +++- Server/wwwroot/Content/Install-arm.sh | 15 +++++---------- 7 files changed, 53 insertions(+), 25 deletions(-) create mode 100644 Desktop.XPlat/Properties/PublishProfiles/desktop-linux-arm.pubxml create mode 100644 Desktop.XPlat/Properties/PublishProfiles/packaged-linux-arm.pubxml diff --git a/Desktop.XPlat/Properties/PublishProfiles/desktop-linux-arm.pubxml b/Desktop.XPlat/Properties/PublishProfiles/desktop-linux-arm.pubxml new file mode 100644 index 000000000..9ad02ee4f --- /dev/null +++ b/Desktop.XPlat/Properties/PublishProfiles/desktop-linux-arm.pubxml @@ -0,0 +1,19 @@ + + + + + FileSystem + Release + arm + net6.0 + ..\Server\wwwroot\Content\Linux-arm\ + linux-arm + true + True + False + true + true + + \ No newline at end of file diff --git a/Desktop.XPlat/Properties/PublishProfiles/packaged-linux-arm.pubxml b/Desktop.XPlat/Properties/PublishProfiles/packaged-linux-arm.pubxml new file mode 100644 index 000000000..94d882739 --- /dev/null +++ b/Desktop.XPlat/Properties/PublishProfiles/packaged-linux-arm.pubxml @@ -0,0 +1,17 @@ + + + + + FileSystem + Release + arm + net6.0 + ..\Agent\bin\Release\net6.0\linux-arm\publish\Desktop + linux-arm + true + False + False + + \ No newline at end of file diff --git a/Server.Installer/Models/WebServerType.cs b/Server.Installer/Models/WebServerType.cs index 23876cd51..309c5bdd6 100644 --- a/Server.Installer/Models/WebServerType.cs +++ b/Server.Installer/Models/WebServerType.cs @@ -14,7 +14,7 @@ public enum WebServerType UbuntuNginx, CentOsCaddy, CentOsNginx, - IisWindows3, + IisWindows, LinuxNginx } } diff --git a/Server.Installer/Resources/LinuxArm_Nginx_Install.sh b/Server.Installer/Resources/LinuxArm_Nginx_Install.sh index 6eae5b6cb..d811fc23e 100644 --- a/Server.Installer/Resources/LinuxArm_Nginx_Install.sh +++ b/Server.Installer/Resources/LinuxArm_Nginx_Install.sh @@ -36,18 +36,13 @@ apt-get -y install software-properties-common apt-get -y install gnupg # Install .NET Core Runtime. -wget -q https://packages.microsoft.com/config/ubuntu/$UbuntuVersion/packages-microsoft-prod.deb -dpkg -i packages-microsoft-prod.deb -add-apt-repository universe -apt-get update -apt-get -y install apt-transport-https -apt-get -y install aspnetcore-runtime-5.0 -rm packages-microsoft-prod.deb - -curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin -c 5.0 - +# Install .NET Core Runtime. +curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin -c 6.0 +echo 'export DOTNET_ROOT=$HOME/.dotnet' >> ~/.bashrc +echo 'export PATH=$PATH:$HOME/.dotnet' >> ~/.bashrc +source ~/.bashrc - # Install other prerequisites. +# Install other prerequisites. apt-get -y install unzip apt-get -y install acl apt-get -y install libc6-dev @@ -146,7 +141,7 @@ Description=Remotely Server [Service] WorkingDirectory=$AppRoot -ExecStart=/usr/bin/dotnet $AppRoot/Remotely_Server.dll +ExecStart=/home/pi/.dotnet/dotnet $AppRoot/Remotely_Server.dll Restart=always # Restart service after 10 seconds if the dotnet service crashes: RestartSec=10 diff --git a/Server.Installer/Services/ServerInstaller.cs b/Server.Installer/Services/ServerInstaller.cs index 51a963943..b3073cfe7 100644 --- a/Server.Installer/Services/ServerInstaller.cs +++ b/Server.Installer/Services/ServerInstaller.cs @@ -136,7 +136,7 @@ private async Task LaunchExternalInstaller(CliParams cliParams) WebServerType.CentOsCaddy => "CentOS_Caddy_Install.sh", WebServerType.CentOsNginx => "CentOS_Nginx_Install.sh", WebServerType.IisWindows => "IIS_Windows_Install.ps1", - WebServerType.LinuxNginx => "LinuxArm_Nginx_Install.ps1", + WebServerType.LinuxNginx => "LinuxArm_Nginx_Install.sh", _ => throw new Exception("Unrecognized reverse proxy type."), }; diff --git a/Server/Pages/Downloads.razor b/Server/Pages/Downloads.razor index d86c0b661..dfbc24025 100644 --- a/Server/Pages/Downloads.razor +++ b/Server/Pages/Downloads.razor @@ -186,12 +186,14 @@ Linux arm-32-Bit

linux-arm-32bit Bash Installer +
Linux Files Only

Example Install:
- sudo [path]/Install-arm.sh + sudo chmod +x [path]/Install-arm.sh + sudo [path]/./Install-arm.sh

Example Local Install:
diff --git a/Server/wwwroot/Content/Install-arm.sh b/Server/wwwroot/Content/Install-arm.sh index 9cf039c90..5588dde4d 100644 --- a/Server/wwwroot/Content/Install-arm.sh +++ b/Server/wwwroot/Content/Install-arm.sh @@ -23,13 +23,11 @@ done UbuntuVersion=$(lsb_release -r -s) -wget -q https://packages.microsoft.com/config/ubuntu/$UbuntuVersion/packages-microsoft-prod.deb -O packages-microsoft-prod.deb -dpkg -i packages-microsoft-prod.deb -apt-get update -apt-get -y install apt-transport-https -apt-get update -apt-get -y install dotnet-runtime-5.0 -rm packages-microsoft-prod.deb +# Install .NET Core Runtime. +curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin -c 6.0 +echo 'export DOTNET_ROOT=$HOME/.dotnet' >> ~/.bashrc +echo 'export PATH=$PATH:$HOME/.dotnet' >> ~/.bashrc +source ~/.bashrc apt-get -y install libx11-dev apt-get -y install libxrandr-dev @@ -44,9 +42,6 @@ apt-get -y install curl sudo curl -fsSL https://deb.nodesource.com/setup_17.x | bash - sudo apt install nodejs -curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin -c 5.0 - - if [ -f "/usr/local/bin/Remotely/ConnectionInfo.json" ]; then SavedGUID=`cat "/usr/local/bin/Remotely/ConnectionInfo.json" | jq -r '.DeviceID'` if [[ "$SavedGUID" != "null" && -n "$SavedGUID" ]]; then From c7d5d6875fa1ce3cc33e61576118cabcad9dbbd4 Mon Sep 17 00:00:00 2001 From: Retschga Date: Sun, 2 Jan 2022 14:11:29 +0100 Subject: [PATCH 4/5] enable dotnet 6 system drawing support --- Server/wwwroot/Content/Install-arm.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Server/wwwroot/Content/Install-arm.sh b/Server/wwwroot/Content/Install-arm.sh index 5588dde4d..94cda9a52 100644 --- a/Server/wwwroot/Content/Install-arm.sh +++ b/Server/wwwroot/Content/Install-arm.sh @@ -79,6 +79,16 @@ connectionInfo="{ echo "$connectionInfo" > ./ConnectionInfo.json +runtimeOptions="{ + \"runtimeOptions\": { + \"configProperties\": { + \"System.Drawing.EnableUnixSupport\": true + } + } +}" + +echo "$runtimeOptions" > ./Desktop/Remotely_Desktop.runtimeconfig.json + curl --head $HostName/Content/Remotely-Linux.zip | grep -i "etag" | cut -d' ' -f 2 > ./etag.txt echo Creating service... >> /tmp/Remotely_Install.log From cf8e302603e071c0b01620e66bf18aa3bc9b8ea6 Mon Sep 17 00:00:00 2001 From: Retschga Date: Sun, 2 Jan 2022 14:48:57 +0100 Subject: [PATCH 5/5] build upstream --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b8ce8deca..f90e03106 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -109,7 +109,7 @@ jobs: with: # Comment out the below 'repository' line if you want to build from # your fork instead of the author's. - # repository: lucent-sea/Remotely + repository: lucent-sea/Remotely fetch-depth: 0 # Test the Server URL to make sure it's valid