Remote Desktop: Difference between revisions
imported>MichaelCTS Add information about starting desktop sessions |
|||
(13 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
== | = Software = | ||
Remote desktop software is split into two types: servers and clients. | |||
To access a computer remotely, it must have a server running, which usually is exposed to a port or set thereof. Access to that server can be gained using a client; many protocols, like RDP, are open to all clients willing to support them. Others require specific clients, so consult the documentation for whichever service you choose to use. | |||
== | == Server Protocols == | ||
* VNC | |||
* XRDP | * XRDP | ||
=== Configuration === | |||
== Self hosting == | |||
* Rustdesk (nixpkgs: rustdesk-server) | |||
== Clients == | |||
* Apache Guacamole | |||
* freerdp | |||
* KRDC (KDE) | |||
* remmina | |||
* tightvnc and its forks tigervnc and turbovnc | |||
* x2goclient | |||
* GNOME Connections | |||
* RustDesk | |||
= Configuration = | |||
== VNC == | |||
Most servers provide a <code>vncserver</code> command. | Most servers provide a <code>vncserver</code> command. | ||
Various servers provide | Various servers provide configuration options either by CLI or by configuration file. | ||
==== Desktop session ==== | ==== Desktop session ==== | ||
To start a desktop session or window manager, one currently has to do this manually | To start a desktop session or window manager, one currently has to do this manually because servers still have hard-coded paths to <code>/usr/share/xsessions</code> to look for <code>.desktop</code> files. That means one has to write a script that starts the desktop session, window manager, or any other X application. | ||
Some servers will automatically run <code>$HOME/.vnc/xstartup</code> but the more secure option is to write an executable script and run <code>vncserver -xstartup $pathToScript</code> | |||
An example script | An example script: | ||
< | <syntaxhighlight lang="bash"> | ||
#!/usr/bin/env bash | #!/usr/bin/env bash | ||
Line 29: | Line 43: | ||
# start window manager | # start window manager | ||
exec icewm | exec icewm | ||
</ | </syntaxhighlight> | ||
<code>pathToScript</code> can also be a path to an executable like <code>${pkgs.icewm}/bin/icewm</code> | <code>pathToScript</code> can also be a path to an executable like <code>${pkgs.icewm}/bin/icewm</code> | ||
=== Tiger VNC === | === Tiger VNC === | ||
Line 40: | Line 51: | ||
Nixpkgs has a package but no service. | Nixpkgs has a package but no service. | ||
The server component can be started using the <code>vncserver</code> command. | The server component can be started using the <code>vncserver</code> command. | ||
To connect use the <code>vncviewer</code> command. | To connect, use the <code>vncviewer</code> command. | ||
=== x2go === | === x2go === | ||
Line 46: | Line 57: | ||
X2go client is packaged in nixos as <code>x2goclient</code>. | X2go client is packaged in nixos as <code>x2goclient</code>. | ||
The server is installed by | The server is installed by adding the following line:<br/> | ||
<code>services.x2goserver.enable = true;</code><br> | <code>services.x2goserver.enable = true;</code><br/> | ||
to /etc/nixos/configuration.nix. | to /etc/nixos/configuration.nix. | ||
=== | === Guacamole === | ||
==== Guacamole Server ==== | |||
In nixos the guacamole server component is provided by [https://github.com/NixOS/nixpkgs/blob/nixos-24.05/nixos/modules/services/web-apps/guacamole-server.nix guacamole-server] | |||
A basic server setup service entry would look like this: | |||
services.guacamole-server = { | |||
enable = true; | |||
host = "127.0.0.1"; | |||
port = 4822; | |||
userMappingXml = ./user-mapping.xml; | |||
}; | |||
This creates the <code>guacamole-server.service</code> systemd unit. | |||
See the [https://search.nixos.org/options?channel=24.05&from=0&size=50&sort=relevance&type=packages&query=services.guacamole-server search.nixos options] for other configuration options. | |||
The <code>host</code> entry indicates on which IP the server component listens. The <code>port</code> entry here is the default port of <code>4822</code>. | |||
The <code>./user-mapping.xml</code> is a relative path to the file which declares the service. So if the service is in <code>/etc/nixos/configuration.nix</code> then in this example the file would reside at <code>/etc/nixos/user-mapping.xml</code>. Contents of the file are discussed below. | |||
==== user-mapping.xml ==== | |||
The <code>user-mapping.xml</code> file is how to define the user(s) that are allowed to login to the webportal, as well as the connections available to the user. | |||
The file content should look something like this: | |||
<user-mapping> | |||
<authorize username="USERNAME_HERE" password="ENCRYPTED_PASSWORD_HERE" encoding="sha256"> | |||
<connection name="NAME_OF_THE_CONNECTION"> | |||
<protocol>rdp</protocol> | |||
<param name="hostname">XXX.XXX.XXX.XXX</param> | |||
<param name="port">3389</param> | |||
<param name="ignore-cert">true</param> | |||
</connection> | |||
<connection name="NAME_OF_THE_CONNECTION"> | |||
<protocol>ssh</protocol> | |||
<param name="hostname">XXX.XXX.XXX.XXX</param> | |||
<param name="port">22</param> | |||
</connection> | |||
</authorize> | |||
</user-mapping> | |||
The <code>password=""</code> can be a plain text password, but it is not recommended. An easy way to encrypt a password would be something like: | |||
$ echo -n 'SUPERsecretPASSWORD' | openssl dgst -sha256 | |||
SHA2-256(stdin)= 491cf91d586fb9442db7efe92b7839190206a653971573c23fed0435ceb596e8 | |||
The [https://guacamole.apache.org/doc/gug/configuring-guacamole.html#configuring-connections upstream documentation] has complete configuration options avaiable. | |||
==== Guacamole Client ==== | |||
In nixos the guacamole client component is provided by the [https://github.com/NixOS/nixpkgs/blob/nixos-24.05/nixos/modules/services/web-apps/guacamole-client.nix guacamole-client] component. | |||
This is the part of the service that provides the webportal for end users. | |||
< | A basic client setup service entry would look like this: | ||
services.guacamole-client = { | |||
enable = true; | |||
enableWebserver = true; | |||
settings = { | |||
guacd-port = 4822; | |||
guacd-hostname = "localhost"; | |||
}; | |||
}; | |||
This creates a <code>tomcat.service</code> systemd unit. | |||
See the [https://search.nixos.org/options?channel=24.05&from=0&size=50&sort=relevance&type=packages&query=services.guacamole-client search.nixos options] for other configuration options. | |||
The webportal this provides is served by the tomcat server, and listens on port <code>8080</code> by default. The <code>settings.guacd-port</code> tells the client software how to communicate with the guacamole-server component. | |||
The [https://guacamole.apache.org/doc/gug/configuring-guacamole.html#guacamole-properties upstream documentation] has the list of <code>guacamole.properties</code> options that can be provided for this setting. | |||
At this point if you are intending to serve the webportal directly, then the service can be reached at the url <code>http://<your-computer-ip:8080/guacamole</code>. | |||
==== Reverse Proxy ==== | |||
If you want to use <code>nginx</code> as a reverse proxy in front of the webportal, then the below options can serve as an example setup. | |||
This example has a virtual host available as <code>https://remote.mydomain.net</code>. It uses the [https://search.nixos.org/options?channel=24.05&from=0&size=50&sort=relevance&type=packages&query=services.nginx nginx] service, and [https://letsencrypt.org/ LetsEncrypt] for SSL. Configuration of a DNS domain and records is outside the scope of this document. | |||
services.nginx = { | |||
enable = true; | |||
upstreams."guacamole_server" = { | |||
extraConfig = '' | |||
keepalive 4; | |||
''; | |||
servers = { | |||
"127.0.0.1:8080" = {}; | |||
}; | |||
}; | |||
virtualHosts."remote.mydomain.net" = { | |||
forceSSL = true; # redirect http to https | |||
enableACME = true; | |||
locations."/" = { | |||
extraConfig = '' | |||
proxy_buffering off; | |||
proxy_set_header Upgrade $http_upgrade; | |||
proxy_set_header Connection $http_connection; | |||
proxy_set_header X-Real-IP $remote_addr; | |||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |||
proxy_set_header Host $host; | |||
proxy_set_header X-NginX-Proxy true; | |||
proxy_pass http://guacamole_server/guacamole$request_uri; | |||
proxy_redirect http://guacamole_server/ https://$server_name/; | |||
''; | |||
}; | |||
}; | |||
}; | |||
# this sets up the letsencrypt service to get ssl certs for the above | |||
security.acme = { | |||
acceptTerms = true; | |||
defaults.email = "your.email@server.name"; | |||
}; | |||
The <code>upstreams."guacamole_server".servers</code> setting points the to IP:port where the <code>guacamole-client</code> webportal is hosted. In this example <code>nginx</code> and <code>guacamole</code> are on the same host. | |||
The <code>virtualHosts."name".forceSSL</code> ensures requests sent to HTTP are redirected to HTTPS. The <code>enableACME</code> sets up LetsEncrypt and nginx to get and renew SSL certs. | |||
The <code>proxy_buffering off;</code>, <code>proxy_set_header Upgrade $http_upgrade;</code>, and <code>proxy_set_header Connection $http_connection;</code> settings are required to prevent nginx from buffering traffic, which can prevent guacamole from operating properly. | |||
The optional <code>proxy_pass http://guacamole_server/guacamole$request_uri;</code> allows end users to access the service at <code>https://remote.mydomain.net</code> as opposed to <code>https://remote.mydomain.net/guacamole</code>. | |||
See the [https://guacamole.apache.org/doc/gug/reverse-proxy.html# upstream documentation] for more details and other proxy examples. | |||
==== Firewall ==== | |||
In the case of the above reverse proxy example, the correct firewall ports will also need to be opened on the server hosting the <code>nginx</code> proxy. | |||
networking.firewall = { | |||
enable = true; | |||
allowedTCPPorts = [ | |||
80 # http | |||
443 # https | |||
8080 # guacamole | |||
4822 # guacamole | |||
]; | |||
}; | |||
For any systems that will be reached from the guacamole service, the corresponding ports will need to be opened. The below example opens ports that match the connection settings in the above <code>user-mapping.xml</code>. | |||
networking.firewall = { | |||
enable = true; | |||
allowedTCPPorts = [ | |||
22 # ssh | |||
3389 # rdp | |||
]; | |||
}; | |||
==== References ==== | |||
[https://github.com/NixOS/nixpkgs/issues/17879 The original package request has good discussions as well] | |||
== RDP == | |||
NixOS has first-class support for XRDP. Client-wise, RDP can be accessed in many ways, but `remmina` and `freerdp` support it natively. | |||
All of the options for the <code>xrdp</code> service can be viewed on the [https://search.nixos.org/options?channel=23.11&from=0&size=50&sort=relevance&type=packages&query=xrdp NixOS Options wiki], though an example setup inside of <code>configuration.nix</code> is provided below: | |||
<syntaxhighlight lang="nix"> | |||
services.xserver.enable = true; | services.xserver.enable = true; | ||
Line 63: | Line 230: | ||
services.xrdp.defaultWindowManager = "startplasma-x11"; | services.xrdp.defaultWindowManager = "startplasma-x11"; | ||
services.xrdp.openFirewall = true; | services.xrdp.openFirewall = true; | ||
</ | </syntaxhighlight> | ||
(Source: [https://discourse.nixos.org/t/please-post-working-xrdp-setting-in-configuration-nix/7404/10 Discourse Link], [https://github.com/NixOS/nixpkgs/blob/86a80807d8d7051c63ab2b9d7f630abe066468b1/nixos/modules/services/networking/xrdp.nix nixpkgs code]) | (Source: [https://discourse.nixos.org/t/please-post-working-xrdp-setting-in-configuration-nix/7404/10 Discourse Link], [https://github.com/NixOS/nixpkgs/blob/86a80807d8d7051c63ab2b9d7f630abe066468b1/nixos/modules/services/networking/xrdp.nix nixpkgs code]) | ||
A different window manager can be used for XRDP than a machine user, provided it has been enabled (through NixOS <code>services</code> or <code>nixpkgs</code>. | |||
Make sure you log out the visual user first on the remote machine, otherwise you'll get a black screen. (Source: [https://www.reddit.com/r/Proxmox/comments/hxp28j/black_screen_in_microsoft_remote_desktop_noob/fzm7zbo/ Reddit]). You may be able to work around this by enabling and configuring [[Polkit]], as demonstrated on that page. | |||
=== | === GNOME === | ||
[[File:Screenshot from 2024-03-02 03-15-05.png|thumb|right|GNOME running in an XRDP shell in Remmina.]] | |||
The XRDP <code>defaultWindowManager</code> setting to access a remote GNOME shell should be set to <code>gnome-remote-desktop</code>. Also ensure you include the package <code>pkgs.gnome.gnome-remote-desktop</code> in your configuration files and that you have a firewall port open for XRDP to communicate on (for the GNOME connections app, this is usually <code>3389</code>). | |||
=== Meshcentral === | |||
Meshcentral is a self-hosted open source administration tool similar to teamviewer. | Meshcentral is a self-hosted open source administration tool similar to teamviewer. | ||
It can be added with: | |||
<code>services.meshcentral.enable = true;</code> | <code>services.meshcentral.enable = true;</code> | ||
( | However, the agent (client) is not available. ([https://github.com/NixOS/nixpkgs/issues/167527 Request]) | ||
[[Category:Applications]] | |||
[[Category:Desktop]] | |||
[[Category:Server]] |
Latest revision as of 19:55, 5 October 2024
Software
Remote desktop software is split into two types: servers and clients. To access a computer remotely, it must have a server running, which usually is exposed to a port or set thereof. Access to that server can be gained using a client; many protocols, like RDP, are open to all clients willing to support them. Others require specific clients, so consult the documentation for whichever service you choose to use.
Server Protocols
- VNC
- XRDP
Self hosting
- Rustdesk (nixpkgs: rustdesk-server)
Clients
- Apache Guacamole
- freerdp
- KRDC (KDE)
- remmina
- tightvnc and its forks tigervnc and turbovnc
- x2goclient
- GNOME Connections
- RustDesk
Configuration
VNC
Most servers provide a vncserver
command.
Various servers provide configuration options either by CLI or by configuration file.
Desktop session
To start a desktop session or window manager, one currently has to do this manually because servers still have hard-coded paths to /usr/share/xsessions
to look for .desktop
files. That means one has to write a script that starts the desktop session, window manager, or any other X application.
Some servers will automatically run $HOME/.vnc/xstartup
but the more secure option is to write an executable script and run vncserver -xstartup $pathToScript
An example script:
#!/usr/bin/env bash
# set some env variables
# start window manager
exec icewm
pathToScript
can also be a path to an executable like ${pkgs.icewm}/bin/icewm
Tiger VNC
Nixpkgs has a package but no service.
The server component can be started using the vncserver
command.
To connect, use the vncviewer
command.
x2go
X2go client is packaged in nixos as x2goclient
.
The server is installed by adding the following line:
services.x2goserver.enable = true;
to /etc/nixos/configuration.nix.
Guacamole
Guacamole Server
In nixos the guacamole server component is provided by guacamole-server
A basic server setup service entry would look like this:
services.guacamole-server = { enable = true; host = "127.0.0.1"; port = 4822; userMappingXml = ./user-mapping.xml; };
This creates the guacamole-server.service
systemd unit.
See the search.nixos options for other configuration options.
The host
entry indicates on which IP the server component listens. The port
entry here is the default port of 4822
.
The ./user-mapping.xml
is a relative path to the file which declares the service. So if the service is in /etc/nixos/configuration.nix
then in this example the file would reside at /etc/nixos/user-mapping.xml
. Contents of the file are discussed below.
user-mapping.xml
The user-mapping.xml
file is how to define the user(s) that are allowed to login to the webportal, as well as the connections available to the user.
The file content should look something like this:
<user-mapping> <authorize username="USERNAME_HERE" password="ENCRYPTED_PASSWORD_HERE" encoding="sha256"> <connection name="NAME_OF_THE_CONNECTION"> <protocol>rdp</protocol> <param name="hostname">XXX.XXX.XXX.XXX</param> <param name="port">3389</param> <param name="ignore-cert">true</param> </connection> <connection name="NAME_OF_THE_CONNECTION"> <protocol>ssh</protocol> <param name="hostname">XXX.XXX.XXX.XXX</param> <param name="port">22</param> </connection> </authorize> </user-mapping>
The password=""
can be a plain text password, but it is not recommended. An easy way to encrypt a password would be something like:
$ echo -n 'SUPERsecretPASSWORD' | openssl dgst -sha256 SHA2-256(stdin)= 491cf91d586fb9442db7efe92b7839190206a653971573c23fed0435ceb596e8
The upstream documentation has complete configuration options avaiable.
Guacamole Client
In nixos the guacamole client component is provided by the guacamole-client component.
This is the part of the service that provides the webportal for end users.
A basic client setup service entry would look like this:
services.guacamole-client = { enable = true; enableWebserver = true; settings = { guacd-port = 4822; guacd-hostname = "localhost"; }; };
This creates a tomcat.service
systemd unit.
See the search.nixos options for other configuration options.
The webportal this provides is served by the tomcat server, and listens on port 8080
by default. The settings.guacd-port
tells the client software how to communicate with the guacamole-server component.
The upstream documentation has the list of guacamole.properties
options that can be provided for this setting.
At this point if you are intending to serve the webportal directly, then the service can be reached at the url http://<your-computer-ip:8080/guacamole
.
Reverse Proxy
If you want to use nginx
as a reverse proxy in front of the webportal, then the below options can serve as an example setup.
This example has a virtual host available as https://remote.mydomain.net
. It uses the nginx service, and LetsEncrypt for SSL. Configuration of a DNS domain and records is outside the scope of this document.
services.nginx = { enable = true; upstreams."guacamole_server" = { extraConfig = keepalive 4; ; servers = { "127.0.0.1:8080" = {}; }; }; virtualHosts."remote.mydomain.net" = { forceSSL = true; # redirect http to https enableACME = true; locations."/" = { extraConfig = proxy_buffering off; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header X-NginX-Proxy true; proxy_pass http://guacamole_server/guacamole$request_uri; proxy_redirect http://guacamole_server/ https://$server_name/; ; }; }; }; # this sets up the letsencrypt service to get ssl certs for the above security.acme = { acceptTerms = true; defaults.email = "your.email@server.name"; };
The upstreams."guacamole_server".servers
setting points the to IP:port where the guacamole-client
webportal is hosted. In this example nginx
and guacamole
are on the same host.
The virtualHosts."name".forceSSL
ensures requests sent to HTTP are redirected to HTTPS. The enableACME
sets up LetsEncrypt and nginx to get and renew SSL certs.
The proxy_buffering off;
, proxy_set_header Upgrade $http_upgrade;
, and proxy_set_header Connection $http_connection;
settings are required to prevent nginx from buffering traffic, which can prevent guacamole from operating properly.
The optional proxy_pass http://guacamole_server/guacamole$request_uri;
allows end users to access the service at https://remote.mydomain.net
as opposed to https://remote.mydomain.net/guacamole
.
See the upstream documentation for more details and other proxy examples.
Firewall
In the case of the above reverse proxy example, the correct firewall ports will also need to be opened on the server hosting the nginx
proxy.
networking.firewall = { enable = true; allowedTCPPorts = [ 80 # http 443 # https 8080 # guacamole 4822 # guacamole ]; };
For any systems that will be reached from the guacamole service, the corresponding ports will need to be opened. The below example opens ports that match the connection settings in the above user-mapping.xml
.
networking.firewall = { enable = true; allowedTCPPorts = [ 22 # ssh 3389 # rdp ]; };
References
The original package request has good discussions as well
RDP
NixOS has first-class support for XRDP. Client-wise, RDP can be accessed in many ways, but `remmina` and `freerdp` support it natively.
All of the options for the xrdp
service can be viewed on the NixOS Options wiki, though an example setup inside of configuration.nix
is provided below:
services.xserver.enable = true;
services.xserver.displayManager.sddm.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
services.xrdp.enable = true;
services.xrdp.defaultWindowManager = "startplasma-x11";
services.xrdp.openFirewall = true;
(Source: Discourse Link, nixpkgs code)
A different window manager can be used for XRDP than a machine user, provided it has been enabled (through NixOS services
or nixpkgs
.
Make sure you log out the visual user first on the remote machine, otherwise you'll get a black screen. (Source: Reddit). You may be able to work around this by enabling and configuring Polkit, as demonstrated on that page.
GNOME
The XRDP defaultWindowManager
setting to access a remote GNOME shell should be set to gnome-remote-desktop
. Also ensure you include the package pkgs.gnome.gnome-remote-desktop
in your configuration files and that you have a firewall port open for XRDP to communicate on (for the GNOME connections app, this is usually 3389
).
Meshcentral
Meshcentral is a self-hosted open source administration tool similar to teamviewer. It can be added with:
services.meshcentral.enable = true;
However, the agent (client) is not available. (Request)