<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://cryostat.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://cryostat.io/" rel="alternate" type="text/html" /><updated>2026-06-11T02:51:52+00:00</updated><id>https://cryostat.io/feed.xml</id><title type="html">Cryostat</title><subtitle>Observability, monitoring, profiling, and JDK Flight Recorder Management for JVMs in containers. Sponsored by Red Hat.</subtitle><author><name>Cryostat Community</name></author><entry><title type="html">Cryostat 4.2.0 is Released!</title><link href="https://cryostat.io/2026/06/02/cryostat-420.html" rel="alternate" type="text/html" title="Cryostat 4.2.0 is Released!" /><published>2026-06-02T00:00:00+00:00</published><updated>2026-06-02T00:00:00+00:00</updated><id>https://cryostat.io/2026/06/02/cryostat-420</id><content type="html" xml:base="https://cryostat.io/2026/06/02/cryostat-420.html"><![CDATA[<h4 id="table-of-contents">Table of Contents</h4>
<ul id="markdown-toc">
  <li><a href="#table-of-contents" id="markdown-toc-table-of-contents">Table of Contents</a></li>
  <li><a href="#release-highlights" id="markdown-toc-release-highlights">Release Highlights</a>    <ul>
      <li><a href="#new-features" id="markdown-toc-new-features">New Features</a></li>
      <li><a href="#feature-enhancements" id="markdown-toc-feature-enhancements">Feature Enhancements</a></li>
    </ul>
  </li>
  <li><a href="#where-can-i-get-the-latest-version-of-cryostat" id="markdown-toc-where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</a></li>
  <li><a href="#feedback" id="markdown-toc-feedback">Feedback</a></li>
</ul>
<hr />

<p>Hello everyone,</p>

<p>We are pleased to announce that Cryostat 4.2.0 is now here!</p>

<h2 id="release-highlights">Release Highlights</h2>

<h3 id="new-features"><a href="#new-features">New Features</a></h3>

<ol>
    <li>
        <b><a href="/guides/#view-a-recording-in-jfr-analytics">Support for JFR analytics</a></b>: custom SQL queries can now be performed on archived JFR data without explicitly needing to download JFR files from Cryostat storage.
    </li>
    <li>
        <b><a href="/guides/#using-smart-triggers">Smart trigger UI</a></b>: provides a new <i>Triggers</i> view for managing smart triggers in the Cryostat web console. This view provides a way to declaratively configure the Cryostat Agent to start JFR recordings based on defined conditions. In earlier releases, the only available way to define smart triggers were by appending them to the agent's JAR file path or by using a JVM system property or environment variable.
    </li>
    <li>
        <b><a href="/guides/#view-the-audit-log">Audit Logging</a></b>: actions performed when interacting with Cryostat's API are now tracked. This is especially useful for Administrators wanting traceability and accountability of actions performed within Cryostat. This enhances the Archives views (Flight Recordings, thread dumps, heap dumps) enabling a detailed view of information about the target application an archived data file was sourced from, even if that target has since gone offline.
    </li>
    <li>
        <b><a href="/guides/#use-async-profiler">Async-profiler Integration</a></b>: Attach the async-profiler.jar to your application and create profiling sessions to capture async-profiler event types.
    </li>
    <li>
        <b><a href="/guides/#analyze-a-thread-dump">Thread dump visualizations</a></b>: Thread dumps can now be analyzed within the Cryostat console through list views and pie charts.
    </li>
    <li>
        <b>Cryostat Agent discovery enhancements</b>: When using the Cryostat Agent in a Kubernetes or OpenShift context, the Agent instances will now appear nested within Pod, Deployment, ReplicaSet, and Namespace elements merged with any EndpointSlice-discovered targets.
    </li>
</ol>

<h3 id="feature-enhancements"><a href="#feature-enhancements">Feature Enhancements</a></h3>

<ol>
    <li>
        <b>Harvester period and Harvester max file settings</b>: <code> cryostat.io/harvester-period </code> and <code> cryostat.io/harvester-max-files</code> labels are now available and can be specified in the application's deployment.
    </li>
    <li>
        <b>Cryostat web console navigation menu enhancements</b>: 
        <ul>
            <li>The <i>Diagnostics &gt; Analyze &gt; Thread Dumps </i> view is renamed <i>Diagnostics &gt; Analyze &gt; Thread Dump Archives</i> in this release. </li>
            <li>The <i>Security &gt; Certificates</i> view now replaces the <b>Certificates</b> pane that was in the top-level Security view in earlier releases.</li>
            <li>The <i>Security &gt; Credentials</i> view now replaces the <b>Credentials</b> pane that was in the top-level Security view in earlier releases</li>
        </ul>
    </li>
    <li>
        <b>"All Archives" and "Targets" tab for Heap and Thread dumps views </b>: The <i>Diagnostics &gt; Analyze &gt; Heap Dumps</i> and <i>Diagnostics &gt; Analyze &gt; Thread Dump Archives</i> views in the Cryosat web console both now include an <b>All Archives</b> tab in addition to a <b>Targets</b> tab. Each of these <b>All Archives</b> tabs provides the same type of functionality and look-and-feel as the <b>All Archives</b> tab in the <i>Flight Recorder &gt; Analyze &gt; Archives view</i>.
    </li>
    <li>
        <b>"All Archives" table updates</b>: Several usability updates were added to this table include filtering by time range or lineage and displaying fields such as Target Name and URL details.
    </li>
    <li>
        <b>POST Discovery endpoint</b>: Plug-ins that are registered with Cryostat can now use a POST <i> /api/v4.2/discovery</i> API for sending requests to the Discovery POST endpoint. This new POST API supports the addition of a “fill strategy” in API requests, which can be set to either NONE or KUBERNETES. If the fill strategy is NONE, the POST <i>/api/v4.2/discovery</i> API provides the same behavior as the existing POST <i>/api/v4/discovery</i> API. If the fill strategy is KUBERNETES, this works in conjunction with a context map to determine contextual lineage data for a node in terms of its associated pod, replica set, deployment, namespace, and realm.
    </li>
    <li>
        <b>GraphQL API enhancements</b>: 
        <ul>     
            <li>The <b>targetNodes</b> top-level query now includes a useAuditLog optional parameter, which is set to false by default. When this parameter is set to true, querying information about target applications that might have been previously discovered but subsequently lost is possible. </li>
            <li>The <b>DiscoveryNodeFilterInput</b> now accepts jvmId, jvmIds and targetIds as search parameters for filtering discovery nodes.</li>
        </ul>
    </li>
</ol>

<p>For further details on these items, <a href="https://github.com/cryostatio/cryostat/discussions/1555">check the GitHub Discussions release announcement</a>.</p>

<h2 id="where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</h2>
<p>You can install Cryostat using our
<a href="https://operatorhub.io/operator/cryostat-operator">Kubernetes operator on OperatorHub.io</a>
or via a
<a href="https://github.com/cryostatio/cryostat-helm/releases/tag/v2.2.0">Helm Chart</a>
. As always, you can also run Cryostat in other environments with a little more manual setup.</p>

<p>If this is your first time installing Cryostat on Kubernetes, you can <a href="/get-started">Get Started</a> right here on this
website.</p>

<p>If you had previously installed Cryostat Operator 4.1.x with OLM, then you may have already been upgraded to 4.2.0, or
else you should be able to approve and install the upgrade.</p>

<h2 id="feedback">Feedback</h2>
<p>Please reach out to the <a href="mailto:cryostat-development@googlegroups.com">Cryostat mailing list</a> or
<a href="https://github.com/cryostatio/cryostat/discussions/1555">GitHub Discussion</a> with any questions or comments.</p>]]></content><author><name>Chris Mah</name><email>cmah@ibm.com</email></author><summary type="html"><![CDATA[Table of Contents Table of Contents]]></summary></entry><entry><title type="html">Deploying Cryostat with External Storage</title><link href="https://cryostat.io/2026/01/08/external-storage.html" rel="alternate" type="text/html" title="Deploying Cryostat with External Storage" /><published>2026-01-08T00:00:00+00:00</published><updated>2026-01-08T00:00:00+00:00</updated><id>https://cryostat.io/2026/01/08/external-storage</id><content type="html" xml:base="https://cryostat.io/2026/01/08/external-storage.html"><![CDATA[<h4 id="table-of-contents">Table of Contents</h4>
<ul id="markdown-toc">
  <li><a href="#table-of-contents" id="markdown-toc-table-of-contents">Table of Contents</a></li>
  <li><a href="#intro" id="markdown-toc-intro">Intro</a>    <ul>
      <li><a href="#history" id="markdown-toc-history">History</a></li>
      <li><a href="#current-state" id="markdown-toc-current-state">Current State</a></li>
    </ul>
  </li>
  <li><a href="#example" id="markdown-toc-example">Example</a>    <ul>
      <li><a href="#preface" id="markdown-toc-preface">Preface</a></li>
      <li><a href="#configurations" id="markdown-toc-configurations">Configurations</a>        <ul>
          <li><a href="#helm-chart" id="markdown-toc-helm-chart">Helm Chart</a></li>
          <li><a href="#operator-custom-resource" id="markdown-toc-operator-custom-resource">Operator Custom Resource</a></li>
          <li><a href="#compose" id="markdown-toc-compose">Compose</a></li>
        </ul>
      </li>
      <li><a href="#additional-information" id="markdown-toc-additional-information">Additional Information</a>        <ul>
          <li><a href="#integrations" id="markdown-toc-integrations">Integrations</a></li>
          <li><a href="#recommendations" id="markdown-toc-recommendations">Recommendations</a></li>
          <li><a href="#side-effect" id="markdown-toc-side-effect">Side Effect</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
<hr />

<h2 id="intro">Intro</h2>

<h3 id="history">History</h3>

<p>Feel free to <a href="#current-state">skip</a> this historical recap of how we arrived at where we are now and jump directly to
the current capabilities and features.</p>

<p>Originally, Cryostat stored all data as files written to its local filesystem, within directories like
<code class="language-plaintext highlighter-rouge">/opt/cryostat.d/recordings.d</code>. This was decided when the only data to be stored were Flight Recording Archives and
custom Event Templates. Over time Cryostat grew new features and new types of data to store: Stored Credentials and
Automated Rules, Discovery Plugins (Cryostat Agents) and persisting Targets and Discovery Nodes, and most recently
Thread Dumps and Heap Dumps.</p>

<p>In the Cryostat 2.x series a small <code class="language-plaintext highlighter-rouge">h2</code> database was added, which was simply backed by a file within the local
filesystem, which would house Stored Credentials, Targets, Discovery Nodes, and Discovery Plugins. This took care of
most of the “small” data, but the “large data” Flight Recording archives were still simply written to a local
filesystem path. All of these data types could survive Cryostat being temporarily scaled down or restarting due to a
crash, but the data being kept within a local filesystem (in Kubernetes, a <code class="language-plaintext highlighter-rouge">PersistentVolumeClaim</code>) meant that it
might not persist if Cryostat was uninstalled completely. This also made it more difficult or infeasible for users to
have Cryostat export captured data to object storage providers - users
<a href="/2025/12/10/docker-compose.html">deploying Cryostat to Docker</a> might need to do something convoluted like mount an
S3-backed FUSE volume mount to their machine and then share that as a volume mount to the container. Kubernetes users
could do something similar to configure their object storage provider with a CSI driver to provide <code class="language-plaintext highlighter-rouge">PersistentVolumes</code>,
which could be selected for the <code class="language-plaintext highlighter-rouge">PersistentVolumeClaim</code> used by Cryostat. But, even after going through these extra
steps, that data in the <code class="language-plaintext highlighter-rouge">PersistentVolumeClaim</code> needs to be carefully handled so that it isn’t tied to the Cryostat
deployment’s lifecycle, and sharing the data between services is difficult when it’s written “raw” into a <code class="language-plaintext highlighter-rouge">PVC</code>.</p>

<p>So, as part of the big rewrite and re-architecture of Cryostat 3.0, the database was moved from file-backed <code class="language-plaintext highlighter-rouge">h2</code> on
local filesystem to a Postgres container, and other object storage was moved from direct local filesystem to using the
AWS S3 SDK and a <a href="https://github.com/cryostatio/cryostat-storage"><code class="language-plaintext highlighter-rouge">cryostat-storage</code></a> container (a “fork” of
<a href="https://github.com/seaweedfs/seaweedfs">SeaweedFS</a> which just layers on a custom entrypoint script and container
build). At this point, however, these containers and their Kubernetes Deployments are tightly integrated into the
Cryostat installation - the database and object storage had their own <code class="language-plaintext highlighter-rouge">PersistentVolumeClaim</code>s to back their own
data storage, and without resorting to FUSE mounts or CSI drivers and <code class="language-plaintext highlighter-rouge">PersistentVolume</code> storage class selectors it
still wouldn’t be possible to have Cryostat export Flight Recordings to your own object storage provider of choice.
Still, this was an important step to get us where we are today, and also opened the door for easier sharing of data
between Cryostat’s components.</p>

<p>Cryostat 4.0 did further work toward loosening the coupling of database and object storage containers to the Cryostat
installation by splitting them into their own Kubernetes Deployment objects tied to the same Custom Resource, but went
no further.</p>

<h3 id="current-state">Current State</h3>

<p>Finally, in Cryostat 4.1 the Cryostat <code class="language-plaintext highlighter-rouge">Custom Resource</code> in Kubernetes/OpenShift and the Cryostat Helm Chart both allow
for “external” storage to be configured. If no such configuration is made then the Cryostat Operator or Helm Chart will
default to deploying the same <code class="language-plaintext highlighter-rouge">cryostat-storage</code> as usual, to act as a “batteries included” S3-compatible object
storage. However, if you would rather have Cryostat use some other object storage provider for Flight Recordings, you
can now do so easily. Cryostat 4.1 also adds two new types of data that can be captured - Thread Dumps and Heap Dumps.
Heap Dumps in particular tend to be rather large binary files, so users expecting to make heavy use of this feature
should appreciate this new External Storage feature, too. When the Operator or Helm Chart see these configurations they
will configure the Cryostat installation to connect to this external storage provider and skip the <code class="language-plaintext highlighter-rouge">cryostat-storage</code>
<code class="language-plaintext highlighter-rouge">Deployment</code> entirely.</p>

