Remote admin desktop

# Remote admin desktop

## Install desktop

### Centos

```sh
ocfuser@engs-28010:~$ ssh ocf@129.67.94.25
su -
yum update
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install yum install lxqt* openbox tigervnc-server firefox chromium --exclude=lxqt-*-devel
reboot
```

### Ubuntu

```sh
ocfuser@engs-28010:~$ ssh ocf@129.67.94.25
sudo apt-get -y update
sudo apt-get -y upgrade
sudo apt-get -y install lxqt qterminal openbox tigervnc-standalone-server firefox chromium-browser
#disable graphical boot
sudo systemctl set-default multi-user.target
#revert network control changes
sudo apt-get remove connman
sudo unlink /etc/resolv.conf
sudo systemctl enable systemd-networkd
sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
sudo systemd-resolve --status
sudo reboot
```

## Configure VNC daemon

### Auto generate .Xauthority and populate user VNC config files

Set password to `Password0`

```sh
ocf@OCF-admin:~$ vncserver

You will require a password to access your desktops.

Password:
Verify:
Would you like to enter a view-only password (y/n)? n
/usr/bin/xauth:  file /home/ocf/.Xauthority does not exist

New 'OCF-admin.robots.university.ac.uk:1 (ocf)' desktop at :1 on machine OCF-admin.robots.university.ac.uk

Starting applications specified in /etc/X11/Xvnc-session
Log file is /home/ocf/.vnc/OCF-admin.robots.university.ac.uk:1.log

Use xtigervncviewer -SecurityTypes VncAuth -passwd /home/ocf/.vnc/passwd :1 to connect to the VNC server.
```

### Create VNC profile for desktop environment

```sh
nano -cw ~/.vnc/xstartup

#!/bin/sh
unset SESSION_MANAGER
#unset DBUS_SESSION_BUS_ADDRESS
exec openbox-session &
startlxqt &
[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &
```

### Create systemd unit file for VNC on port 5901

```sh
sudo nano /etc/systemd/system/vncserver@.service

[Unit]
Description=a wrapper to launch an X server for VNC
After=syslog.target network.target

[Service]
Type=forking
User=ocf
Group=ocf
WorkingDirectory=/home/ocf

ExecStartPre=-/usr/bin/vncserver -kill :%i > /dev/null 2>&1
ExecStart=/usr/bin/vncserver -depth 24 -geometry 1920x1080 -interface 10.0.1.60 -localhost no :%i
#Centos vncserver is older, does not support -localhost switch
#ExecStart=/usr/bin/vncserver -depth 24 -geometry 1920x1080 -interface 10.0.1.60 :%i
ExecStop=/usr/bin/vncserver -kill :%i

[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload
```

### Start/Enable systemd unit file

```sh
sudo systemctl start vncserver@1
sudo systemctl enable vncserver@1
```

## Install Docker

### Centos

```sh
su -
sudo yum remove docker \
                docker-client \
                docker-client-latest \
                docker-common \
                docker-latest \
                docker-latest-logrotate \
                docker-logrotate \
                docker-engine
sudo yum install -y yum-utils
sudo yum-config-manager \
     --add-repo \
     https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -G docker ocf
sudo docker run hello-world
```

### Ubuntu

```sh
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
sudo /etc/init.d/docker start
sudo usermod -G sudo,docker ocf
#logout/login for group membership to take effect on current user session
docker run hello-world
```

## Install docker-compose

```sh
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
```

## Prepare Guacamole database and self signed SSL cert

### Create volume mount directories

```sh
sudo mkdir -p /opt/guacamole-docker/init /opt/guacamole-docker/data /opt/guacamole-docker/drive /opt/guacamole-docker/record /opt/guacamole-docker/nginx/ssl
sudo chmod +x /opt/guacamole-docker/init
```

### Prep postgress data directory

```sh
sudo su -
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgres > /opt/guacamole-docker/init/initdb.sql
exit
```

### Prep self signed cert

