{"id":7956,"date":"2024-05-21T14:50:07","date_gmt":"2024-05-21T12:50:07","guid":{"rendered":"https:\/\/www.credativ.de\/?p=7956"},"modified":"2025-11-24T18:29:17","modified_gmt":"2025-11-24T17:29:17","slug":"apache-guacamole-do-you-prefer-salsa-or-guacamole","status":"publish","type":"post","link":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/","title":{"rendered":"Apache Guacamole &#8211; Do you prefer Salsa or Guacamole?"},"content":{"rendered":"<p data-source-line=\"2\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-7967\" src=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-1024x410.png\" alt=\"\" width=\"512\" height=\"205\" srcset=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-1024x410.png 1024w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-300x120.png 300w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-768x307.png 768w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-1536x614.png 1536w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-600x240.png 600w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-180x72.png 180w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole.png 1600w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/p>\n<p data-source-line=\"2\">If you had the choice, would you rather take Salsa or Guacamole? Let me explain, why you should choose Guacamole over Salsa.<\/p>\n<p data-source-line=\"4\">In this blog article, we want to take a look at one of the smaller Apache projects out there called <a href=\"https:\/\/guacamole.apache.org\/\">Apache Guacamole<\/a>. Apache Guacamole allows administrators to run a web based client tool for accessing remote applications and servers. This can include remote desktop systems, applications or terminal sessions. Users can simply access them by using their web browsers. No special client or other tools are required. From there, they can login and access all pre-configured remote connections that have been specified by an administrator.<\/p>\n<p data-source-line=\"7\">Thereby, Guacamole supports a wide variety of protocols like VNC, RDP, and SSH. This way, users can basically access anything from remote terminal sessions to full fledged Graphical User Interfaces provided by operation systems like Debian, Ubuntu, Windows and many more.<\/p>\n<h2 id=\"convert-every-window-application-to-a-web-application\" data-source-line=\"9\">Convert every window application to a web application<\/h2>\n<p data-source-line=\"11\">If we spin this idea further, technically every window application that isn&#8217;t designed to run as an web application can be transformed to a web application by using Apache Guacamole. We helped a customer to bring its legacy application to Kubernetes, so that other users could use their web browsers to run it. Sure, implementing the application from ground up, so that it follows the Cloud Native principles, is the preferred solution. As always though, efforts, experience and costs may exceed the available time and budget and in that cases, Apache Guacamole can provide a relatively easy way for realizing such projects.<\/p>\n<p data-source-line=\"13\">In this blog article, I want to show you, how easy it is to run a legacy window application as a web app on Kubernetes. For this, we will use a Kubernetes cluster created by <code>kind<\/code> and create a Kubernetes Deployment to make\u00a0<code>kate<\/code>\u00a0&#8211; a KDE based text editor &#8211; our own web application. It&#8217;s just an example, so there might be better application to transform but this one should be fine to show you the concepts behind Apache Guacamole.<\/p>\n<p data-source-line=\"15\">So, without further ado, let&#8217;s create our <code>kate<\/code>\u00a0web application.<\/p>\n<h2 id=\"preparation-of-kubernetes\" data-source-line=\"17\">Preparation of Kubernetes<\/h2>\n<p data-source-line=\"19\">Before we can start, we must make sure that we have a Kubernetes cluster, that we can test on. If you already have a cluster, simply skip this section. If not, let&#8217;s spin one up by using\u00a0<code>kind<\/code>.<\/p>\n<p data-source-line=\"19\"><code>kind<\/code> is a lightweight implementation of Kubernetes that can be run on every machine. It&#8217;s written in Go and can be installed like this:<\/p>\n<pre class=\"language-bash bash\" data-role=\"codeBlock\" data-info=\"bash {data-source-line=&quot;21&quot;}\" data-source-line=\"21\"><code><span class=\"token comment\"># For AMD64 \/ x86_64<\/span>\r\n<span class=\"token punctuation\">[<\/span> <span class=\"token variable\">$(<span class=\"token function\">uname<\/span> <span class=\"token parameter variable\">-m<\/span>)<\/span> <span class=\"token operator\">=<\/span> x86_64 <span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token function\">curl<\/span> <span class=\"token parameter variable\">-Lo<\/span> .\/kind https:\/\/kind.sigs.k8s.io\/dl\/v0.22.0\/kind-linux-amd64\r\n<span class=\"token comment\"># For ARM64<\/span>\r\n<span class=\"token punctuation\">[<\/span> <span class=\"token variable\">$(<span class=\"token function\">uname<\/span> <span class=\"token parameter variable\">-m<\/span>)<\/span> <span class=\"token operator\">=<\/span> aarch64 <span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token function\">curl<\/span> <span class=\"token parameter variable\">-Lo<\/span> .\/kind https:\/\/kind.sigs.k8s.io\/dl\/v0.22.0\/kind-linux-arm64\r\n<span class=\"token function\">chmod<\/span> +x .\/kind\r\n<span class=\"token function\">sudo<\/span> <span class=\"token function\">mv<\/span> .\/kind \/usr\/local\/bin\/kind\r\n<\/code><\/pre>\n<p data-source-line=\"30\">Next, we need to install some dependencies for our cluster. This includes for example <code>docker<\/code> and <code>kubectl<\/code>.<\/p>\n<pre class=\"language-bash bash\" data-role=\"codeBlock\" data-info=\"bash {data-source-line=&quot;31&quot;}\" data-source-line=\"31\"><code>$ <span class=\"token function\">sudo<\/span> <span class=\"token function\">apt<\/span> <span class=\"token function\">install<\/span> docker.io kubernetes-client\r\n<\/code><\/pre>\n<p data-source-line=\"35\">By creating our Kubernetes Cluster with <code>kind<\/code>, we need <code>docker<\/code> because the Kubernetes cluster is running within Docker containers on your host machine. Installing <code>kubectl<\/code> allows us to access the Kubernetes after creating it.<\/p>\n<p data-source-line=\"35\">Once we installed those packages, we can start to create our cluster now. First, we must define a cluster configuration. It defines which ports are accessible from our host machine, so that we can access our Guacamole application. Remember, the cluster itself is operated within Docker containers, so we must ensure that we can access it from our machine. For this, we define the following configuration which we save in a file called <code>cluster.yaml<\/code>:<\/p>\n<pre class=\"language-yaml yaml\" data-role=\"codeBlock\" data-info=\"yaml {data-source-line=&quot;36&quot;}\" data-source-line=\"36\"><code><span class=\"token key atrule\">kind<\/span><span class=\"token punctuation\">:<\/span> Cluster\r\n<span class=\"token key atrule\">apiVersion<\/span><span class=\"token punctuation\">:<\/span> kind.x<span class=\"token punctuation\">-<\/span>k8s.io\/v1alpha4\r\n<span class=\"token key atrule\">nodes<\/span><span class=\"token punctuation\">:<\/span>\r\n<span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">role<\/span><span class=\"token punctuation\">:<\/span> control<span class=\"token punctuation\">-<\/span>plane\r\n  <span class=\"token key atrule\">extraPortMappings<\/span><span class=\"token punctuation\">:<\/span>\r\n  <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">containerPort<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">30000<\/span>\r\n    <span class=\"token key atrule\">hostPort<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">30000<\/span>\r\n    <span class=\"token key atrule\">listenAddress<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"127.0.0.1\"<\/span>\r\n    <span class=\"token key atrule\">protocol<\/span><span class=\"token punctuation\">:<\/span> TCP\r\n<\/code><\/pre>\n<p data-source-line=\"47\">Hereby, we basically map the container&#8217;s port 30000 to our local machine&#8217;s port 30000, so that we can easily access it later on. Keep this in mind because it will be the port that we will use with our web browser to access our <code>kate<\/code> instance.<\/p>\n<p data-source-line=\"47\">Ultimately, this configuration is consumed by <code>kind<\/code> . With it, you can also adjust multiple other parameters of your cluster besides of just modifying the port configuration which are not mentioned here. It&#8217;s worth to take a look kate&#8217;s <a href=\"https:\/\/kind.sigs.k8s.io\/docs\/user\/configuration\">documentation<\/a> for this.<\/p>\n<p data-source-line=\"49\">As soon as you saved the configuration to <code>cluster.yaml<\/code>, we can now start to create our cluster:<\/p>\n<pre class=\"language-bash bash\" data-role=\"codeBlock\" data-info=\"bash {data-source-line=&quot;50&quot;}\" data-source-line=\"50\"><code>$ <span class=\"token function\">sudo<\/span> kind create cluster <span class=\"token parameter variable\">--name<\/span> guacamole <span class=\"token parameter variable\">--config<\/span> cluster.yaml\r\nCreating cluster <span class=\"token string\">\"guacamole\"<\/span> <span class=\"token punctuation\">..<\/span>.\r\n \u2713 Ensuring <span class=\"token function\">node<\/span> image <span class=\"token punctuation\">(<\/span>kindest\/node:v1.29.2<span class=\"token punctuation\">)<\/span> \ud83d\uddbc\r\n \u2713 Preparing nodes \ud83d\udce6\r\n \u2713 Writing configuration \ud83d\udcdc\r\n \u2713 Starting control-plane \ud83d\udd79\ufe0f\r\n \u2713 Installing CNI \ud83d\udd0c\r\n \u2713 Installing StorageClass \ud83d\udcbe\r\nSet kubectl context to <span class=\"token string\">\"kind-guacamole\"<\/span>\r\nYou can now use your cluster with:\r\n\r\nkubectl cluster-info <span class=\"token parameter variable\">--context<\/span> kind-guacamole\r\n\r\nHave a question, bug, or feature request? Let us know<span class=\"token operator\">!<\/span> https:\/\/kind.sigs.k8s.io\/<span class=\"token comment\">#community \ud83d\ude42<\/span>\r\n<\/code><\/pre>\n<p data-source-line=\"67\">Since we don&#8217;t want to run everything in root context, let&#8217;s export the\u00a0<code>kubeconfig<\/code>, so that we can use it with\u00a0<code>kubectl<\/code> by using our unpriviledged user:<\/p>\n<pre class=\"language-bash bash\" data-role=\"codeBlock\" data-info=\"bash {data-source-line=&quot;68&quot;}\" data-source-line=\"68\"><code>$ <span class=\"token function\">sudo<\/span> kind <span class=\"token builtin class-name\">export<\/span> kubeconfig <span class=\"token punctuation\">\\<\/span>\r\n    <span class=\"token parameter variable\">--name<\/span> guacamole <span class=\"token punctuation\">\\<\/span>\r\n    <span class=\"token parameter variable\">--kubeconfig<\/span> <span class=\"token environment constant\">$PWD<\/span>\/config\r\n\r\n$ <span class=\"token builtin class-name\">export<\/span> <span class=\"token assign-left variable\">KUBECONFIG<\/span><span class=\"token operator\">=<\/span><span class=\"token environment constant\">$PWD<\/span>\/config\r\n$ <span class=\"token function\">sudo<\/span> <span class=\"token function\">chown<\/span> <span class=\"token variable\">$(<span class=\"token function\">logname<\/span>)<\/span><span class=\"token builtin class-name\">:<\/span> <span class=\"token variable\">$KUBECONFIG<\/span>\r\n<\/code><\/pre>\n<p data-source-line=\"77\">By doing so, we are ready and can access our Kubernetes cluster using <code>kubectl<\/code> now. This is our baseline to start migrating our application.<\/p>\n<h2 id=\"creation-of-the-guacamole-deployment\" data-source-line=\"79\">Creation of the Guacamole Deployment<\/h2>\n<p data-source-line=\"80\">In order to run our application on Kubernetes, we need some sort of workload resource. Typically, you could create a Pod, Deployment, Statefulset or Daemonset to run workloads on a cluster.<\/p>\n<p data-source-line=\"82\">Let&#8217;s create the Kubernetes Deployment for our own application. The example shown below shows the deployment&#8217;s general structure. Each container definition will have their dedicated examples afterwards to explain them in more detail.<\/p>\n<pre class=\"language-yaml yaml\" data-role=\"codeBlock\" data-info=\"yaml {data-source-line=&quot;84&quot;}\" data-source-line=\"84\"><code><span class=\"token key atrule\">apiVersion<\/span><span class=\"token punctuation\">:<\/span> apps\/v1\r\n<span class=\"token key atrule\">kind<\/span><span class=\"token punctuation\">:<\/span> Deployment\r\n<span class=\"token key atrule\">metadata<\/span><span class=\"token punctuation\">:<\/span>\r\n  <span class=\"token key atrule\">labels<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token key atrule\">app<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate\r\n  <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate\r\n<span class=\"token key atrule\">spec<\/span><span class=\"token punctuation\">:<\/span>\r\n  <span class=\"token key atrule\">replicas<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">1<\/span>\r\n  <span class=\"token key atrule\">selector<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token key atrule\">matchLabels<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token key atrule\">app<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate\r\n  <span class=\"token key atrule\">template<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token key atrule\">metadata<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token key atrule\">labels<\/span><span class=\"token punctuation\">:<\/span>\r\n        <span class=\"token key atrule\">app<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate\r\n    <span class=\"token key atrule\">spec<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token key atrule\">containers<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token comment\"># The guacamole server component that each<\/span>\r\n      <span class=\"token comment\"># user will connect to via their browser<\/span>\r\n      <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> guacamole<span class=\"token punctuation\">-<\/span>server\r\n        <span class=\"token key atrule\">image<\/span><span class=\"token punctuation\">:<\/span> docker.io\/guacamole\/guacamole<span class=\"token punctuation\">:<\/span>1.5.4\r\n        <span class=\"token punctuation\">...<\/span>\r\n      <span class=\"token comment\"># The daemon that opens the connection to the<\/span>\r\n      <span class=\"token comment\"># remote entity<\/span>\r\n      <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> guacamole<span class=\"token punctuation\">-<\/span>guacd\r\n        <span class=\"token key atrule\">image<\/span><span class=\"token punctuation\">:<\/span> docker.io\/guacamole\/guacd<span class=\"token punctuation\">:<\/span>1.5.4\r\n        <span class=\"token punctuation\">...<\/span>\r\n      <span class=\"token comment\"># Our own self written application that we<\/span>\r\n      <span class=\"token comment\"># want to make accessible via the web.<\/span>\r\n      <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate\r\n        <span class=\"token key atrule\">image<\/span><span class=\"token punctuation\">:<\/span> registry.example.com\/own<span class=\"token punctuation\">-<\/span>app\/web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate<span class=\"token punctuation\">:<\/span>0.0.1\r\n        <span class=\"token punctuation\">...<\/span>\r\n      <span class=\"token key atrule\">volumes<\/span><span class=\"token punctuation\">:<\/span>\r\n        <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> guacamole<span class=\"token punctuation\">-<\/span>config\r\n          <span class=\"token key atrule\">secret<\/span><span class=\"token punctuation\">:<\/span>\r\n            <span class=\"token key atrule\">secretName<\/span><span class=\"token punctuation\">:<\/span> guacamole<span class=\"token punctuation\">-<\/span>config\r\n        <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> guacamole<span class=\"token punctuation\">-<\/span>server\r\n          <span class=\"token key atrule\">emptyDir<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span>\r\n        <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate<span class=\"token punctuation\">-<\/span>home\r\n          <span class=\"token key atrule\">emptyDir<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span>\r\n        <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate<span class=\"token punctuation\">-<\/span>tmp\r\n          <span class=\"token key atrule\">emptyDir<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span>\r\n<\/code><\/pre>\n<p data-source-line=\"129\">As you can see, we need three containers and some volumes for our application. The first two containers are dedicated to Apache Guacamole itself. First, it&#8217;s the server component which is the external endpoint for clients to access our web application. It serves the web server as well as the user management and configuration to run Apache Guacamole.<\/p>\n<p data-source-line=\"131\">Next to this, there is the <code>guacd<\/code> daemon. This is the core component of Guacamole which creates the remote connections to the application based on the configuration done to the server. This daemon forwards the remote connection to the clients by making it accessible to the Guacamole server which then forwards the connection to the end user.<\/p>\n<p data-source-line=\"133\">Finally, we have our own application. It will offer a connection endpoint to the <code>guacd<\/code> daemon using one of Guacamole&#8217;s supported protocols and provide the Graphical User Interface (GUI).<\/p>\n<h4 id=\"guacamole-server\" data-source-line=\"137\">Guacamole Server<\/h4>\n<p data-source-line=\"138\">Now, let&#8217;s deep dive into each container specification. We are starting with the Guacamole server instance. This one handles the session and user management and contains the configuration which defines what remote connections are available and what are not.<\/p>\n<pre class=\"language-yaml yaml\" data-role=\"codeBlock\" data-info=\"yaml {data-source-line=&quot;140&quot;}\" data-source-line=\"140\"><code><span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> guacamole<span class=\"token punctuation\">-<\/span>server\r\n  <span class=\"token key atrule\">image<\/span><span class=\"token punctuation\">:<\/span> docker.io\/guacamole\/guacamole<span class=\"token punctuation\">:<\/span>1.5.4\r\n  <span class=\"token key atrule\">env<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> GUACD_HOSTNAME\r\n      <span class=\"token key atrule\">value<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"localhost\"<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> GUACD_PORT\r\n      <span class=\"token key atrule\">value<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"4822\"<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> GUACAMOLE_HOME\r\n      <span class=\"token key atrule\">value<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"\/data\/guacamole\/settings\"<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> HOME\r\n      <span class=\"token key atrule\">value<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"\/data\/guacamole\"<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> WEBAPP_CONTEXT\r\n      <span class=\"token key atrule\">value<\/span><span class=\"token punctuation\">:<\/span> ROOT\r\n  <span class=\"token key atrule\">volumeMounts<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> guacamole<span class=\"token punctuation\">-<\/span>config\r\n      <span class=\"token key atrule\">mountPath<\/span><span class=\"token punctuation\">:<\/span> \/data\/guacamole\/settings\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> guacamole<span class=\"token punctuation\">-<\/span>server\r\n      <span class=\"token key atrule\">mountPath<\/span><span class=\"token punctuation\">:<\/span> \/data\/guacamole\r\n  <span class=\"token key atrule\">ports<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> http\r\n      <span class=\"token key atrule\">containerPort<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">8080<\/span>\r\n  <span class=\"token key atrule\">securityContext<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token key atrule\">allowPrivilegeEscalation<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token boolean important\">false<\/span>\r\n    <span class=\"token key atrule\">privileged<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token boolean important\">false<\/span>\r\n    <span class=\"token key atrule\">readOnlyRootFilesystem<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token boolean important\">true<\/span>\r\n    <span class=\"token key atrule\">capabilities<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token key atrule\">drop<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">\"all\"<\/span><span class=\"token punctuation\">]<\/span>\r\n  <span class=\"token key atrule\">resources<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token key atrule\">limits<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token key atrule\">cpu<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"250m\"<\/span>\r\n      <span class=\"token key atrule\">memory<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"256Mi\"<\/span>\r\n    <span class=\"token key atrule\">requests<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token key atrule\">cpu<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"250m\"<\/span>\r\n      <span class=\"token key atrule\">memory<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"256Mi\"<\/span>\r\n<\/code><\/pre>\n<p data-source-line=\"177\">Since it needs to connect to the <code>guacd<\/code> daemon, we have to provide the connection information for <code>guacd<\/code> by passing them into the container using environment variables like <code>GUACD_HOSTNAME<\/code> or <code>GUACD_PORT<\/code>. In addition, Guacamole would usually be accessible via <code>http:\/\/&lt;your domain&gt;\/guacamole<\/code>.<\/p>\n<p data-source-line=\"177\">This behavior however can be adjusted by modifying the <code>WEBAPP_CONTEXT<\/code> environment variable. In our case for example, we don&#8217;t want a user to type in <code>\/guacamole<\/code> to access it but simply using it like this <code>http:\/\/&lt;your domain&gt;\/<\/code><\/p>\n<h4 id=\"guacamole-guacd\" data-source-line=\"177\">Guacamole Guacd<\/h4>\n<p data-source-line=\"179\">Then, there is the <code>guacd<\/code> daemon.<\/p>\n<pre class=\"language-yaml yaml\" data-role=\"codeBlock\" data-info=\"yaml {data-source-line=&quot;181&quot;}\" data-source-line=\"181\"><code><span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> guacamole<span class=\"token punctuation\">-<\/span>guacd\r\n  <span class=\"token key atrule\">image<\/span><span class=\"token punctuation\">:<\/span> docker.io\/guacamole\/guacd<span class=\"token punctuation\">:<\/span>1.5.4\r\n  <span class=\"token key atrule\">args<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token punctuation\">-<\/span> \/bin\/sh\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token punctuation\">-<\/span>c\r\n    <span class=\"token punctuation\">-<\/span> \/opt\/guacamole\/sbin\/guacd <span class=\"token punctuation\">-<\/span>b 127.0.0.1 <span class=\"token punctuation\">-<\/span>L $GUACD_LOG_LEVEL <span class=\"token punctuation\">-<\/span>f\r\n  <span class=\"token key atrule\">securityContext<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token key atrule\">allowPrivilegeEscalation<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token boolean important\">true<\/span>\r\n    <span class=\"token key atrule\">privileged<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token boolean important\">false<\/span>\r\n    <span class=\"token key atrule\">readOnlyRootFileSystem<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token boolean important\">true<\/span>\r\n    <span class=\"token key atrule\">capabilities<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token key atrule\">drop<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">\"all\"<\/span><span class=\"token punctuation\">]<\/span>\r\n  <span class=\"token key atrule\">resources<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token key atrule\">limits<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token key atrule\">cpu<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"250m\"<\/span>\r\n      <span class=\"token key atrule\">memory<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"512Mi\"<\/span>\r\n    <span class=\"token key atrule\">requests<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token key atrule\">cpu<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"250m\"<\/span>\r\n      <span class=\"token key atrule\">memory<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"512Mi\"<\/span>\r\n<\/code><\/pre>\n<p data-source-line=\"203\">It&#8217;s worth mentioning that you should modify the arguments used to start the <code>guacd<\/code> container. In the example above, we want <code>guacd<\/code> to only listen to localhost for security reasons. All containers within the same pod share the same network namespace. As a a result, they can access each other via localhost. This said, there is no need to make this service accessible to over services running outside of this pod, so we can limit it to localhost only. To achieve this, you would need to set the <code>-b 127.0.0.1<\/code> parameter which sets the corresponding listen address. Since you need to overwrite the whole command, don&#8217;t forget to also specify the <code>-L<\/code> and <code>-f<\/code> parameter. The first parameter sets the log level and the second one set the process in the foreground.<\/p>\n<h4 id=\"web-based-kate\" data-source-line=\"203\">Web Based Kate<\/h4>\n<p data-source-line=\"205\">To finish everything off, we have the\u00a0<code>kate<\/code>\u00a0application which we want to transform to a web application.<\/p>\n<pre class=\"language-yaml yaml\" data-role=\"codeBlock\" data-info=\"yaml {data-source-line=&quot;207&quot;}\" data-source-line=\"207\"><code><span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate\r\n  <span class=\"token key atrule\">image<\/span><span class=\"token punctuation\">:<\/span> registry.example.com\/own<span class=\"token punctuation\">-<\/span>app\/web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate<span class=\"token punctuation\">:<\/span>0.0.1\r\n  <span class=\"token key atrule\">env<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> VNC_SERVER_PORT\r\n      <span class=\"token key atrule\">value<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"5900\"<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> VNC_RESOLUTION_WIDTH\r\n      <span class=\"token key atrule\">value<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"1280\"<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> VNC_RESOLUTION_HEIGHT\r\n      <span class=\"token key atrule\">value<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">\"720\"<\/span>\r\n  <span class=\"token key atrule\">securityContext<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token key atrule\">allowPrivilegeEscalation<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token boolean important\">true<\/span>\r\n    <span class=\"token key atrule\">privileged<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token boolean important\">false<\/span>\r\n    <span class=\"token key atrule\">readOnlyRootFileSystem<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token boolean important\">true<\/span>\r\n    <span class=\"token key atrule\">capabilities<\/span><span class=\"token punctuation\">:<\/span>\r\n      <span class=\"token key atrule\">drop<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">\"all\"<\/span><span class=\"token punctuation\">]<\/span>\r\n  <span class=\"token key atrule\">volumeMounts<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate<span class=\"token punctuation\">-<\/span>home\r\n      <span class=\"token key atrule\">mountPath<\/span><span class=\"token punctuation\">:<\/span> \/home\/kate\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate<span class=\"token punctuation\">-<\/span>tmp\r\n      <span class=\"token key atrule\">mountPath<\/span><span class=\"token punctuation\">:<\/span> \/tmp\r\n<\/code><\/pre>\n<h2 id=\"configuration-of-our-guacamole-setup\" data-source-line=\"230\">Configuration of our Guacamole setup<\/h2>\n<p data-source-line=\"231\">After having the deployment in place, we need to prepare the configuration for our Guacamole setup. In order to know, what users exist and which connections should be offered, we need to provide a mapping configuration to Guacamole.<\/p>\n<p data-source-line=\"233\">In this example, a simple user mapping is shown for demonstration purposes. It uses a static mapping defined in a XML file that is handed over to the Guacamole server. Typically, you would use other authentication methods instead like a database or LDAP.<\/p>\n<p data-source-line=\"235\">This said however, let&#8217;s continue with our static one. For this, we simply define a Kubernetes Secret which is mounted into the Guacamole server. Hereby, it defines two configuration files. One is the so called\u00a0<code>guacamole.properties<\/code>. This is Guacamole&#8217;s main configuration file. Next to this, we also define the <code>user-mapping.xml<\/code>\u00a0which contains all available users and their connections.<\/p>\n<pre class=\"language-yaml yaml\" data-role=\"codeBlock\" data-info=\"yaml {data-source-line=&quot;237&quot;}\" data-source-line=\"237\"><code><span class=\"token key atrule\">apiVersion<\/span><span class=\"token punctuation\">:<\/span> v1\r\n<span class=\"token key atrule\">kind<\/span><span class=\"token punctuation\">:<\/span> Secret\r\n<span class=\"token key atrule\">metadata<\/span><span class=\"token punctuation\">:<\/span>\r\n  <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> guacamole<span class=\"token punctuation\">-<\/span>config\r\n<span class=\"token key atrule\">stringData<\/span><span class=\"token punctuation\">:<\/span>\r\n  <span class=\"token key atrule\">guacamole.properties<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">|<\/span><span class=\"token scalar string\">\r\n    enable-environment-properties: true<\/span>\r\n  <span class=\"token key atrule\">user-mapping.xml<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">|<\/span><span class=\"token scalar string\">\r\n    &lt;user-mapping&gt;\r\n      &lt;authorize username=\"admin\" password=\"PASSWORD\" encoding=\"sha256\"&gt;\r\n        &lt;connection name=\"web-based-kate\"&gt;\r\n          &lt;protocol&gt;vnc&lt;\/protocol&gt;\r\n          &lt;param name=\"hostname\"&gt;localhost&lt;\/param&gt;\r\n          &lt;param name=\"port\"&gt;5900&lt;\/param&gt;\r\n        &lt;\/connection&gt;\r\n      &lt;\/authorize&gt;\r\n    &lt;\/user-mapping&gt;<\/span>\r\n<\/code><\/pre>\n<p data-source-line=\"256\">As you can see, we only defined on specific user called\u00a0<code>admin<\/code>\u00a0which can use a connection called\u00a0<code>web-based-kate<\/code>. In order to access the\u00a0<code>kate<\/code> instance, Guacamole would use VNC as the configured protocol. To make this happen, our web application must offer a VNC Server port on the other side, so that the <code>guacd<\/code> daemon can then access it to forward the remote session to clients. Keep in mind that you need to replace the string <code>PASSWORD<\/code> to a proper sha256 sum which contains the password. The sha256 sum could look like this for example:<\/p>\n<pre class=\"language-bash bash\" data-role=\"codeBlock\" data-info=\"bash {data-source-line=&quot;258&quot;}\" data-source-line=\"258\"><code>$ <span class=\"token builtin class-name\">echo<\/span> <span class=\"token parameter variable\">-n<\/span> <span class=\"token string\">\"test\"<\/span> <span class=\"token operator\">|<\/span> sha256sum\r\n9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08  -\r\n<\/code><\/pre>\n<p data-source-line=\"263\">Next, the hostname parameter is referencing the corresponding VNC server of our <code>kate<\/code> container. Since we are starting our container alongside with our Guacamole containers within the same pod, the Guacamole Server as well as the <code>guacd<\/code>\u00a0daemon can access this application via\u00a0<code>localhost<\/code>. There is no need to set up a Kubernetes Service in front of it since only <code>guacd<\/code>\u00a0will access the VNC server and forward the remote session via HTTP to clients accessing Guacamole via their web browsers. Finally, we also need to specify the VNC server port which is typically\u00a0<code>5900<\/code>\u00a0but this could be adjusted if needed.<\/p>\n<p data-source-line=\"265\">The corresponding\u00a0<code>guacamole.properties<\/code>\u00a0is quite short. By enabling the\u00a0<code>enabling-environment-properties<\/code>\u00a0configuration parameter, we make sure that every Guacamole configuration parameter can also be set via environment variables. This way, we don&#8217;t need to modify this configuration file each and every time when we want to adjust the configuration but we only need to provide updated environment variables to the Guacamole server container.<\/p>\n<h2 id=\"make-guacamole-accessible\" data-source-line=\"267\">Make Guacamole accessible<\/h2>\n<p>Last but not least, we must make the Guacamole server accessible for clients. Although each provided service can access each other via localhost, the same does not apply to clients trying to access Guacamole. Therefore, we must make Guacamole&#8217;s server port 8080 available to the outside world. This can be achieved by creating a Kubernetes Service of type <code>NodePort<\/code>. This service is forwarding each request from a local node port to the corresponding container that is offering the configured target port. In our case, this would be the Guacamole server container which is offering port 8080.<\/p>\n<pre class=\"language-yaml yaml\" data-role=\"codeBlock\" data-info=\"yaml {data-source-line=&quot;269&quot;}\" data-source-line=\"269\"><code><span class=\"token key atrule\">apiVersion<\/span><span class=\"token punctuation\">:<\/span> v1\r\n<span class=\"token key atrule\">kind<\/span><span class=\"token punctuation\">:<\/span> Service\r\n<span class=\"token key atrule\">metadata<\/span><span class=\"token punctuation\">:<\/span>\r\n  <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate\r\n<span class=\"token key atrule\">spec<\/span><span class=\"token punctuation\">:<\/span>\r\n  type: NodePort\r\n  <span class=\"token key atrule\">selector<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token key atrule\">app<\/span><span class=\"token punctuation\">:<\/span> web<span class=\"token punctuation\">-<\/span>based<span class=\"token punctuation\">-<\/span>kate\r\n  <span class=\"token key atrule\">ports<\/span><span class=\"token punctuation\">:<\/span>\r\n    <span class=\"token punctuation\">-<\/span> <span class=\"token key atrule\">name<\/span><span class=\"token punctuation\">:<\/span> http\r\n      <span class=\"token key atrule\">protocol<\/span><span class=\"token punctuation\">:<\/span> TCP\r\n      <span class=\"token key atrule\">port<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">8080<\/span>\r\n      <span class=\"token key atrule\">targetPort<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">8080\r\n      nodePort: 30000<\/span>\r\n<\/code><\/pre>\n<p data-source-line=\"284\">This specific port is then mapped to the Node&#8217;s 30000 port for which we also configured the <code>kind<\/code> cluster in such a way that it forwards its node port 30000 to the host system&#8217;s port 30000. This port is the one that we would need to use to access Guacamole with our web browsers.<\/p>\n<h2 id=\"prepartion-of-the-application-container\" data-source-line=\"284\">Prepartion of the Application container<\/h2>\n<p data-source-line=\"285\">Before we can start to deploy our application, we need to prepare our\u00a0<code>kate<\/code> container. For this, we simply create a Debian container that is running <code>kate<\/code>. Keep in mind that you would typically use lightweight base images like\u00a0<code>alpine<\/code> to run applications like this. For this demonstration however, we use the Debian images since it is easier to spin it up but in general you only need a small friction of the functionality that is provided by this base image. Moreover &#8211; from an security point of view &#8211; you want to keep your images small to minimize the attack surface and make sure it is easier to maintain. For now however, we will continue with the Debian image.<\/p>\n<p data-source-line=\"287\">In the example below, you can see a Dockerfile for the\u00a0<code>kate<\/code> container.<\/p>\n<pre class=\"language-dockerfile Dockerfile\" data-role=\"codeBlock\" data-info=\"Dockerfile {data-source-line=&quot;289&quot;}\" data-source-line=\"289\"><code><span class=\"token instruction\"><span class=\"token keyword keyword-FROM\">FROM<\/span> debian:12<\/span>\r\n\r\n<span class=\"token comment\"># Install all required packages<\/span>\r\n<span class=\"token instruction\"><span class=\"token keyword keyword-RUN\">RUN<\/span> apt update &amp;&amp; <span class=\"token operator\">\\<\/span>\r\n    apt install -y x11vnc xvfb kate<\/span>\r\n\r\n<span class=\"token comment\"># Add user for kate<\/span>\r\n<span class=\"token instruction\"><span class=\"token keyword keyword-RUN\">RUN<\/span> adduser kate --system --home \/home\/kate -uid 999<\/span>\r\n\r\n<span class=\"token comment\"># Copy our entrypoint in the container<\/span>\r\n<span class=\"token instruction\"><span class=\"token keyword keyword-COPY\">COPY<\/span> entrypoint.sh \/opt<\/span>\r\n\r\n<span class=\"token instruction\"><span class=\"token keyword keyword-USER\">USER<\/span> 999<\/span>\r\n<span class=\"token instruction\"><span class=\"token keyword keyword-ENTRYPOINT\">ENTRYPOINT<\/span> [ <span class=\"token string\">\"\/opt\/entrypoint.sh\"<\/span> ]<\/span>\r\n<\/code><\/pre>\n<p data-source-line=\"305\">Here you see that we create a dedicated user called\u00a0<code>kate<\/code> (User ID 999) for which we also create a home directory. This home directory is used for all files that <code>kate<\/code>\u00a0is creating during runtime. Since we set the\u00a0<code>readOnlyRootFilesystem<\/code>\u00a0to\u00a0<code>true<\/code>, we must make sure that we mount some sort of writable volume (e.g <code>EmptyDir<\/code>) to kate&#8217;s home directory. Otherwise, kate wouldn&#8217;t be able to write any runtime data then.<\/p>\n<p data-source-line=\"307\">Moreover, we have to install the following three packages:<\/p>\n<ul data-source-line=\"309\">\n<li data-source-line=\"309\">x11vnc<\/li>\n<li data-source-line=\"310\">xvfb<\/li>\n<li data-source-line=\"311\">kate<\/li>\n<\/ul>\n<p data-source-line=\"313\">These are the only packages we need for our container. In addition, we also need to create an entrypoint script to start the application and prepare the container accordingly. This entrypoint script creates the configuration for <code>kate<\/code>, starts it in a virtual display by using\u00a0<code>xvfb-run<\/code> and provides this virtual display to end users by using the VNC server via <code>x11vnc<\/code>. In the meantime,\u00a0<code>xdrrinfo<\/code> is used to check if the virtual display came up successfully after starting <code>kate<\/code>. If it takes to long, the entrypoint script will fail by returning the exit code 1.<\/p>\n<p data-source-line=\"313\">By doing this, we ensure that the container is not stuck in an infinite loop during a failure and let Kubernetes restart the container whenever it couldn&#8217;t start the application successfully. Furthermore, it is important to check if the virtual display came up prior of handing it over to the VNC server because the VNC server would crash if the virtual display is not up and running since it needs something to share. On the other hand though, our container will be killed whenever <code>kate<\/code> is terminated because it would also terminate the virtual display and in the end it would then also terminate the VNC server which let&#8217;s the container exit, too. This way, we don&#8217;t need take care of it by our own.<\/p>\n<pre class=\"language-bash bash\" data-role=\"codeBlock\" data-info=\"bash {data-source-line=&quot;315&quot;}\" data-source-line=\"315\"><code><span class=\"token shebang important\">#!\/bin\/bash<\/span>\r\n\r\n<span class=\"token builtin class-name\">set<\/span> <span class=\"token parameter variable\">-e<\/span>\r\n\r\n<span class=\"token comment\"># If no resolution is provided<\/span>\r\n<span class=\"token keyword keyword-if\">if<\/span> <span class=\"token punctuation\">[<\/span> <span class=\"token parameter variable\">-z<\/span> <span class=\"token variable\">$VNC_RESOLUTION_WIDTH<\/span> <span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword keyword-then\">then<\/span>\r\n  <span class=\"token assign-left variable\">VNC_RESOLUTION_WIDTH<\/span><span class=\"token operator\">=<\/span><span class=\"token number\">1920<\/span>\r\n<span class=\"token keyword keyword-fi\">fi<\/span>\r\n\r\n<span class=\"token keyword keyword-if\">if<\/span> <span class=\"token punctuation\">[<\/span> <span class=\"token parameter variable\">-z<\/span> <span class=\"token variable\">$VNC_RESOLUTION_HEIGHT<\/span> <span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword keyword-then\">then<\/span>\r\n  <span class=\"token assign-left variable\">VNC_RESOLUTION_HEIGHT<\/span><span class=\"token operator\">=<\/span><span class=\"token number\">1080<\/span>\r\n<span class=\"token keyword keyword-fi\">fi<\/span>\r\n\r\n<span class=\"token comment\"># If no server port is provided<\/span>\r\n<span class=\"token keyword keyword-if\">if<\/span> <span class=\"token punctuation\">[<\/span> <span class=\"token parameter variable\">-z<\/span> <span class=\"token variable\">$VNC_SERVER_PORT<\/span> <span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword keyword-then\">then<\/span>\r\n  <span class=\"token assign-left variable\">VNC_SERVER_PORT<\/span><span class=\"token operator\">=<\/span><span class=\"token number\">5900<\/span>\r\n<span class=\"token keyword keyword-fi\">fi<\/span>\r\n\r\n<span class=\"token comment\"># Prepare configuration for kate<\/span>\r\n<span class=\"token function\">mkdir<\/span> <span class=\"token parameter variable\">-p<\/span> <span class=\"token environment constant\">$HOME<\/span>\/.local\/share\/kate\r\n<span class=\"token builtin class-name\">echo<\/span> <span class=\"token string\">\"[MainWindow0]\r\n\"<\/span><span class=\"token variable\">$VNC_RESOLUTION_WIDTH<\/span><span class=\"token string\">\"x\"<\/span><span class=\"token variable\">$VNC_RESOLUTION_HEIGHT<\/span><span class=\"token string\">\" screen: Height=<span class=\"token variable\">$VNC_RESOLUTION_HEIGHT<\/span>\r\n\"<\/span><span class=\"token variable\">$VNC_RESOLUTION_WIDTH<\/span><span class=\"token string\">\"x\"<\/span><span class=\"token variable\">$VNC_RESOLUTION_HEIGHT<\/span><span class=\"token string\">\" screen: Width=<span class=\"token variable\">$VNC_RESOLUTION_WIDTH<\/span>\r\n\"<\/span><span class=\"token variable\">$VNC_RESOLUTION_WIDTH<\/span><span class=\"token string\">\"x\"<\/span><span class=\"token variable\">$VNC_RESOLUTION_HEIGHT<\/span><span class=\"token string\">\" screen: XPosition=0\r\n\"<\/span><span class=\"token variable\">$VNC_RESOLUTION_WIDTH<\/span><span class=\"token string\">\"x\"<\/span><span class=\"token variable\">$VNC_RESOLUTION_HEIGHT<\/span><span class=\"token string\">\" screen: YPosition=0\r\nActive ViewSpace=0\r\nKate-MDI-Sidebar-Visible=false\"<\/span> <span class=\"token operator\">&gt;<\/span> <span class=\"token environment constant\">$HOME<\/span>\/.local\/share\/kate\/anonymous.katesession\r\n\r\n<span class=\"token comment\"># We need to define an XAuthority file<\/span>\r\n<span class=\"token builtin class-name\">export<\/span> <span class=\"token assign-left variable\"><span class=\"token environment constant\">XAUTHORITY<\/span><\/span><span class=\"token operator\">=<\/span><span class=\"token environment constant\">$HOME<\/span>\/.Xauthority\r\n\r\n<span class=\"token comment\"># Define execution command<\/span>\r\n<span class=\"token assign-left variable\">APPLICATION_CMD<\/span><span class=\"token operator\">=<\/span><span class=\"token string\">\"kate\"<\/span>\r\n\r\n<span class=\"token comment\"># Let's start our application in a virtual display<\/span>\r\nxvfb-run <span class=\"token punctuation\">\\<\/span>\r\n  <span class=\"token parameter variable\">-n<\/span> <span class=\"token number\">99<\/span> <span class=\"token punctuation\">\\<\/span>\r\n  <span class=\"token parameter variable\">-s<\/span> <span class=\"token string\">':99 -screen 0 '<\/span><span class=\"token variable\">$VNC_RESOLUTION_WIDTH<\/span><span class=\"token string\">'x'<\/span><span class=\"token variable\">$VNC_RESOLUTION_HEIGHT<\/span><span class=\"token string\">'x16'<\/span> <span class=\"token punctuation\">\\<\/span>\r\n  <span class=\"token parameter variable\">-f<\/span> <span class=\"token environment constant\">$XAUTHORITY<\/span> <span class=\"token punctuation\">\\<\/span>\r\n  <span class=\"token variable\">$APPLICATION_CMD<\/span> <span class=\"token operator\">&amp;<\/span>\r\n\r\n<span class=\"token comment\"># Let's wait until the virtual display is initalize before<\/span>\r\n<span class=\"token comment\"># we proceed. But don't wait infinitely.<\/span>\r\n<span class=\"token assign-left variable\">TIMEOUT<\/span><span class=\"token operator\">=<\/span><span class=\"token number\">10<\/span>\r\n<span class=\"token keyword keyword-while\">while<\/span> <span class=\"token operator\">!<\/span> <span class=\"token punctuation\">(<\/span>xdriinfo <span class=\"token parameter variable\">-display<\/span> :99 nscreens<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword keyword-do\">do<\/span> \r\n  <span class=\"token function\">sleep<\/span> <span class=\"token number\">1<\/span>\r\n  <span class=\"token builtin class-name\">let<\/span> TIMEOUT-<span class=\"token operator\">=<\/span><span class=\"token number\">1<\/span>\r\n<span class=\"token keyword keyword-done\">done<\/span>\r\n\r\n<span class=\"token comment\"># Now, let's make the virtual display accessible by<\/span>\r\n<span class=\"token comment\"># exposing it via the VNC Server that is listening on<\/span>\r\n<span class=\"token comment\"># localhost and the specified port (e.g. 5900)<\/span>\r\nx11vnc <span class=\"token punctuation\">\\<\/span>\r\n  <span class=\"token parameter variable\">-display<\/span> :99 <span class=\"token punctuation\">\\<\/span>\r\n  <span class=\"token parameter variable\">-nopw<\/span> <span class=\"token punctuation\">\\<\/span>\r\n  <span class=\"token parameter variable\">-localhost<\/span> <span class=\"token punctuation\">\\<\/span>\r\n  <span class=\"token parameter variable\">-rfbport<\/span> <span class=\"token variable\">$VNC_SERVER_PORT<\/span> <span class=\"token punctuation\">\\<\/span>\r\n  <span class=\"token parameter variable\">-forever<\/span>\r\n<\/code><\/pre>\n<p data-source-line=\"376\">After preparing those files, we can now create our image and import it to our Kubernetes cluster by using the following commands:<\/p>\n<pre class=\"language-bash bash\" data-role=\"codeBlock\" data-info=\"bash {data-source-line=&quot;377&quot;}\" data-source-line=\"377\"><code><span class=\"token comment\"># Do not forget to give your entrypoint script<\/span>\r\n<span class=\"token comment\"># the proper permissions do be executed<\/span>\r\n$ <span class=\"token function\">chmod<\/span> +x entrypoint.sh\r\n\r\n<span class=\"token comment\"># Next, build the image and import it into kind,<\/span>\r\n<span class=\"token comment\"># so that it can be used from within the clusters.<\/span>\r\n$ <span class=\"token function\">sudo<\/span> <span class=\"token function\">docker<\/span> build <span class=\"token parameter variable\">-t<\/span> registry.example.com\/own-app\/web-based-kate:0.0.1 <span class=\"token builtin class-name\">.<\/span>\r\n$ <span class=\"token function\">sudo<\/span> kind load <span class=\"token parameter variable\">-n<\/span> guacamole docker-image registry.example.com\/own-app\/web-based-kate:0.0.1\r\n<\/code><\/pre>\n<p data-source-line=\"388\">The image will be imported to\u00a0<code>kind<\/code>, so that every workload resource operated in our <code>kind<\/code> cluster can access it. If you use some other Kubernetes cluster, you would need to upload this to a registry that your cluster can pull images from.<\/p>\n<p data-source-line=\"390\">Finally, we can also apply our previously created Kubernetes manifests to the cluster. Let&#8217;s say we saved everything to one file called <code>kuberentes.yaml<\/code>. Then, you can simply apply it like this:<\/p>\n<pre class=\"language-bash bash\" data-role=\"codeBlock\" data-info=\"bash {data-source-line=&quot;392&quot;}\" data-source-line=\"392\"><code>$ kubectl apply <span class=\"token parameter variable\">-f<\/span> kubernetes.yaml\r\ndeployment.apps\/web-based-kate configured\r\nsecret\/guacamole-config configured\r\nservice\/web-based-kate unchanged\r\n<\/code><\/pre>\n<p data-source-line=\"399\">This way, a Kubernetes Deployment, Secret and Service is created which ultimately creates a Kubernetes Pod which we can access afterwards.<\/p>\n<pre class=\"language-bash bash\" data-role=\"codeBlock\" data-info=\"bash {data-source-line=&quot;400&quot;}\" data-source-line=\"400\"><code>$ kubectl get pod\r\nNAME                              READY   STATUS    RESTARTS   AGE\r\nweb-based-kate-7894778fb6-qwp4z   <span class=\"token number\">3<\/span>\/3     Running   <span class=\"token number\">0<\/span>          10m\r\n<\/code><\/pre>\n<h2 id=\"verification-of-our-deployment\" data-source-line=\"406\">Verification of our Deployment<\/h2>\n<p data-source-line=\"408\">Now, it&#8217;s money time! After preparing everything, we should be able to access our web based <code>kate<\/code>\u00a0application by using our web browser. As mentioned earlier, we configured\u00a0<code>kind<\/code> in such a way that we can access our application by using our local port 30000. Every request to this port is forwarded to the kind control plane node from where it is picked up by the Kubernetes Service of type <code>NodePort<\/code>. This one is then forwarding all requests to our designated Guacamole server container which is offering the web server for accessing remote application&#8217;s via Guacamole.<\/p>\n<p data-source-line=\"410\">If everything works out, you should be able to see the the following login screen:<\/p>\n<p data-source-line=\"410\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-7963 size-large\" src=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-18.31.09-1024x829.png\" alt=\"\" width=\"1024\" height=\"829\" srcset=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-18.31.09-1024x829.png 1024w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-18.31.09-300x243.png 300w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-18.31.09-768x622.png 768w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-18.31.09-600x486.png 600w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-18.31.09-180x146.png 180w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-18.31.09.png 1110w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p data-source-line=\"412\">After successfully login in, the remote connection is established and you should be able to see the welcome screen from <code>kate<\/code>:<\/p>\n<p data-source-line=\"412\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-7959\" src=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.26-1024x825.png\" alt=\"\" width=\"1024\" height=\"825\" srcset=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.26-1024x825.png 1024w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.26-300x242.png 300w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.26-768x619.png 768w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.26-600x483.png 600w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.26-180x145.png 180w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.26.png 1110w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p data-source-line=\"414\">If you click on\u00a0<code>New<\/code>, you can create a new text file:<\/p>\n<p data-source-line=\"414\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-7961\" src=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.55-1024x825.png\" alt=\"\" width=\"1024\" height=\"825\" srcset=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.55-1024x825.png 1024w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.55-300x242.png 300w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.55-768x619.png 768w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.55-600x483.png 600w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.55-180x145.png 180w, https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Screenshot-2024-05-06-at-17.52.55.png 1110w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p data-source-line=\"416\">Those text files can even be saved but keep in mind that they will only exist as long as our Kubernetes Pod exists. Once it gets deleted, the corresponding <code>EmptyDir<\/code>, that we mounted into our <code>kate<\/code> container, gets deleted as well and all files in it are lost. Moreover, the container is set to read-only meaning that a user can only write files to the volumes (e.g.\u00a0<code>EmptyDir<\/code>) that we mounted to our container.<\/p>\n<h2 id=\"conclusion\" data-source-line=\"418\">Conclusion<\/h2>\n<p data-source-line=\"419\">After seeing that it&#8217;s relatively easy to convert every application to a web based one by using Apache Guacamole, there is only one major question left&#8230;<\/p>\n<p data-source-line=\"421\">What do you prefer the most. Salsa or Guacamole?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you had the choice, would you rather take Salsa or Guacamole? Let me explain, why you should choose Guacamole over Salsa. In this blog article, we want to take a look at one of the smaller Apache projects out there called Apache Guacamole. Apache Guacamole allows administrators to run a web based client tool [&hellip;]<\/p>\n","protected":false},"author":38,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1885],"tags":[1936,1931,1932,1941,1940,1775,1938,1933,1937,1935,1934,1838,1939],"class_list":["post-7956","post","type-post","status-publish","format-standard","hentry","category-howtos-en","tag-alpine","tag-apache","tag-apache-guacamole","tag-configmap","tag-daemonset","tag-debian-en","tag-deployment","tag-guacamole","tag-k8s","tag-kate","tag-kind","tag-kubernetes-en","tag-statefulset"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.7 (Yoast SEO v27.7) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Apache Guacamole - Do you prefer Salsa or Guacamole? - credativ\u00ae<\/title>\n<meta name=\"description\" content=\"Apache Guacamole allows users to easily access remote connections via their web browser. Learn more about it.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Apache Guacamole - Do you prefer Salsa or Guacamole?\" \/>\n<meta property=\"og:description\" content=\"Apache Guacamole allows users to easily access remote connections via their web browser. Learn more about it.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/\" \/>\n<meta property=\"og:site_name\" content=\"credativ\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/credativDE\/\" \/>\n<meta property=\"article:published_time\" content=\"2024-05-21T12:50:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-24T17:29:17+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"640\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Michael Sprengel\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@credativde\" \/>\n<meta name=\"twitter:site\" content=\"@credativde\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Michael Sprengel\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/\"},\"author\":{\"name\":\"Michael Sprengel\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#\\\/schema\\\/person\\\/a3e4af81335b70b26cda81a7690bee16\"},\"headline\":\"Apache Guacamole &#8211; Do you prefer Salsa or Guacamole?\",\"datePublished\":\"2024-05-21T12:50:07+00:00\",\"dateModified\":\"2025-11-24T17:29:17+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/\"},\"wordCount\":2518,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/Apache_Guacamole-1024x410.png\",\"keywords\":[\"Alpine\",\"Apache\",\"Apache Guacamole\",\"Configmap\",\"Daemonset\",\"Debian\",\"Deployment\",\"Guacamole\",\"k8s\",\"kate\",\"kind\",\"Kubernetes\",\"Statefulset\"],\"articleSection\":[\"HowTos\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#respond\"]}],\"copyrightYear\":\"2024\",\"copyrightHolder\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/\",\"url\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/\",\"name\":\"Apache Guacamole - Do you prefer Salsa or Guacamole? - credativ\u00ae\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/Apache_Guacamole-1024x410.png\",\"datePublished\":\"2024-05-21T12:50:07+00:00\",\"dateModified\":\"2025-11-24T17:29:17+00:00\",\"description\":\"Apache Guacamole allows users to easily access remote connections via their web browser. Learn more about it.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/Apache_Guacamole-1024x410.png\",\"contentUrl\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/Apache_Guacamole-1024x410.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Apache Guacamole &#8211; Do you prefer Salsa or Guacamole?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/\",\"name\":\"credativ GmbH\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Organization\",\"Place\"],\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#organization\",\"name\":\"credativ\u00ae\",\"url\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/\",\"logo\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#local-main-organization-logo\"},\"image\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#local-main-organization-logo\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/credativDE\\\/\",\"https:\\\/\\\/x.com\\\/credativde\",\"https:\\\/\\\/mastodon.social\\\/@credativde\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/credativ-gmbh\",\"https:\\\/\\\/www.instagram.com\\\/credativ\\\/\"],\"description\":\"Die credativ GmbH ist ein f\u00fchrendes, auf Open Source Software spezialisiertes IT-Dienstleistungs- und Beratungsunternehmen. Wir bieten umfassende und professionelle Services, von Beratung und Infrastruktur-Betrieb \u00fcber 24\\\/7 Support bis hin zu individuellen L\u00f6sungen und Schulungen. Unser Fokus liegt auf dem ganzheitlichen Management von gesch\u00e4ftskritischen Open-Source-Systemen, darunter Betriebssysteme (z.B. Linux), Datenbanken (z.B. PostgreSQL), Konfigurationsmanagement (z.B. Ansible, Puppet) und Virtualisierung. Als engagierter Teil der Open-Source-Community unterst\u00fctzen wir unsere Kunden dabei, die Vorteile freier Software sicher, stabil und effizient in ihrer IT-Umgebung zu nutzen.\",\"legalName\":\"credativ GmbH\",\"foundingDate\":\"2025-03-01\",\"duns\":\"316387060\",\"numberOfEmployees\":{\"@type\":\"QuantitativeValue\",\"minValue\":\"11\",\"maxValue\":\"50\"},\"address\":{\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#local-main-place-address\"},\"geo\":{\"@type\":\"GeoCoordinates\",\"latitude\":\"51.1732374\",\"longitude\":\"6.392010099999999\"},\"telephone\":[\"+4921619174200\",\"08002733284\"],\"contactPoint\":{\"@type\":\"ContactPoint\",\"telephone\":\"08002733284\",\"email\":\"vertrieb@credativ.de\"},\"openingHoursSpecification\":[{\"@type\":\"OpeningHoursSpecification\",\"dayOfWeek\":[\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\"],\"opens\":\"09:00\",\"closes\":\"17:00\"},{\"@type\":\"OpeningHoursSpecification\",\"dayOfWeek\":[\"Saturday\",\"Sunday\"],\"opens\":\"00:00\",\"closes\":\"00:00\"}],\"email\":\"info@credativ.de\",\"areaServed\":\"D-A-CH\",\"vatID\":\"DE452151696\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/#\\\/schema\\\/person\\\/a3e4af81335b70b26cda81a7690bee16\",\"name\":\"Michael Sprengel\",\"description\":\"Michael Sprengel has been with credativ since 2015, after completing his Bachelor degree in computer science at the University of Applied Science Hochschule Niederrhein. After his study, he started his career as a consultant here at credativ and quickly became one of the team leads in our company. His expertise ranges from DevOps, automation up to containerization.\"},{\"@type\":\"PostalAddress\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#local-main-place-address\",\"streetAddress\":\"Hennes-Weisweiler-Allee 23\",\"addressLocality\":\"M\u00f6nchengladbach\",\"postalCode\":\"41179\",\"addressRegion\":\"Deutschland\",\"addressCountry\":\"DE\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.credativ.de\\\/en\\\/blog\\\/howtos-en\\\/apache-guacamole-do-you-prefer-salsa-or-guacamole\\\/#local-main-organization-logo\",\"url\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/credativ-logo-right.svg\",\"contentUrl\":\"https:\\\/\\\/www.credativ.de\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/credativ-logo-right.svg\",\"caption\":\"credativ\u00ae\"}]}<\/script>\n<meta name=\"geo.placename\" content=\"M\u00f6nchengladbach\" \/>\n<meta name=\"geo.position\" content=\"51.1732374;6.392010099999999\" \/>\n<meta name=\"geo.region\" content=\"Germany\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Apache Guacamole - Do you prefer Salsa or Guacamole? - credativ\u00ae","description":"Apache Guacamole allows users to easily access remote connections via their web browser. Learn more about it.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/","og_locale":"en_US","og_type":"article","og_title":"Apache Guacamole - Do you prefer Salsa or Guacamole?","og_description":"Apache Guacamole allows users to easily access remote connections via their web browser. Learn more about it.","og_url":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/","og_site_name":"credativ\u00ae","article_publisher":"https:\/\/www.facebook.com\/credativDE\/","article_published_time":"2024-05-21T12:50:07+00:00","article_modified_time":"2025-11-24T17:29:17+00:00","og_image":[{"width":1600,"height":640,"url":"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole.png","type":"image\/png"}],"author":"Michael Sprengel","twitter_card":"summary_large_image","twitter_creator":"@credativde","twitter_site":"@credativde","twitter_misc":{"Written by":"Michael Sprengel","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#article","isPartOf":{"@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/"},"author":{"name":"Michael Sprengel","@id":"https:\/\/www.credativ.de\/en\/#\/schema\/person\/a3e4af81335b70b26cda81a7690bee16"},"headline":"Apache Guacamole &#8211; Do you prefer Salsa or Guacamole?","datePublished":"2024-05-21T12:50:07+00:00","dateModified":"2025-11-24T17:29:17+00:00","mainEntityOfPage":{"@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/"},"wordCount":2518,"commentCount":0,"publisher":{"@id":"https:\/\/www.credativ.de\/en\/#organization"},"image":{"@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#primaryimage"},"thumbnailUrl":"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-1024x410.png","keywords":["Alpine","Apache","Apache Guacamole","Configmap","Daemonset","Debian","Deployment","Guacamole","k8s","kate","kind","Kubernetes","Statefulset"],"articleSection":["HowTos"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#respond"]}],"copyrightYear":"2024","copyrightHolder":{"@id":"https:\/\/www.credativ.de\/#organization"}},{"@type":"WebPage","@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/","url":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/","name":"Apache Guacamole - Do you prefer Salsa or Guacamole? - credativ\u00ae","isPartOf":{"@id":"https:\/\/www.credativ.de\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#primaryimage"},"image":{"@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#primaryimage"},"thumbnailUrl":"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-1024x410.png","datePublished":"2024-05-21T12:50:07+00:00","dateModified":"2025-11-24T17:29:17+00:00","description":"Apache Guacamole allows users to easily access remote connections via their web browser. Learn more about it.","breadcrumb":{"@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#primaryimage","url":"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-1024x410.png","contentUrl":"https:\/\/www.credativ.de\/wp-content\/uploads\/2024\/05\/Apache_Guacamole-1024x410.png"},{"@type":"BreadcrumbList","@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.credativ.de\/en\/"},{"@type":"ListItem","position":2,"name":"Apache Guacamole &#8211; Do you prefer Salsa or Guacamole?"}]},{"@type":"WebSite","@id":"https:\/\/www.credativ.de\/en\/#website","url":"https:\/\/www.credativ.de\/en\/","name":"credativ GmbH","description":"","publisher":{"@id":"https:\/\/www.credativ.de\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.credativ.de\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Organization","Place"],"@id":"https:\/\/www.credativ.de\/en\/#organization","name":"credativ\u00ae","url":"https:\/\/www.credativ.de\/en\/","logo":{"@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#local-main-organization-logo"},"image":{"@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#local-main-organization-logo"},"sameAs":["https:\/\/www.facebook.com\/credativDE\/","https:\/\/x.com\/credativde","https:\/\/mastodon.social\/@credativde","https:\/\/www.linkedin.com\/company\/credativ-gmbh","https:\/\/www.instagram.com\/credativ\/"],"description":"Die credativ GmbH ist ein f\u00fchrendes, auf Open Source Software spezialisiertes IT-Dienstleistungs- und Beratungsunternehmen. Wir bieten umfassende und professionelle Services, von Beratung und Infrastruktur-Betrieb \u00fcber 24\/7 Support bis hin zu individuellen L\u00f6sungen und Schulungen. Unser Fokus liegt auf dem ganzheitlichen Management von gesch\u00e4ftskritischen Open-Source-Systemen, darunter Betriebssysteme (z.B. Linux), Datenbanken (z.B. PostgreSQL), Konfigurationsmanagement (z.B. Ansible, Puppet) und Virtualisierung. Als engagierter Teil der Open-Source-Community unterst\u00fctzen wir unsere Kunden dabei, die Vorteile freier Software sicher, stabil und effizient in ihrer IT-Umgebung zu nutzen.","legalName":"credativ GmbH","foundingDate":"2025-03-01","duns":"316387060","numberOfEmployees":{"@type":"QuantitativeValue","minValue":"11","maxValue":"50"},"address":{"@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#local-main-place-address"},"geo":{"@type":"GeoCoordinates","latitude":"51.1732374","longitude":"6.392010099999999"},"telephone":["+4921619174200","08002733284"],"contactPoint":{"@type":"ContactPoint","telephone":"08002733284","email":"vertrieb@credativ.de"},"openingHoursSpecification":[{"@type":"OpeningHoursSpecification","dayOfWeek":["Monday","Tuesday","Wednesday","Thursday","Friday"],"opens":"09:00","closes":"17:00"},{"@type":"OpeningHoursSpecification","dayOfWeek":["Saturday","Sunday"],"opens":"00:00","closes":"00:00"}],"email":"info@credativ.de","areaServed":"D-A-CH","vatID":"DE452151696"},{"@type":"Person","@id":"https:\/\/www.credativ.de\/en\/#\/schema\/person\/a3e4af81335b70b26cda81a7690bee16","name":"Michael Sprengel","description":"Michael Sprengel has been with credativ since 2015, after completing his Bachelor degree in computer science at the University of Applied Science Hochschule Niederrhein. After his study, he started his career as a consultant here at credativ and quickly became one of the team leads in our company. His expertise ranges from DevOps, automation up to containerization."},{"@type":"PostalAddress","@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#local-main-place-address","streetAddress":"Hennes-Weisweiler-Allee 23","addressLocality":"M\u00f6nchengladbach","postalCode":"41179","addressRegion":"Deutschland","addressCountry":"DE"},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.credativ.de\/en\/blog\/howtos-en\/apache-guacamole-do-you-prefer-salsa-or-guacamole\/#local-main-organization-logo","url":"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/04\/credativ-logo-right.svg","contentUrl":"https:\/\/www.credativ.de\/wp-content\/uploads\/2025\/04\/credativ-logo-right.svg","caption":"credativ\u00ae"}]},"geo.placename":"M\u00f6nchengladbach","geo.position":{"lat":"51.1732374","long":"6.392010099999999"},"geo.region":"Germany"},"_links":{"self":[{"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/posts\/7956","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/users\/38"}],"replies":[{"embeddable":true,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/comments?post=7956"}],"version-history":[{"count":1,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/posts\/7956\/revisions"}],"predecessor-version":[{"id":10240,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/posts\/7956\/revisions\/10240"}],"wp:attachment":[{"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/media?parent=7956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/categories?post=7956"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.credativ.de\/en\/wp-json\/wp\/v2\/tags?post=7956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}