<h2 id="example">Example</h2>

<h3 id="preface">Preface</h3>

<p>The new <a href="/docs">“Docs”</a> section of this website <a href="/docs/#connect-cryostat-to-external-storage">contains a setup guide</a>
with much of the same information as below. The goal of this blog post is to apply that same information to a concrete
scenario with an actual object storage provider selected, and to demonstrate different Cryostat installations with
equivalent configurations.</p>

<p>I’ll illustrate this capability by giving example configurations to hook up <a href="#helm-chart">the Helm Chart</a>,
<a href="#operator-custom-resource">Operator Custom Resource</a>, and <a href="#compose">Compose</a> installations to an external object
storage provider.</p>

<p>I will use a <a href="https://www.backblaze.com/cloud-storage">Backblaze B2</a> account in these examples, but the general
structure will be the same for any provider. You should do your own analysis of the available commercial S3-compatible
object storage providers as well as the available open source self-hosted object storage providers to determine which
best suits your needs.</p>

<p>Go ahead and create an account with your chosen object storage service provider, or prepare an account in your
self-hosted storage solution. You will need to take note of the following pieces of information:</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">AWS_ACCESS_KEY_ID</code> or similar - this is the equivalent of a username or serviceaccount name</li>
  <li><code class="language-plaintext highlighter-rouge">AWS_SECRET_ACCESS_KEY</code> or similar - this is the equivalent of a password or auth token</li>
  <li>Provider or Endpoint URL - this is the root or base API endpoint for the object storage service, not including any
bucket name or other additional information</li>
  <li>Region - this may be important for your storage provider for CDN, caching, or geolocation reasons</li>
  <li>Path-style access vs Virtual Host access - small self-hosted object storage (like <code class="language-plaintext highlighter-rouge">cryostat-storage</code>) may not be set
up to support storage bucket resolution by virtual host/subdomain, but only by path. If your storage provider supports
virtual host access then you should generally choose to use it.</li>
  <li>API support for Object Tagging or Object Metadata - not all S3-compatible providers implement the full AWS S3 API,
and one particular feature which Cryostat uses and not all providers (like Backblaze B2) implement is Object Tagging.
We have alternate strategies in Cryostat to use Object Metadata or separate sidecar metadata files instead for broad
compatibility, so you’ll need to know which options are available for your selected provider.</li>
  <li>A randomized string prefix or some other naming scheme, especially if you are using a commercial provider and not a
self-hosted private one. S3 bucket names are generally publicly resolvable and not unique to an account, but need to be
globally unique across the service. Check with your storage provider about allowable character classes and length
limitations. You might try including a randomized string, your application or organization name, the storage region, or
other information into the bucket names.</li>
</ol>

<p>I will use the following parameters for this demo, based on my real Backblaze B2 account but modified/redacted to not
actually expose my account:</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">AWS_ACCESS_KEY_ID</code> will be represented by <code class="language-plaintext highlighter-rouge">$AWS_ACCESS_KEY_ID</code></li>
  <li><code class="language-plaintext highlighter-rouge">AWS_SECRET_ACCESS_KEY</code> will be represented by <code class="language-plaintext highlighter-rouge">$AWS_SECRET_ACCESS_KEY</code></li>
  <li>Provider URL will be <code class="language-plaintext highlighter-rouge">https://s3.us-east-005.backblazeb2.com</code></li>
  <li>Region will be <code class="language-plaintext highlighter-rouge">us-east-005</code></li>
  <li>Virtual Host access is enabled</li>
  <li>Object Tagging API is not supported, so Object Metadata will be used</li>
  <li>Storage bucket names will simply be prefixed with <code class="language-plaintext highlighter-rouge">abcd1234-</code></li>
</ol>

<h3 id="configurations">Configurations</h3>

<h4 id="helm-chart">Helm Chart</h4>

<ol>
  <li>Create a YAML file like so:
    <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">apiVersion</span><span class="pi">:</span> <span class="s">v1</span>
<span class="na">stringData</span><span class="pi">:</span>
 <span class="na">STORAGE_ACCESS_KEY</span><span class="pi">:</span> <span class="s">$AWS_ACCESS_KEY_ID</span>
 <span class="na">STORAGE_ACCESS_KEY_ID</span><span class="pi">:</span> <span class="s">$AWS_SECRET_ACCESS_KEY</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">Secret</span>
<span class="na">metadata</span><span class="pi">:</span>
 <span class="na">name</span><span class="pi">:</span> <span class="s">s3cred</span>
<span class="na">type</span><span class="pi">:</span> <span class="s">Opaque</span>
</code></pre></div>    </div>
    <p>substituting the two values for your actual account values. Save this as <code class="language-plaintext highlighter-rouge">s3cred.yml</code>.</p>
  </li>
  <li>Create the <code class="language-plaintext highlighter-rouge">Secret</code> object in your Cryostat installation namespace: <code class="language-plaintext highlighter-rouge">kubectl create -f s3cred.yml</code>.</li>
  <li>Install the Cryostat Helm Chart with the following configuration values:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>helm <span class="nb">install</span> <span class="se">\</span>
 <span class="nt">--set</span> storage.storageSecretName<span class="o">=</span>s3cred <span class="se">\</span>
 <span class="nt">--set</span> storage.provider.url<span class="o">=</span>https://s3.us-east-005.backblazeb2.com <span class="se">\</span>
 <span class="nt">--set</span> storage.provider.region<span class="o">=</span>us-east-005 <span class="se">\</span>
 <span class="nt">--set</span> storage.provider.usePathStyleAccess<span class="o">=</span><span class="nb">false</span> <span class="se">\</span>
 <span class="nt">--set</span> storage.provider.metadata.storageMode<span class="o">=</span>metadata <span class="se">\</span>
 <span class="nt">--set</span> storage.buckets.names.archivedRecordings<span class="o">=</span>abcd1234-archivedrecordings <span class="se">\</span>
 <span class="nt">--set</span> storage.buckets.names.archivedReports<span class="o">=</span>archivedreports <span class="se">\</span>
 <span class="nt">--set</span> storage.buckets.names.eventTemplates<span class="o">=</span>abcd1234-eventtemplates <span class="se">\</span>
 <span class="nt">--set</span> storage.buckets.names.jmcAgentProbeTemplates<span class="o">=</span>abcd1234-jmcagentprobetemplates <span class="se">\</span>
 <span class="nt">--set</span> storage.buckets.names.threadDumps<span class="o">=</span>abcd1234-threaddumps <span class="se">\</span>
 <span class="nt">--set</span> storage.buckets.names.heapDumps<span class="o">=</span>abcd1234-heapdumps <span class="se">\</span>
 cryostat ./charts/cryostat
</code></pre></div>    </div>
    <p>feel free to add other configuration values as desired, ex. <code class="language-plaintext highlighter-rouge">--set reports.replicas=1</code> or
<code class="language-plaintext highlighter-rouge">--set core.discovery.kubernetes.enabled=true --set core.discovery.kubernetes.namespaces='{mynamespace}'</code>.
The <code class="language-plaintext highlighter-rouge">storage.storageSecretName</code> setting tells the Helm Chart the name of the <code class="language-plaintext highlighter-rouge">s3cred</code> <code class="language-plaintext highlighter-rouge">Secret</code> which we created, where
it will expect to find the <code class="language-plaintext highlighter-rouge">STORAGE_ACCESS_KEY</code> and <code class="language-plaintext highlighter-rouge">STORAGE_ACCESS_KEY_ID</code> key-value pairs. These will be used to
configure Cryostat’s S3 API client. The <code class="language-plaintext highlighter-rouge">storage.provider.url</code> is the S3 API endpoint. The <code class="language-plaintext highlighter-rouge">storage.provider.region</code>
should be self-explanatory. <code class="language-plaintext highlighter-rouge">storage.provider.usePathStyleAccess=false</code> configures Cryostat to use virtual host access
since Backblaze B2 supports it, and <code class="language-plaintext highlighter-rouge">storage.provider.metadata.storageMode=metadata</code> configures Cryostat to use the
Object Metadata API since Backblaze B2 does not support Object Tagging. The <code class="language-plaintext highlighter-rouge">storage.buckets.names.*</code> values set the
globally unique bucket names to use for various different types of data which Cryostat may store. Each of these are
placed into separate buckets so that you can choose to configure different bucket-level policies for different types of
data - storage quotas, object lifecycles, versioning, encryption, storage classes, etc.</p>
  </li>
</ol>

<h4 id="operator-custom-resource">Operator Custom Resource</h4>

<p>This will look rather similar to the previous <a href="#helm">Helm</a> example.</p>

<ol>
  <li><a href="/get-started/#installing-cryostat-operator">Install the Cryostat Operator</a>.</li>
  <li>Create a YAML file like so:
    <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">apiVersion</span><span class="pi">:</span> <span class="s">v1</span>
<span class="na">stringData</span><span class="pi">:</span>
 <span class="na">ACCESS_KEY</span><span class="pi">:</span> <span class="s">$AWS_ACCESS_KEY_ID</span>
 <span class="na">SECRET_KEY</span><span class="pi">:</span> <span class="s">$AWS_SECRET_ACCESS_KEY</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">Secret</span>
<span class="na">metadata</span><span class="pi">:</span>
 <span class="na">name</span><span class="pi">:</span> <span class="s">s3cred</span>
<span class="na">type</span><span class="pi">:</span> <span class="s">Opaque</span>
</code></pre></div>    </div>
    <p>substituting the two values for your actual account values. Save this as <code class="language-plaintext highlighter-rouge">s3cred.yml</code>.</p>
  </li>
  <li>Create the <code class="language-plaintext highlighter-rouge">Secret</code> object in your Cryostat installation namespace: <code class="language-plaintext highlighter-rouge">kubectl create -f s3cred.yml</code>.</li>
  <li>Create a Cryostat Custom Resource:
    <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">apiVersion</span><span class="pi">:</span> <span class="s">operator.cryostat.io/v1beta2</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">Cryostat</span>
<span class="na">metadata</span><span class="pi">:</span>
 <span class="na">name</span><span class="pi">:</span> <span class="s">cryostat-sample</span>
<span class="na">spec</span><span class="pi">:</span>
 <span class="na">objectStorageOptions</span><span class="pi">:</span>
   <span class="na">secretName</span><span class="pi">:</span> <span class="s">s3cred</span>
   <span class="na">provider</span><span class="pi">:</span>
     <span class="na">url</span><span class="pi">:</span> <span class="s">https://s3.us-east-005.backblazeb2.com</span>
     <span class="na">region</span><span class="pi">:</span> <span class="s">us-east-005</span>
     <span class="na">usePathStyleAccess</span><span class="pi">:</span> <span class="no">false</span>
     <span class="na">metadataMode</span><span class="pi">:</span> <span class="s">metadata</span>
   <span class="na">storageBucketNameOptions</span><span class="pi">:</span>
     <span class="na">archivedRecordings</span><span class="pi">:</span> <span class="s">abcd1234-archivedrecordings</span>
     <span class="na">archivedReports</span><span class="pi">:</span> <span class="s">abcd1234-archivedreports</span>
     <span class="na">eventTemplates</span><span class="pi">:</span> <span class="s">abcd1234-eventtemplates</span>
     <span class="na">heapDumps</span><span class="pi">:</span> <span class="s">abcd1234-heapdumps</span>
     <span class="na">jmcAgentProbeTemplates</span><span class="pi">:</span> <span class="s">abcd1234-jmcagentprobetemplates</span>
     <span class="na">threadDumps</span><span class="pi">:</span> <span class="s">abcd1234-threaddumps</span>
</code></pre></div>    </div>
    <p>Refer back to the <a href="#helm">Helm</a> example for a line-by-line explanation of what each of these configuration properties
means. Of course, you can also combine these properties with other Custom Resource properties.</p>
  </li>
</ol>

<h4 id="compose">Compose</h4>

<p>Following my previous <a href="/2025/12/10/docker-compose.html">Cryostat in Compose</a> post, let’s simply build on that
foundation and use the Cryostat smoketest script’s <code class="language-plaintext highlighter-rouge">-s ext</code> (“storage external”) flag to generate a Compose YAML
manifest:</p>

<ol>
  <li>Export environment variables:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">cd </span>cryostat
<span class="nv">$ </span><span class="nb">export </span><span class="nv">AWS_ACCESS_KEY_ID</span><span class="o">=</span>replaceme
<span class="nv">$ </span><span class="nb">export </span><span class="nv">AWS_SECRET_ACCESS_KEY</span><span class="o">=</span>replaceme
<span class="nv">$ </span><span class="nb">export </span><span class="nv">S3_ENDPOINT</span><span class="o">=</span>https://s3.us-east-005.backblazeb2.com
<span class="nv">$ </span><span class="nb">export </span><span class="nv">S3_REGION</span><span class="o">=</span>us-east-005
<span class="nv">$ </span><span class="nb">export </span><span class="nv">S3_PATH_STYLE_ACCESS</span><span class="o">=</span><span class="nb">false</span>
</code></pre></div>    </div>
    <p>The <code class="language-plaintext highlighter-rouge">smoketest.bash</code> script generates default bucket names which include the bucket base name (ex. “archives”), the
first few characters of <code class="language-plaintext highlighter-rouge">AWS_ACCESS_KEY_ID</code> (this is not considered secret information), the <code class="language-plaintext highlighter-rouge">S3_REGION</code>, and a few
random characters as an instance ID. Don’t worry about finding those generated bucket names and manually creating them
- Cryostat will automatically check if the buckets already exist and try to create them if they don’t when it starts.</p>
  </li>
  <li>Generate the manifest:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./smoketest.bash <span class="nt">-n</span> <span class="nt">-s</span> ext <span class="o">&gt;</span> cryostat-compose.yml
</code></pre></div>    </div>
  </li>
  <li>Import volumes:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="k">for </span>i <span class="k">in</span> <span class="k">*</span>.tar.gz <span class="p">;</span> <span class="k">do</span> <span class="se">\</span>
  <span class="nv">f</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="nv">$i</span> | <span class="nb">cut</span> <span class="nt">-d</span><span class="nb">.</span> <span class="nt">-f1</span><span class="si">)</span><span class="p">;</span> podman volume create <span class="nv">$f</span><span class="p">;</span> podman volume import <span class="nv">$f</span> <span class="nv">$f</span>.tar.gz<span class="p">;</span> <span class="se">\</span>