```sh
sudo su -
openssl req -nodes -newkey rsa:2048 -new -x509 -keyout /opt/guacamole-docker/nginx/ssl/self-ssl.key -out /opt/guacamole-docker/nginx/ssl/self.cert -subj '/C=GB/ST=University/L=University/O=Eng/OU=Robots/CN=OCF-admin.robots.university.ac.uk/emailAddress=root@robots.university.ac.uk'
cat /opt/guacamole-docker/nginx/ssl/self-ssl.key >> /opt/guacamole-docker/nginx/ssl/robots.cert
cat /opt/guacamole-docker/nginx/ssl/self.cert >> /opt/guacamole-docker/nginx/ssl/robots.cert
rm -f /opt/guacamole-docker/nginx/ssl/self-ssl.key /opt/guacamole-docker/nginx/ssl/self.cert
exit
```

## Setup Guacamole as a Docker service

> Useful docker-compose file template
> 
> https://github.com/boschkundendienst/guacamole-docker-compose

### Populate nginx daemon configuration file

```sh
sudo nano -cw /opt/guacamole-docker/nginx/nginx.conf

### AAA
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
```

### Populate nginx default config

```sh
sudo nano -cw /opt/guacamole-docker/nginx/robots.conf

### BBB
server {
    listen       443 ssl http2;
    server_name  localhost;

        ssl_certificate /etc/nginx/ssl/self.cert;
        ssl_certificate_key /etc/nginx/ssl/self.cert;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
        ssl_ecdh_curve secp384r1;
        ssl_session_cache shared:SSL:10m;
        ssl_session_tickets off;
        ssl_stapling off;
        ssl_stapling_verify off;
#        resolver 8.8.8.8 8.8.4.4 valid=300s;
#        resolver_timeout 5s;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
 #forward to container
    proxy_pass http://guacamole:8080/guacamole/;
    proxy_buffering off;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
    proxy_cookie_path /guacamole/ /;
    access_log off;
    # allow large uploads (default=1m)
    # 4096m = 4GByte
    client_max_body_size 4096m;
}

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}
```

### Create docker compose file

```sh
sudo mkdir -p /etc/docker/compose/guacamole
sudo nano -cw /etc/docker/compose/guacamole/docker-compose.yml

# docker-compose file for Apache Guacamole
# created by PCFreak 2017-06-28

version: '2.0'

# networks
# create a network 'guacnetwork_compose' in mode 'bridged'
networks:
  guacnetwork_compose:
    driver: bridge

# services
services:
  # guacd
  guacd:
    container_name: guacd_compose
    image: guacamole/guacd
    networks:
      guacnetwork_compose:
    restart: always
    volumes:
    - /opt/guacamole-docker/drive:/drive:rw
    - /opt/guacamole-docker/record:/record:rw
  # postgres
  postgres:
    container_name: postgres_guacamole_compose
    environment:
      PGDATA: /var/lib/postgresql/data/guacamole
      POSTGRES_DB: guacamole_db
      POSTGRES_PASSWORD: Password0
      POSTGRES_USER: guacamole_user
    image: postgres
    networks:
      guacnetwork_compose:
    restart: always
    volumes:
    - /opt/guacamole-docker/init:/docker-entrypoint-initdb.d:ro
    - /opt/guacamole-docker/data:/var/lib/postgresql/data:rw

  # guacamole
  guacamole:
    container_name: guacamole_compose
    depends_on:
    - guacd
    - postgres
    environment:
      GUACD_HOSTNAME: guacd
      POSTGRES_DATABASE: guacamole_db
      POSTGRES_HOSTNAME: postgres
      POSTGRES_PASSWORD: Password0
      POSTGRES_USER: guacamole_user
    image: guacamole/guacamole
    links:
    - guacd
    networks:
      guacnetwork_compose:
    ports:
## enable next line if not using nginx
##    - 8080:8080/tcp # Guacamole is on :8080/guacamole, not /.
## enable next line when using nginx
    - 8080/tcp
    restart: always

  # nginx
  nginx:
   container_name: nginx_guacamole_compose
   restart: always
   image: nginx
   volumes:
   - /opt/guacamole-docker/nginx/ssl/robots.cert:/etc/nginx/ssl/self.cert:ro
   - /opt/guacamole-docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
   - /opt/guacamole-docker/nginx/robots.conf:/etc/nginx/conf.d/default.conf:ro
   ports:
   - 9443:443
   links:
   - guacamole
   networks:
     guacnetwork_compose:
   # run nginx
   command: /bin/bash -c "nginx -g 'daemon off;'"
# nginx-debug-mode
#   command: /bin/bash -c "nginx-debug -g 'daemon off;'"
```

