Headless RDP for Fun and Profit

This solution has been checked on Windows 2019 fully patched as-of spring 2022. Other Windows variations may require tweaks. Those on *nix-based platforms looking to create a headless connection to a Windows host should skip the Windows related initial instructions.


Some applications are just not suited to running as a Windows Services – indeed some applications, such as those which require a full Windows desktop context, cannot be run as a plain Windows Service. One of the possible ways to get around this limitation is to run them under a fully scripted remote desktop instance – the remote user receiving a standard Windows Desktop experience with all the pros and cons this entails – however the default client available on Windows does not allow such a headless connect. Fortunately, newer releases of Windows – including Windows 2019 and Windows 10 – are able to run several versions of Linux as applications.


Enable the Windows Subsystem for Linux (WSL) and Install Ubuntu 21.10

See the instructions here.

Update Ubuntu 20.10 to the latest version

Log into your WSL instance and run…

sudo apt update 
sudo apt upgrade

This will ensure your Ubuntu install is fully up to date.

Install the package ‘freerdp2-x11’

The ‘freerdp2-x11’ package can be installed with the following command.

sudo apt install freerdp2-x11

This install the ‘freerdp’ client. Details of this Ubuntu package can be found here.

Install the package ‘xvfb’

The ‘xvfb’ package can be installed with the following command.

sudo apt install xvfb

This installs the ‘xvfb’ server. Details of this Ubuntu package can be found here.

Create a ‘.bat’ to run the command

Create a ‘.bat’ file and add the following:

wsl bash xvfb-run -a xfreerdp /v:<host> /u:<user> /p:<password>

This command can be broken down thus..


This tells windows to run the following commands via the default linux install for the Windows Subsystem for Linux. In this example the default linux instance will be an Ubuntu instance.


Run the followings commands under the default bash environment for our instance of Ubuntu 21.10.

xvfb-run -a

Provides a self-configuring instance of the xvfb virtual framebuffer. This provides an xWindows server that xWindows clients can write to but that then discards the input it receives. In this function it is analogous to piping a command line program’s output to ‘/dev/null’. The ‘-a’ flag allows xvfb to automatically select an unused xWindows display number and thus adds a level of robustness in day to day use.


This the instance of the freerdp we will be using.