<span class="k">done</span>
</code></pre></div>    </div>
  </li>
  <li>Start Cryostat:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>podman compose <span class="nt">-f</span> cryostat-compose.yml up
</code></pre></div>    </div>
  </li>
</ol>

<h3 id="additional-information">Additional Information</h3>

<h4 id="integrations">Integrations</h4>

<p>Depending on the object storage provider you choose, you may gain additional integration points for the data Cryostat
exports to storage. In Backblaze B2 for example, you can set up Event Notifications as a webhook-like system to notify
another application when things change. You might choose to have B2 send a notification to another service of yours
whenever Cryostat uploads a new Flight Recorder or Heap Dump file to archives, in case you have some additional
analysis tooling that you want to build a pipeline to.</p>

<h4 id="recommendations">Recommendations</h4>

<p>Various object storage providers also implement concepts like object lifecycles and bucket storage quotas. You should
consider how heavily you use Cryostat and how much data your usage generally produces and set quotas accordingly to
avoid accidentally using too much storage space and racking up a large bill. Using object lifecycles to manage old data,
especially large objects like Flight Recorder files and Heap Dumps, can also be very helpful. You might choose to move
files from standard storage into deep/cold storage after one week, and delete them entirely after one month, for
example. Think carefully about how these features might interact with Cryostat’s
<a href="/guides/#create-an-automated-rule">Automated Rules</a> and periodic archival if you choose to use them.</p>

<h4 id="side-effect">Side Effect</h4>

<p>An interesting side-effect of using external storage in this way arises from the fact that Cryostat does not maintain
any separate metadata about what files it has uploaded to the storage buckets. Cryostat simply queries the storage
provider for the current bucket contents as needed. This ensures Cryostat is resilient to external modifications of the
bucket contents - which may be due to object lifecycle policies, or other applications, or users interacting directly
with the storage provider console or API - but also means that you can connect two or more Cryostat instances to the
same set of buckets using the same credentials. When Cryostat A pushes a Flight Recorder file to the shared archives,
that same file will become visible in Cryostat B’s view of the archives, although Cryostat B will not produce any
notification for you that this has happened.</p>

<p>So one interesting use-case you might explore is to install a Cryostat A alongside your applications in Kubernetes and
have it export data to a shared storage, then run a Cryostat B in Compose on your local machine hooked up to the same
storage. These two Cryostat instances will not share a database so they will not see the same discovered targets, or
have the same Automated Rules, etc., but they will share
<a href="/guides/#all-archives-archived-recordings-view">Recording Archives</a>,
<a href="/guides/#capture-a-thread-dump">Thread Dump Archives</a>, and <a href="/guides/#capture-a-heap-dump">Heap Dump Archives</a>. Just
be sure to select the “All Archives” tab of each of these views.</p>

<p>You can then use features like <a href="/guides/#view-a-recording-in-grafana">View in Grafana</a> or
<a href="/guides/#view-automated-analysis-for-a-target">Automated Analysis</a> (see Step 6) and have the computation done on your
local machine instead of by the Cryostat instance installed in your cloud environment.</p>]]></content><author><name>Andrew Azores</name><email>aazores@ibm.com</email></author><summary type="html"><![CDATA[Table of Contents Table of Contents]]></summary></entry><entry><title type="html">Deploying Cryostat in Docker Compose</title><link href="https://cryostat.io/2025/12/10/docker-compose.html" rel="alternate" type="text/html" title="Deploying Cryostat in Docker Compose" /><published>2025-12-10T00:00:00+00:00</published><updated>2025-12-10T00:00:00+00:00</updated><id>https://cryostat.io/2025/12/10/docker-compose</id><content type="html" xml:base="https://cryostat.io/2025/12/10/docker-compose.html"><![CDATA[<h4 id="table-of-contents">Table of Contents</h4>
<ul id="markdown-toc">
  <li><a href="#table-of-contents" id="markdown-toc-table-of-contents">Table of Contents</a></li>
  <li><a href="#intro" id="markdown-toc-intro">Intro</a></li>
  <li><a href="#objective" id="markdown-toc-objective">Objective</a></li>
  <li><a href="#setup" id="markdown-toc-setup">Setup</a>    <ul>
      <li><a href="#application" id="markdown-toc-application">Application</a></li>
      <li><a href="#cryostat" id="markdown-toc-cryostat">Cryostat</a></li>
      <li><a href="#linking-up" id="markdown-toc-linking-up">Linking Up</a></li>
    </ul>
  </li>
  <li><a href="#cleaning-up" id="markdown-toc-cleaning-up">Cleaning Up</a>    <ul>
      <li><a href="#upgrading-cryostat" id="markdown-toc-upgrading-cryostat">Upgrading Cryostat</a></li>
    </ul>
  </li>
</ul>
<hr />

<h2 id="intro">Intro</h2>

<p>Although most of this website and other external documentation about Cryostat focuses on how to install and use it in a
Kubernetes or OpenShift environment, none of that is actually required for Cryostat itself. Cryostat could be run as a
bare metal JVM process, and it can certainly be run as an OCI container in a Docker/Podman environment - in fact,
day-to-day Cryostat development testing mostly takes place in Podman containers and doesn’t touch Kubernetes at all!</p>

<p>Since Cryostat 3.0 the development testing setup has relied on YAML <code class="language-plaintext highlighter-rouge">docker-compose</code> definition files to piece together
an installation. This is done by the <a href="https://github.com/cryostatio/cryostat/blob/main/smoketest.bash"><code class="language-plaintext highlighter-rouge">smoketest.bash</code></a>
script and <a href="https://github.com/cryostatio/cryostat/tree/main/compose">various YAML base files</a>. The smoketest script
supports a small suite of command line switches and environment variables to customize exactly what gets deployed,
which is obviously useful in development to test various scenarios (like different S3-like object storage providers).</p>

<p>It is also possible to run the script in a dry-run mode and have it print out the final Docker Compose YAML definition,
rather than continuing to actually deploy it. There are a few configuration volumes that are also created and mounted
by the script, such as the one that contains the proxy config and <code class="language-plaintext highlighter-rouge">htpasswd</code> file for the <code class="language-plaintext highlighter-rouge">oauth2-proxy</code> container.
There is a walkthrough of this process and some sample configuration files that can be downloaded
<a href="https://github.com/cryostatio/cryostat/wiki/Deploying-Cryostat-in-Docker-or-Podman-Compose">on the project’s GitHub Wiki page</a>.
In particular, you might want to try customizing the Cryostat Compose YAML using the <code class="language-plaintext highlighter-rouge">-s ext</code> flag, which allows you
to hook up Cryostat to an external S3-like object storage provider. This could be another self-hosted Docker Compose
project you’re running locally, or it could be a commercial service - it’s up to you to decide what fits best.</p>

<h2 id="objective">Objective</h2>

<p>Java, containers, Docker/Podman, and observability are all common things nowadays. In the same way that there are many
people, teams, and businesses deploying Java in containers to Kubernetes clouds every day - or multiple times per day -
and needing a way to profile and observe <em>how</em> those Java VMs are performing, there are people, teams, and businesses
running their workloads <em>without</em> Kubernetes. So let’s put together a scenario where someone might be deploying a Java-
based application in their home lab, or on their small office NAS, or in the corner of their startup’s garage, running
Compose instead of Kubernetes.</p>

<h2 id="setup">Setup</h2>

<div class="tip-callout">
  <b>💡 TIP</b>
  <p>This example will use Podman and <code>podman-compose</code>, but should also work with little to no modification with Docker and Docker Compose.</p>
</div>

<h3 id="application">Application</h3>

<p>Let’s put together a <code class="language-plaintext highlighter-rouge">compose.yml</code> for a sample application. In practice this might be a Compose file you download from
the project you’re trying to deploy, or it could be a Compose file you’ve written yourself to deploy the thing you’re
developing. I’ll use <a href="https://github.com/cryostatio/cryostat/blob/main/compose/sample_apps/quarkus-petclinic.yml">Cryostat’s <code class="language-plaintext highlighter-rouge">quarkus-petclinic</code></a>
testing sample, which is based on <a href="https://github.com/redhat-developer-demos/quarkus-petclinic">this demo <code class="language-plaintext highlighter-rouge">quarkus-petclinic</code></a>.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">name</span><span class="pi">:</span> <span class="s">petclinic-cryostat</span>
<span class="na">services</span><span class="pi">:</span>
  <span class="na">quarkus-petclinic</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">${QUARKUS_PETCLINIC_IMAGE:-quay.io/redhat-java-monitoring/quarkus-petclinic:latest}</span>
    <span class="na">hostname</span><span class="pi">:</span> <span class="s">quarkus-petclinic</span>
    <span class="na">depends_on</span><span class="pi">:</span>
      <span class="na">quarkus-petclinic-db</span><span class="pi">:</span>
        <span class="na">condition</span><span class="pi">:</span> <span class="s">service_healthy</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s2">"</span><span class="s">10011:10011"</span>
    <span class="na">environment</span><span class="pi">:</span>
      <span class="na">QUARKUS_HTTP_HOST</span><span class="pi">:</span> <span class="s">0.0.0.0</span>
      <span class="na">QUARKUS_HTTP_PORT</span><span class="pi">:</span> <span class="m">10011</span>
      <span class="na">QUARKUS_DATASOURCE_JDBC_URL</span><span class="pi">:</span> <span class="s">jdbc:postgresql://quarkus-petclinic-db:5432/petclinic</span>
    <span class="na">restart</span><span class="pi">:</span> <span class="s">always</span>
    <span class="na">healthcheck</span><span class="pi">:</span>
      <span class="na">test</span><span class="pi">:</span> <span class="s">curl --fail http://localhost:10010 || exit </span><span class="m">1</span>
      <span class="na">interval</span><span class="pi">:</span> <span class="s">10s</span>
      <span class="na">retries</span><span class="pi">:</span> <span class="m">3</span>
      <span class="na">start_period</span><span class="pi">:</span> <span class="s">30s</span>
      <span class="na">timeout</span><span class="pi">:</span> <span class="s">5s</span>

  <span class="na">quarkus-petclinic-db</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s2">"</span><span class="s">quay.io/sclorg/postgresql-15-c9s"</span>
    <span class="na">deploy</span><span class="pi">:</span>
      <span class="na">resources</span><span class="pi">:</span>
        <span class="na">limits</span><span class="pi">:</span>
          <span class="na">cpus</span><span class="pi">:</span> <span class="s2">"</span><span class="s">1"</span>
          <span class="na">memory</span><span class="pi">:</span> <span class="s">128m</span>
    <span class="na">environment</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">POSTGRESQL_USER=developer</span>
      <span class="pi">-</span> <span class="s">POSTGRESQL_PASSWORD=developer</span>
      <span class="pi">-</span> <span class="s">POSTGRESQL_DATABASE=petclinic</span>
    <span class="na">healthcheck</span><span class="pi">:</span>
      <span class="na">test</span><span class="pi">:</span> <span class="pi">[</span><span class="s2">"</span><span class="s">CMD-SHELL"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">pg_isready</span><span class="nv"> </span><span class="s">--dbname</span><span class="nv"> </span><span class="s">$$POSTGRES_DB</span><span class="nv"> </span><span class="s">--username</span><span class="nv"> </span><span class="s">$$POSTGRES_USER"</span><span class="pi">]</span>
      <span class="na">interval</span><span class="pi">:</span> <span class="s">5s</span>
      <span class="na">timeout</span><span class="pi">:</span> <span class="s">5s</span>
      <span class="na">retries</span><span class="pi">:</span> <span class="m">6</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s2">"</span><span class="s">5432:5432"</span>
</code></pre></div></div>

<p>This just describes a simple Quarkus-based webserver application in one container, and a Postgres database in a second
container, with a bit of configuration to tell the application how to hook up to that database.</p>

<p>Save this YAML as <code class="language-plaintext highlighter-rouge">petclinic.yml</code>, then run <code class="language-plaintext highlighter-rouge">podman compose up -f petclinic.yml</code> in a terminal to spin up the
application. Wait a few moments for the two containers to come up and become ready, then go to
<a href="http://localhost:10011"><code class="language-plaintext highlighter-rouge">http://localhost:10011</code></a> and ensure it is running. Then return to your terminal and press
<code class="language-plaintext highlighter-rouge">Ctrl-c</code> to shut it down for now.</p>

<h3 id="cryostat">Cryostat</h3>

<p>As I mentioned above, there is a more complete description of the Cryostat setup process 
<a href="https://github.com/cryostatio/cryostat/wiki/Deploying-Cryostat-in-Docker-or-Podman-Compose">on the project’s GitHub Wiki page</a>
with sample configuration volume files.</p>

<p>Download the <code class="language-plaintext highlighter-rouge">.tar.gz</code> configuration file volumes and import them as instructed. Copy the main <code class="language-plaintext highlighter-rouge">cryostat-compose.yml</code>
YAML file content and save it locally. Then, run <code class="language-plaintext highlighter-rouge">podman compose -f cryostat-compose.yml up -d</code>, wait for the containers
to pull, start, and become healthy, then go to <a href="https://localhost:8443"><code class="language-plaintext highlighter-rouge">https://localhost:8443</code></a> to ensure Cryostat is
up and running in the background.</p>

<h3 id="linking-up">Linking Up</h3>

