<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Daniel von Rohr</title>
        <link>https://www.dvonrohr.com</link>
        <description>Your blog description</description>
        <lastBuildDate>Fri, 18 Sep 2026 09:13:18 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Daniel von Rohr</title>
            <url>https://www.dvonrohr.com/favicon.ico</url>
            <link>https://www.dvonrohr.com</link>
        </image>
        <copyright>All rights reserved 2026</copyright>
        <item>
            <title><![CDATA[Effortless Local Development: Setting Up Directus CMS on Kubernetes]]></title>
            <link>https://www.dvonrohr.com/articles/setting-up-directus-cms-on-kubernetes</link>
            <guid>https://www.dvonrohr.com/articles/setting-up-directus-cms-on-kubernetes</guid>
            <pubDate>Fri, 29 Dec 2023 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>This post aims to guide web developers through the process of setting up Directus CMS on a local Kubernetes environment. Directus CMS is an open-source, headless content management system ideal for flexible and scalable web applications. Paired with Kubernetes, a powerful container-orchestration system, it forms a robust platform for development. We'll also touch on the role of Minikube, a tool that simplifies running Kubernetes locally.</p>
<h2>Getting Started</h2>
<p>Before beginning our journey into setting up Directus CMS on Kubernetes, it's essential to have the right tools in place. You’ll need Docker or an alternative like Podman, as well as Minikube. These tools are crucial for creating and managing containerized applications and a local Kubernetes environment. While this post won't cover the installation steps for these tools, you can find detailed instructions at their respective websites:</p>
<p>For Docker, visit <a href="https://www.docker.com/products/docker-desktop/">Docker Desktop</a>.</p>
<p>To install Minikube, head over to <a href="https://kubernetes.io/en/docs/tasks/tools/install-minikube/">Minikube's official documentation</a>.</p>
<p>As an alternative to Docker Desktop, consider exploring <a href="https://podman.io/">Podman</a>.</p>
<h2>Understanding Kubernetes and Minikube</h2>
<p>Kubernetes has revolutionized how we deploy and manage containerized applications, offering a level of efficiency and scalability previously unattainable. It orchestrates containers across multiple hosts, automates deployment processes, and manages workloads. Key features include automated scheduling, self-healing capabilities, horizontal scaling, and service discovery and load balancing. Minikube brings the power of Kubernetes to your local machine, providing a lightweight, easy-to-use platform for development and testing.</p>
<h2>Deploying PostgreSQL on Kubernetes</h2>
<p>Setting up PostgreSQL on Kubernetes involves several steps, each defined by specific configurations in YAML files. We start with a PersistentVolumeClaim (PVC) for data persistence, move to deploying the PostgreSQL container, and finally, define a service to expose it.</p>
<h3>PersistentVolumeClaim for PostgreSQL</h3>
<p>First, we create a PVC for PostgreSQL:</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> PersistentVolumeClaim
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> postgres<span class="token punctuation">-</span>pv<span class="token punctuation">-</span>claim
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> mynamespace
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">accessModes</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> ReadWriteOnce
  <span class="token key atrule">resources</span><span class="token punctuation">:</span>
    <span class="token key atrule">requests</span><span class="token punctuation">:</span>
      <span class="token key atrule">storage</span><span class="token punctuation">:</span> 1Gi