The target host. This can either be an IP address (such as or a dns entry.


The user account you are attempting to connect too.


The password for the remote user account.

Enable Remote Desktop for the target user.

See the instructions here. Ensure you are able to log in via the standard windows RDP client.

Run the Batch File

This will connect to the remote server. This batch file can now be used in a variety of situations.


There are several ways to run an application when a Window user logs into a new session. The easiest of these is to place a script (or a shortcut to a script) in the remote user’s ‘Startup’ directory. It is important to ensure that whatever method you choose ends the remote user’s session by logging the user out rather than just disconnecting the remote session. This is because a reconnection to a disconnected remote session will not trigger any programs or scripts placed in the user’s ‘Startup’ directory.


Freerdp is a flexible RDP client and has a multitude of options. Of all the options, the following three may be the most useful.


Allows the user’s authentication domain to be specified.


Forces the Freerdp client to ignore any certification errors with the connection.


Allows the connection’s resolution to be explicitly specified.

Other options that may be useful can be found below.

FreeRDP - A Free Remote Desktop Protocol Implementation
See www.freerdp.com for more information

Usage: xfreerdp [file] [options] [/v:<server>[:port]]

    /flag (enables flag)
    /option:<value> (specifies option with value)
    +toggle -toggle (enables or disables toggle, where '/' is a synonym of '+')

    /a:<addin>[,<options>]            Addin
    /action-script:<file-name>        Action script
    /admin                            Admin (or console) session
    +aero                             Enable desktop composition
    /app:<path> or ||<alias>          Remote application program
    /app-cmd:<parameters>             Remote application command-line parameters
    /app-file:<file-name>             File to open with remote application
    /app-guid:<app-guid>              Remote application GUID
    /app-icon:<icon-path>             Remote application icon for user interface
    /app-name:<app-name>              Remote application name for user interface
    /app-workdir:<workspace path>     Remote application workspace path
    /assistance:<password>            Remote assistance password
    /auto-request-control             Automatically request remote assistance
                                      input control
    +async-channels                   Enable Asynchronous channels
    +async-input                      Enable Asynchronous input
    +async-update                     Enable Asynchronous update
    /audio-mode:<mode>                Audio output mode
    +auth-only                        Enable Authenticate only
    -authentication                   Disable Authentication (experimental)
    +auto-reconnect                   Enable Automatic reconnection
                                      Automatic reconnection maximum retries, 0
                                      for unlimited [0,1000]
    +bitmap-cache                     Enable bitmap cache
    /bpp:<depth>                      Session bpp (color depth)
    /buildconfig                      Print the build configuration
    /cert:[deny,ignore,name:<name>,tofu,fingerprint:<hash>:<hash as hex>
          [,fingerprint:<hash>:<another hash>]]
                                      Certificate accept options. Use with care!
                                      * deny         ... Automatically abort
                                      connection if the certificate does not
                                      match, no user interaction.           *
                                      ignore       ... Ignore the certificate
                                      checks altogether (overrules all other
                                      options)                           * name 
                                             ... Use the alternate <name>
                                      instead of the certificate subject to
                                      match locally stored certificates * tofu  
                                            ... Accept certificate
                                      unconditionally on first connect and deny
                                      on subsequent connections if the
                                      certificate does not match * fingerprints
                                      ... A list of certificate hashes that are
                                      accepted unconditionally for a connection
    /cert-deny                        [deprecated, use /cert:deny] Automatically
                                      abort connection for any certificate that
                                      can not be validated.
    /cert-ignore                      [deprecated, use /cert:ignore] Ignore
    /cert-name:<name>                 [deprecated, use /cert:name:<name>]
                                      Certificate name
    /cert-tofu                        [deprecated, use /cert:tofu] Automatically
                                      accept certificate on first connect
    /client-build-number:<number>     Client Build Number sent to server
                                      (influences smartcard behaviour, see
    /client-hostname:<name>           Client Hostname to send to server
                                      Disable Redirect clipboard.                       
                                      * use-selection:<atom>  ... (X11) Specify
                                      which X selection to access. Default is
                                      CLIPBOARD. PRIMARY is the X-style
                                      middle-click selection.
    /codec-cache:[rfx|nsc|jpeg]       Bitmap codec cache
    -compression                      Disable compression
    /compression-level:<level>        Compression level (0,1,2)
    +credentials-delegation           Enable credentials delegation
    /d:<domain>                       Domain
    -decorations                      Disable Window decorations
    /disp                             Display control
    /drive:<name>,<path>              Redirect directory <path> as named share
                                      <name>. Hotplug support is enabled with
                                      /drive:hotplug,*. This argument provides
                                      the same function as "Drives that I plug
                                      in later" option in MSTSC.
    +drives                           Enable Redirect all mount points as shares
    /dvc:<channel>[,<options>]        Dynamic virtual channel
    /dynamic-resolution               Send resolution updates when the window is
    /echo                             Echo channel
    -encryption                       Disable Encryption (experimental)
                                      RDP standard security encryption methods
    /f                                Fullscreen mode (<Ctrl>+<Alt>+<Enter>
                                      toggles fullscreen)
    -fast-path                        Disable fast-path input/output
    +fipsmode                         Enable FIPS mode
                                      floatbar is disabled by default (when
                                      enabled defaults to sticky in fullscreen
    -fonts                            Disable smooth fonts (ClearType)
    /frame-ack:<number>               Number of frame acknowledgement
    /from-stdin[:force]               Read credentials from stdin. With <force>
                                      the prompt is done before connection,
                                      otherwise on server request.
    /g:<gateway>[:<port>]             Gateway Hostname
                                      Gateway usage method
    /gd:<domain>                      Gateway domain
    /gdi:sw|hw                        GDI rendering
    /geometry                         Geometry tracking channel
    +gestures                         Enable Consume multitouch input locally
    /gfx[:RFX]                        RDP8 graphics pipeline
    +gfx-progressive                  Enable RDP8 graphics pipeline using progressive
    +gfx-small-cache                  Enable RDP8 graphics pipeline using small cache
    +gfx-thin-client                  Enable RDP8 graphics pipeline using thin client
    +glyph-cache                      Enable Glyph cache (experimental)
    /gp:<password>                    Gateway password
    -grab-keyboard                    Disable Grab keyboard
                                      Gateway transport type
                                      Gateway username
    /gat:<access token>               Gateway Access Token
    /h:<height>                       Height
    -heartbeat                        Disable Support heartbeat PDUs
    /help                             Print help
    +home-drive                       Enable Redirect user home as share
    /ipv6                             Prefer IPv6 AAA record over IPv4 A record
    /jpeg                             JPEG codec support
    /jpeg-quality:<percentage>        JPEG quality
    /kbd:0x<id> or <name>             Keyboard layout
    /kbd-lang:0x<id>                  Keyboard active language identifier
    /kbd-fn-key:<value>               Function key value
    /kbd-list                         List keyboard layouts
    /kbd-lang-list                    List keyboard languages
    /kbd-remap:List of <key>=<value>,... pairs to remap scancodes
                                      Keyboard scancode remapping
    /kbd-subtype:<id>                 Keyboard subtype
    /kbd-type:<id>                    Keyboard type
    /load-balance-info:<info-string>  Load balance info
                                      Set logger filters, see wLog(7) for
                                      Set the default log level, see wLog(7) for
    /max-fast-path-size:<size>        Specify maximum fast-path update size
    /max-loop-time:<time>             Specify maximum time in milliseconds spend
                                      treating packets
    +menu-anims                       Enable menu animations
                 [channel:<channel>]] Audio input (microphone)
    /monitor-list                     List detected monitors
    /monitors:<id>[,<id>[,...]]       Select monitors to use
    -mouse-motion                     Disable Send mouse motion
    /multimon[:force]                 Use multiple monitors
    +multitouch                       Enable Redirect multitouch input
    +multitransport                   Enable Support multitransport protocol
    -nego                             Disable protocol security negotiation
                                      Network connection type
    /nsc                              NSCodec support
    +offscreen-cache                  Enable offscreen bitmap cache
    /orientation:[0|90|180|270]       Orientation of display in degrees
    +old-license                      Enable Use the old license workflow (no CAL and
                                      hwId set to 0)
    /p:<password>                     Password
    /parallel[:<name>[,<path>]]       Redirect parallel device
    /parent-window:<window-id>        Parent window id
    +password-is-pin                  Enable Use smart card authentication with
                                      password as smart card PIN
    /pcb:<blob>                       Preconnection Blob
    /pcid:<id>                        Preconnection Id
    /pheight:<height>                 Physical height of display (in
    /play-rfx:<pcap-file>             Replay rfx pcap file
    /port:<number>                    Server port
    -suppress-output                  Disable suppress output when minimized
    +print-reconnect-cookie           Enable Print base64 reconnect cookie after
    /printer[:<name>[,<driver>]]      Redirect printer device
                                      Proxy settings: override env. var (see
                                      also environment variable below). Protocol
                                      "socks5" should be given explicitly where
                                      "http" is default.
    /pth:<password-hash>              Pass the hash (restricted admin mode)
    /pwidth:<width>                   Physical width of display (in millimeters)
    /rdp2tcp:<executable path[:arg...]>
                                      TCP redirection
    /reconnect-cookie:<base64-cookie> Pass base64 reconnect cookie to the
                                      Override the preferred redirection order
    /relax-order-checks               Do not check if a RDP order was announced
                                      during capability exchange, only use when
                                      connecting to a buggy server
    /restricted-admin                 Restricted admin mode
    /rfx                              RemoteFX
    /rfx-mode:[image|video]           RemoteFX mode
    /scale:[100|140|180]              Scaling factor of the display
    /scale-desktop:<percentage>       Scaling factor for desktop applications
                                      (value between 100 and 500)
    /scale-device:100|140|180         Scaling factor for app store applications
    /sec:[rdp|tls|nla|ext]            Force specific protocol security
    +sec-ext                          Enable NLA extended protocol security
    -sec-nla                          Disable NLA protocol security
    -sec-rdp                          Disable RDP protocol security
    -sec-tls                          Disable TLS protocol security
                                      Redirect serial device
    /shell:<shell>                    Alternate shell
    /shell-dir:<dir>                  Shell working directory
    /size:<width>x<height> or <percent>%[wh]
                                      Screen size
    /smart-sizing[:<width>x<height>]  Scale remote desktop to window size
    /smartcard[:<str>[,<str>...]]     Redirect the smartcard devices containing
                                      any of the <str> in their names.
    /smartcard-logon                  Activates Smartcard Logon authentication.
                                      (EXPERIMENTAL: NLA not supported)
                                      Audio output (sound)
    /span                             Span screen over multiple monitors
    /spn-class:<service-class>        SPN authentication service class
    /ssh-agent                        SSH Agent forwarding channel
    /t:<title>                        Window title
    -themes                           Disable themes
    /timeout:<time in ms>             Advanced setting for high latency links:
                                      Adjust connection timeout, use if you
                                      encounter timeout failures with your
    /tls-ciphers:[netmon|ma|ciphers]  Allowed TLS ciphers
    /tls-seclevel:<level>             TLS security level - defaults to 1
    -toggle-fullscreen                Disable Alt+Ctrl+Enter to toggle
                                      [experimental] directly manipulate freerdp
                                      settings, use with extreme caution!
    /tune-list                        Print options allowed for /tune
    +unmap-buttons                    Enable Let server see real physical pointer
                                      Redirect USB device
    /v:<server>[:port]                Server hostname
    /vc:<channel>[,<options>]         Static virtual channel
    /version                          Print version
    /video                            Video optimized remoting channel
    /vmconnect[:<vmid>]               Hyper-V console (use port 2179, disable
    /w:<width>                        Width
    -wallpaper                        Disable wallpaper
    +window-drag                      Enable full window drag
    /window-position:<xpos>x<ypos>    window position
    /wm-class:<class-name>            Set the WM_CLASS hint for the window
    /workarea                         Use available work area

    xfreerdp connection.rdp /p:Pwd123! /f
    xfreerdp /u:CONTOSO\JohnDoe /p:Pwd123! /v:rdp.contoso.com
    xfreerdp /u:JohnDoe /p:Pwd123! /w:1366 /h:768 /v:
    xfreerdp /u:JohnDoe /p:Pwd123! /vmconnect:C824F53E-95D2-46C6-9A18-23A5BB403532 /v:

Clipboard Redirection: +clipboard

Drive Redirection: /drive:home,/home/user
Smartcard Redirection: /smartcard:<device>
Serial Port Redirection: /serial:<name>,<device>,[SerCx2|SerCx|Serial],[permissive]
Serial Port Redirection: /serial:COM1,/dev/ttyS0
Parallel Port Redirection: /parallel:<name>,<device>
Printer Redirection: /printer:<device>,<driver>
TCP redirection: /rdp2tcp:/usr/bin/rdp2tcp

Audio Output Redirection: /sound:sys:oss,dev:1,format:1
Audio Output Redirection: /sound:sys:alsa
Audio Input Redirection: /microphone:sys:oss,dev:1,format:1
Audio Input Redirection: /microphone:sys:alsa

Multimedia Redirection: /video
USB Device Redirection: /usb:id:054c:0268#4669:6e6b,addr:04:0c

For Gateways, the https_proxy environment variable is respected:
    export https_proxy=http://proxy.contoso.com:3128/
    xfreerdp /g:rdp.contoso.com ...

More documentation is coming, in the meantime consult source files