diff --git a/README.md b/README.md index e5afaa0..3026cd5 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ Within Mistborn is a panel to enable and manage these free extra services (off b - [Jellyfin](https://jellyfin.org): The Free Media Software System. - [Tor](https://www.torproject.org): The Onion Router. One tool in the arsenal of online security and privacy. - [Jitsi](https://jitsi.org): Multi-platform open-source video conferencing +- [Guacamole](https://guacamole.apache.org): A clientless remote desktop gateway that supports standard protocols like VNC, RDP, and SSH. # Quickstart Tested Operating Systems (in order of thoroughness): @@ -69,7 +70,7 @@ The Mistborn docker images exist for these architectures: | Mistborn Docker Images (hub.docker.com) | Architectures | |------------------------------------------------|---------------------| -| mistborn (django, celery{worker,beat}, flower) | amd64, arm64, arm/v7 | +| mistborn (django, celery{worker,beat}) | amd64, arm64, arm/v7 | | dnscrypt-proxy | amd64, arm64, arm/v7 | Recommended System Specifications: @@ -277,6 +278,7 @@ Mistborn uses the following domains (that can be reached by all Wireguard client | Syncthing | syncthing.mistborn | Off | | OnlyOffice | onlyoffice.mistborn | Off | | Jitsi | jitsi.mistborn | Off | +| Guacamole | guac.mistborn | Off | # Default Credentials These are the default credentials to use in the services you choose to use: @@ -286,6 +288,7 @@ These are the default credentials to use in the services you choose to use: | Pihole | | {{default mistborn password}} | | Cockpit | cockpit | {{default mistborn password}} | | Nextcloud | mistborn | {{default mistborn password}} | +| Guacamole | mistborn | {{default mistborn password }} | You can find the credentials sent to the Docker containers in: `/opt/mistborn/.envs/.production/` @@ -445,6 +448,7 @@ sudo journalctl -xfu Mistborn-syncthing sudo journalctl -xfu Mistborn-jellyfin sudo journalctl -xfu Mistborn-nextcloud sudo journalctl -xfu Mistborn-jitsi +sudo journalctl -xfu Mistborn-guacamole sudo journalctl -xfu Mistborn-rocketchat sudo journalctl -xfu Mistborn-onlyoffice sudo journalctl -xfu Mistborn-tor diff --git a/extra/guacamole.yml b/extra/guacamole.yml new file mode 100644 index 0000000..f3310a7 --- /dev/null +++ b/extra/guacamole.yml @@ -0,0 +1,71 @@ +version: '3' + +# services +services: + # guacd + guacd: + container_name: mistborn_production_guacd + image: guacamole/guacd + networks: + guacnetwork: + restart: unless-stopped + volumes: + - ../../mistborn_volumes/extra/guacamole/drive:/drive:rw + - ../../mistborn_volumes/extra/guacamole/record:/record:rw + + + # postgres + guac_postgres: + container_name: mistborn_production_guac_postgres + env_file: + - ../.envs/.production/.guacamole + environment: + PGDATA: /var/lib/postgresql/data/guacamole + image: postgres + networks: + guacnetwork: + restart: unless-stopped + volumes: + - ../../mistborn_volumes/extra/guacamole/init:/docker-entrypoint-initdb.d:ro + - ../../mistborn_volumes/extra/guacamole/data:/var/lib/postgresql/data:rw + + + # guacamole + guacamole: + container_name: mistborn_production_guacamole + labels: + - "traefik.enable=true" + - "traefik.http.routers.guacamole-http.rule=Host(`guac.mistborn`)" + - "traefik.http.routers.guacamole-http.entrypoints=web" + - "traefik.http.routers.guacamole-http.middlewares=mistborn_auth@file" + - "traefik.http.routers.guacamole-https.rule=Host(`guac.mistborn`)" + - "traefik.http.routers.guacamole-https.entrypoints=websecure" + - "traefik.http.routers.guacamole-https.middlewares=mistborn_auth@file" + - "traefik.http.routers.guacamole-https.tls.certresolver=basic" + - "traefik.http.services.guacamole-service.loadbalancer.server.port=8080" + depends_on: + - guacd + - guac_postgres + environment: + GUACD_HOSTNAME: guacd + GUACD_PORT: 4822 + #GUACAMOLE_HOME: /config + env_file: + - ../.envs/.production/.guacamole + image: guacamole/guacamole + links: + - guacd + networks: + guacnetwork: + #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: unless-stopped + +# networks +# create a network 'guacnetwork' in mode 'bridged' +networks: + guacnetwork: + driver: bridge diff --git a/scripts/env/guacamole_init.sh b/scripts/env/guacamole_init.sh new file mode 100755 index 0000000..50c846f --- /dev/null +++ b/scripts/env/guacamole_init.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +mkdir -p /opt/mistborn_volumes/extra/guacamole/init/ >/dev/null 2>&1 +chmod -R +x /opt/mistborn_volumes/extra/guacamole/init/ +docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgres > /opt/mistborn_volumes/extra/guacamole/init/initdb.sql + +# grab values in initdb.sql to replace +HEXSTRINGS=($(egrep -o [0-9a-fA-F]{64} /opt/mistborn_volumes/extra/guacamole/init/initdb.sql)) + +# reset default password in init.db +SALT=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice('0123456789ABCDEF') for x in range(64)]))") +GUAC_PASSWORD_HASHED=$(echo -n "${MISTBORN_DEFAULT_PASSWORD}${SALT}" | sha256sum | awk '{print $1}' | tr a-z A-Z) + +sed -i "s/${HEXSTRINGS[1]}/$SALT/" /opt/mistborn_volumes/extra/guacamole/init/initdb.sql +sed -i "s/${HEXSTRINGS[0]}/$GUAC_PASSWORD_HASHED/" /opt/mistborn_volumes/extra/guacamole/init/initdb.sql +sed -i "s/guacadmin/mistborn/g" /opt/mistborn_volumes/extra/guacamole/init/initdb.sql \ No newline at end of file diff --git a/scripts/services/Mistborn-guacamole.service b/scripts/services/Mistborn-guacamole.service new file mode 100644 index 0000000..be4f9f1 --- /dev/null +++ b/scripts/services/Mistborn-guacamole.service @@ -0,0 +1,24 @@ +[Unit] +Description=Mistborn Guacamole +Requires=Mistborn-base.service +After=Mistborn-base.service +PartOf=Mistborn-base.service + +[Service] +Restart=always +User=root +Group=docker +PermissionsStartOnly=true +EnvironmentFile=/opt/mistborn/.envs/.production/.guacamole +ExecStartPre=/opt/mistborn/scripts/env/guacamole_init.sh +# Shutdown container (if running) when unit is stopped +ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/guacamole.yml down + +# Start container when unit is started +ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/guacamole.yml up --build +# Stop container when unit is stopped +ExecStop=/usr/local/bin/docker-compose -f /opt/mistborn/extra/guacamole.yml down +# Post stop + +[Install] +WantedBy=multi-user.target diff --git a/scripts/subinstallers/gen_prod_env.sh b/scripts/subinstallers/gen_prod_env.sh index ef9bab6..bc06297 100755 --- a/scripts/subinstallers/gen_prod_env.sh +++ b/scripts/subinstallers/gen_prod_env.sh @@ -78,3 +78,15 @@ sed -i "s/JVB_AUTH_PASSWORD.*/JVB_AUTH_PASSWORD=$(python3 -c "import secrets; im sed -i "s/JIGASI_XMPP_PASSWORD.*/JIGASI_XMPP_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")/" "$JITSI_PROD_FILE" sed -i "s/JIBRI_RECORDER_PASSWORD.*/JIBRI_RECORDER_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")/" "$JITSI_PROD_FILE" sed -i "s/JIBRI_XMPP_PASSWORD.*/JIBRI_XMPP_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")/" "$JITSI_PROD_FILE" + +# Guacamole +GUAC_PROD_FILE="./.envs/.production/.guacamole" +GUAC_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))") +echo "POSTGRES_HOST=guac_postgres" > $GUAC_PROD_FILE +echo "POSTGRES_HOSTNAME=guac_postgres" > $GUAC_PROD_FILE +echo "POSTGRES_PORT=5432" >> $GUAC_PROD_FILE +echo "POSTGRES_DB=guacamole_db" >> $GUAC_PROD_FILE +echo "POSTGRES_DATABASE=guacamole_db" >> $GUAC_PROD_FILE +echo "POSTGRES_USER=guac_user" >> $GUAC_PROD_FILE +echo "POSTGRES_PASSWORD=$GUAC_PASSWORD" >> $GUAC_PROD_FILE +echo "MISTBORN_DEFAULT_PASSWORD=$MISTBORN_DEFAULT_PASSWORD" >> $GUAC_PROD_FILE \ No newline at end of file