<p>Now that we have Cryostat up and running, let’s get our application running again and in a way that Cryostat is able
to see it and collect that precious performance data. Modify your <code class="language-plaintext highlighter-rouge">petclinic.yml</code> to add some container labels and
enable JMX:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">name</span><span class="pi">:</span> <span class="s">petclinic-cryostat</span> <span class="c1"># this must match the name: property of the petclinic.yml</span>
<span class="na">services</span><span class="pi">:</span>
  <span class="na">quarkus-petclinic</span><span class="pi">:</span>
    <span class="na">labels</span><span class="pi">:</span>
      <span class="na">io.cryostat.discovery</span><span class="pi">:</span> <span class="s2">"</span><span class="s">true"</span>
      <span class="na">io.cryostat.jmxHost</span><span class="pi">:</span> <span class="s2">"</span><span class="s">quarkus-petclinic"</span> <span class="c1"># this must match the service's name</span>
      <span class="na">io.cryostat.jmxPort</span><span class="pi">:</span> <span class="s2">"</span><span class="s">11223"</span> <span class="c1"># this must match the jmxremote.port and jmxremote.rmi.port number configured below</span>
    <span class="na">environment</span><span class="pi">:</span>
      <span class="na">JAVA_OPTS_APPEND</span><span class="pi">:</span> <span class="pi">&gt;-</span>
        <span class="s">-Dcom.sun.management.jmxremote</span>
        <span class="s">-Dcom.sun.management.jmxremote.port=11223</span>
        <span class="s">-Dcom.sun.management.jmxremote.rmi.port=11223</span>
        <span class="s">-Djava.rmi.server.hostname=quarkus-petclinic # this must also match the service's name</span>
        <span class="s">-Dcom.sun.management.jmxremote.authenticate=false</span>
        <span class="s">-Dcom.sun.management.jmxremote.ssl=false</span>
        <span class="s">-Dcom.sun.management.jmxremote.local.only=false</span>
    <span class="s">...</span>
</code></pre></div></div>

<p>This is only a demo, so we’re skipping JMX authentication and TLS setup. You should always configure this on your
production workloads, and check <a href="/guides/">the guides on this site</a> for instructions on how to configure Cryostat to
work with <a href="/guides/#add-a-trusted-certificate">JMX+TLS</a> and <a href="/guides/#store-credentials">JMX+auth</a>.
Depending on your Java application, framework, base image, entrypoint script, etc. you may need to change the
<code class="language-plaintext highlighter-rouge">JAVA_OPTS_APPEND</code> environment variable name or use a different configuration entirely.</p>

<p>Let’s start up this application again and run it in the background: <code class="language-plaintext highlighter-rouge">podman compose -f petclinic.yml up -d</code>. Go back
to Cryostat at <a href="https://localhost:8443/topology"><code class="language-plaintext highlighter-rouge">https://localhost:8443/topology</code></a> and
<a href="/guides/#use-topology-view">check out the Topology view</a>. You should see a target JVM named
<code class="language-plaintext highlighter-rouge">compose-quarkus-petclinic-1</code>.</p>

<h2 id="cleaning-up">Cleaning Up</h2>

<p><code class="language-plaintext highlighter-rouge">podman compose -f cryostat-compose.yml down</code> can be used to tear down the Cryostat installation. You can also pass
<code class="language-plaintext highlighter-rouge">--volumes</code> if you’d like to delete the persistent volumes that were attached to this installation, which contain
captured data such as archived Flight Recording files.</p>

<p>Likewise, <code class="language-plaintext highlighter-rouge">podman compose -f petclinic.yml down [--volumes]</code> can be used to tear down the <code class="language-plaintext highlighter-rouge">quarkus-petclinic</code>
application.</p>

<h3 id="upgrading-cryostat">Upgrading Cryostat</h3>

<p>Let’s say you have followed this guide and installed Cryostat 4.1.0, which is the current latest version. Later down
the line you notice that Cryostat 4.1.1 or Cryostat 4.2.0 has been released, and you want to upgrade your
Cryostat-in-Compose installation. How would you do that?</p>

<p>Using the same <code class="language-plaintext highlighter-rouge">cryostat-compose.yml</code> file from before, do <code class="language-plaintext highlighter-rouge">podman compose -f cryostat-compose.yml down</code>.
Then follow the <a href="https://github.com/cryostatio/cryostat/wiki/Deploying-Cryostat-in-Docker-or-Podman-Compose">guide on getting a Cryostat Compose file</a>
again, and replace the <code class="language-plaintext highlighter-rouge">cryostat-compose.yml</code> to ensure that all of the appropriate updates have been made to container
version tags, environment variables, etc. Then, <code class="language-plaintext highlighter-rouge">podman compose -f cryostat-compose.yml up -d</code> will spin up the updated
deployment, apply any database migrations, and restore your Cryostat functionality.</p>]]></content><author><name>Andrew Azores</name><email>aazores@ibm.com</email></author><summary type="html"><![CDATA[Table of Contents Table of Contents]]></summary></entry><entry><title type="html">Cryostat 4.1.0 is Released!</title><link href="https://cryostat.io/2025/11/27/cryostat-410-release.html" rel="alternate" type="text/html" title="Cryostat 4.1.0 is Released!" /><published>2025-11-27T00:00:00+00:00</published><updated>2025-11-27T00:00:00+00:00</updated><id>https://cryostat.io/2025/11/27/cryostat-410-release</id><content type="html" xml:base="https://cryostat.io/2025/11/27/cryostat-410-release.html"><![CDATA[<h4 id="table-of-contents">Table of Contents</h4>
<ul id="markdown-toc">
  <li><a href="#table-of-contents" id="markdown-toc-table-of-contents">Table of Contents</a></li>
  <li><a href="#release-highlights" id="markdown-toc-release-highlights">Release Highlights</a>    <ul>
      <li><a href="#new-features" id="markdown-toc-new-features">New Features</a>        <ul>
          <li><a href="#openshift-specific" id="markdown-toc-openshift-specific">OpenShift-specific</a></li>
          <li><a href="#general" id="markdown-toc-general">General</a></li>
        </ul>
      </li>
      <li><a href="#feature-enhancements" id="markdown-toc-feature-enhancements">Feature Enhancements</a></li>
      <li><a href="#general-maintenance" id="markdown-toc-general-maintenance">General Maintenance</a></li>
    </ul>
  </li>
  <li><a href="#where-can-i-get-the-latest-version-of-cryostat" id="markdown-toc-where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</a></li>
  <li><a href="#feedback" id="markdown-toc-feedback">Feedback</a></li>
</ul>
<hr />

<p>Hello everyone,</p>

<p>Cryostat 4.1.0 has landed. It’s a minor release in semantic versioning terms, but it’s a big release in terms of functionality and features. Read on to find out what’s new.</p>

<h2 id="release-highlights">Release Highlights</h2>

<h3 id="new-features"><a href="#new-features">New Features</a></h3>

<h4 id="openshift-specific"><a href="#openshift-specific">OpenShift-specific</a></h4>

<ol>
    <li>
        <b>Console Plugin auto-configuration UI</b>: <a href="/2025/03/20/cryostat-400-release.html#openshift-specific-features">Cryostat 4.0</a> introduced a Console Plugin and Cryostat Agent Autoconfiguration feature for OpenShift users. Cryostat 4.1 expands on that with a new feature allowing Agent Autoconfiguration to be performed graphically within the Console UI, rather than requiring you to manually edit your application <code>Deployment</code> YAML.
    </li>
</ol>

<h4 id="general"><a href="#general">General</a></h4>

<ol>
    <li>
        <b>New Navigation</b>: the navigation sidebar has been reorganized into nested sections, and a few new navigable pages have been added (more details below). The old <code>Automated Rules</code> view is now under the <code>Flight Recorder</code> section, under the <code>Capture</code> subsection, as the <code>Automated Rules</code> item - or <i>Flight Recorder/Capture/Automated Rules</i>. <code>Recordings</code> has been split into <i>Flight Recorder/Capture/Recordings</i> and <i>Flight Recorder/Analyze/Archives</i>, and <code>Events</code> has been split into <i>Flight Recorder/Capture/Events</i> and <i>Flight Recorder/Capture/Instrumentation</i>.
    </li>
    <li>
        <b>Automated Reports view</b>: the new <i>Flight Recorder/Analyze/Automated Reports</i> view provides an overview of all recent automated analysis reports per target. It has controls to sort and filter the reports to help surface which JVMs in your deployment may require your attention.
    </li>
    <li>
        <b>Diagnostics section</b>: the new <i>Diagnostics</i> contains controls for <a href="/guides/#perform-garbage-collection">performing garbage collection</a>, <a href="/guides/#capture-a-thread-dump">capturing a thread dump</a>, and <a href="/guides/#capture-a-heap-dump">capturing a heap dump</a>. Performing garbage collection is still possible via a <code>Dashboard</code> card, and that same card also now contains the same thread and heap dump controls as this new navigable view. Thread and heap dumps are stored in new, separate buckets in Cryostat's object storage, and have similar <i>Targets</i>, <i>All-Targets</i>, and <i>All-Archives</i> viewing modes as <code>Archived Recordings</code>. They can also be downloaded, deleted, and labeled like archived recordings, but there are no analysis tools for these data types within the Cryostat UI.
    </li>
    <li>
        <b>External object storage</b>: since Cryostat 3.0, file-based data like archived recordings have been stored in a <a href="https://github.com/cryostatio/cryostat-storage"><code>cryostat-storage</code></a> S3-compatible object storage instance, as opposed to simply written to local filesystem within the Cryostat container. In Cryostat 4.1 the configuration knobs to choose your own S3-compatible object storage are now finally exposed, so when you install a Cryostat instance you can choose the batteries-included <code>cryostat-storage</code> option, or opt for your own choice of object storage provider. This may be your own self-hosted object storage which you manage or it can be a commercial service provider. For long-lived production Cryostat installations it is highly recommended that you should choose a commercial service provider or your own self-managed object storage, rather than relying on the simple object storage included with Cryostat. Various internal improvements have also been made for the communication between Cryostat, <code>cryostat-storage</code>, <code>cryostat-reports</code>, and <code>jfr-datasource</code> to optimize the transfer of files between containers.
    </li>
    <li>
        <b>Declarative configurations</b> have new additions. These are configurations that allow you to define ex. <a href="/guides/#preconfiguring-event-templates-within-cryostat">custom event templates</a> by mounting a volume containing definition files to Cryostat, rather than needing to use the Cryostat UI or API to create these resources. In Kubernetes or OpenShift this can be achieved using <code>ConfigMaps</code> or <code>Secrets.</code> It is now also possible to define the following resource types declaratively:
        <ul>
            <li>automated rules</li>
            <li>JMC agent probe templates</li>
            <li>stored credentials</li>
        </ul>
    </li>
    <li>
        <b>Cryostat Agent Smart Triggers via file</b>: similarly, <a href="/guides/#using-smart-triggers">Cryostat Agent Smart Triggers</a> can be configured by providing the Agent with a path to a file containing Smart Triggers definitions, not only by passing them as command line parameters. Use the JVM flag <code>-Dcryostat.agent.smart-trigger.config.path=/path/to/file</code> or the environment variable <code>CRYOSTAT_AGENT_SMART_TRIGGER_CONFIG_PATH=/path/to/file</code>.
    </li>
    <li>
        <b>Accessibility settings</b>: the Settings view has a new <i>General/Accessibility</i> section, which allows you to select the colour palette and icon size used for components like the <code>Automated Analysis Reports</code>.
    </li>
    <li>
        <b>Topology analysis filtering</b>: the Settings view has a new <i>Topology</i> section which allows you to configure the behaviour of the <i>Overview/Topology</i> view. The <code>Topology</code> view indicates <code>Automated Analysis</code> scores on discovered targets using a status badge displaying the maximum (most critical) analysis score. However, some of these analysis scores are static, configuration-based scores which may not be of particular interest in all cases - for example, the <i>Passwords in Environment Variables</i> score. In many cases it is acceptable to include passwords in environment variables, so if this is the only detected "issue" with a target JVM, it may not be desirable for this to reflect as a critical status on the <code>Topology</code> view. You can use this new Settings configuration to control which analysis results are used for determining the Topology view status badges.
    </li>
    <li>
        <b>Target-based automated analysis</b>: along with the split of <code>Recordings</code> into <i>Flight Recorder/Capture/Recordings</i> and <i>Flight Recorder/Analyze/Archives</i> and the new <i>Flight Recorder/Analyze,Automated Reports</i> and <code>autoanalyze=true</code> feature described above, the workflow for manually generating an Automated Analysis report for a target JVM <a href="/guides/#view-automated-analysis-for-a-target">has been reworked</a>. The new workflow guides you through creating a recording (with selected default values) if required, then creates, archives, and deletes a Snapshot recording with the `autoanalyze=true` label to trigger the automated analysis. The results will be viewable in the new <code>Analyze</code> panel in the <i>Flight Recorder/Capture/Recordings</i> view as well as at <i>Flight Recorder/Analyze/Automated Reports</i>, and will also be cached and connected to the archived recording copy viewable at <i>Flight Recorder/Analyze/Archives</i>. This reduces the number of clicks to get to an automated analysis report for a target application, as well as ensuring the results are easy to both view immediately and reference back to in the future.
    </li>
</ol>

<h3 id="feature-enhancements"><a href="#feature-enhancements">Feature Enhancements</a></h3>

