---
title: "K3S High Availability with SafeKit: Install the k3s.safe Module for Failover"
description: "SafeKit Video: Application-Level Clustering (8:47) In this video, discover how SafeKit implements a mirror HA cluster without the complexity of a SAN. While this demonstration uses Microsoft SQL Server, the solution works identically for other databases and applications. Chapters 2 nodes with SQL Server (0:32) Configure the cluster and the mirror.safe module (3:58) Start and […]"
canonical: "https://safekit.eviden.com/quick-install/safekit-quick-installation-guide-with-kubernetes/"
topics: "High Availability Quick Installation Guide for Kubernetes, SafeKit High Availability Limitations, Overview of the SafeKit / Kubernetes solution, Installation and configuration of the SafeKit / Kubernetes solution on Linux (k3s.safe), What are the different scenarios in case of network isolation in a cluster?, Demonstration of the SafeKit mirror solution, 🔍 SafeKit High Availability Navigation Hub"
category: "quick-install"
lang: "en"
---

<h1 id="k3s-high-availability-with-safekit-install-the-k3ssafe-module-for-failover">K3S High Availability with SafeKit: Install the k3s.safe Module for Failover</h1>
<h2 id="quick-guide">High Availability Quick Installation Guide for Kubernetes</h2>
<p>This guide explains how to set up a <strong>k3s cluster</strong> for Kubernetes using SafeKit, ensuring automatic failover and synchronous replication without the need for shared storage.</p>
<p>For help, you can use <a href="/resources/safekit-support/">SafeKit AI 🤖</a>.</p>
<h3 id="1-overview">1. Overview</h3>
<ul>
<li><strong>Architecture:</strong> Uses a two-node system (Primary/Secondary).</li>
<li><strong>Data Protection:</strong> Implements real-time synchronous replication for <strong>zero data loss</strong> (RPO=0).</li>
</ul>
<h3 id="2-installation">2. Installation</h3>
<ul>
<li><strong>Software:</strong> Install the SafeKit engine on both servers.</li>
<li><strong>Module:</strong> Download the pre-configured <code>k3s.safe</code> application module.</li>
</ul>
<h3 id="3-configuration">3. Configuration</h3>
<ul>
<li><strong>Web Console:</strong> Configure the specific folders containing the Kubernetes files.</li>
<li><strong>Monitoring:</strong> Start monitoring and protecting the Kubernetes application.</li>
</ul>
<h2 id="safekit-ha-limitations">SafeKit High Availability Limitations</h2>
<h3 id="why-a-replication-of-a-few-tera-bytes">Why a replication of a few Tera-bytes?</h3>
<p>Resynchronization time after a failure (<a href="/architectures/file-replication-byte-level-with-failover-k3s-cluster/#safekit-k3s-cluster">step 3</a>)</p>
<ul>
<li>1 Gb/s network ≈ 3 Hours for 1 Tera-bytes.</li>
<li>10 Gb/s network ≈ 1 Hour for 1 Tera-bytes or less depending on disk write performances.</li>
</ul>
<h4 id="alternative">Alternative</h4>
<ul>
<li>For a large volume of data, use <a href="/best-practises/san-vs-nas-shared-storage-for-a-failover-cluster/">external shared storage</a>.</li>
<li>More expensive, more complex.</li>
</ul>
<h3 id="why-a-replication-lt-1000000-files">Why a replication &lt; 1,000,000 files?</h3>
<ul>
<li>Resynchronization time performance after a failure (<a href="/architectures/file-replication-byte-level-with-failover-k3s-cluster/#safekit-k3s-cluster">step 3</a>).</li>
<li>Time to check each file between both nodes.</li>
</ul>
<h4 id="alternative-1">Alternative</h4>
<ul>
<li>Put the many files to replicate in a virtual hard disk / virtual machine.</li>
<li>Only the files representing the virtual hard disk / virtual machine will be replicated and resynchronized in this case.</li>
</ul>
<h3 id="why-a-failover--32-replicated-vms">Why a failover ≤ 32 replicated VMs?</h3>
<ul>
<li>Each VM runs in an independent k3s module.</li>
<li>Maximum of 32 k3s modules running on the same cluster.</li>
</ul>
<h4 id="alternative-2">Alternative</h4>
<ul>
<li>Use an external shared storage and another VM clustering solution.</li>
<li>More expensive, more complex.</li>
</ul>
<h3 id="why-a-lanvlan-network-between-remote-sites">Why a LAN/VLAN network between remote sites?</h3>
<ul>
<li>Automatic failover of the <a href="/best-practises/how-a-virtual-ip-address-works/">virtual IP address</a> with 2 nodes in the same subnet.</li>
<li>Good bandwidth for resynchronization (<a href="/architectures/file-replication-byte-level-with-failover-k3s-cluster/#safekit-k3s-cluster">step 3</a>) and good latency for <a href="/best-practises/synchronous-replication-vs-asynchronous-replication/">synchronous replication</a> (typically a round-trip of less than 2ms).</li>
</ul>
<h4 id="alternative-3">Alternative</h4>
<ul>
<li>Use a <a href="/best-practises/how-a-virtual-ip-address-works/">load balancer for the virtual IP address</a> if the 2 nodes are in 2 subnets (supported by SafeKit, especially in the cloud).</li>
<li>Use backup solutions with asynchronous replication for high latency network.</li>
</ul>
<h2 id="overview-of-the-safekit--kubernetes-solution">Overview of the SafeKit / Kubernetes solution</h2>
<p>The solution is described here: <strong><a href="/solutions/kubernetes-k3s-the-simplest-high-availability-cluster-with-synchronous-replication-and-failover-between-two-redundant-servers/">Kubernetes K3s High Availability: 2-Node Synchronous Replication&amp; Failover</a></strong></p>
<h2 id="installation-and-configuration-of-the-safekit--kubernetes-solution-on-linux-k3ssafe">Installation and configuration of the SafeKit / Kubernetes solution on Linux (k3s.safe)</h2>
<h3 id="1-download-packages">1. Download packages</h3>
<ul>
<li>Download the free version of SafeKit 8.2 on Linux (safekitlinux_xx.bin)</li>
<li>Download the k3s.safe Linux module</li>
<li>Download the k3sconfig.sh script</li>
<li>Documentation (pptx)</li>
</ul>
<p>Note: the k3sconfig.sh script installs K3S, MariaDB, NFS, SafeKit on 2 Linux Ubuntu 24.04 nodes.</p>
<p><a href="/resources/safekit-free-trial/"> Download SafeKit (Linux) &gt; </a></p>
<p><a class="btn-download" href="/wp-content/uploads/downloads_safekit/version-82/modules_linux/k3s.safe" download="k3s.safe">⬇️ Download k3s.safe (Linux) &gt;</a></p>
<p><a href="/wp-content/uploads/downloads_safekit/version-82/modules_linux/k3sconfig.sh"> Download k3sconfig.sh &gt; </a></p>
<p><a href="/wp-content/uploads/documents/safekit-k3s-en.pdf" target="_blank" rel="noopener"> Documentation (pdf) &gt; </a></p>
<h3 id="2-first-on-both-nodes">2. First on both nodes</h3>
<p>On 2 Linux Ubuntu 24.04 nodes, as root:</p>
<ul>
<li>Make sure the node has internet access (could be through a proxy)</li>
<li>Copy k3sconfig.sh, k3s.safe and the safekit_xx.bin package into a directory and cd into it</li>
<li>Rename the .bin file as &ldquo;safekit.bin&rdquo;</li>
<li>Make sure k3sconfig.sh and safekit.bin are executable.</li>
<li>Edit the k3sconfig.sh script and customize the environment variables according to your environment (including a virtual IP)</li>
<li>Execute on both nodes: <code>./k3sconfig.sh prereq</code></li>
</ul>
<p>The script will:</p>
<ul>
<li>Install required debian packages: alien, nfs-kernel-server, nfs-common, mariadb-server</li>
<li>Secure mariadb installation</li>
<li>Create directories for file replication</li>
<li>Prepare the NFS server for sharing replicated directories</li>
<li>Install SafeKit</li>
</ul>
<h3 id="3-on-the-first-node">3. On the first node</h3>
<p>Execute on the first node: <code>./k3sconfig.sh first</code></p>
<p>The script will:</p>
<ul>
<li>Create the K3S configuration database and the k3s user</li>
<li>Create the replicated storage volume file (sparse file) and format it as an xfs filesystem</li>
<li>Create the safekit cluster configuration and apply it</li>
<li>Install and configure the k3s.safe module on the cluster</li>
<li>Start the k3s module as &ldquo;prim&rdquo; on the first node</li>
<li>Download, install and start k3s</li>
<li>Download and install nfs-subdir-external-provisioner Helm chart</li>
<li>Display K3S token (to be used during second node installation phase)</li>
</ul>
<h3 id="4-on-the-second-node">4. On the second node</h3>
<p>Execute on the second node: <code>./k3sconfig.sh second &lt;token&gt;</code></p>
<ul>
<li><token> is the string displayed at the end of the &ldquo;k3sconfig.sh first&rdquo; execution on the first node</li>
</ul>
<p>The script will:</p>
<ul>
<li>Make sure the k3s module is started as prim on the first node</li>
<li>Install k3s on the second node</li>
<li>Start the k3s module</li>
</ul>
<h3 id="5-check-that-the-k3s-safekit-module-is-running-on-both-nodes">5. Check that the k3s SafeKit module is running on both nodes</h3>
<p>Check with this command on both nodes: <code>/opt/safekit/safekit –H &quot;*&quot; state</code></p>
<p>The reply should be similar to the image.</p>
<pre><code>/opt/safekit/safekit –H &quot;*&quot; state
---------------- Server=http://10.0.0.20:9010 ----------------
admin action=exec
--------------------- k3s State ---------------------

  Local  (127.0.0.1)    : PRIM (Service : Available)(Color : Green)
