February 25, 2026
๐ Full Ubuntu Desktop in Browser on AWS Ubuntu 24.04 with Guacamole
Have you ever wanted a full desktop experience on your cloud server, accessible entirely via your browser? Today, Iโll show you how to setโฆ
Arjun Dandagi
4 min read
Have you ever wanted a full desktop experience on your cloud server, accessible entirely via your browser? Today, I'll show you how to set up a full Ubuntu 24.04 desktop, run it with XRDP, and expose it via Apache Guacamole โ all inside Docker containers. This allows browser-based, clientless remote desktop access.
Step 1: Launch an Ubuntu 24.04 Server on AWS
- Create a t3.medium instance (2 vCPUs, 4GB RAM recommended) for smooth desktop performance.
- Open ports 22 (SSH) and 8080 (HTTP) in your security group.
Step 2: Update System and Install Docker
# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
sudo systemctl start docker# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
sudo systemctl start dockerdocker.ioinstalls Docker engine.docker-composeallows us to orchestrate multiple containers.
Step 3: Install Full Ubuntu Desktop
Inside your server:
sudo apt install -y ubuntu-desktop gnome-session gdm3
sudo apt install -y dbus-x11 gnome-shell gnome-session ubuntu-session libcanberra-gtk-module libcanberra-gtk3-modulesudo apt install -y ubuntu-desktop gnome-session gdm3
sudo apt install -y dbus-x11 gnome-shell gnome-session ubuntu-session libcanberra-gtk-module libcanberra-gtk3-module- Installs the full GNOME desktop environment.
- Required for XRDP to provide a proper GUI session.
Note: GNOME is heavy; for lighter and faster browser RDP, you can replace with
ubuntu-mate-desktoporcinnamon-desktop-environment.
Step 4: Install XRDP
sudo apt install -y xrdp
sudo systemctl enable xrdp
sudo systemctl start xrdp
sudo adduser xrdp ssl-certsudo apt install -y xrdp
sudo systemctl enable xrdp
sudo systemctl start xrdp
sudo adduser xrdp ssl-certxrdpallows RDP connections to your desktop session.ssl-certgroup ensures proper permissions.
Disable Wayland (required for XRDP):
sudo sed -i 's/#WaylandEnable=false/WaylandEnable=false/' /etc/gdm3/custom.conf
sudo systemctl restart gdm3sudo sed -i 's/#WaylandEnable=false/WaylandEnable=false/' /etc/gdm3/custom.conf
sudo systemctl restart gdm3Step 5: Create a Docker-based Guacamole Stack
Create a directory for your Docker setup:
mkdir ~/guac && cd ~/guacmkdir ~/guac && cd ~/guacCreate a docker-compose.yml:
version: '3'
services:
guacd:
image: guacamole/guacd:latest
restart: unless-stopped
guacamole:
image: guacamole/guacamole:latest
restart: unless-stopped
ports:
- "8080:8080"
environment:
GUACD_HOSTNAME: guacd
GUACAMOLE_HOME: /etc/guacamole
volumes:
- ./config:/etc/guacamole
depends_on:
- guacdversion: '3'
services:
guacd:
image: guacamole/guacd:latest
restart: unless-stopped
guacamole:
image: guacamole/guacamole:latest
restart: unless-stopped
ports:
- "8080:8080"
environment:
GUACD_HOSTNAME: guacd
GUACAMOLE_HOME: /etc/guacamole
volumes:
- ./config:/etc/guacamole
depends_on:
- guacdStep 6: Configure Guacamole User
Create configuration directory:
mkdir -p config
vi config/user-mapping.xmlmkdir -p config
vi config/user-mapping.xmlPaste the following (replace with your Linux username/password):
<user-mapping>
<authorize username="guacadmin" password="guacadmin">
<connection name="Ubuntu Desktop">
<protocol>rdp</protocol>
<param name="hostname">172.17.0.1</param>
<param name="port">3389</param>
<param name="username">YOUR_LINUX_USERNAME</param>
<param name="password">YOUR_LINUX_PASSWORD</param>
</connection>
</authorize>
</user-mapping><user-mapping>
<authorize username="guacadmin" password="guacadmin">
<connection name="Ubuntu Desktop">
<protocol>rdp</protocol>
<param name="hostname">172.17.0.1</param>
<param name="port">3389</param>
<param name="username">YOUR_LINUX_USERNAME</param>
<param name="password">YOUR_LINUX_PASSWORD</param>
</connection>
</authorize>
</user-mapping>guacadmin / guacadminis web login.YOUR_LINUX_USERNAME/PASSWORDare your Ubuntu credentials for XRDP.- Since AWS ubuntu ssh is based on pem , you might have to create a password for this user ,
sudo passwd ubuntuis the trick to do that ๐
Step 7: Start Guacamole Stack
docker compose up -ddocker compose up -dguacdacts as a RDP proxy daemon.- Guacamole web runs on http://YOUR_SERVER_IP:8080/guacamole.
Step 8: Connect from Browser
- Open http://YOUR_SERVER_IP:8080/guacamole
- Login with:
Username: guacadmin
Password: guacadminUsername: guacadmin
Password: guacadminClick the "Ubuntu Desktop" connection โ full Ubuntu desktop loads in your browser.
โ Single-Shot Script for a Fresh Ubuntu 24.04 Server
Copy-paste this on a bare Ubuntu 24.04 server:
#download the script and run it OR see the entire script in next code block and adjust it
wget https://gist.githubusercontent.com/ArjunDandagi/d48cff36a062e18201f37fa90d9bdad7/raw/a12365d23205dd4958eb1122a2c19750594b345d/ubuntu-desktop.sh
bash ubuntu-desktop.sh
#!/bin/bash
# set up locale with US so installation goes without user input
export DEBIAN_FRONTEND=noninteractive
sudo apt install -y locales
sudo locale-gen en_US.UTF-8
sudo update-locale LANG=en_US.UTF-8
echo 'locales locales/default_environment_locale select en_US.UTF-8' | sudo debconf-set-selections
echo 'locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8' | sudo debconf-set-selections
echo 'keyboard-configuration keyboard-configuration/layoutcode string us' | sudo debconf-set-selections
echo 'keyboard-configuration keyboard-configuration/modelcode string pc105' | sudo debconf-set-selections
echo 'keyboard-configuration keyboard-configuration/variantcode string' | sudo debconf-set-selections
sudo apt install -y keyboard-configuration
echo "gdm3 shared/default-x-display-manager select gdm3" | sudo debconf-set-selections
# Full Desktop + XRDP + Guacamole on Ubuntu 24.04
set -e
# Update
sudo apt update -y && sudo apt upgrade -y
# Install desktop and XRDP
sudo apt install -y ubuntu-desktop gnome-session gdm3 xrdp
sudo apt install -y dbus-x11 gnome-shell gnome-session ubuntu-session libcanberra-gtk-module libcanberra-gtk3-module
sudo apt install -y pipewire-module-xrdp
sudo systemctl enable xrdp
sudo systemctl start xrdp
sudo adduser xrdp ssl-cert
# Disable Wayland for XRDP
sudo sed -i 's/#WaylandEnable=false/WaylandEnable=false/' /etc/gdm3/custom.conf
# Fix GNOME session for XRDP (prevents silent window manager crash)
sudo tee /etc/xrdp/startwm.sh > /dev/null << 'STARTWM'
#!/bin/sh
if test -r /etc/profile; then
. /etc/profile
fi
if test -r ~/.profile; then
. ~/.profile
fi
export GNOME_SHELL_SESSION_MODE=ubuntu
export XDG_SESSION_TYPE=x11
export XDG_CURRENT_DESKTOP=ubuntu:GNOME
export XDG_SESSION_DESKTOP=ubuntu
export XDG_RUNTIME_DIR=/run/user/$(id -u)
mkdir -p "$XDG_RUNTIME_DIR"
chmod 700 "$XDG_RUNTIME_DIR"
# Start D-Bus first (without exec, so the script continues)
eval $(dbus-launch --sh-syntax)
export DBUS_SESSION_BUS_ADDRESS
# Now D-Bus is up โ start PipeWire stack
systemctl --user start pipewire pipewire-pulse wireplumber 2>/dev/null
sleep 1
# Launch the desktop session
exec gnome-session
STARTWM
sudo chmod 755 /etc/xrdp/startwm.sh
# Set XRDP security layer to RDP
sudo sed -i 's/security_layer=negotiate/security_layer=rdp/' /etc/xrdp/xrdp.ini
# Disable Wayland in GDM3 config (kept for reference) then disable GDM3
# GDM3 conflicts with xrdp on Ubuntu 24.04 - holds DBus/XDG_RUNTIME_DIR
sudo systemctl disable gdm3
sudo systemctl stop gdm3
sudo systemctl restart xrdp xrdp-sesman
# Install Docker
# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
sudo systemctl start docker
# Create Guacamole folder
mkdir -p ~/guac/config && cd ~/guac
# Create user-mapping.xml
cat <<EOF > ./config/user-mapping.xml
<user-mapping>
<authorize username="guacadmin" password="guacadmin">
<connection name="Ubuntu Desktop">
<protocol>rdp</protocol>
<param name="security">rdp</param>
<param name="hostname">172.17.0.1</param>
<param name="port">3389</param>
<param name="username">YOUR_LINUX_USERNAME</param>
<param name="password">YOUR_LINUX_PASSWORD</param>
</connection>
</authorize>
</user-mapping>
EOF
# Create docker-compose.yml
cat <<EOF > docker-compose.yml
version: '3'
services:
guacd:
image: guacamole/guacd:latest
restart: unless-stopped
guacamole:
image: guacamole/guacamole:latest
restart: unless-stopped
ports:
- "8080:8080"
environment:
GUACD_HOSTNAME: guacd
GUACAMOLE_HOME: /etc/guacamole
volumes:
- ./config:/etc/guacamole
depends_on:
- guacd
EOF
# install brave browser? :)
curl -fsS https://dl.brave.com/install.sh | sh
# Start Guacamole stack
sudo docker compose up -d
echo "Setup complete! Visit http://YOUR_SERVER_IP:8080/guacamole"
echo "Login with guacadmin / guacadmin"#download the script and run it OR see the entire script in next code block and adjust it
wget https://gist.githubusercontent.com/ArjunDandagi/d48cff36a062e18201f37fa90d9bdad7/raw/a12365d23205dd4958eb1122a2c19750594b345d/ubuntu-desktop.sh
bash ubuntu-desktop.sh
#!/bin/bash
# set up locale with US so installation goes without user input
export DEBIAN_FRONTEND=noninteractive
sudo apt install -y locales
sudo locale-gen en_US.UTF-8
sudo update-locale LANG=en_US.UTF-8
echo 'locales locales/default_environment_locale select en_US.UTF-8' | sudo debconf-set-selections
echo 'locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8' | sudo debconf-set-selections
echo 'keyboard-configuration keyboard-configuration/layoutcode string us' | sudo debconf-set-selections
echo 'keyboard-configuration keyboard-configuration/modelcode string pc105' | sudo debconf-set-selections
echo 'keyboard-configuration keyboard-configuration/variantcode string' | sudo debconf-set-selections
sudo apt install -y keyboard-configuration
echo "gdm3 shared/default-x-display-manager select gdm3" | sudo debconf-set-selections
# Full Desktop + XRDP + Guacamole on Ubuntu 24.04
set -e
# Update
sudo apt update -y && sudo apt upgrade -y
# Install desktop and XRDP
sudo apt install -y ubuntu-desktop gnome-session gdm3 xrdp
sudo apt install -y dbus-x11 gnome-shell gnome-session ubuntu-session libcanberra-gtk-module libcanberra-gtk3-module
sudo apt install -y pipewire-module-xrdp
sudo systemctl enable xrdp
sudo systemctl start xrdp
sudo adduser xrdp ssl-cert
# Disable Wayland for XRDP
sudo sed -i 's/#WaylandEnable=false/WaylandEnable=false/' /etc/gdm3/custom.conf
# Fix GNOME session for XRDP (prevents silent window manager crash)
sudo tee /etc/xrdp/startwm.sh > /dev/null << 'STARTWM'
#!/bin/sh
if test -r /etc/profile; then
. /etc/profile
fi
if test -r ~/.profile; then
. ~/.profile
fi
export GNOME_SHELL_SESSION_MODE=ubuntu
export XDG_SESSION_TYPE=x11
export XDG_CURRENT_DESKTOP=ubuntu:GNOME
export XDG_SESSION_DESKTOP=ubuntu
export XDG_RUNTIME_DIR=/run/user/$(id -u)
mkdir -p "$XDG_RUNTIME_DIR"
chmod 700 "$XDG_RUNTIME_DIR"
# Start D-Bus first (without exec, so the script continues)
eval $(dbus-launch --sh-syntax)
export DBUS_SESSION_BUS_ADDRESS
# Now D-Bus is up โ start PipeWire stack
systemctl --user start pipewire pipewire-pulse wireplumber 2>/dev/null
sleep 1
# Launch the desktop session
exec gnome-session
STARTWM
sudo chmod 755 /etc/xrdp/startwm.sh
# Set XRDP security layer to RDP
sudo sed -i 's/security_layer=negotiate/security_layer=rdp/' /etc/xrdp/xrdp.ini
# Disable Wayland in GDM3 config (kept for reference) then disable GDM3
# GDM3 conflicts with xrdp on Ubuntu 24.04 - holds DBus/XDG_RUNTIME_DIR
sudo systemctl disable gdm3
sudo systemctl stop gdm3
sudo systemctl restart xrdp xrdp-sesman
# Install Docker
# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
sudo systemctl start docker
# Create Guacamole folder
mkdir -p ~/guac/config && cd ~/guac
# Create user-mapping.xml
cat <<EOF > ./config/user-mapping.xml
<user-mapping>
<authorize username="guacadmin" password="guacadmin">
<connection name="Ubuntu Desktop">
<protocol>rdp</protocol>
<param name="security">rdp</param>
<param name="hostname">172.17.0.1</param>
<param name="port">3389</param>
<param name="username">YOUR_LINUX_USERNAME</param>
<param name="password">YOUR_LINUX_PASSWORD</param>
</connection>
</authorize>
</user-mapping>
EOF
# Create docker-compose.yml
cat <<EOF > docker-compose.yml
version: '3'
services:
guacd:
image: guacamole/guacd:latest
restart: unless-stopped
guacamole:
image: guacamole/guacamole:latest
restart: unless-stopped
ports:
- "8080:8080"
environment:
GUACD_HOSTNAME: guacd
GUACAMOLE_HOME: /etc/guacamole
volumes:
- ./config:/etc/guacamole
depends_on:
- guacd
EOF
# install brave browser? :)
curl -fsS https://dl.brave.com/install.sh | sh
# Start Guacamole stack
sudo docker compose up -d
echo "Setup complete! Visit http://YOUR_SERVER_IP:8080/guacamole"
echo "Login with guacadmin / guacadmin"Replace
YOUR_LINUX_USERNAMEandYOUR_LINUX_PASSWORDbefore running.
โ Conclusion
You now have:
- Full Ubuntu 24.04 Desktop in the cloud
- XRDP server for remote desktop
- Guacamole web gateway for browser-based access
- Single script to spin up everything from scratch
This is perfect for labs, demos, or cloud-based GUI access without installing a local RDP client.
Cheers!!