<ol>
    <li>
        <b>Automatic Automated Analysis</b>: when an <code>Archived Recording</code> with the label <code>autoanalyze=true</code> is created, Cryostat will automatically perform <a href="/guides/#view-automated-analysis-for-a-target">automated analysis</a> of that recording. The results will be cached and viewable in the new <i>Flight Recorder/Analyze/Automated Reports</i> view. Hint: labels applied to <code>Active Recordings</code> are copied to <code>Archived Recordings</code>, so the act of archiving any active recording with this label applied will trigger this behaviour. You will notice that the active recording creation form and Automated Rule creation form have new controls to enable this feature, which is turned on by default. Cryostat will also automatically perform this function for "external recordings" - ones which Cryostat observes are available in a target JVM, which Cryostat did not initiate. Such recordings are often present due to the use of the <code>-XX:StartFlightRecording</code> JVM flag.
    </li>
    <li>
        <b>External recording enhancements</b>: continuing on the topic of external recordings, these are now handled completely as if they were started by Cryostat with the "archive on stop" and "automatically analyze" options enabled. Whether the recording is manually stopped or its fixed duration elapses, Cryostat will copy the recording data into the archives and automatically analyze the contents.
    </li>
    <li>
        <b>Archive On Stop for Continuous Recordings</b>: previously, the "archive on stop" option was only available for fixed-duration recordings, so that Cryostat would automatically copy JFR data to archives when the configured duration elapsed. This option is now available for continuous recordings (those without a fixed duration) and is enabled by default. When a continuous recording is manually stopped, Cryostat will also automatically copy the JFR data to archives.
    </li>
    <li>
        <b>Automated Rule copying and editing</b> has been implemented. Previously, if you wanted to use an existing <code>Automated Rule</code> from the Cryostat UI as a basis for a new rule, you would need to either:
        <ul>
            <li>
                <a href="/guides/#download-an-automated-rule">download the Rule</a>, make edits locally with a text or JSON editor, and <a href="/guides/#upload-an-automated-rule">upload the new Rule</a>
            </li>
            <li>
                <a href="/guides/#create-an-automated-rule">create a new Rule</a> graphically and manually copy the settings
            </li>
        </ul>
        In the Automated Rule overflow menu there is a new <code>Edit</code> action which allows you to edit a Rule in-place (with some limitations), and a new <code>Copy</code> action which allows you to create a new Rule using the existing Rule as a template with the same configuration.
    </li>
    <li>
        <b>JVM details modal</b> anywhere: the <a href="/guides/#target-jvm-details-card"><code>Dashboard</code></a> and <a href="/guides/#view-jvm-details-and-resources"><code>Topology</code></a> views contain a component which displays details about a selected JVM target. This also includes components where a miniature Topology view is included, such as <code>Automated Rules</code> and <code>Security</code>. Other views, such as <i>Flight Recorder/Capture/Recordings</i> provided no way to view JVM details beyond the alias and connection URL via the target selector dropdown. There is a new info button beside the dropdown which, when clicked, summons a modal dialog containing the same details component so that this information is visible anywhere a target selection has been made.
    </li>
    <li>
        <b>Merged Target and All-Targets archives</b>: the old <code>Recordings</code> view had a tab for target-specific archived recordings, and the old <code>Archives</code> view had a tab for <i>All Targets</i>. These were extremely similar and redundant. The new <i>Flight Recorder/Capture/Recordings</i> view focuses only on active recordings and removes the target-specific archives tab. The new <i>Flight Recorder/Analyze/Archives</i> view has a <i>Targets</i> tab with a target selector dropdown. If a target is selected this behaves just like the old <code>Recordings</code> view and its target-specific archives tab. If the target selection is cleared then this behaves just like the old <code>Archives</code> view and its <i>All Targets</i> tab.
    </li>
    <li>
        <b>Grafana dashboard</b> now includes a <code>Frameworks</code> row. This includes a chart for <a href="https://mvnrepository.com/artifact/org.hibernate.orm/hibernate-jfr"><code>Hibernate ORM</code></a> JFR events, and a chart and a table for <a href="https://quarkus.io/guides/jfr"><code>Quarkus REST</code></a> JFR events. <a href="/2025/03/20/cryostat-400-release.html">Cryostat 4.0</a> previously shipped <i>Preset Event Templates</i>, <i>Preset Automated Rules</i>, and a <code>Match Expression</code> feature to help you take capture these JFR event types, so this new feature provides a convenient way for you to visualize this captured data.
    </li>
    <li>
        <b>IPv6 targets</b>: support for IPv6 is improved, including for Kubernetes/OpenShift EndpointSlice-based discovery. Kubernetes clusters using IPv6 or running IPv4/IPv6 dual-stack should pose no issue for Cryostat.
    </li>
</ol>

<h3 id="general-maintenance"><a href="#general-maintenance">General Maintenance</a></h3>
<ol>
    <li>
        Container resource limits and requests: when deploying Cryostat via the operator or Helm chart, the default resource requests have been raised to avoid low-resource scenarios which were often seen in Cryostat 4.0, and there are now default resource limits applied so that Cryostat will not try to consume all available resources if you give it a lot of work to do.
    </li>
    <li>
        Routine maintenance: dependency version updates and container base image version updates.
    </li>
</ol>

<p>For further details on these items, <a href="https://github.com/cryostatio/cryostat/discussions/1191">check the GitHub Discussions release announcement</a>.</p>

<h2 id="where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</h2>
<p>You can install Cryostat using our
<a href="https://operatorhub.io/operator/cryostat-operator">Kubernetes operator on OperatorHub.io</a>
or via a
<a href="https://github.com/cryostatio/cryostat-helm/releases/tag/v2.1.0">Helm Chart</a>
. As always, you can also run Cryostat in other environments with a little more manual setup.</p>

<p>If this is your first time installing Cryostat on Kubernetes, you can <a href="/get-started">Get Started</a> right here on this
website.</p>

<p>If you had previously installed Cryostat Operator 4.0.x with OLM, then you may have already been upgraded to 4.1.0, or
else you should be able to approve and install the upgrade.</p>

<h2 id="feedback">Feedback</h2>
<p>Please reach out to the <a href="mailto:cryostat-development@googlegroups.com">Cryostat mailing list</a> or
<a href="https://github.com/cryostatio/cryostat/discussions/1191">GitHub Discussion</a> with any questions or comments.</p>]]></content><author><name>Andrew Azores</name><email>aazores@ibm.com</email></author><summary type="html"><![CDATA[Table of Contents Table of Contents]]></summary></entry><entry><title type="html">Cryostat 4.0.1 is Released!</title><link href="https://cryostat.io/2025/06/12/cryostat-401-release.html" rel="alternate" type="text/html" title="Cryostat 4.0.1 is Released!" /><published>2025-06-12T00:00:00+00:00</published><updated>2025-06-12T00:00:00+00:00</updated><id>https://cryostat.io/2025/06/12/cryostat-401-release</id><content type="html" xml:base="https://cryostat.io/2025/06/12/cryostat-401-release.html"><![CDATA[<h4 id="table-of-contents">Table of Contents</h4>
<ul id="markdown-toc">
  <li><a href="#table-of-contents" id="markdown-toc-table-of-contents">Table of Contents</a></li>
  <li><a href="#whats-fixed-in-401" id="markdown-toc-whats-fixed-in-401">What’s Fixed in 4.0.1?</a></li>
  <li><a href="#where-can-i-get-the-latest-version-of-cryostat" id="markdown-toc-where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</a></li>
  <li><a href="#feedback" id="markdown-toc-feedback">Feedback</a></li>
</ul>
<hr />

<p>Hello everyone,</p>

<p>We are pleased to announce the release of Cryostat 4.0.1! This is a minor bugfix release addressing some issues
uncovered with the previous 4.0.0 feature release.</p>

<h2 id="whats-fixed-in-401"><a href="#whats-new-in-401">What’s Fixed in 4.0.1?</a></h2>
<ol>
  <li>Routine maintenance: dependency version updates and container base image version updates</li>
  <li><strong>Cryostat</strong> <code class="language-plaintext highlighter-rouge">Automated Rules</code> error handling was improved</li>
  <li><strong>Cryostat</strong> <code class="language-plaintext highlighter-rouge">Discovery</code> only <em>Custom Targets</em> should be deletable</li>
  <li><strong>Cryostat</strong> <code class="language-plaintext highlighter-rouge">Discovery</code> handles <em>Kubernetes Services (Endpoints)</em> which have <code class="language-plaintext highlighter-rouge">nil</code> <em>targets</em></li>
  <li><strong>Cryostat Agent</strong> <code class="language-plaintext highlighter-rouge">logging</code> goes to <code class="language-plaintext highlighter-rouge">stdout</code> by default, not <code class="language-plaintext highlighter-rouge">stderr</code>, can be configured using Agent properties overrides arguments, and passes down log level to the <em>Red Hat Insights client</em></li>
  <li><strong>Cryostat Agent</strong> <code class="language-plaintext highlighter-rouge">shutdown</code> avoids a potential NPE</li>
  <li><strong>Cryostat Agent</strong> <code class="language-plaintext highlighter-rouge">recording queries</code> include recordings started by the Agent’s own <em>Harvester</em> facility</li>
  <li><strong>Cryostat Agent</strong> <code class="language-plaintext highlighter-rouge">startup</code> performs callback DNS resolution within the discovery registration loop, not only once on startup</li>
  <li><strong>Cryostat Operator</strong> <code class="language-plaintext highlighter-rouge">autoconfig</code> allows control of the <em>Agent’s</em> log level, and disables <em>Agent</em> logging by default</li>
  <li><strong>Cryostat Operator</strong> <code class="language-plaintext highlighter-rouge">secrets/configmaps</code> are hashed and appended to <em>Deployment pod templates</em> so that configuration updates like renewed certificates cause a rollout</li>
  <li><strong>Cryostat Operator</strong> <code class="language-plaintext highlighter-rouge">reports</code> sidecars are correctly configured so that they handle automated analysis report generations</li>
  <li><strong>Cryostat OpenShift Console Plugin</strong> <code class="language-plaintext highlighter-rouge">proxy</code> handles connection failures to upstream Cryostat instances gracefully, avoiding proxy restart</li>
  <li><strong>Cryostat OpenShift Console Plugin</strong> <code class="language-plaintext highlighter-rouge">dashboard</code> correctly updates <em>MBean Metrics</em> charts</li>
  <li><strong>Cryostat Storage</strong> <code class="language-plaintext highlighter-rouge">volumes</code> configuration by the entrypoint script respects the underlying implementation’s enforced limits</li>
</ol>

<p>For further details on these items, <a href="https://github.com/cryostatio/cryostat/discussions/938">check the GitHub Discussions release announcement</a>.</p>

<h2 id="where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</h2>
<p>You can install Cryostat using our
<a href="https://operatorhub.io/operator/cryostat-operator">Kubernetes operator on OperatorHub.io</a>
or via a
<a href="https://github.com/cryostatio/cryostat-helm/releases/tag/v2.0.1">Helm Chart</a>
. As always, you can also run Cryostat in other environments with a little more manual setup.</p>

<p>If this is your first time installing Cryostat on Kubernetes, you can <a href="/get-started">Get Started</a> right here on this
website.</p>

<p>If you had previously installed Cryostat Operator 4.0.0 with OLM, then you may have already been upgraded to 4.0.1, or
else you should be able to approve and install the upgrade.</p>

<h2 id="feedback">Feedback</h2>
<p>Please reach out to the <a href="mailto:cryostat-development@googlegroups.com">Cryostat mailing list</a> or
<a href="https://github.com/cryostatio/cryostat/discussions/938">GitHub Discussion</a> with any questions or comments.</p>]]></content><author><name>Andrew Azores</name><email>aazores@ibm.com</email></author><summary type="html"><![CDATA[Table of Contents Table of Contents]]></summary></entry><entry><title type="html">Cryostat 4.0.0 is Released!</title><link href="https://cryostat.io/2025/03/20/cryostat-400-release.html" rel="alternate" type="text/html" title="Cryostat 4.0.0 is Released!" /><published>2025-03-20T00:00:00+00:00</published><updated>2025-03-20T00:00:00+00:00</updated><id>https://cryostat.io/2025/03/20/cryostat-400-release</id><content type="html" xml:base="https://cryostat.io/2025/03/20/cryostat-400-release.html"><![CDATA[<h4 id="table-of-contents">Table of Contents</h4>
<ul id="markdown-toc">
  <li><a href="#table-of-contents" id="markdown-toc-table-of-contents">Table of Contents</a></li>
  <li><a href="#release-highlights" id="markdown-toc-release-highlights">Release Highlights</a>    <ul>
      <li><a href="#new-features" id="markdown-toc-new-features">New Features</a>        <ul>
          <li><a href="#openshift-specific-features" id="markdown-toc-openshift-specific-features">OpenShift-specific Features</a></li>
        </ul>
      </li>
      <li><a href="#architectural-updates" id="markdown-toc-architectural-updates">Architectural Updates</a></li>
      <li><a href="#helm-chart" id="markdown-toc-helm-chart">Helm Chart</a></li>
      <li><a href="#agent" id="markdown-toc-agent">Agent</a></li>
      <li><a href="#general-maintenance" id="markdown-toc-general-maintenance">General Maintenance</a></li>
      <li><a href="#bug-fixes" id="markdown-toc-bug-fixes">Bug Fixes</a></li>
    </ul>
  </li>
  <li><a href="#media" id="markdown-toc-media">Media</a></li>
  <li><a href="#where-can-i-get-the-latest-version-of-cryostat" id="markdown-toc-where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</a></li>
  <li><a href="#feedback" id="markdown-toc-feedback">Feedback</a></li>
</ul>
<hr />

<p>Hello everyone,</p>

<p>It’s time for another Cryostat release. This time, we are very proud to present Cryostat 4.0, a new major version with again some significant under-the-hood changes,
and some exciting new OpenShift-specific features.</p>

<h2 id="release-highlights">Release Highlights</h2>

<h3 id="new-features">New Features</h3>
<ol>
  <li><strong>Quarkus and Hibernate JFR integrations</strong> for framework-specific <em>Flight Recorder</em> events. If your target application uses Quarkus and contains the <code class="language-plaintext highlighter-rouge">quarkus-jfr</code> extension (along with <code class="language-plaintext highlighter-rouge">quarkus-rest</code>), or has <code class="language-plaintext highlighter-rouge">hibernate-jfr</code> on its classpath, then you can take advantage of the new <em>Preset Event Templates</em> that ship with Cryostat. These are open to community contributions for any other popular frameworks and libraries that provide JFR events. Simply start a recording using the relevant preset template and begin capturing these framework-specific events.</li>
  <li><strong>Automated Rules by JFR Event Type ID</strong>: there is a new <code class="language-plaintext highlighter-rouge">jfrEventTypeIds(target): string[]</code> function available in the <code class="language-plaintext highlighter-rouge">matchExpression</code> Common Expression Language scope. Pass in the <code class="language-plaintext highlighter-rouge">target</code> object also in scope and this function returns a list of JFR event type IDs for that target JVM. This enables functionality such as that seen in the new <code class="language-plaintext highlighter-rouge">quarkus</code> and <code class="language-plaintext highlighter-rouge">hibernate</code> Automated Rules that ship with Cryostat 4.0, where the rules’ expressions are satisfied by target JVMs that support the relevant JFR event types. This makes it even quicker and easier to get started capturing data from applications using these frameworks and libraries.</li>
  <li><strong>Diagnostics Card</strong>: the Cryostat dashboard has a new <em>Diagnostics</em> card, which currently exposes one new piece of functionality: you can fire a request for the remote target JVM to run a Garbage Collection cycle. This can be useful when troubleshooting a misbehaving application, or when attempting to optimize the resource allocation for a container.</li>
  <li><strong>Events View</strong> in the Cryostat Web UI is visible even when no target application is selected. Previously this view would lock out until a target JVM was selected. Now, the <em>Event Types</em> and <em>JMC Agent Live Configuration</em> tabs will be disabled, but the <em>Event Templates</em> and <em>JMC Agent Probe Templates</em> remain usable so that you can see which templates are available, or upload new ones, even when you have no target applications discoverable.</li>