Success
---------------- Server=http://10.0.0.21:9010 ----------------
admin action=exec
--------------------- k3s State ---------------------

  Local  (127.0.0.1)    : SECOND (Service : Available)(Color : Green)
Success
</code></pre>
<h3 id="6-start-the-safekit-web-console-to-administer-the-cluster">6. Start the SafeKit web console to administer the cluster</h3>
<ul>
<li>Connect a browser to the SafeKit web console url <code>http://server0-IP:9010</code>.</li>
<li>You should see a page similar to the image.</li>
<li>Check with Linux command lines that K3S is started on both nodes (started in <code>start_prim</code> and <code>start_second</code>) and that MariaDB is started on the primary node (started in <code>start_prim</code>).</li>
</ul>
<img src="/wp-content/uploads/2024/03/14-monitoring-prim-second.png" alt="Kubernetes cluster started in the SafeKit web console">
<h3 id="7-testing">7. Testing</h3>
<ul>
<li>Stop the PRIM node by scrolling down its contextual menu and clicking <code>Stop</code>.</li>
<li>Verify that there is a failover on the SECOND node which should become ALONE (green).</li>
<li>And with command lines on Linux, check the failover of services (stopped on node 1 in the <code>stop_prim</code> script and started on node 2 in the <code>start_prim</code> script). MariaDB and K3S should run on node2.</li>
</ul>
<div class="callout callout-warning"><img src="/wp-content/uploads/2022/07/warning-small.png" alt="Warning"><span>If ALONE (green) is not reached on node2, analyze why with the module log of node 2.</span></div>
<ul>
<li>click on <code>node2</code> to display the module log.</li>
<li><a href="/wp-content/uploads/2024/03/24-module-log-script.png">example of a SQL Server module log</a> where the service name in <code>start_prim</code> is invalid. The sqlserver.exe process is monitored but as it is not started, at the end the module stops.</li>
</ul>
<div class="callout callout-warning"><img src="/wp-content/uploads/2022/07/warning-small.png" alt="Warning"><span>If everything is okay, initiate a start on node1, which will resynchronize the replicated directories from node2.</span></div>
<p>If things go wrong, stop node2 and <a href="/wp-content/uploads/2024/03/10-monitoring-mirror-stop-stop-prim.png">force the start as primary</a> of node1, which will restart with its locally healthy data at the time of the stop.</p>
<div class="callout"><img src="/wp-content/uploads/2022/07/note.png" alt="Note"><span><a href="/resources/safekit-user-guide-82/#tests">More information on tests in the User's Guide.</a></span></div>
<img src="/wp-content/uploads/2024/03/16-monitoring-prim-second-stop.png" alt="Stop the  module on the PRIM server">
<h3 id="8-try-the-cluster-with-a-kubernetes-application-like-wordpress">8. Try the cluster with a Kubernetes application like WordPress</h3>
<p>You have the example of a WordPress installation in the image: a web portal with a backend database implemented by pods.</p>
<p>You can deploy your own application in the same way.</p>
<p>WordPress is automatically highly available:</p>
<ul>
<li>with its data (php + database) in persistent volumes replicated in real-time by SafeKit</li>
<li>with a virtual IP address to access the WordPress site for users</li>
<li>with automatic failover and automatic failback</li>
</ul>
<p>Notes:</p>
<ul>
<li>
<p>The WordPress chart defines a load balanced service that listens on &lt;service.port&gt; and &lt;service.httpsport&gt; ports.</p>
</li>
<li>
<p>WordPress is accessible through the url: <code>http://&lt;virtual-ip&gt;:&lt;service.port&gt;.</code></p>
</li>
<li>
<p>The virtual IP is managed by SafeKit and automatically switched in case of failover.</p>
</li>
<li>
<p>By default, K3S implements load balancers with Klipper.</p>
</li>
<li>
<p>Klipper listens on <virtual ip>:&lt;service.port&gt; and routes the TCP/IP packets to the IP address and port of the WordPress pod that it has selected.</p>
<p>$ export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
$ helm repo add bitnami <a href="https://charts.bitnami.com/bitnami" target="_blank" rel="noopener">https://charts.bitnami.com/bitnami</a>
$ helm install my-release bitnami/wordpress &ndash;set global.storageClass=nfs-client &ndash;set service.ports.http=8099,service.ports.https=4439</p>
</li>
</ul>
<p>The previous helm command should download the WordPress image from <code>registry-1.docker.io</code>. You may encounter authentication issues on <code>registry-1.docker.io</code>. In this case, you should:</p>
<ul>
<li>
<p>create <code>/etc/rancher/k3s/registries.yaml</code> on both nodes with inside:</p>
<pre><code>configs:
  &quot;registry-1.docker.io&quot;:
    auth:
      username: your_user_name
      password: your_password
    tls:
      insecure_skip_verify: true