</code></pre>
<h3>PostgreSQL Deployment</h3>
<p>Next, we deploy PostgreSQL:</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> apps/v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Deployment
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> postgres
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> mynamespace
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">selector</span><span class="token punctuation">:</span>
    <span class="token key atrule">matchLabels</span><span class="token punctuation">:</span>
      <span class="token key atrule">app</span><span class="token punctuation">:</span> postgres
  <span class="token key atrule">template</span><span class="token punctuation">:</span>
    <span class="token key atrule">metadata</span><span class="token punctuation">:</span>
      <span class="token key atrule">labels</span><span class="token punctuation">:</span>
        <span class="token key atrule">app</span><span class="token punctuation">:</span> postgres
    <span class="token key atrule">spec</span><span class="token punctuation">:</span>
      <span class="token key atrule">containers</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> postgres
        <span class="token key atrule">image</span><span class="token punctuation">:</span> postgres<span class="token punctuation">:</span>latest
        <span class="token key atrule">env</span><span class="token punctuation">:</span>
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> POSTGRES_DB
          <span class="token key atrule">value</span><span class="token punctuation">:</span> directus
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> POSTGRES_USER
          <span class="token key atrule">value</span><span class="token punctuation">:</span> username
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> POSTGRES_PASSWORD
          <span class="token key atrule">value</span><span class="token punctuation">:</span> mypassword
        <span class="token key atrule">ports</span><span class="token punctuation">:</span>
          <span class="token punctuation">-</span> <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">5432</span>
        <span class="token key atrule">volumeMounts</span><span class="token punctuation">:</span>
        <span class="token punctuation">-</span> <span class="token key atrule">mountPath</span><span class="token punctuation">:</span> /var/lib/postgresql/data
          <span class="token key atrule">name</span><span class="token punctuation">:</span> postgres<span class="token punctuation">-</span>storage
      <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> postgres<span class="token punctuation">-</span>storage
        <span class="token key atrule">persistentVolumeClaim</span><span class="token punctuation">:</span>
          <span class="token key atrule">claimName</span><span class="token punctuation">:</span> postgres<span class="token punctuation">-</span>pv<span class="token punctuation">-</span>claim
</code></pre>
<h3>PostgreSQL Service</h3>
<p>Finally, we define a Service:</p>
<pre class="language-yaml"><code class="language-yaml">Copy code
<span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Service
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> postgres
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> mynamespace
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">selector</span><span class="token punctuation">:</span>
    <span class="token key atrule">app</span><span class="token punctuation">:</span> postgres
  <span class="token key atrule">ports</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">protocol</span><span class="token punctuation">:</span> TCP
      <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">5432</span>
      <span class="token key atrule">targetPort</span><span class="token punctuation">:</span> <span class="token number">5432</span>
</code></pre>
<h2>Setting Up Directus CMS</h2>
<p>Deploying Directus CMS on Kubernetes follows a similar pattern to PostgreSQL.</p>
<h3>PersistentVolumeClaim for Directus</h3>
<p>First, a PVC for Directus:</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> PersistentVolumeClaim
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> directus<span class="token punctuation">-</span>pv<span class="token punctuation">-</span>claim
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> mynamespace
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">accessModes</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> ReadWriteOnce
  <span class="token key atrule">resources</span><span class="token punctuation">:</span>
    <span class="token key atrule">requests</span><span class="token punctuation">:</span>
      <span class="token key atrule">storage</span><span class="token punctuation">:</span> 1Gi
