├── .dockerignore ├── bin ├── xfce-logout ├── auto-logout ├── create-users.sh └── docker-entrypoint.sh ├── screenshot.png ├── etc ├── supervisor │ ├── conf.d │ │ ├── sshd.conf │ │ ├── xrdp.conf │ │ └── xrdp-sesman.conf │ └── supervisord.conf ├── users.list ├── asound.conf ├── xrdp │ └── pulse │ │ └── default.pa └── skel │ └── .config │ └── pulse │ └── client.conf ├── autostart └── auto-logout.desktop ├── docker-compose.yml ├── LICENSE ├── Dockerfile └── Readme.md /.dockerignore: -------------------------------------------------------------------------------- 1 | data/ 2 | -------------------------------------------------------------------------------- /bin/xfce-logout: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | xfce4-session-logout --logout 3 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielguerra69/ubuntu-xrdp/HEAD/screenshot.png -------------------------------------------------------------------------------- /etc/supervisor/conf.d/sshd.conf: -------------------------------------------------------------------------------- 1 | [program:sshd] 2 | command=/usr/sbin/sshd -D 3 | user=root 4 | autorestart=true 5 | priority=400 6 | -------------------------------------------------------------------------------- /etc/users.list: -------------------------------------------------------------------------------- 1 | 999 ubuntu $6$9DorSQJl$7/vYvQlX6qfyLEbehwX9NNmEsL0MsQCCY3ZGueQE5juFP.Jqp1XtBx3fR5pp5ZXVwOIoRQR7a9VSMOlHVd4sB0 sudo 2 | -------------------------------------------------------------------------------- /etc/supervisor/conf.d/xrdp.conf: -------------------------------------------------------------------------------- 1 | [program:xrdp] 2 | command=/usr/sbin/xrdp --nodaemon 3 | user=root 4 | autorestart=true 5 | priority=400 6 | -------------------------------------------------------------------------------- /etc/supervisor/conf.d/xrdp-sesman.conf: -------------------------------------------------------------------------------- 1 | [program:xrdp-sesman] 2 | command=/usr/sbin/xrdp-sesman --nodaemon 3 | user=root 4 | autorestart=true 5 | priority=400 6 | -------------------------------------------------------------------------------- /etc/asound.conf: -------------------------------------------------------------------------------- 1 | pcm.pulse { 2 | type pulse 3 | } 4 | 5 | ctl.pulse { 6 | type pulse 7 | } 8 | 9 | pcm.!default { 10 | type pulse 11 | } 12 | 13 | ctl.!default { 14 | type pulse 15 | } -------------------------------------------------------------------------------- /bin/auto-logout: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ $IDLETIME ]; then 3 | xautolock -time $IDLETIME -locker /usr/bin/xfce-logout 4 | elif [ $LOCKTIME ]; then 5 | xautolock -time $LOCKTIME -locker xflock4 6 | else 7 | xautolock -time 10 -locker xflock4 8 | fi 9 | -------------------------------------------------------------------------------- /autostart/auto-logout.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Version=0.9.4 4 | Type=Application 5 | Name=auto-logout 6 | Comment=Automatically logout idle session 7 | Exec=/usr/bin/auto-logout 8 | OnlyShowIn=XFCE; 9 | StartupNotify=false 10 | Terminal=false 11 | Hidden=false 12 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | services: 3 | terminalserver: 4 | build: ./ 5 | image: danielguerra/ubuntu-xrdp:latest 6 | container_name: uxrdp 7 | hostname: terminalserver 8 | restart: always 9 | shm_size: 1g 10 | environment: 11 | PASSWORDHASH: $$1$$z53Cg/fV$$06o379IvIOxj/ESruVKrG1 12 | IDLETIME: 11 13 | ports: 14 | - "3389:3389" 15 | - "2222:22" 16 | volumes: 17 | - ssh:/etc/ssh/ 18 | - home:/home 19 | 20 | volumes: 21 | ssh: 22 | home: 23 | -------------------------------------------------------------------------------- /bin/create-users.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | test -f /etc/users.list || exit 0 4 | 5 | while read id username hash groups; do 6 | # Skip, if user already exists 7 | grep ^$username /etc/passwd && continue 8 | # Create group 9 | addgroup --gid $id $username 10 | # Create user 11 | useradd -m -u $id -s /bin/bash -g $username $username 12 | # Set password 13 | echo "$username:$hash" | /usr/sbin/chpasswd -e 14 | # Add supplemental groups 15 | if [ $groups ]; then 16 | usermod -aG $groups $username 17 | fi 18 | done < /etc/users.list 19 | -------------------------------------------------------------------------------- /etc/xrdp/pulse/default.pa: -------------------------------------------------------------------------------- 1 | .nofail 2 | .fail 3 | load-module module-augment-properties 4 | load-module module-always-sink 5 | .ifexists module-xrdp-sink.so 6 | load-module module-xrdp-sink 7 | .endif 8 | .ifexists module-xrdp-source.so 9 | load-module module-xrdp-source 10 | .endif 11 | .ifexists /var/lib/xrdp-pulseaudio-installer/module-xrdp-sink.so 12 | load-module /var/lib/xrdp-pulseaudio-installer/module-xrdp-sink.so 13 | .endif 14 | .ifexists /var/lib/xrdp-pulseaudio-installer/module-xrdp-source.so 15 | load-module /var/lib/xrdp-pulseaudio-installer/module-xrdp-source.so 16 | .endif 17 | load-module module-native-protocol-unix 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 danielguerra69 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /etc/skel/.config/pulse/client.conf: -------------------------------------------------------------------------------- 1 | # This file is part of PulseAudio. 2 | # 3 | # PulseAudio is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU Lesser General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # PulseAudio is distributed in the hope that it will be useful, but 9 | # WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | # General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU Lesser General Public License 14 | # along with PulseAudio; if not, see . 15 | 16 | ## Configuration file for PulseAudio clients. See pulse-client.conf(5) for 17 | ## more information. Default values are commented out. Use either ; or # for 18 | ## commenting. 19 | 20 | ; default-sink = 21 | ; default-source = 22 | ; default-server = 23 | ; default-dbus-server = 24 | 25 | ; autospawn = yes 26 | ; daemon-binary = /usr/bin/pulseaudio 27 | extra-arguments = --enable-memfd=True 28 | 29 | ; cookie-file = 30 | 31 | enable-shm = yes 32 | ; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB 33 | 34 | ; auto-connect-localhost = no 35 | ; auto-connect-display = no 36 | -------------------------------------------------------------------------------- /etc/supervisor/supervisord.conf: -------------------------------------------------------------------------------- 1 | ; supervisor config file 2 | 3 | [supervisord] 4 | nodaemon=true 5 | logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) 6 | pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) 7 | childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) 8 | 9 | ; the below section must remain in the config file for RPC 10 | ; (supervisorctl/web interface) to work, additional interfaces may be 11 | ; added by defining them in separate rpcinterface: sections 12 | 13 | [rpcinterface:supervisor] 14 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 15 | 16 | [supervisorctl] 17 | serverurl=http://localhost:9001 18 | 19 | [rpcinterface:supervisor] 20 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 21 | 22 | [inet_http_server] 23 | port = :9001 24 | [unix_http_server] 25 | file=/var/run//supervisor.sock ; (the path to the socket file) 26 | chmod=0700 ; sockef file mode (default 0700) 27 | 28 | ; The [include] section can just contain the "files" setting. This 29 | ; setting can list multiple files (separated by whitespace or 30 | ; newlines). It can also contain wildcards. The filenames are 31 | ; interpreted as relative to this file. Included files *cannot* 32 | ; include files themselves. 33 | 34 | [include] 35 | files = /etc/supervisor/conf.d/*.conf 36 | 37 | [supervisord] 38 | nodaemon=true -------------------------------------------------------------------------------- /bin/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Add users 4 | bash /usr/bin/create-users.sh 5 | 6 | # Add the ssh config if needed 7 | 8 | if [ ! -f "/etc/ssh/sshd_config" ]; 9 | then 10 | cp /ssh_orig/sshd_config /etc/ssh 11 | fi 12 | 13 | if [ ! -f "/etc/ssh/ssh_config" ]; 14 | then 15 | cp /ssh_orig/ssh_config /etc/ssh 16 | fi 17 | 18 | if [ ! -f "/etc/ssh/moduli" ]; 19 | then 20 | cp /ssh_orig/moduli /etc/ssh 21 | fi 22 | 23 | # generate fresh rsa key if needed 24 | if [ ! -f "/etc/ssh/ssh_host_rsa_key" ]; 25 | then 26 | ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa 27 | fi 28 | 29 | # generate fresh dsa key if needed 30 | if [ ! -f "/etc/ssh/ssh_host_dsa_key" ]; 31 | then 32 | ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa 33 | fi 34 | 35 | #prepare run dir 36 | mkdir -p /var/run/sshd 37 | 38 | 39 | # generate xrdp key 40 | if [ ! -f "/etc/xrdp/rsakeys.ini" ]; 41 | then 42 | xrdp-keygen xrdp auto 43 | fi 44 | 45 | # generate certificate for tls connection 46 | if [ ! -f "/etc/xrdp/cert.pem" ]; 47 | then 48 | # delete eventual leftover private key 49 | rm -f /etc/xrdp/key.pem || true 50 | cd /etc/xrdp 51 | if [ ! $CERTIFICATE_SUBJECT ]; then 52 | CERTIFICATE_SUBJECT="/C=US/ST=Some State/L=Some City/O=Some Org/OU=Some Unit/CN=Terminalserver" 53 | fi 54 | openssl req -x509 -newkey rsa:2048 -nodes -keyout /etc/xrdp/key.pem -out /etc/xrdp/cert.pem -days 365 -subj "$CERTIFICATE_SUBJECT" 55 | crudini --set /etc/xrdp/xrdp.ini Globals security_layer tls 56 | crudini --set /etc/xrdp/xrdp.ini Globals certificate /etc/xrdp/cert.pem 57 | crudini --set /etc/xrdp/xrdp.ini Globals key_file /etc/xrdp/key.pem 58 | 59 | fi 60 | 61 | # generate machine-id 62 | uuidgen > /etc/machine-id 63 | 64 | # set keyboard for all sh users 65 | echo "export QT_XKB_CONFIG_ROOT=/usr/share/X11/locale" >> /etc/profile 66 | 67 | 68 | exec "$@" 69 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 as builder 2 | MAINTAINER Daniel Guerra 3 | 4 | # Install packages 5 | 6 | ENV DEBIAN_FRONTEND noninteractive 7 | RUN sed -i "s/# deb-src/deb-src/g" /etc/apt/sources.list 8 | RUN apt-get -y update 9 | RUN apt-get -yy upgrade 10 | ENV BUILD_DEPS="git autoconf pkg-config libssl-dev libpam0g-dev \ 11 | libx11-dev libxfixes-dev libxrandr-dev nasm xsltproc flex \ 12 | bison libxml2-dev dpkg-dev libcap-dev" 13 | RUN apt-get -yy install sudo apt-utils software-properties-common $BUILD_DEPS 14 | 15 | 16 | # Build xrdp 17 | 18 | WORKDIR /tmp 19 | RUN apt-get source pulseaudio 20 | RUN apt-get build-dep -yy pulseaudio 21 | WORKDIR /tmp/pulseaudio-11.1 22 | RUN dpkg-buildpackage -rfakeroot -uc -b 23 | WORKDIR /tmp 24 | RUN git clone --branch v0.9.16 --recursive https://github.com/neutrinolabs/xrdp.git 25 | WORKDIR /tmp/xrdp 26 | RUN ./bootstrap 27 | RUN ./configure 28 | RUN make 29 | RUN make install 30 | WORKDIR /tmp 31 | RUN apt -yy install libpulse-dev 32 | RUN git clone --recursive https://github.com/neutrinolabs/pulseaudio-module-xrdp.git 33 | WORKDIR /tmp/pulseaudio-module-xrdp 34 | RUN ./bootstrap && ./configure PULSE_DIR=/tmp/pulseaudio-11.1 35 | RUN make 36 | RUN mkdir -p /tmp/so 37 | RUN cp src/.libs/*.so /tmp/so 38 | 39 | FROM ubuntu:18.04 40 | ARG ADDITIONAL_PACKAGES="" 41 | ENV ADDITIONAL_PACKAGES=${ADDITIONAL_PACKAGES} 42 | ENV DEBIAN_FRONTEND noninteractive 43 | RUN apt update && apt install -y software-properties-common 44 | RUN add-apt-repository "deb http://archive.canonical.com/ $(lsb_release -sc) partner" && apt update 45 | RUN apt -y full-upgrade && apt install -y \ 46 | adobe-flashplugin \ 47 | browser-plugin-freshplayer-pepperflash \ 48 | ca-certificates \ 49 | crudini \ 50 | firefox \ 51 | less \ 52 | locales \ 53 | openssh-server \ 54 | pulseaudio \ 55 | sudo \ 56 | supervisor \ 57 | uuid-runtime \ 58 | vim \ 59 | vlc \ 60 | wget \ 61 | xauth \ 62 | xautolock \ 63 | xfce4 \ 64 | xfce4-clipman-plugin \ 65 | xfce4-cpugraph-plugin \ 66 | xfce4-netload-plugin \ 67 | xfce4-screenshooter \ 68 | xfce4-taskmanager \ 69 | xfce4-terminal \ 70 | xfce4-xkb-plugin \ 71 | xorgxrdp \ 72 | xprintidle \ 73 | xrdp \ 74 | $ADDITIONAL_PACKAGES && \ 75 | apt-get remove -yy xscreensaver && \ 76 | apt-get autoremove -yy && \ 77 | rm -rf /var/cache/apt /var/lib/apt/lists && \ 78 | mkdir -p /var/lib/xrdp-pulseaudio-installer 79 | COPY --from=builder /tmp/so/module-xrdp-source.so /var/lib/xrdp-pulseaudio-installer 80 | COPY --from=builder /tmp/so/module-xrdp-sink.so /var/lib/xrdp-pulseaudio-installer 81 | ADD bin /usr/bin 82 | ADD etc /etc 83 | ADD autostart /etc/xdg/autostart 84 | #ADD pulse /usr/lib/pulse-10.0/modules/ 85 | 86 | # Configure 87 | RUN mkdir /var/run/dbus && \ 88 | cp /etc/X11/xrdp/xorg.conf /etc/X11 && \ 89 | sed -i "s/console/anybody/g" /etc/X11/Xwrapper.config && \ 90 | sed -i "s/xrdp\/xorg/xorg/g" /etc/xrdp/sesman.ini && \ 91 | locale-gen en_US.UTF-8 && \ 92 | echo "xfce4-session" > /etc/skel/.Xclients && \ 93 | cp -r /etc/ssh /ssh_orig && \ 94 | rm -rf /etc/ssh/* && \ 95 | rm -rf /etc/xrdp/rsakeys.ini /etc/xrdp/*.pem 96 | 97 | # Docker config 98 | VOLUME ["/etc/ssh","/home"] 99 | EXPOSE 3389 22 9001 100 | ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"] 101 | CMD ["supervisord"] 102 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | ## Ubuntu 20.04/18.04/16.04 Multi User Remote Desktop Server 2 | 3 | Fully implemented Multi User xrdp 4 | with xorgxrdp and pulseaudio 5 | on Ubuntu 20.04/18.04/16.04/kali. 6 | Copy/Paste and sound is working. 7 | Users can re-login in the same session. 8 | Xfce4, Firefox are pre installed. 9 | 10 | # Tags 11 | 12 | danielguerra/ubuntu-xrdp:16.04 13 | danielguerra/ubuntu-xrdp:18.04 or latest 14 | danielguerra/ubuntu-xrdp:20.04 15 | danielguerra/ubuntu-xrdp:clean (for development) 16 | 17 | and a debian version kali linux (experiment) 18 | danielguerra/ubuntu-xrdp:kali 19 | 20 | ## Usage 21 | 22 | Start the rdp server 23 | (WARNING: use the --shm-size 1g or firefox/chrome will crash) 24 | 25 | ```bash 26 | docker run -d --name uxrdp --hostname terminalserver --shm-size 1g -p 3389:3389 -p 2222:22 danielguerra/ubuntu-xrdp:20.04 27 | ``` 28 | *note if you already use a rdp server on 3389 change -p :3389 29 | -p 2222:22 is for ssh access ( ssh -p 2222 ubuntu@ ) 30 | 31 | Connect with your remote desktop client to the docker server. 32 | Use the Xorg session (leave as it is), user and pass. 33 | 34 | ## Creation of users 35 | 36 | To automate the creation of users, supply a file users.list in the /etc directory of the container. 37 | The format is as follows: 38 | 39 | ```bash 40 | id username password-hash list-of-supplemental-groups 41 | ``` 42 | 43 | The provided users.list file will create a sample user with sudo rights 44 | 45 | Username: ubuntu 46 | Password: ubuntu 47 | 48 | To generate the password hash use the following line 49 | 50 | ```bash 51 | openssl passwd -1 'newpassword' 52 | ``` 53 | 54 | Run the xrdp container with your file 55 | 56 | ```bash 57 | docker run -d -v $PWD/users.list:/etc/users.list 58 | ``` 59 | 60 | You can change your password in the rdp session in a terminal 61 | 62 | ```bash 63 | passwd 64 | ``` 65 | 66 | ## Add new users 67 | 68 | No configuration is needed for new users just do 69 | 70 | ```bash 71 | docker exec -ti uxrdp adduser mynewuser 72 | ``` 73 | 74 | After this the new user can login 75 | 76 | ## Add new services 77 | 78 | To make sure all processes are working supervisor is installed. 79 | The location for services to start is /etc/supervisor/conf.d 80 | 81 | Example: Add mysql as a service 82 | 83 | ```bash 84 | apt-get -yy install mysql-server 85 | echo "[program:mysqld] \ 86 | command= /usr/sbin/mysqld \ 87 | user=mysql \ 88 | autorestart=true \ 89 | priority=100" > /etc/supervisor/conf.d/mysql.conf 90 | supervisorctl update 91 | ``` 92 | 93 | ## Volumes 94 | This image uses two volumes: 95 | 1. `/etc/ssh/` holds the sshd host keys and config 96 | 2. `/home/` holds the `ubuntu/` default user home directory 97 | 98 | When bind-mounting `/home/`, make sure it contains a folder `ubuntu/` with proper permission, otherwise no login will be possible. 99 | 100 | ``` 101 | mkdir -p ubuntu 102 | chown 999:999 ubuntu 103 | ``` 104 | 105 | ## Installing additional packages during build 106 | 107 | The Dockerfile has support for the build argument ADDITIONAL_PACKAGES to install additional packages during build. Either pass it with `--build-arg` during `docker build` or add it 108 | as `args` in your `docker-compose.override.yml` and run `docker-compose build`. 109 | 110 | ## To run with docker-compose 111 | 112 | ```bash 113 | git clone https://github.com/danielguerra69/ubuntu-xrdp.git 114 | cd ubuntu-xrdp/ 115 | vi docker-compose.override.yml # if you want to override any default value 116 | docker-compose up -d 117 | ``` 118 | --------------------------------------------------------------------------------