</code></pre>
</li>
<li>
<p>stop and start k3s to take it into account, with <code>systemctl stop k3s</code> and <code>systemctl start k3s</code>.</p>
</li>
<li>
<p>Execute <code>helm registry login -u your_user_name docker.io</code>, then enter your password</p>
</li>
</ul>
<h3 id="9-support">9. Support</h3>
<ul>
<li>For getting support, take 2 SafeKit <code>Snapshots</code> (2 .zip files), one for each node.</li>
</ul>
<div class="callout"><img src="/wp-content/uploads/2022/07/note.png" alt="Note"><span><a href="/resources/safekit-user-guide-82/#Troubleshooting">Troubleshooting in the User's Guide.</a></span></div>
<img src="/wp-content/uploads/2024/03/30-snapshots-mirror.png" alt="Take the  snaphots for support">
<h3 id="10-if-necessary-configure-a-splitbrain-checker">10. If necessary, configure a splitbrain checker</h3>
<ul>
<li>
<p>See below <a href="#isolation">&ldquo;What are the different scenarios in case of network isolation in a cluster?&rdquo;</a> to know if you need to configure a splitbrain checker.</p>
</li>
<li>
<p>In the module configuration, click on <code>Advanced Configuration</code> (see image) to edit <code>userconfig.xml</code>.</p>
</li>
<li>
<p>Declare the splitbrain checker by adding in the <code>&lt;check&gt;</code> section of <code>userconfig.xml</code>:</p>
<pre><code>&lt;service&gt;
 ...
 &lt;check&gt;
  ...
  &lt;splitbrain ident=&quot;witness&quot; exec=&quot;ping&quot; arg=&quot;witness IP&quot;/&gt;
 &lt;/check&gt;
