You have a Fedora Workstation sitting under a desk and a laptop somewhere else that speaks RDP. GNOME Remote Desktop is the piece that ties them together, and it can do it two ways: Remote Login hands the laptop a fresh GNOME session behind the login screen, even when nobody is signed in at the machine, while Desktop Sharing mirrors the session someone already has open on the monitor. They keep separate certificates and password stores, and they fight over the same default port when both run. That’s where most failed connections come from.
This guide wires up both on Fedora with grdctl and GNOME Settings, connects a FreeRDP client to each, and walks through what happens when you disconnect, lock the screen or log in twice. We confirmed the whole setup working in October 2026 on Fedora 45 Workstation with GNOME 51 and gnome-remote-desktop 51.0, connecting from FreeRDP 3.32 on a second Fedora machine.
Choose Remote Login or Desktop Sharing
Pick Remote Login for a headless box or any machine you reach while nobody sits at it, and Desktop Sharing when you want to see and drive the screen a person is already using. Both come in the gnome-remote-desktop package that Workstation installs by default. The choice is only about which service you turn on. This is how the two behaved on our Fedora workstation.
| Item | Remote Login | Desktop Sharing |
|---|---|---|
| What the client gets | The GDM login screen, then its own headless session | The session already open on the monitor |
| Configured with | grdctl --system as root | grdctl as the logged-in user |
| Service | system unit gnome-remote-desktop.service | user unit gnome-remote-desktop.service |
| Port on our box | 3389 | 3390, because Remote Login already held 3389 |
| Where the password lives | TPM, or a key file readable only by the gnome-remote-desktop user when there is no TPM | The user’s GNOME login keyring |
| Screen resolution | Set by the client | Whatever the local monitor uses |
Remote Login is the one most people mean when they ask how to RDP into a Fedora box, because it works with the machine sitting at the login screen and survives the client disconnecting. Desktop Sharing is closer to a screen-sharing tool for support calls. You can run both at once, as we did, and the port table above is the reason that works without a clash.
Check the workstation and the client
Confirm the server side first, because a Fedora Server or a trimmed install may not have the remote desktop daemon. Our workstation was a standard Workstation install, done the way our Fedora 45 install guide shows. On our Workstation install the package came with the edition and its system unit sat disabled until we turned it on.
rpm -q gnome-remote-desktop gnome-shell gdm
systemctl is-enabled gnome-remote-desktop.service
Ours printed gnome-remote-desktop-51.0-1.fc45.x86_64 next to the matching GNOME Shell and GDM builds, and the unit read disabled. If the package is missing, sudo dnf install gnome-remote-desktop adds it, but on Fedora Server that is not enough: Remote Login hands clients to GDM and a GNOME session, so a Server install needs the GNOME desktop added and gdm.service enabled first. On the client side we tested FreeRDP on Linux; Microsoft’s Remote Desktop Connection on Windows and its Windows App on macOS are the usual choices there, but we did not test them.
Enable Remote Login from the command line
Remote Login needs three things before it will answer a client, and we set them up in this order:
- Generate a TLS certificate and key owned by the
gnome-remote-desktopuser. - Store a gate username and password with
grdctl --system. - Enable RDP and start the system service.
The certificate has to belong to the gnome-remote-desktop system user, because the daemon runs as that account and reads its files from /var/lib/gnome-remote-desktop. Our Workstation had no winpr-makecert tool, so we generated the pair with openssl, the way the upstream configuration docs show. Replace ws01 with your own hostname.
sudo -u gnome-remote-desktop sh -c 'mkdir -p ~/.local/share/gnome-remote-desktop && openssl req -new -newkey rsa:4096 -days 720 -nodes -x509 -subj /CN=ws01 -out ~/.local/share/gnome-remote-desktop/tls.crt -keyout ~/.local/share/gnome-remote-desktop/tls.key'
Point the daemon at both files. These paths are where the command above put them, under the service account’s home directory. The certificate is valid for 720 days, so put a reminder in to regenerate it before then.
sudo grdctl --system rdp set-tls-key /var/lib/gnome-remote-desktop/.local/share/gnome-remote-desktop/tls.key
sudo grdctl --system rdp set-tls-cert /var/lib/gnome-remote-desktop/.local/share/gnome-remote-desktop/tls.crt
Next comes the gate account. It is not a Linux user; it only lets the client through to the login screen, where each person still signs in with their own account. Run set-credentials with no arguments, so it asks for the username and password itself.
sudo grdctl --system rdp set-credentials
It prompted for Username: and then a hidden Password:, and we used rdpgate as the name. Don’t pass the two values as arguments instead. We tried that first, and both sudo and pkexec, which grdctl --system uses to run as the service account, wrote the full command line, password included, to the system journal. With the prompt form the journal only showed grdctl rdp set-credentials.
Every one of these grdctl --system calls printed “Init TPM credentials failed because No TPM device found, using GKeyFile as fallback” on our VM, which had no virtual TPM. That line matters more than it looks. Without a TPM, the gate password went into credentials.ini under the service’s home in plain text, in a file only the gnome-remote-desktop user and root can read. We did not test a machine with a TPM, where the daemon tries to keep the credentials in the TPM; if that matters to you, a VM can get a virtual TPM, and our TPM on KVM guide shows how to add one.
Now enable RDP and start the system service. GDM has to be running too, because the client is handed to the login screen, but on Workstation it already is.
sudo grdctl --system rdp enable
sudo systemctl enable --now gnome-remote-desktop.service
Check the result with sudo grdctl --system status and look at what is listening. Ours reported the unit active, RDP enabled on 3389 with the certificate and key paths filled in, and hid the gate credentials. The daemon journal ended with “RDP server started”.