</ol>

<h4 id="openshift-specific-features">OpenShift-specific Features</h4>
<ol>
  <li><strong>Agent Autoconfiguration</strong> by the Operator dramatically simplifies the setup and usage of the <em>Cryostat Agent</em> with your JVM target applications. Simply install the Operator, create a Cryostat CR, and ensure your target application is located in one of the Cryostat CR’s <em>Target Namespaces</em>. Then, edit your application’s Deployment <code class="language-plaintext highlighter-rouge">.spec.template.metadata.labels</code> and add <code class="language-plaintext highlighter-rouge">cryostat.io/namespace: ${cryostat-cr-ns}</code> and <code class="language-plaintext highlighter-rouge">cryostat.io/name: ${cryostat-cr-name}</code> labels (replacing the <code class="language-plaintext highlighter-rouge">${var}</code> expressions with corresponding values). This prompts the Cryostat Operator to patch your Deployment to include Volumes containing the Cryostat Agent JAR and required TLS certificates, to include a <code class="language-plaintext highlighter-rouge">JAVA_TOOL_OPTIONS</code> environment variable containing the <code class="language-plaintext highlighter-rouge">-javaagent</code> flag to statically attach the Agent to your application, and to include other environment variables to configure the Agent to communicate with the specified Cryostat instance.</li>
  <li><strong>OpenShift Console Plugin</strong> to allow your cluster administrators to access Cryostat features directly from the OpenShift Console, without needing to visit each Cryostat instance’s Application (Route) URL and with no secondary authentication step.</li>
  <li><strong>Agent Gateway</strong> container is included in the main Cryostat Deployment for each Cryostat CR. This is a TLS authentication proxy that Agent instances can use with appropriate TLS client certificates to authenticate to their Cryostat instance, rather than needing to use serviceaccount Bearer tokens. This is also used by the <em>autoconfiguration</em> feature.</li>
</ol>

<h3 id="architectural-updates">Architectural Updates</h3>
<ol>
  <li><strong>Split Deployments</strong> when deployed via Operator or Helm Chart. The <em>database</em> and <em>storage</em> containers are now split out to their own separate Deployments so that their Pods have separate lifecycles from the main Cryostat Pod. Cryostat now also uses Flyway to handle database migrations between version upgrades. This lays out some groundwork that didn’t get finished in time for 3.0, so that (hopefully) the next several Cryostat releases can be minor versions with seamless upgrade paths. The database and storage <em>PersistentVolumeClaims</em> are also separated so that storage can be allocated appropriately. Additionally, when using the Operator, communications between these split Pods will always use TLS by default, use generated credentials for authentication, and use <em>NetworkPolicies</em> to control ingress so that traffic is only accepted from expected origins. The storage container also enables at-rest data encryption by default.</li>
  <li><strong>Removal of deprecated API</strong> version prefixes. The old <code class="language-plaintext highlighter-rouge">/api/v1</code> through <code class="language-plaintext highlighter-rouge">/api/v3</code> path prefixes are no longer used, and all API endpoints are now prefixed with <code class="language-plaintext highlighter-rouge">/api/v4</code>. Many of these are fully backward compatible with how they behaved in 3.0.</li>
  <li><strong>Long-running API operations</strong> are now handled more asynchronously. These are operations such as archiving recordings, uploading recordings to <code class="language-plaintext highlighter-rouge">jfr-datasource</code> for analysis in Grafana, or performing automated analysis on recordings. When a client request for one of these operations comes in, Cryostat will immediately send back a response containing a Job ID. At some later point in time, a WebSocket notification will be sent containing the same Job ID and indicating the success/failure of that job and any particular details about it. For automated analysis report generation in particular, the first time a request is sent the response will contain a Job ID, but when the job completes then Cryostat will hold the result in a cache for some time. The client should send a follow-up request after the WebSocket notification is received, and this time Cryostat will respond with the actual report JSON document. This differs from 3.0 and prior Cryostat versions, where the client would send a request and Cryostat would send no response at all until the entire operation completed - which could result in the client timing out and abandoning the request.</li>
</ol>

<h3 id="helm-chart">Helm Chart</h3>
<ol>
  <li><strong>Reports Generator sidecars</strong> are now also available in the Helm Chart using <code class="language-plaintext highlighter-rouge">reports.replicas</code>. Simply <code class="language-plaintext highlighter-rouge">--set reports.replicas=1</code> (or any positive integer you choose) when installing or upgrading the Helm Chart.</li>
  <li><strong>User-provided Secrets</strong> can be specified when installing or upgrading the Helm Chart using <code class="language-plaintext highlighter-rouge">storage.storageSecretName</code> and <code class="language-plaintext highlighter-rouge">authentication.cookieSecretName</code>. When these are specified the Helm Chart does not need to do a dynamic lookup of any self-generated Secrets already in the cluster, so the installation is more declarative and can be more easily managed with GitOps-style workflows. Be sure to create the Secrets first before referencing them in the Helm Chart installation.</li>
</ol>

<h3 id="agent">Agent</h3>
<ol>
  <li><a href="https://quay.io/repository/cryostat/cryostat-agent-init"><strong><code class="language-plaintext highlighter-rouge">cryostat-agent-init</code></strong> container image</a> is now available. This is a small container image simply containing the Cryostat Agent <code class="language-plaintext highlighter-rouge">-shaded</code> JAR. This can be used in multistage OCI container image builds as a potentially simpler way to insert the JAR, rather than using a Maven dependency. This is also what the Operator uses for <em>autoconfiguration</em> to mount a Volume containing the JAR.</li>
  <li><strong>Server version check</strong> on startup. The Agent queries the Cryostat server it is connecting to and checks that its version falls within the expected range for compatibility. The Agent will log a warning if it is configured to talk to a Cryostat server outside of its compatible version range.</li>
  <li><strong>Build info as system properties</strong>: Agent build information such as the git commit hash, Agent version string, and compatible Cryostat server minimum/maximum versions are embedded as resources in the Agent JAR. The Agent sets JVM system properties with these values at startup. These can be viewed in the Cryostat Web Topology view for enhanced details about the particular Agent instances registered with your Cryostat server.</li>
</ol>

<h3 id="general-maintenance">General Maintenance</h3>
<ol>
  <li><strong>Base Image</strong> version updates to <code class="language-plaintext highlighter-rouge">ubi9</code> and <code class="language-plaintext highlighter-rouge">JDK 21</code>. Cryostat 3.0 containers used <code class="language-plaintext highlighter-rouge">ubi8</code> and <code class="language-plaintext highlighter-rouge">JDK 17</code>.</li>
  <li><strong>Quarkus 3.15</strong> update for Cryostat, Cryostat Reports, and JFR Datasource.</li>
  <li><strong>Patternfly 5</strong> update for Cryostat Web.</li>
  <li><strong>Grafana Dashboard</strong> no longer uses the deprecated <code class="language-plaintext highlighter-rouge">simple-json-datasource</code>.</li>
</ol>

<h3 id="bug-fixes">Bug Fixes</h3>
<ol>
  <li><strong>HTTP Connection Flakiness</strong> between components - in particular Cryostat to Cryostat Reports, or Cryostat to Cryostat Storage - has been resolved.</li>
  <li><strong>Automated Rules</strong> can sometimes fail to activate for various reasons. Cryostat will now attempt to re-test any failed rules with an exponential backoff strategy to ensure that rules are activated on targets as expected.</li>
  <li><strong>WildFly / Agent</strong>: when attaching the Agent to WildFly/JBoss EAP applications previously, the Agent’s configuration defaults would not be loaded and all parameters would need to be set explicitly. Now, the default parameters are loaded as usual and only the typical parameters need to be specifically configured.</li>
</ol>

<h2 id="media">Media</h2>

<p>To accompany this release I have recorded several demo/tutorial videos. These illustrate some of the new features as well
as highlighting existing Cryostat functionality that seemed to connect naturally:</p>
<ul>
  <li><a href="https://www.youtube.com/watch?v=uXQt4wCUYsM">Cryostat 4.0 Agent Automatic Configuration and OpenShift Console Plugin</a></li>
  <li><a href="https://www.youtube.com/watch?v=wuqxM1h5g_w">Cryostat 4.0 Non-Java JVM Applications</a></li>
  <li><a href="https://www.youtube.com/watch?v=Dr3XW25XJUE">Cryostat 4.0 Quarkus and Hibernate Integrations</a></li>
  <li><a href="https://www.youtube.com/watch?v=lG_LHOPu1Mk">Cryostat 4.0 Quarkus Native Image Applications</a></li>
  <li><a href="https://www.youtube.com/watch?v=d8CEy_Q03Ts">Cryostat 4.0 Agent Harvester</a></li>
  <li><a href="https://www.youtube.com/watch?v=dIlV-Zszcp0">Cryostat 4.0 Advanced Agent Autoconfiguration</a></li>
  <li><a href="https://www.youtube.com/watch?v=aPGoaV4O5L8">Cryostat 4.0 Agent Autoconfiguration Extensions</a></li>
</ul>

<h2 id="where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</h2>
<p>You can install Cryostat using our
<a href="https://operatorhub.io/operator/cryostat-operator">Kubernetes operator on OperatorHub.io</a>
or via a
<a href="https://github.com/cryostatio/cryostat-helm">Helm Chart</a>
. As always, you can also run Cryostat in other environments with a little more manual setup.</p>

<p><strong>Note</strong>: the Helm Chart 4.0.0 release will be a bit delayed this time around. Please watch the GitHub repository for updates
if you require the Helm Chart.</p>

<p>If this is your first time installing Cryostat on Kubernetes, you can <a href="/get-started">Get Started</a> right here on this
website.</p>

<p>If you had previously installed Cryostat Operator 3.0.0 with OLM you will need to perform a manual upgrade to 4.0.0.
You should back up all data (Automated Rules, Custom Event Templates, Stored Credentials, Archived Recordings), perform
the upgrade, then restore all of your data. We plan that the next release will allow a seamless in-place upgrade once again.</p>

<h2 id="feedback">Feedback</h2>
<p>Please reach out to the <a href="mailto:cryostat-development@googlegroups.com">Cryostat mailing list</a> or
<a href="https://github.com/cryostatio/cryostat/discussions">GitHub Discussions</a> with any questions or comments.</p>]]></content><author><name>Andrew Azores</name><email>aazores@ibm.com</email></author><summary type="html"><![CDATA[Table of Contents Table of Contents]]></summary></entry><entry><title type="html">Cryostat 3.0.1 is Released!</title><link href="https://cryostat.io/2024/09/24/cryostat-301-release.html" rel="alternate" type="text/html" title="Cryostat 3.0.1 is Released!" /><published>2024-09-24T00:00:00+00:00</published><updated>2024-09-24T00:00:00+00:00</updated><id>https://cryostat.io/2024/09/24/cryostat-301-release</id><content type="html" xml:base="https://cryostat.io/2024/09/24/cryostat-301-release.html"><![CDATA[<h4 id="table-of-contents">Table of Contents</h4>
<ul id="markdown-toc">
  <li><a href="#table-of-contents" id="markdown-toc-table-of-contents">Table of Contents</a></li>
  <li><a href="#whats-fixed-in-301" id="markdown-toc-whats-fixed-in-301">What’s Fixed in 3.0.1?</a></li>
  <li><a href="#where-can-i-get-the-latest-version-of-cryostat" id="markdown-toc-where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</a></li>
  <li><a href="#feedback" id="markdown-toc-feedback">Feedback</a></li>
</ul>
<hr />

<p>Hello everyone,</p>

<p>We are pleased to announce the release of Cryostat 3.0.1! This is a minor bugfix release addressing some issues
uncovered with the previous 3.0.0 feature release.</p>

<h2 id="whats-fixed-in-301"><a href="#whats-new-in-301">What’s Fixed in 3.0.1?</a></h2>
<ol>
  <li>Routine maintenance: dependency version updates and container base image version updates</li>
  <li><a href="https://github.com/cryostatio/cryostat-operator/pull/927">Failure to create or update a Cryostat custom resource due to webhook TLS errors</a></li>
  <li><a href="https://github.com/cryostatio/cryostat-core/pull/454">Inability to upload JMC ByteCode Agent instrumentation templates</a></li>
  <li><a href="https://github.com/cryostatio/cryostat-web/pull/1327">Archived Recording uploads with Labels File fails to parse</a></li>
  <li><a href="https://github.com/cryostatio/cryostat-web/pull/1314">Topology View fails to filter JVM Targets by Label/Annotation</a></li>
  <li><a href="https://github.com/cryostatio/cryostat/pull/599">MatchExpressions cannot use the target.agent property</a></li>
</ol>

<h2 id="where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</h2>
<p>You can install Cryostat using our
<a href="https://operatorhub.io/operator/cryostat-operator">Kubernetes operator on OperatorHub.io</a>
or via a
<a href="https://github.com/cryostatio/cryostat-helm/releases/tag/v1.0.1">Helm Chart</a>
. As always, you can also run Cryostat in other environments with a little more manual setup.</p>

<p>If this is your first time installing Cryostat on Kubernetes, you can <a href="/get-started">Get Started</a> right here on this
website.</p>

<p>If you had previously installed Cryostat Operator 3.0.0 with OLM, then you may have already been upgraded to 3.0.1, or
else you should be able to approve and install the upgrade.</p>

<h2 id="feedback">Feedback</h2>
<p>Please reach out to the <a href="mailto:cryostat-development@googlegroups.com">Cryostat mailing list</a> or
<a href="https://github.com/cryostatio/cryostat/discussions/665">GitHub Discussion</a> with any questions or comments.</p>]]></content><author><name>Andrew Azores</name><email>aazores@ibm.com</email></author><summary type="html"><![CDATA[Table of Contents Table of Contents]]></summary></entry><entry><title type="html">Cryostat 3.0.0 is Released!</title><link href="https://cryostat.io/2024/07/04/cryostat-release.html" rel="alternate" type="text/html" title="Cryostat 3.0.0 is Released!" /><published>2024-07-04T00:00:00+00:00</published><updated>2024-07-04T00:00:00+00:00</updated><id>https://cryostat.io/2024/07/04/cryostat-release</id><content type="html" xml:base="https://cryostat.io/2024/07/04/cryostat-release.html"><![CDATA[<h4 id="table-of-contents">Table of Contents</h4>
<ul id="markdown-toc">
  <li><a href="#table-of-contents" id="markdown-toc-table-of-contents">Table of Contents</a></li>
  <li><a href="#feature-highlights" id="markdown-toc-feature-highlights">Feature Highlights</a>    <ul>
      <li><a href="#operator" id="markdown-toc-operator">Operator</a></li>
      <li><a href="#helm-chart" id="markdown-toc-helm-chart">Helm Chart</a></li>
      <li><a href="#agent" id="markdown-toc-agent">Agent</a></li>
    </ul>
  </li>
  <li><a href="#non-changes" id="markdown-toc-non-changes">Non-Changes</a></li>