</code></pre>
</li>
<li>
<p><code>Save and apply</code> the new configuration to redeploy the modified userconfig.xml file on both nodes (module must be stopped on both nodes to save and apply).</p>
</li>
</ul>
<p><strong>Parameters</strong> :</p>
<ul>
<li><code>ident=&quot;witness&quot;</code> identifies the witness with a resource name: <code>splitbrain.witness</code>. You can change this value to identify the witness.</li>
<li><code>exec=&quot;ping&quot;</code> references the ping code to execute. Do not change this value.</li>
<li><code>arg=&quot;witness IP&quot;</code> is an argument for the ping. Change this value with the IP of the witness (a robust element, typically a router).</li>
</ul>
<img src="/wp-content/uploads/2024/03/05-module-mirror-edit-config.png" alt="Enter the  parameters">
<h2 id="isolation">What are the different scenarios in case of network isolation in a cluster?</h2>
<h3 id="a-single-network">A single network</h3>
<p>When there is a network isolation, the default behavior is:</p>
<ul>
<li>as heartbeats are lost for each node, each node goes to ALONE and runs the application with its virtual IP address (double execution of the application modifying its local data),</li>
<li>when the isolation is repaired, one ALONE node is forced to stop and to resynchronize its data from the other node,</li>
<li>at the end the cluster is PRIM-SECOND (or SECOND-PRIM according the duplicate virtual IP address detection made by Windows).</li>
</ul>
<h3 id="two-networks-with-a-dedicated-replication-network">Two networks with a dedicated replication network</h3>
<p>When there is a network isolation, the behavior with a dedicated replication network is:</p>
<ul>
<li>a dedicated replication network is implemented on a private network,</li>
<li>heartbeats on the production network are lost (isolated network),</li>
<li>heartbeats on the replication network are working (not isolated network),</li>
<li>the cluster stays in PRIM/SECOND state.</li>
</ul>
<h3 id="a-single-network-and-a-splitbrain-checker">A single network and a splitbrain checker</h3>
<p>When there is a network isolation, the behavior with a split-brain checker is:</p>
<ul>
<li>a split-brain checker has been configured with the IP address of a witness (typically a router),</li>
<li>the split-brain checker operates when a server goes from PRIM to ALONE or from SECOND to ALONE,</li>
<li>in case of network isolation, before going to ALONE, both nodes test the IP address,</li>
<li>the node which can access the IP address goes to ALONE, the other one goes to WAIT,</li>
<li>when the isolation is repaired, the WAIT node resynchronizes its data and becomes SECOND.</li>
</ul>
<p>Note: If the witness is down or disconnected, both nodes go to WAIT and the application is no more running. That&rsquo;s why you must choose a robust witness like a router.</p>
<h2 id="demonstration-of-the-safekit-mirror-solution">Demonstration of the SafeKit mirror solution</h2>
<h3 id="demo-mirror-ha-cluster">SafeKit Video: Application-Level Clustering (8:47)</h3>
<p>In this video, discover how SafeKit implements a <strong>mirror HA cluster</strong> without the complexity of a SAN. While this demonstration uses Microsoft SQL Server, the solution works identically for other databases and applications.</p>
<h3 id="chapters">Chapters</h3>
<ol>
<li><a href="https://www.youtube.com/watch?v=mGwEguDnnH0&amp;amp;t=0s" target="_blank" rel="noopener">2 nodes with SQL Server</a> (0:32)</li>
<li><a href="https://www.youtube.com/watch?v=mGwEguDnnH0&amp;amp;t=32s" target="_blank" rel="noopener">Configure the cluster and the mirror.safe module</a> (3:58)</li>
<li><a href="https://www.youtube.com/watch?v=mGwEguDnnH0&amp;amp;t=270s" target="_blank" rel="noopener">Start and test SQL replication, migration, failover on crash</a> (4:17)</li>
</ol>
<h3 id="step-by-step-implementation">Step-by-Step Implementation</h3>
<ul>
<li><a href="/quick-install/safekit-quick-installation-guide-for-a-new-windows-application-with-real-time-replication-and-failover/">Read the guide on setting up a mirrored cluster on Windows</a></li>
<li><a href="/quick-install/safekit-quick-installation-guide-for-a-new-linux-application-with-real-time-replication-and-failover/">Read the guide on setting up a mirrored cluster on Linux</a></li>
</ul>
<p>&amp;amp;amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;amp;amp;gt;</p>
<h2 id="hub">🔍 SafeKit High Availability Navigation Hub</h2>
<p><strong>Explore SafeKit: Features, technical videos, documentation, and free trial</strong></p>
<table>
<thead>
<tr>
<th>Resource Type</th>
<th>Description</th>
<th>Direct Link</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Key Features</strong></td>
<td>Why Choose SafeKit for Simple and Cost-Effective High Availability?</td>
<td><a href="/#why-choose-safekit-for-ha" title="Discover SafeKit features for simple and cost-effective high availability">See Why Choose SafeKit for High Availability</a></td>
</tr>
<tr>
<td><strong>Use Cases</strong></td>
<td>Explore How SafeKit Ensures the High Availability of Critical Infrastructure</td>
<td><a href="/#safekit-use-cases" title="Explore SafeKit high availability use cases">See All Use Cases (OEM Software, Edge Servers, SCADA, and more)</a></td>
</tr>
<tr>
<td><strong>Deployment Model</strong></td>
<td>All-in-One SANless HA: Shared-Nothing Software Clustering</td>
<td><a href="/#all-in-one-sanless-ha" title="Learn about all-in-one SANless high availability with shared-nothing software clustering">See SafeKit All-in-One SANless HA</a></td>
</tr>
<tr>
<td><strong>HA Strategies</strong></td>
<td>SafeKit: Infrastructure (VM) vs. Application-Level High Availability</td>
<td><a href="/#safekit-ha-redundancy-choices" title="Compare VM-level redundancy with SafeKit application-level high availability strategies">See SafeKit HA &amp; Redundancy: VM vs. Application Level</a></td>
</tr>
<tr>
<td><strong>Technical Specifications</strong></td>
<td>Technical Limitations for SafeKit Clustering</td>
<td><a href="/#safekit-ha-limitations" title="Technical requirements and limitations for SafeKit application clustering">See SafeKit High Availability Limitations</a></td>
</tr>
<tr>
<td><strong>Proof of Concept</strong></td>
<td>SafeKit: High Availability Configuration &amp; Failover Demos</td>
<td><a href="/#safekit-failover-tutorials" title="Step-by-step videos on SafeKit high availability, from installation to automated failover">See SafeKit Failover Tutorials</a></td>
</tr>
<tr>
<td><strong>Architecture</strong></td>
<td>How the SafeKit Mirror Cluster works (Real-Time Replication &amp; Failover)</td>
<td><a href="/#safekit-mirror-cluster" title="See technical architecture and failover mechanism of SafeKit Mirror Cluster">See SafeKit Mirror Cluster: Real-Time Replication &amp; Failover</a></td>
</tr>
<tr>
<td><strong>Architecture</strong></td>
<td>How the SafeKit Farm Cluster works (Network Load Balancing &amp; Failover)</td>
<td><a href="/#safekit-farm-cluster" title="Technical overview of SafeKit Farm Cluster architecture with network load balancing">See SafeKit Farm Cluster: Network Load Balancing &amp; Failover</a></td>
</tr>
<tr>
<td><strong>Competitive Advantages</strong></td>
<td>Comparison: SafeKit vs. Traditional High Availability (HA) Clusters</td>
<td><a href="/#safekit-ha-comparison" title="Detailed comparison of SafeKit software vs traditional hardware-based HA clusters">See SafeKit vs. Traditional HA Cluster Comparison</a></td>
</tr>
<tr>
<td><strong>Technical Resources</strong></td>
<td>SafeKit High Availability: Documentation, Downloads &amp; Trial</td>
<td><a href="/#safekit-ha-technical-resources" title="Access SafeKit free trial, technical documentation, and high availability white papers">See SafeKit HA Free Trial &amp; Technical Documentation</a></td>
</tr>
<tr>
<td><strong>Pre-configured Solutions</strong></td>
<td>SafeKit Application Module Library: Ready-to-Use HA Solutions</td>
<td><a href="/#safekit-ha-application-modules" title="Browse the library of pre-configured SafeKit modules for automated application failover">See SafeKit High Availability Application Modules</a></td>
</tr>
</tbody>
</table>
<div class="button-row">
  <a class="btn-action" href="https://safekit.eviden.com/contact-us-for-safekit/">🧑 Contact us</a>
  <a class="btn-action" href="/resources/safekit-free-trial/">🎁 SafeKit free trial</a>
  <a class="btn-action" href="https://training.my.evidian.com/mod/page/view.php?id=712">🏅 Free certification</a>
  <a class="btn-action" href="https://safekit.eviden.com/get-a-quote-safekit/">💰 Perpetual license cost</a>
</div>