Note the TLS fingerprint in that output. Your client shows the same value the first time it connects, and comparing the two is how you know nobody is sitting in the middle of the connection.
The same switch exists in GNOME Settings under System, Remote Desktop, on the Remote Login tab. The panel is locked until you click Unlock and enter an administrator password, and once we had enabled the service with grdctl, the tab showed Remote Login switched on with the hostname and port 3389 filled in.

Settings and grdctl write the same configuration, so use whichever suits the machine. On a headless box you only have the command line, and that is why this guide leads with it.
Open the firewall only where it’s closed
On Fedora Workstation you don’t need a firewall change at all. The default FedoraWorkstation zone opens TCP and UDP ports 1025 to 65535, and 3389 sits inside that range, so our client reached the port the moment the service started. That’s convenient on a home network. On any other, remember that every machine on the LAN can reach the RDP port too.
Fedora Server and other zones that don’t open the high ports need the rdp service, which firewalld defines as 3389/tcp. The gnome-remote-desktop README gives the same two commands. The service only covers 3389, so add --add-port=3390/tcp as well if you run Desktop Sharing next to Remote Login.
sudo firewall-cmd --permanent --add-service=rdp
sudo firewall-cmd --reload
To go the other way on Workstation and let only one admin machine in, add a rich rule that rejects 3389 from everyone else. Rich rules that reject are checked before the zone’s open port range, which is why this works even though 3389 is otherwise allowed. Put your client’s address in place of 10.0.1.126.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source NOT address="10.0.1.126" port port="3389" protocol="tcp" reject'
sudo firewall-cmd --reload
With the rule in place our client at that address still connected, while another machine on the same LAN got “Connection refused” from nc -zv on port 3389. Add a second rule for 3390 if you also turn on Desktop Sharing. The rule above is IPv4 only, and the daemon listens on IPv6 too, so on a network with IPv6 add the same rule with family="ipv6" and your client’s stable IPv6 address or its /64 prefix, since privacy addresses rotate. The firewalld on Fedora guide covers zones and rich rules in more depth.
Connect from an RDP client
Point the client at the workstation with the gate credentials, not your own login. Check the certificate before you trust it: run FreeRDP once without any /cert option and it refuses the self-signed certificate, but prints its details first.
xfreerdp /v:10.0.1.113 /u:rdpgate /from-stdin:force
Ours printed a “Certificate details” block with the common name, the validity dates and a Thumbprint: line, then aborted with “certificate not trusted”. That thumbprint matched the TLS fingerprint grdctl --system status showed on the workstation. Once they match, connect for real and let FreeRDP store the certificate.
xfreerdp /v:10.0.1.113 /u:rdpgate /from-stdin:force /cert:tofu /size:1440x900
The /from-stdin:force flag makes FreeRDP ask for the password, and then a domain, before it connects, so the password never appears in the process list or your shell history. Press Enter at the Domain: prompt. The /cert:tofu flag trusts the certificate on first use and saves it as ~/.config/freerdp/server/10.0.1.113_3389.pem. On that first connection current FreeRDP prints two loud banners. “CERTIFICATE NAME MISMATCH” appears because we connected by IP while the certificate names ws01, so connect by hostname if your DNS resolves it. “REMOTE HOST IDENTIFICATION HAS CHANGED” follows, then the log says “No certificate stored, automatically accepting”, so read past both banners to that line. The /size flag sets the resolution of the new session, because Remote Login builds a fresh desktop at whatever size the client asks for. The request goes from the client to the gate, the gate hands it to GDM, and what came up was the normal Fedora login screen.

