diff --git a/README.md b/README.md index 7c41216..e964146 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Thinlinc CycleCloud Project -This project is used for Azure CycleCloud integrated with Thinlinc to allow thinlinc work smoothly on Cyclecloud cluster nodes. +ThinLinc is a powerful remote desktop server solution for Linux environments, offering seamless access to applications from various clients with robust security and high performance. See the [ThinLinc site](https://www.cendio.com/) and [documentation](https://www.cendio.com/thinlinc/docs/) for an overview and detailed information. + +This project integrates Azure CycleCloud with ThinLinc to ensure seamless operation of ThinLinc on CycleCloud cluster nodes. Please reference the [CycleCloud Projects page](https://docs.microsoft.com/en-us/azure/cyclecloud/projects) dives into greater detail on the concepts and examples. @@ -46,7 +48,7 @@ Prepare the credentials to access the blob container associated with the locker: matches = az://cendiocyclecloud/cyclecloud ``` - *You can locate your Subscription ID using the Azure CLI (`az` command) to list the accounts:* `az account list -o table` + _You can locate your Subscription ID using the Azure CLI (`az` command) to list the accounts:_ `az account list -o table` * Your `~/.cycle/config.ini` should now look something like this @@ -84,11 +86,43 @@ Prepare the credentials to access the blob container associated with the locker: ### 1.3 Create a new Cluster with the Thinlinc Project -*Note: /tempplates/signle-nodearray_teampate_1.0.0.2.txt is a sample signle nodearray cluster template, please make the necessary adjustment when using it.* - Having uploaded the Thinlinc project into the CycleCloud locker, you can now create a new cluster in CycleCloud and specify that each node should use the `cyclecloud-thinlinc:default` spec. -* From the Cluster page of your Azure CycleCloud web portal, navigate to the *Advanced Settings* section. Under the *Software* section, click on the "Browse" button which will open a file selector dialog, You will see a folder named `cyclecloud-thinlinc/`. Open it by double-clicking it. Then open the `1.0.0/` folder. Finally, select the `default/` folder by clicking on it once and pressing the "Select" button on the bottom of the dialog window. After pressing "Select" the file selector dialog will close. This selects the `default` spec of version `1.0.0` of the project `cyclecloud-thinlinc`. - ![Browse Specs](images/cluster-init.png) +* Import cluster template by referencing the sample template located at /templates/single-nodearray_template_1.0.0.3.txt. Make the necessary adjustments accordingly. + + ```sh + (venv) xuan@dhcp-130:~/cyclecloud-thinlinc$ cyclecloud import_template single-nodearray -f ./templates/single-nodearray_template_1.0.0.3.txt + Importing template single-nodearray.... + ----------------------------- + single-nodearray : *template* + ----------------------------- + Resource group: + Cluster nodes: + my-tl: Off -- -- + Total nodes: 1 + (venv) xuan@dhcp-130:~/cyclecloud-thinlinc$ + ``` + + +* From the Cluster page of your Azure CycleCloud web portal, use the "+" symbol in the bottom-left-hand corner of the page to add a new cluster, select "single-nodearray" template created in the last step: + ![Browse Specs](images/cluster-template.png) + + +* Input the cluster name and complete the other required fields. + +* Navigate to the *Advanced Settings* section. Under the *Software* section, click on the "Browse" button for "Cluster-Init" which will open a file selector dialog, You will see a folder named `cyclecloud-thinlinc/`. Open it by double-clicking it. Then open the `1.0.0/` folder. Finally, select the `default/` folder by clicking on it once and pressing the "Select" button on the bottom of the dialog window. After pressing "Select" the file selector dialog will close. This selects the `default` spec of version `1.0.0` of the project `cyclecloud-thinlinc`. + +* Under the *Thinlinc* section, for `Enable Web Interface` choose to enable or disable ThinLinc web interface access (default is disabled), we recommend to enable it. Once selected, input your web interface port number in the `Web Port` field (default is 443). + + *Note: Please ensure your network security or firewall rules allow inbound access on this port.* + +* In the `Connection Mode` dropdown, select the mode for the client connect from, the three options are: + **Public IP**: Connect trhough a public IP address. + + **Private IP**: Connect through a VPN with direct connectivity to the Cluster. + + **SSH Tunnel**: Connect through a bastion host. + + ![Browse Specs](images/advanced-settings.png) -* Save the cluster and start it. When the master node turns green, log into it and verify that Thinlinc web interface configured correctly. +* Save the cluster and start it. When the master node turns green, connet to it using Thinlinc client to verify that it is configured correctly. diff --git a/images/advanced-settings.png b/images/advanced-settings.png new file mode 100644 index 0000000..2816a76 Binary files /dev/null and b/images/advanced-settings.png differ diff --git a/images/cluster-init.png b/images/cluster-init.png deleted file mode 100644 index 06665dc..0000000 Binary files a/images/cluster-init.png and /dev/null differ diff --git a/images/cluster-template.png b/images/cluster-template.png new file mode 100644 index 0000000..7b1984c Binary files /dev/null and b/images/cluster-template.png differ diff --git a/specs/default/cluster-init/scripts/01_configure_tlwebaccess.sh b/specs/default/cluster-init/scripts/01_configure_tlwebaccess.sh index d35aca8..4c3b0d7 100644 --- a/specs/default/cluster-init/scripts/01_configure_tlwebaccess.sh +++ b/specs/default/cluster-init/scripts/01_configure_tlwebaccess.sh @@ -1,24 +1,39 @@ #!/bin/bash -# Define the path to the configuration file -CONFIG_FILE="/opt/thinlinc/etc/conf.d/webaccess.hconf" +# Fetch thinlinc web access parameters +enable_web=$(jetpack config thinlinc.enable_web False) +thinlinc_web_port=$(jetpack config thinlinc.web_port 443) -# Update the /opt/thinlinc/etc/conf.d/webaccess.hconf file -if [ -f "$CONFIG_FILE" ]; then - sed -i 's/^listen_port=300$/listen_port=443/' "$CONFIG_FILE" -else - echo "Configuration file not found: $CONF_FILE" - exit 1 -fi +# Function to restart tlwebaccess service +restart_tlwebaccess() { + if ! systemctl restart tlwebaccess; then + echo "Failed to restart tlwebaccess service." + exit 1 + fi + echo "Thinlinc tlwebaccess service restarted successfully." +} -echo "listen_port updated successfully." +# Function to disable tlwebaccess service +disable_tlwebaccess() { + if ! systemctl disable --now tlwebaccess; then + echo "Failed to disable tlwebaccess service." + exit 1 + fi + echo "Thinlinc tlwebaccess service disable successfully." +} -# Restart the tlwebaccess service -systemctl restart tlwebaccess; -if [ $? -ne 0 ]; then - echo "Failed to restart tlwebaccess service" - exit 1 +if [[ "$enable_web" == "True" ]]; then + # Update the listen_port + /opt/thinlinc/bin/tl-config /webaccess/listen_port=$thinlinc_web_port + if [[ $? -ne 0 ]]; then + echo "Failed to configure Thinlinc Web Access port number." + exit 1 + fi + # Restart the tlwebaccess service to apply changes + restart_tlwebaccess + echo "Thinlinc Web Access port number configurations completed." +else + # Disable the tlwebaccess service + disable_tlwebaccess + echo "Disable Thinlinc Web access completed." fi - -echo "tlwebaccess service restarted successfully." -echo "tlwebaccess configurations completed." diff --git a/specs/default/cluster-init/scripts/02_configure_vsmagent.sh b/specs/default/cluster-init/scripts/02_configure_vsmagent.sh new file mode 100644 index 0000000..0d381c2 --- /dev/null +++ b/specs/default/cluster-init/scripts/02_configure_vsmagent.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Fetch the connection mode +connection_mode=$(jetpack config thinlinc.connection_mode private_ip) + +# Determine the agent_hostname based on the connection mode +case "$connection_mode" in + "private_ip") + thinlinc_agent_hostname=$(jetpack config cloud.local_ipv4) + ;; + "public_ip") + thinlinc_agent_hostname=$(jetpack config cloud.public_ipv4) + ;; + "ssh_tunnel") + thinlinc_agent_hostname="localhost" + ;; + *) + echo "Unknown connection mode: $connection_mode. Exiting script." + exit 1 + ;; +esac + +# Update the agent_hostname +/opt/thinlinc/bin/tl-config /vsmagent/agent_hostname=$thinlinc_agent_hostname +if [[ $? -ne 0 ]]; then + echo "Failed to configure Thinlinc agent_hostname." + exit 1 +fi + +# Restart the vsmagent service to apply changes +systemctl restart vsmagent +if [[ $? -ne 0 ]]; then + echo "Failed to restart Thinlinc vsmagent service" + exit 1 +fi + +echo "Thinlinc agent_hostname configurations completed." diff --git a/templates/single-nodearray_template_1.0.0.2.txt b/templates/single-nodearray_template_1.0.0.3.txt similarity index 82% rename from templates/single-nodearray_template_1.0.0.2.txt rename to templates/single-nodearray_template_1.0.0.3.txt index 8f4b318..bbb787c 100644 --- a/templates/single-nodearray_template_1.0.0.2.txt +++ b/templates/single-nodearray_template_1.0.0.3.txt @@ -35,6 +35,11 @@ Category = Infrastructure PublicPort = 443 Protocol = tcp + [[[configuration]]] + thinlinc.enable_web = $EnableWeb + thinlinc.web_port = $WebPort + thinlinc.connection_mode = $ConnectionMode + [[[cluster-init cyclecloud-thinlinc:default:1.0.1]]] [[nodearray login]] @@ -132,6 +137,28 @@ Order = 20 Description = Cluster init specs to apply to the node ParameterType = Cloud.ClusterInitSpecs + [[parameters Thinlinc]] + [[[parameter EnableWeb]]] + Label = Enable Web Interface + DefaultValue = false + ParameterType = Boolean + Config.Label = Enable HTML Remote Desktop + + [[[parameter WebPort]]] + Label = Web Port + Description = Web Port to connect to the Web Interface² + DefaultValue = 443 + ParameterType = Integer + Conditions.Excluded := EnableWeb isnt true + + [[[parameter ConnectionMode]]] + Label = Connection Mode + ParameterType = StringList + Config.Label = The connection mode from the client + Config.Plugin = pico.form.Dropdown + Config.Entries := {[Label="Private IP"; Value="private_ip"], [Label="Public IP"; Value="public_ip"], [Label="SSH Tunnel"; Value="ssh_tunnel"]} + DefaultValue = private_ip + [[parameters Advanced Networking]] Description = Advanced networking settings