</ul>
<hr />

<p>Hello everyone,</p>

<p>It’s time for another Cryostat release. This time, we are pleased to present Cryostat 3.0, a new major version with some significant under-the-hood changes.</p>

<h3 id="feature-highlights">Feature Highlights</h3>

<ol>
  <li><strong>Quarkus</strong> re-implementation of the main container: the main Cryostat container was previously built directly using <a href="https://github.com/vert-x3/vertx-web">Eclipse Vert.x</a>, but now in 3.0 it has been reimplemented using <a href="https://quarkus.io">Quarkus</a>. With this change comes several other changes outlined in the next several points, to take advantage of the Quarkus framework’s strengths and features so that Cryostat can provide higher performance access to your JDK Flight Recorder data, as well as better integrity and security of your data.</li>
  <li><strong>More powerful configuration</strong>: the main Cryostat container can be configured in the usual SmallRye Config style like any other Quarkus application, which means configuration properties can now be supplied by system property as well as by environment variable. More configuration properties are available to help advanced users tailor Cryostat to their particular deployment requirements. If you are using the <a href="https://github.com/cryostatio/cryostat-operator">Cryostat Operator</a> or <a href="https://github.com/cryostatio/cryostat-helm">Helm Chart</a> for deployment and configuration then the configuration changes at those levels are relatively simple, but if you roll your own deployment then you will have to make more significant changes to your deployment configurations.</li>
  <li><strong>Postgres database</strong> by default: Cryostat has used a simple <a href="https://github.com/h2database/h2database">H2</a> file-based database for the past few releases for storing certain kinds of information, in particular the encrypted target JMX credentials keyring. Other kinds of information were stored directly as files on disk, such as Automated Rules definitions. Cryostat 3.0 now deploys with a <a href="https://github.com/cryostatio/cryostat-db"><code class="language-plaintext highlighter-rouge">cryostat-db</code></a> (lightly customized <a href="https://github.com/postgres/postgres">Postgres</a>) database instead of H2 file-based database, and more information is kept in the database: the encrypted target credentials keyring, Automated Rules definitions, discovered targets, and discovery plugins are all persisted in this database. In this release the database schema is still in an early state and it is not yet recommended to attempt to run Cryostat with a separately managed database deployment.</li>
  <li><strong>S3-compatible object storage</strong>: previous versions of Cryostat used direct storage of files on disk for archived Flight Recordings and custom Event Templates. Cryostat 3.0 no longer uses direct filesystem accesses for these kinds of binary large objects, but instead integrates with an S3-compatible storage provider. If you use the Cryostat Operator or Cryostat Helm Chart for installation, your deployment will include a <a href="https://github.com/cryostatio/cryostat-storage"><code class="language-plaintext highlighter-rouge">cryostat-storage</code></a> container (a lightly customized <a href="https://github.com/seaweedfs/seaweedfs">SeaweedFS</a>) for a “batteries included” storage solution. If you roll your own deployment then you can swap this out for any S3-compatible storage provider you prefer or may already use.</li>
  <li><strong>Reverse proxy architecture</strong>: Cryostat 3.0 deployed by the Cryostat Operator or Helm Chart includes a reverse proxy (<a href="https://github.com/openshift/oauth-proxy/"><code class="language-plaintext highlighter-rouge">openshift-oauth-proxy</code></a> or <a href="https://github.com/oauth2-proxy/oauth2-proxy"><code class="language-plaintext highlighter-rouge">oauth2_proxy</code></a>) in the Pod. Only this proxy is exposed to cluster traffic via a Service. This means that all API requests to Cryostat, as well as all visitors to the <a href="https://github.com/cryostatio/cryostat-web">Cryostat Web UI</a> or <a href="https://github.com/cryostatio/cryostat-grafana-dashboard">Grafana dashboard</a> flow through this proxy. The proxy handles user sessions to control access to the application, providing unified access control and user sessions for both the Cryostat Web UI and Grafana dashboard. Both of these UIs are accessible via the same Ingress or Route and present the same TLS certificate. When deployed on <a href="https://developers.redhat.com/products/openshift/overview">OpenShift</a>, the auth proxy will use its Namespace (the Cryostat installation Namespace) to perform Role-Based Access Control checks for user authentication and authorization by integrating with the OpenShift cluster SSO provider, very similar to what previous Cryostat releases directly implemented. Additionally, the auth proxy can be optionally configured with an <code class="language-plaintext highlighter-rouge">htpasswd</code> file to enable Basic authentication. On OpenShift this allows for defining additional user accounts that may access the Cryostat application beyond those with OpenShift SSO RBAC access, whereas on other Kubernetes it is the primary authentication mechanism.</li>
</ol>

<h4 id="operator">Operator</h4>

<p>Specifically for the Cryostat Operator there are a few items of note:</p>
<ol>
  <li><strong>Cluster-wide installation</strong> only: the Cryostat Operator can now only be installed cluster-wide, rather than into a subset of cluster namespaces. <a href="https://docs.openshift.com/container-platform/4.15/operators/olm_v1/arch/olmv1-operator-controller.html#olmv1-operator-api">Cluster-wide installation is the preferred mode</a> for the Operator Lifecycle Manager and per-namespace installations are a deprecated feature, which our Operator has now dropped.</li>
  <li><strong>ClusterCryostat removal</strong>: the <code class="language-plaintext highlighter-rouge">v1beta1/Cryostat</code> and <code class="language-plaintext highlighter-rouge">v1beta1/ClusterCryostat</code> custom resources are now unified in the <code class="language-plaintext highlighter-rouge">v1beta2/Cryostat</code> CR. When creating this CR you may specify an optional list of target namespaces. The installation namespace - the CR’s <code class="language-plaintext highlighter-rouge">.metadata.namespace</code> - is the location where the Operator will create the Cryostat Deployment, and on OpenShift this namespace will also be used by the auth proxy for RBAC to control which users have access to the Cryostat application. The default user Role required is <code class="language-plaintext highlighter-rouge">create pods/exec</code> in the Cryostat CR’s installation namespace, but this can be configured using the <code class="language-plaintext highlighter-rouge">.spec.authorizationOptions.openShiftSSO.accessReview</code> property. The list of target namespaces is used to control which namespaces the Cryostat instance should monitor for new target applications to appear within, the same as before. Taken together with point 1 above it is now simpler to install the Operator and configure your Cryostat instance(s): simply install the Operator cluster-wide, then create one or more Cryostat CRs to correspond to namespaces or groups of namespaces that contain your applications.</li>
  <li><strong>Cryostat CR validation</strong>: the Operator performs additional validations against Cryostat CR objects before accepting them for processing. One noteworthy new validation is that a user who creates a Cryostat CR with a list of target namespaces must have sufficient permissions to create single-namespaced Cryostat CRs in each of those target namespaces.</li>
  <li><strong>Custom host/domain support</strong>: there is a new <code class="language-plaintext highlighter-rouge">.spec.networkOptions.coreConfig.externalHost</code> CRD property available, which can be used to set a custom domain for the OpenShift <code class="language-plaintext highlighter-rouge">Route</code> which the Operator creates for your Cryostat deployment.</li>
</ol>

<h4 id="helm-chart">Helm Chart</h4>

<p>For the Cryostat Helm Chart, there are new configuration values that can be set:</p>
<ol>
  <li><strong>authentication.openshift.enabled</strong>: to enable deployment of <code class="language-plaintext highlighter-rouge">openshift-oauth-proxy</code>. If disabled (as default) then <code class="language-plaintext highlighter-rouge">oauth2_proxy</code> is deployed instead. Both proxies may be configured to enable Basic authentication (see next item), but for users deploying onto OpenShift, the <code class="language-plaintext highlighter-rouge">openshift-oauth-proxy</code> also implements integration with the OpenShift cluster SSO.</li>
  <li><strong>authentication.basicAuth</strong>: to configure Basic authentication on the auth proxy. When deploying <code class="language-plaintext highlighter-rouge">openshift-oauth-proxy</code> this is in addition to the OpenShift SSO, whereas when deploying <code class="language-plaintext highlighter-rouge">oauth2_proxy</code> this is the only out-of-the-box supported user authentication mechanism.</li>
  <li><strong>openshiftOauthProxy.accessReview</strong> (OpenShift only): the <code class="language-plaintext highlighter-rouge">SubjectAccessReview</code> for testing user/client access via OpenShift SSO can be configured with this property.</li>
  <li>Installation will now include the auth proxy, a <code class="language-plaintext highlighter-rouge">cryostat-db</code> instance, and a <code class="language-plaintext highlighter-rouge">cryostat-storage</code> instance as outlined at the top of this post. There will be only one Service, and one Ingress/Route, pointing to the auth proxy.</li>
</ol>

<p>This is not an exhaustive list of all the new configuration values, only a highlight of a few that control new visible features. Please check the chart’s updated <a href="https://github.com/cryostatio/cryostat-helm/blob/main/charts/cryostat/README.md"><code class="language-plaintext highlighter-rouge">README</code></a> for a full listing.</p>

<h4 id="agent">Agent</h4>

<p>In this release there is only one new feature implemented and one enhancement.</p>

<p>The minor enhancement first: when the <a href="https://github.com/cryostatio/cryostat-agent">Cryostat Agent</a> starts up it also starts a tiny embedded webserver, which it uses to service requests made by the Cryostat server. This embedded webserver secures itself using Basic authentication. Previously, the Basic username was always <code class="language-plaintext highlighter-rouge">user</code> and the password was randomly generated and 24 ASCII characters in length. In this release both of these are configurable: the username can be overridden (but defaults to <code class="language-plaintext highlighter-rouge">user</code>), and the generated password length can be changed (but defaults to 24 characters). The generated password also draws from a larger character set.</p>

<p>The new feature is <strong>Dynamic Attach</strong>. In short, this means that the Cryostat Agent can be attached to an already-running application JVM, as opposed to requiring attachment at JVM startup time via the <code class="language-plaintext highlighter-rouge">-javaagent</code> flag. This requires that the Agent JAR is available on the same host or in the same container filesystem as the application JVM, and that the user has some way to <code class="language-plaintext highlighter-rouge">exec</code> the Agent JAR as a separate <code class="language-plaintext highlighter-rouge">java</code> process to bootstrap the attachment. For example, if the application is deployed in Kubernetes, then the user can set this up by downloading the Cryostat Agent JAR locally, copying it into the application container using <code class="language-plaintext highlighter-rouge">kubectl cp</code>, and then run the Agent JAR using <code class="language-plaintext highlighter-rouge">kubectl exec</code>.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>kubectl <span class="nb">cp</span> <span class="se">\</span>
    /path/to/cryostat-agent.jar <span class="se">\</span>
    <span class="nt">-n</span> my-namespace <span class="se">\</span>
    mypod:/tmp/cryostat/cryostat-agent.jar
<span class="nv">$ </span>kubectl <span class="nb">exec</span> <span class="se">\</span>
    <span class="nt">-n</span> my-namespace <span class="se">\</span>
    mypod <span class="nt">-c</span> mycontainer <span class="se">\</span>
    <span class="nt">-i</span> <span class="nt">-t</span> <span class="nt">--</span> <span class="se">\</span>
      java <span class="nt">-jar</span> /tmp/cryostat/cryostat-agent.jar <span class="se">\</span>
      <span class="nt">-Dcryostat</span>.agent.baseuri<span class="o">=</span>http://cryostat:8181 <span class="se">\</span>
      <span class="nt">-Dcryostat</span>.agent.authorization<span class="o">=</span><span class="s2">"Bearer </span><span class="k">${</span><span class="nv">MY_AUTH_TOKEN</span><span class="k">}</span><span class="s2">"</span> <span class="se">\</span>
      <span class="nt">-Dcryostat</span>.agent.callback<span class="o">=</span>http://<span class="k">${</span><span class="nv">POD_IP</span><span class="k">}</span>:9977 <span class="se">\</span>
      <span class="nt">-Dcryostat</span>.agent.api.writes-enabled<span class="o">=</span><span class="nb">true</span>
</code></pre></div></div>

<p>Please note that the <code class="language-plaintext highlighter-rouge">-D</code> system properties for the Agent are placed <em>after</em> the <code class="language-plaintext highlighter-rouge">-jar /path/to/cryostat-agent.jar</code>. This ensures that they are arguments picked up by the Agent process after it starts, which it receives and uses to set the system properties again when it attaches to the application JVM process that it finds. Any other system properties, including ones passed <em>before</em> the <code class="language-plaintext highlighter-rouge">-jar</code> flag, will take effect on the separate Agent process but will <em>not</em> be carried over to the application JVM when the Agent attaches.</p>

<h3 id="non-changes">Non-Changes</h3>

<p>What <em>hasn’t</em> changed?</p>

<p>If you are a cluster administrator installing Cryostat you will notice some changes in the Cryostat Operator and Cryostat CR, or in the Cryostat Helm Chart configuration values. If you manually deploy Cryostat then there are a large number of setup and configuration changes required, with different and new environment variables and new additional containers to deploy (the auth proxy, database, and object storage mentioned above).</p>

<p>From an end user’s perspective most things remain the exact same. Despite the major version number increment and breaking configuration changes, this release did not target adding any significant new user features or modifying existing ones. Only a few noteworthy items stand out:</p>