</code></pre>
<h3>Directus Deployment</h3>
<p>Then, the Directus deployment:</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> apps/v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Deployment
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> directus
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> mynamespace
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">selector</span><span class="token punctuation">:</span>
    <span class="token key atrule">matchLabels</span><span class="token punctuation">:</span>
      <span class="token key atrule">app</span><span class="token punctuation">:</span> directus
  <span class="token key atrule">template</span><span class="token punctuation">:</span>
    <span class="token key atrule">metadata</span><span class="token punctuation">:</span>
      <span class="token key atrule">labels</span><span class="token punctuation">:</span>
        <span class="token key atrule">app</span><span class="token punctuation">:</span> directus
    <span class="token key atrule">spec</span><span class="token punctuation">:</span>
      <span class="token key atrule">containers</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> directus
        <span class="token key atrule">image</span><span class="token punctuation">:</span> directus/directus<span class="token punctuation">:</span>latest
        <span class="token key atrule">env</span><span class="token punctuation">:</span>
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> DATABASE_URL
          <span class="token key atrule">value</span><span class="token punctuation">:</span> postgresql<span class="token punctuation">:</span>//username<span class="token punctuation">:</span>mypassword@postgres<span class="token punctuation">:</span>5432/directus
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> KEY
          <span class="token key atrule">value</span><span class="token punctuation">:</span> <span class="token string">"prod"</span>
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> SECRET
          <span class="token key atrule">value</span><span class="token punctuation">:</span> <span class="token string">"myverysecretkey"</span>
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> ADMIN_EMAIL
          <span class="token key atrule">value</span><span class="token punctuation">:</span> <span class="token string">"dev@admin.com"</span>
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> ADMIN_PASSWORD
          <span class="token key atrule">value</span><span class="token punctuation">:</span> <span class="token string">"123456"</span>
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> PUBLIC_URL
          <span class="token key atrule">value</span><span class="token punctuation">:</span> <span class="token string">"http://localhost:8055"</span>
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> CORS_ORIGIN
          <span class="token key atrule">value</span><span class="token punctuation">:</span> <span class="token string">"http://localhost:5173"</span>
        <span class="token key atrule">ports</span><span class="token punctuation">:</span>
        <span class="token punctuation">-</span> <span class="token key atrule">containerPort</span><span class="token punctuation">:</span> <span class="token number">8055</span>
        <span class="token key atrule">volumeMounts</span><span class="token punctuation">:</span>
        <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> directus<span class="token punctuation">-</span>storage
          <span class="token key atrule">mountPath</span><span class="token punctuation">:</span> /directus/uploads
      <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> directus<span class="token punctuation">-</span>storage
        <span class="token key atrule">persistentVolumeClaim</span><span class="token punctuation">:</span>
          <span class="token key atrule">claimName</span><span class="token punctuation">:</span> directus<span class="token punctuation">-</span>pv<span class="token punctuation">-</span>claim
</code></pre>
<h3>Directus Service</h3>
<p>And finally, the Directus service:</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Service
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> directus
  <span class="token key atrule">namespace</span><span class="token punctuation">:</span> mynamespace
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">selector</span><span class="token punctuation">:</span>
    <span class="token key atrule">app</span><span class="token punctuation">:</span> directus
  <span class="token key atrule">ports</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">protocol</span><span class="token punctuation">:</span> TCP
      <span class="token key atrule">port</span><span class="token punctuation">:</span> <span class="token number">8055</span>
      <span class="token key atrule">targetPort</span><span class="token punctuation">:</span> <span class="token number">8055</span>
</code></pre>
<h2>Integrating Directus with PostgreSQL</h2>
<p>Integration is crucial for Directus to function correctly with the PostgreSQL database. This is primarily handled through environment variables in the Directus deployment YAML:</p>
<p><strong>DATABASE_URL:</strong> Configured to connect Directus to the PostgreSQL service. It includes the database name, user, and password, as well as the PostgreSQL service name and port.
<strong>Admin Account Setup:</strong> Environment variables like ADMIN_EMAIL and ADMIN_PASSWORD are used to create the initial admin account in Directus.</p>
<p>This integration allows Directus to effectively manage and store content in the PostgreSQL database, ensuring a seamless content management experience.</p>
<h2>Accessing Directus via Port Forwarding</h2>
<p>Once Directus is successfully deployed, you can access it through port forwarding. This is done using the kubectl port-forward command, which allows you to access Directus from your local machine:</p>
<pre class="language-bash"><code class="language-bash">kubectl port-forward service/directus <span class="token number">8055</span>:8055 -n mynamespace
</code></pre>
<p>After executing this command, Directus will be accessible at <a href="http://localhost:8055">http://localhost:8055</a>. This step is crucial for testing your setup and ensures that Directus is properly configured and operational.</p>
<h2>Conclusion</h2>
<p>Conclude by summarizing the process and its benefits. Highlight the efficiency and scalability of using Kubernetes for local development with Directus CMS. Encourage readers to experiment with different configurations, adapt the setup to their needs, and share their experiences and feedback.</p>]]></content:encoded>
            <author>hi@dvonrohr.com (Daniel von Rohr)</author>
        </item>
    </channel>
</rss>