├── .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 |
--------------------------------------------------------------------------------