Sign in there with your normal Fedora account. On a first login GNOME starts its welcome tour, and in our session a polkit prompt also asked for an administrator password to update firmware metadata, which you can cancel. On the server, loginctl show-session listed the new session as Type=wayland, Remote=yes and no seat, so it runs alongside the physical console instead of taking it over. Now the laptop is driving its own Fedora desktop end to end, with the monitor on the workstation still showing the login screen.
Test disconnect, lock and a second login
We ran three checks against a live Remote Login session, because each one changes how you can use it day to day:
- Close the client and reconnect.
- Leave the session idle until the screen locks.
- Sign in remotely as a user who is already logged in at the console.
Closing the client does not log you out. We stopped FreeRDP, waited 20 seconds and checked loginctl: the session was still there. Reconnecting brought back the GDM screen, and after signing in again we landed in the same session, with the Settings window we had left open still on screen. That makes Remote Login safe to drop and pick up, but it also means a session you never log out of keeps running on the workstation.
The screen lock behaves the same way. After a few idle minutes the remote session locked itself while the client stayed connected, and typing the account password inside the RDP window unlocked it. Desktop Sharing is different here, because upstream documents that locking the screen ends a sharing connection.
The one rule that surprised us: Remote Login will not open a second session for someone already logged in at the console. With Eugene signed in locally, signing in as the same user over RDP stopped on a “Session Already Running” dialog.

Force Stop ends the local session and everything running in it, as the dialog warns, so treat it like pulling the power on that user’s apps. If the person at the console needs to stay, use Desktop Sharing to look at their screen instead, or sign in remotely as a different account.
Enable Desktop Sharing for a logged-in session
Desktop Sharing is configured by the user who owns the session, without sudo, and its settings live in that user’s home directory and keyring. Settings has the same switches under System, Remote Desktop, Desktop Sharing, with toggles for Desktop Sharing and Remote Control. We set it up from a terminal so every step shows, and the commands mirror the system setup with the user’s own paths.
mkdir -p ~/.local/share/gnome-remote-desktop
openssl req -new -newkey rsa:4096 -days 720 -nodes -x509 -subj /CN=ws01 -out ~/.local/share/gnome-remote-desktop/tls.crt -keyout ~/.local/share/gnome-remote-desktop/tls.key
grdctl rdp set-tls-key ~/.local/share/gnome-remote-desktop/tls.key
grdctl rdp set-tls-cert ~/.local/share/gnome-remote-desktop/tls.crt
Both of those commands printed “RDP server certificate is invalid” on our box, because no certificate was stored yet when grdctl started, and grdctl status ran without the warning once both were set. Then store the credentials, allow remote control instead of view-only, and start the user service.
grdctl rdp set-credentials
grdctl rdp enable
grdctl rdp disable-view-only
systemctl --user enable --now gnome-remote-desktop.service
The set-credentials step prompts for a username and password, as the system version does, and it is the one that can hang. These credentials go into the GNOME login keyring, and on our workstation, which logs Eugene in automatically, that keyring was still locked. The command sat waiting until we killed it after 20 seconds, while the monitor showed an unlock prompt nobody was there to answer.