### Create systemd unit files to start Guacamole Docker containers on boot

```sh
sudo nano -cw /etc/systemd/system/docker-compose@.service

[Unit]
Description=%i service with docker compose
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=true
WorkingDirectory=/etc/docker/compose/%i
ExecStart=/usr/local/bin/docker-compose up -d --remove-orphans
ExecStop=/usr/local/bin/docker-compose down

[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload
```

### Start/Enable systemd unit file

```sh
sudo systemctl start docker-compose@guacamole
sudo systemctl enable docker-compose@guacamole
```

## Setup NTP daemon

Edit the chronyd config to include the RDIS ntp server and ensure the daemon listens on the isolated management network for the storage to use as a timesource.

```sh
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
server ntp0.robots.university.ac.uk
server ntp1.robots.university.ac.uk
server ntp2.robots.university.ac.uk
server ntp3.robots.university.ac.uk

# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift

# Allow the system clock to be stepped in the first three updates
# if its offset is larger than 1 second.
makestep 1.0 3

# Enable kernel synchronization of the real-time clock (RTC).
rtcsync

# Enable hardware timestamping on all interfaces that support it.
#hwtimestamp *

# Increase the minimum number of selectable sources required to adjust
# the system clock.
#minsources 2

# Allow NTP client access from local network.
#allow 192.168.0.0/16
allow 10.0.1.0/24

# Serve time even if not synchronized to a time source.
#local stratum 10

# Specify file containing keys for NTP authentication.
#keyfile /etc/chrony.keys

# Specify directory for log files.
logdir /var/log/chrony

# Select which information is logged.
#log measurements statistics tracking
```

Restart chronyd `systemctl enable chronyd;systemctl restart chronyd`

## Login to Guacamole, change credentials, create session

### Edit Credentials

| Attribute | Value |
| --- | --- |
| URL | [https://129.67.94.25:9443/](https://129.67.94.25:8443/) |
| Default User | guacadmin |
| Default Pass | guacadmin (changed to Password0) |
| OCF User | ocf |
| OCF Pass | Password0 |

Edit settings.

![6531057a0617b7b6dcb4a3c5f3ae5b58.png](_resources/32c98d85aa28442cba7d74af4a720c1d.png)

Navigate to users -> new user.

Create the OCF user, add all permissions to user, logout.

Login as the new OCF user.

Navigate to users -> guacadmin -> change password.

### Create session

Edit settings.

Navigate to connections -> new connection

|     |     |     |
| --- | --- | --- |
| Name | OCF-admin |     |
| Protocol | VNC |     |
| Max connections | 1   | only one connection possible for a single VNC session (you may have additional view only sessions) |
| Max # connections per user | 1   |     |
| Hostname | 10.0.1.60 | VNC started with -interface 10.0.1.60 -localhost no<br>Cannot listen on loopback as docker container will route to its own loopback not host, use isolated 10.0.1/24 range for better security. |
| Port | 5901 | systemd unit-file.1@service dynamic unit file starts at default port 5900 + dynamic unit name format 1 = 5901 |
| Username | ocf | set in ~/.vnc/passwd |
| Password | Password0 | set in ~/.vnc/passwd |