<ol>
  <li><strong>Target TLS certificate upload</strong> has been removed: the <code class="language-plaintext highlighter-rouge">Security</code> navigation item in the Cryostat Web UI no longer offers a way to upload TLS certificates directly into the Cryostat server truststore. Instead, this view only provides a list of the certificates that have been loaded. Adding new certificates to the truststore must be done by adding them to the storage volume which Cryostat reads at startup. Using the Operator this can still be done with the existing <code class="language-plaintext highlighter-rouge">TrustedCertSecrets</code> CR property.</li>
  <li><strong>JMX target credentials passthrough</strong> has been removed: the old <code class="language-plaintext highlighter-rouge">X-JMX-Authorization</code> header is no longer supported. Previous versions of Cryostat accepted this header on API requests and would use the header value as basic auth credentials when opening a JMX connection to a target application. This was replaced by the encrypted database table backing the encrypted credentials keyring mechanism a few versions back, which was made the default. In 3.0 only this encrypted credentials keyring is supported, the <code class="language-plaintext highlighter-rouge">X-JMX-Authorization</code> header is no longer handled, and the Cryostat Web UI Settings view no longer offers an advanced configuration for selecting which mechanism to use.
Generally, the rest of the UI and features should look, feel, and behave the same way as they did in 2.4.</li>
  <li><strong>Cryostat self-discovery</strong>: when deployed by the Operator or Helm Chart, Cryostat will no longer discover itself as a target application by default. Previous versions would expose a JMX port on a Kubernetes Service. The Operator would generate credentials and assign a TLS certificate to help secure this port, but it was still a mandatory exposed JMX port that may not have been desirable. This port has been disabled and the corresponding Service port removed, so Cryostat will no longer discover itself as a connectable target - it won’t appear in the target selection list or the Topology view in its own web UI. If you do want to connect Cryostat to itself to inspect its own performance, simply create a Custom Target with the URL value <code class="language-plaintext highlighter-rouge">localhost:0</code>. This special value asks the JVM to open a local JMX connection to itself, without exposing a port to the network, so additional authentication and TLS encryption is not necessary.</li>
  <li><strong>API v1/v2 deprecation</strong>: Cryostat 3.0 remains backward compatible with previous <code class="language-plaintext highlighter-rouge">/api/v1</code>, <code class="language-plaintext highlighter-rouge">/api/v2</code>, <code class="language-plaintext highlighter-rouge">/api/v2.1</code>, <code class="language-plaintext highlighter-rouge">/api/v2.2</code>, and <code class="language-plaintext highlighter-rouge">/api/v2.3</code> API endpoints - many of these will now return <code class="language-plaintext highlighter-rouge">HTTP 3xx</code> redirection responses to the new <code class="language-plaintext highlighter-rouge">/api/v3</code> equivalents, but some will continue to serve requests directly (where the response format differs). There were no new Cryostat 2.4 API additions and so there is no corresponding <code class="language-plaintext highlighter-rouge">/api/v2.4</code> prefix. <code class="language-plaintext highlighter-rouge">/api/beta</code> endpoints have seen some breaking changes. In all cases, <code class="language-plaintext highlighter-rouge">/api/beta</code> endpoints should be considered subject to change or removal in any future release, and all of the <code class="language-plaintext highlighter-rouge">v1|v2|v2.1|v2.2|v2.3</code> endpoints should now be considered deprecated. These will be removed in a future <code class="language-plaintext highlighter-rouge">3.x</code> release in favour of the <code class="language-plaintext highlighter-rouge">/api/v3</code> equivalents that already exist, or in favour of new endpoints with this prefix which will retain the same general semantics as the older versions they replace. If you have built any additional scripts or tooling around the Cryostat API, please consider upgrading these now to be compatible with the new <code class="language-plaintext highlighter-rouge">v3</code> API endpoints.</li>
</ol>]]></content><author><name>Andrew Azores</name><email>aazores@ibm.com</email></author><summary type="html"><![CDATA[Table of Contents Table of Contents]]></summary></entry><entry><title type="html">Cryostat 2.4.0 is Released!</title><link href="https://cryostat.io/2023/12/14/cryostat-240-release.html" rel="alternate" type="text/html" title="Cryostat 2.4.0 is Released!" /><published>2023-12-14T00:00:00+00:00</published><updated>2023-12-14T00:00:00+00:00</updated><id>https://cryostat.io/2023/12/14/cryostat-240-release</id><content type="html" xml:base="https://cryostat.io/2023/12/14/cryostat-240-release.html"><![CDATA[<h4 id="table-of-contents">Table of Contents</h4>
<ul id="markdown-toc">
  <li><a href="#table-of-contents" id="markdown-toc-table-of-contents">Table of Contents</a></li>
  <li><a href="#where-can-i-get-the-latest-version-of-cryostat" id="markdown-toc-where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</a></li>
  <li><a href="#feedback" id="markdown-toc-feedback">Feedback</a></li>
</ul>
<hr />

<p>Hello everyone,</p>

<p>We are pleased to announce the release of Cryostat 2.4.0! This is a feature release with the following key highlights compared to 2.3.1:</p>

<ol>
  <li><strong>ARM64 support</strong>: support added for using Cryostat on ARM64 (aarch64) architecture</li>
  <li><strong>Cryostat Agent</strong> enhancements:
    <ul>
      <li><strong>HTTP API</strong> support for JFR <strong>write</strong> operations: enables the Cryostat agent to accept on-demand requests to start, stop, and delete JFR recordings for any target JVMs that have an agent HTTP connection</li>
      <li><strong>Smart triggers</strong> :custom trigger conditions based on MBean counters (memory, thread, operating system metrics) can be configured to dynamically start JFR recordings</li>
    </ul>
  </li>
</ol>

<p>This was a relatively smaller feature release compared to some previous ones. That’s because more of our development effort has already
shifted to the next major release: <a href="https://github.com/cryostatio/cryostat3">Cryostat 3.0</a>. Stay tuned for more in-depth details about
what 3.0 will entail. For now, here are two things you can expect from 3.0:</p>

<ol>
  <li><strong>Smart Trigger</strong> enhancements: API and “ergonomics”</li>
  <li><strong>S3 compatible</strong> object storage for Cryostat archives</li>
</ol>

<h2 id="where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</h2>
<p>You can install Cryostat using our
<a href="https://operatorhub.io/operator/cryostat-operator">Kubernetes operator on OperatorHub.io</a>
or via a
<a href="https://github.com/cryostatio/cryostat-helm/releases/tag/v0.4.0">Helm Chart</a>
. As always, you can also run Cryostat in other environments with a little more manual setup.</p>

<p>If this is your first time installing Cryostat on Kubernetes, you can <a href="/get-started">Get Started</a> right here on this
website.</p>

<p>If you had previously installed Cryostat Operator 2.3.1 with OLM, then you may have already been upgraded to 2.4.0, or
else you should be able to approve and install the upgrade.</p>

<h2 id="feedback">Feedback</h2>
<p>Please reach out to the <a href="mailto:cryostat-development@googlegroups.com">Cryostat mailing list</a> or
<a href="https://github.com/cryostatio/cryostat/discussions/1817">GitHub Discussion</a> with any questions or comments.</p>]]></content><author><name>Andrew Azores</name><email>aazores@ibm.com</email></author><summary type="html"><![CDATA[Table of Contents Table of Contents]]></summary></entry><entry><title type="html">Cryostat 2.3.1 is Released!</title><link href="https://cryostat.io/2023/09/18/cryostat-231-release.html" rel="alternate" type="text/html" title="Cryostat 2.3.1 is Released!" /><published>2023-09-18T00:00:00+00:00</published><updated>2023-09-18T00:00:00+00:00</updated><id>https://cryostat.io/2023/09/18/cryostat-231-release</id><content type="html" xml:base="https://cryostat.io/2023/09/18/cryostat-231-release.html"><![CDATA[<h4 id="table-of-contents">Table of Contents</h4>
<ul id="markdown-toc">
  <li><a href="#table-of-contents" id="markdown-toc-table-of-contents">Table of Contents</a></li>
  <li><a href="#whats-fixed-in-231" id="markdown-toc-whats-fixed-in-231">What’s Fixed in 2.3.1?</a></li>
  <li><a href="#where-can-i-get-the-latest-version-of-cryostat" id="markdown-toc-where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</a></li>
  <li><a href="#feedback" id="markdown-toc-feedback">Feedback</a></li>
</ul>
<hr />

<p>Hello everyone,</p>

<p>We are pleased to announce the release of Cryostat 2.3.1! This is a minor bugfix release addressing some issues
uncovered with the previous 2.3.0 feature release.</p>

<h2 id="whats-fixed-in-231"><a href="#whats-new-in-231">What’s Fixed in 2.3.1?</a></h2>
<ol>
  <li>routine maintenance: dependency version updates and container base image version updates</li>
  <li>“Log Out” from the Cryostat Web UI was previously broken on OCP 4.12+:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat/issues/1489">cryostat#1489</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-web/pull/1059">cryostat-web#1059</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-operator/pull/599">cryostat-operator#599</a></li>
    </ul>
  </li>
  <li>Deleting an OpenShift Namespace containing a Cryostat installation could hang:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat-operator/issues/584">cryostat-operator#584</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-operator/issues/593">cryostat-operator#593</a></li>
    </ul>
  </li>
  <li>Cryostat Web dashboard configuration could become broken and fail to reload cards:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat-web/pull/1024">cryostat-web#1024</a></li>
    </ul>
  </li>
  <li>Cryostat could fail to discover target applications if the application takes some time to become ready and JMX-connectable:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat/issues/1577">cryostat#1577</a></li>
      <li><a href="https://github.com/cryostatio/cryostat/pull/1593">cryostat#1593</a></li>
    </ul>
  </li>
  <li>Cryostat could fail to start Flight Recordings on some target application JVMs:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat/issues/1516">cryostat#1516</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-core/pull/228">cryostat-core#228</a></li>
      <li><a href="https://github.com/cryostatio/cryostat/pull/1525">cryostat#1525</a></li>
    </ul>
  </li>
  <li>Cryostat would fail to connect to GraalVM native images:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat-core/pull/217">cryostat-core#217</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-core/pull/222">cryostat-core#222</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-core/pull/228">cryostat-core#228</a></li>
      <li><a href="https://github.com/cryostatio/cryostat/pull/1525">cryostat#1525</a></li>
    </ul>
  </li>
  <li>Cryostat Agent would create Stored Credentials with a Match Expression that could result in the credentials being erroneously used for JMX connections to the attached host JVM:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat-agent/issues/133">cryostat-agent#133</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-agent/issues/134">cryostat-agent#134</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-agent/issues/154">cryostat-agent#154</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-agent/issues/156">cryostat-agent#156</a></li>
    </ul>
  </li>
  <li>Cryostat Agent would publish itself as a Discovery Node with the wrong JMX port number in its annotations:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat-agent/issues/153">cryostat-agent#153</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-agent/issues/157">cryostat-agent#157</a></li>
    </ul>
  </li>
  <li>Cryostat would incorrectly fail validation of certain JMC Agent probe templates, and after validation failures would reject further template creation requests:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat-core/issues/238">cryostat-core#238</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-core/issues/239">cryostat-core#239</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-core/issues/241">cryostat-core#241</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-core/issues/243">cryostat-core#243</a></li>
    </ul>
  </li>
  <li>Cryostat would refuse Automated Rules creation requests using <code class="language-plaintext highlighter-rouge">multipart/form-data</code>:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat/issues/1490">cryostat#1490</a></li>
      <li><a href="https://github.com/cryostatio/cryostat/issues/1499">cryostat#1499</a></li>
    </ul>
  </li>
  <li>Cryostat Helm chart instances would use a hardcoded credentials secret name, which would conflict if multiple instances were installed to the same namespace:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat-helm/issues/62">cryostat-helm#62</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-helm/issues/65">cryostat-helm#65</a></li>
    </ul>
  </li>
  <li>Cryostat environment variable <code class="language-plaintext highlighter-rouge">CRYOSTAT_DISABLE_SSL</code> was handled inconsistently and would not always disable server SSL as expected:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat/issues/1507">cryostat#1507</a></li>
      <li><a href="https://github.com/cryostatio/cryostat/issues/1570">cryostat#1570</a></li>
    </ul>
  </li>
  <li>Cryostat environment variable <code class="language-plaintext highlighter-rouge">CRYOSTAT_DISABLE_BUILTIN_DISCOVERY</code> would also disable Custom Targets, and could break server startup in some scenarios:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat/pull/1505">cryostat#1505</a></li>
      <li><a href="https://github.com/cryostatio/cryostat/pull/1506">cryostat#1506</a></li>
    </ul>
  </li>
  <li>Cryostat built-in discovery mechanisms could block server startup if they failed to activate:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat/issues/1546">cryostat#1546</a></li>
      <li><a href="https://github.com/cryostatio/cryostat/issues/1549">cryostat#1549</a></li>
    </ul>
  </li>
  <li>Some minor graphical fixups in Cryostat Web:
    <ul>
      <li><a href="https://github.com/cryostatio/cryostat-web/issues/1019">cryostat-web#1019</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-web/issues/1041">cryostat-web#1041</a></li>
      <li><a href="https://github.com/cryostatio/cryostat-web/pull/1049">cryostat-web#1049</a></li>
    </ul>
  </li>
</ol>

<h2 id="where-can-i-get-the-latest-version-of-cryostat">Where can I get the latest version of Cryostat?</h2>
<p>You can install Cryostat using our
<a href="https://operatorhub.io/operator/cryostat-operator">Kubernetes operator on OperatorHub.io</a>
or via a
<a href="https://github.com/cryostatio/cryostat-helm/releases/tag/v0.3.1">Helm Chart</a>
. As always, you can also run Cryostat in other environments with a little more manual setup.</p>

<p>If this is your first time installing Cryostat on Kubernetes, you can <a href="/get-started">Get Started</a> right here on this
website.</p>

<p>If you had previously installed Cryostat Operator 2.3.0 with OLM, then you may have already been upgraded to 2.3.1, or
else you should be able to approve and install the upgrade.</p>

<h2 id="feedback">Feedback</h2>
<p>Please reach out to the <a href="mailto:cryostat-development@googlegroups.com">Cryostat mailing list</a> or
<a href="https://github.com/cryostatio/cryostat/discussions/1659">GitHub Discussion</a> with any questions or comments.</p>]]></content><author><name>Andrew Azores</name><email>aazores@ibm.com</email></author><summary type="html"><![CDATA[Table of Contents Table of Contents]]></summary></entry></feed>