Automatic login skips the password that normally unlocks the keyring, so anything stored there is out of reach until someone types it. Once we unlocked the keyring at the console, set-credentials returned straight away and grdctl status showed the username and password as hidden. For a machine that has to accept Desktop Sharing unattended, don’t rely on automatic login; use Remote Login, whose credentials don’t touch the user keyring.
With Remote Login already on 3389, grdctl status still printed “Port: 3389” for Desktop Sharing, but ss -tlnp showed the user daemon listening on 3390. The status line is the configured port, and with “Negotiate port: yes” the daemon took the next free one. Without Remote Login running it stays on 3389. Connect to whichever port ss shows, with the username and password you just stored; ours was eugene on 3390.
xfreerdp /v:10.0.1.113:3390 /u:eugene /from-stdin:force /cert:tofu
The client showed the console session at the console’s 1024×768 resolution, which is what Settings means by “the remote connection uses the existing screen resolution”. The orange sharing indicator in the top bar tells the person at the machine that someone is connected.

FreeRDP stores certificates per host and port, so it treated 3390 as a new server and saved a second file, 10.0.1.113_3390.pem, next to the first. Desktop Sharing presents the user’s own certificate, with a different fingerprint from Remote Login, so check it against grdctl status in the session the same way before the first /cert:tofu connection.
Sharing also depends on the console being unlocked. Our first attempt connected while the console had locked itself after idling, and the server ended it at once with ERRINFO_LOGOFF_BY_USER. After we unlocked the console the same command stayed connected, which matches upstream’s note that locking the screen closes a sharing connection.
Disable remote access
Each mode is switched off in its own scope, so disable both if you set up both. The system side stops Remote Login, and the user side stops Desktop Sharing.
sudo grdctl --system rdp disable
sudo systemctl disable --now gnome-remote-desktop.service
grdctl rdp disable
systemctl --user disable --now gnome-remote-desktop.service
After the first two commands ss still showed 3390 open, because the user daemon is a separate process, and only after the last two did nothing listen on either port. Two things stay behind. The gate password is still in credentials.ini on a machine without a TPM, and grdctl has a clear-credentials subcommand for each scope that removes it. Any firewall rules you added also stay until you remove them.
sudo grdctl --system rdp clear-credentials
grdctl rdp clear-credentials
sudo firewall-cmd --permanent --remove-service=rdp
sudo firewall-cmd --reload
Use --remove-rich-rule with the exact rule text instead of --remove-service if you restricted access on Workstation rather than opening the service. firewall-cmd --list-all afterwards should show neither.
Check the RDP link when it fails
Most problems sit on one link in the chain from client to gate to session, and the symptom usually says which one. These are the ones we hit while wiring this up.
grdctl rdp set-credentials hangs after the prompt
The login keyring is locked, usually because the user was signed in automatically. We saw the hang while passing the credentials as arguments, before we switched to the prompt form, and both store them in the same keyring. Unlock it from the prompt on the monitor, or sign out and back in with a password, and run the command again. Over SSH, as that user, this property read returned b true for us before the unlock and b false after.
busctl --user get-property org.freedesktop.secrets /org/freedesktop/secrets/collection/login org.freedesktop.Secret.Collection Locked
If it reads b false and the command still hangs, look at the monitor for another prompt before you look anywhere else.
“RDP server certificate is invalid”
You’ll see this from user-mode grdctl commands before a certificate is stored, including the two that store it, and it’s harmless at that stage. Run grdctl status after setting both: if the warning is gone and the TLS fingerprint line shows a value, the pair is in place.
ERRCONNECT_LOGON_FAILURE after changing the gate password
The running Remote Login daemon kept using the old gate password on our box. We changed it with set-credentials while the service was up, and every client login failed with ERRCONNECT_LOGON_FAILURE even though the new value was on disk. Restarting the service fixed it on the next try.
sudo systemctl restart gnome-remote-desktop.service
We did not test what a restart does to clients that are already connected, so change the gate password while nobody is using the box.
“Session Already Running” after the login screen
That user has a local session at the console. Log it out at the machine, sign in remotely as someone else, or use Force Stop if losing that session’s open apps is acceptable. Desktop Sharing is the mode built for joining a session that is already running.
Remote desktop is one item on our list of things to set up after installing Fedora 45. For other ways into the same box, our SSH server on Fedora guide covers the command-line path. Upstream’s GNOME Remote Desktop configuration notes describe the headless single-user mode we didn’t cover here.