<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Max Wagner]]></title><description><![CDATA[Developer and software architect with a passion for DevOps.]]></description><link>https://wagner-dev.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 10:51:01 GMT</lastBuildDate><atom:link href="https://wagner-dev.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Are you thinking of moving from PHP to Go? Read this first!]]></title><description><![CDATA[Are you a PHP developer contemplating a switch to Go? You're not alone. As technology evolves, many developers find themselves reevaluating their choice of programming languages to keep up with industry trends, improve performance, and enhance their ...]]></description><link>https://wagner-dev.com/are-you-thinking-of-moving-from-php-to-go-read-this-first</link><guid isPermaLink="true">https://wagner-dev.com/are-you-thinking-of-moving-from-php-to-go-read-this-first</guid><category><![CDATA[Go Language]]></category><category><![CDATA[PHP]]></category><dc:creator><![CDATA[Max Wagner]]></dc:creator><pubDate>Tue, 13 Aug 2024 19:10:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723497652177/51f1a63e-ae91-421c-b26d-895bdd35b53e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you a PHP developer contemplating a switch to Go? You're not alone. As technology evolves, many developers find themselves reevaluating their choice of programming languages to keep up with industry trends, improve performance, and enhance their skill sets. PHP has been a reliable workhorse for web development for decades, powering a vast number of websites and applications. However, with the rise of Go, known for its simplicity, efficiency, and powerful concurrency features, it’s no wonder you might be curious about making the transition.</p>
<p>In this post, we'll dive deep into what it means to move from PHP to Go. We'll explore the key differences between these two languages, and provide practical steps to help you navigate this journey. So, before you take the plunge, read on to discover everything you need to know about transitioning from PHP to Go.</p>
<h2 id="heading-history-of-go">History of Go</h2>
<p>Go, also known as Golang, is a statically typed, compiled programming language designed by Google for simplicity and efficiency.</p>
<ul>
<li><p><strong>Origins:</strong></p>
<ul>
<li><p><strong>Developed by Google:</strong> Created by Robert Griesemer, Rob Pike, and Ken Thompson.</p>
</li>
<li><p><strong>First Released:</strong> Publicly announced in 2009, with version 1.0 released in March 2012.</p>
</li>
</ul>
</li>
<li><p><strong>Design Philosophy:</strong></p>
<ul>
<li><p><strong>Simplicity and Clarity:</strong> Designed to be easy to understand, avoiding unnecessary complexity.</p>
</li>
<li><p><strong>Efficiency:</strong> Emphasizes fast compilation and execution.</p>
</li>
<li><p><strong>Concurrency:</strong> Features goroutines and channels for efficient concurrent task management.</p>
</li>
</ul>
</li>
<li><p><strong>Key Milestones:</strong></p>
<ul>
<li><p><strong>2015:</strong> Go 1.5 introduced a major runtime overhaul and self-hosted compiler toolchain.</p>
</li>
<li><p><strong>2017:</strong> Go 1.9 added type aliases and improved concurrent map access.</p>
</li>
<li><p><strong>2021:</strong> Go 1.17 brought performance enhancements and new module features.</p>
</li>
</ul>
</li>
</ul>
<p>Go continues to evolve, supported by an active community and driven by the need for efficient, scalable, and maintainable software.</p>
<h2 id="heading-key-differences-between-go-and-php">Key differences between Go and PHP</h2>
<h3 id="heading-when-to-use-go">When to Use Go</h3>
<p>Go is ideal for high-performance, concurrent, and scalable applications such as microservices, real-time systems, and distributed systems. Its efficient handling of concurrent processes, faster execution times, and maintainable code make it suitable for backend services, network servers, and command-line tools.</p>
<h3 id="heading-when-to-use-php">When to Use PHP</h3>
<p>PHP is perfect for server-side scripting and building dynamic websites and CMS-driven projects. Its ease of use, extensive documentation, and large community support make it ideal for beginners and small to medium-sized projects.</p>
<h3 id="heading-side-by-side-comparison">Side-by-side comparison</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td></td><td><strong>PHP</strong></td><td><strong>Go</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Execution</strong></td><td>interpreted, runtime is needed</td><td>compiled, self-contained</td></tr>
<tr>
<td><strong>Concurrency</strong></td><td>shared nothing architecture</td><td>concurrency is the default</td></tr>
<tr>
<td><strong>Error handling</strong></td><td>exceptions, mixed returns, errors</td><td>error struct returned, very verbose</td></tr>
<tr>
<td><strong>Memory management</strong></td><td>garbage collected</td><td>garbage collected</td></tr>
<tr>
<td><strong>Testing</strong></td><td>3rd party libraries</td><td>part of the standard library</td></tr>
<tr>
<td><strong>Benchmarking</strong></td><td>3rd party libraries</td><td>part of the standard library</td></tr>
<tr>
<td><strong>Frameworks</strong></td><td>large ecosystem</td><td>fewer frameworks but steadily growing</td></tr>
<tr>
<td><strong>Return values</strong></td><td>one or no value returned</td><td>no void type, multiple return values are normal, often accompanied by an “error” type</td></tr>
<tr>
<td><strong>Code formatting</strong></td><td>freestyle, automation via 3rd party libraries, or IDE, no synchronization across application and vendor code</td><td>hard-baked into the language, the base format is mandatory for the code to compile</td></tr>
<tr>
<td><strong>Package management</strong></td><td>via 3rd party tools: composer/packagist</td><td>built in the language core</td></tr>
</tbody>
</table>
</div><h2 id="heading-go-basics">Go basics</h2>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Here are the important basics, but there are more. Check out the linked learning resources for all the details.</div>
</div>

<h3 id="heading-variable-declaration-for-primitives"><strong>Variable declaration for primitives</strong></h3>
<pre><code class="lang-go"> <span class="hljs-comment">// standard declaration</span>
<span class="hljs-keyword">var</span> sum <span class="hljs-keyword">int</span>

<span class="hljs-comment">// type inferred</span>
<span class="hljs-keyword">var</span> a = <span class="hljs-string">"a string"</span>

<span class="hljs-comment">// multiple variables at once</span>
<span class="hljs-keyword">var</span> b, c <span class="hljs-keyword">int64</span> = <span class="hljs-number">1</span>, <span class="hljs-number">2</span>
<span class="hljs-keyword">var</span> (
    d = <span class="hljs-number">42</span>
    e = <span class="hljs-string">"another string"</span>
)

<span class="hljs-comment">// shorthand</span>
f := <span class="hljs-string">"apple"</span>
</code></pre>
<h3 id="heading-arrays-slices-and-maps"><strong>Arrays, Slices and Maps</strong></h3>
<p><strong>Arrays</strong></p>
<pre><code class="lang-go"><span class="hljs-comment">// template</span>
<span class="hljs-keyword">var</span> arrayName [size]Type

<span class="hljs-comment">// example</span>
<span class="hljs-keyword">var</span> num [<span class="hljs-number">3</span>]<span class="hljs-keyword">int</span>

<span class="hljs-comment">// declaration and initialization</span>
numbers := [<span class="hljs-number">5</span>]<span class="hljs-keyword">int</span>{<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>}
fmt.Println(numbers) <span class="hljs-comment">// [1 2 3 0 0]</span>
</code></pre>
<ul>
<li><p>fixed capacity and order</p>
</li>
<li><p>keys are 0 indexed integers without gaps</p>
</li>
<li><p>passed by reference</p>
</li>
</ul>
<p><strong>Slices</strong></p>
<pre><code class="lang-go"><span class="hljs-comment">// template</span>
<span class="hljs-keyword">var</span> sliceName []Type

<span class="hljs-comment">// example</span>
<span class="hljs-keyword">var</span> ages []<span class="hljs-keyword">int</span>

<span class="hljs-comment">// explicit declaration</span>
threeValues := <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">int</span>, <span class="hljs-number">3</span>, <span class="hljs-number">10</span>) <span class="hljs-comment">// 3 is the length, 10 is the capacity</span>

<span class="hljs-comment">// shorthand declaration</span>
numbers := []<span class="hljs-keyword">int</span>{<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>}
fmt.Println(numbers) <span class="hljs-comment">// [1 2 3]</span>
</code></pre>
<ul>
<li><p>size is dynamic</p>
</li>
<li><p>order is fixed</p>
</li>
<li><p>slice is a reference to an underlying array</p>
</li>
<li><p>more flexibility and convenience in comparison to arrays</p>
</li>
</ul>
<p><strong>Maps</strong></p>
<pre><code class="lang-go"><span class="hljs-comment">// template</span>
<span class="hljs-keyword">var</span> mapName <span class="hljs-keyword">map</span>[KeyType]ValueType

<span class="hljs-comment">// explicit declaration</span>
ages := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">int</span>)

<span class="hljs-comment">// shorthand declaration</span>
ages := <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">int</span>{
    <span class="hljs-string">"alice"</span>: <span class="hljs-number">27</span>,
    <span class="hljs-string">"bob"</span>:   <span class="hljs-number">28</span>,
}
</code></pre>
<ul>
<li><p>grows and shrinks dynamically</p>
</li>
<li><p>backed by hash-map</p>
</li>
<li><p>passed by reference</p>
</li>
<li><p>random order when iterating over</p>
</li>
<li><p>cannot be compared with the equality operator</p>
</li>
</ul>
<h3 id="heading-structs">Structs</h3>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> BankAccount <span class="hljs-keyword">struct</span> {
    IBAN     <span class="hljs-keyword">int</span>    
    password <span class="hljs-keyword">string</span>    
}

a := BankAccount{}
b := BankAccount{}

fmt.Println(a == b) <span class="hljs-comment">// true</span>
fmt.Println(&amp;a == &amp;b) <span class="hljs-comment">// false</span>
</code></pre>
<ul>
<li><p>structs are not objects you know in php</p>
</li>
<li><p>just a collection of properties to represent the state</p>
</li>
<li><p>there is no parent/child relationship</p>
</li>
<li><p>structs are composed (composition over inheritance)</p>
</li>
<li><p>structs are compared by comparing each property</p>
</li>
</ul>
<h3 id="heading-visibility">Visibility</h3>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> BankAccount <span class="hljs-keyword">struct</span> {
    IBAN     <span class="hljs-keyword">int</span>    <span class="hljs-comment">// exported (public)</span>
    password <span class="hljs-keyword">string</span>    <span class="hljs-comment">// unexported (private)</span>
}
</code></pre>
<ul>
<li><p>No extra keywords for public and private</p>
</li>
<li><p>Visibility is defined by the lower and upper casing of the property name</p>
</li>
<li><p>The same applies to variables, constants, methods, and types</p>
</li>
</ul>
<h3 id="heading-struct-methods">Struct methods</h3>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> BankAccount <span class="hljs-keyword">struct</span> {
    IBAN     <span class="hljs-keyword">int</span>    
    password <span class="hljs-keyword">string</span>    
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(b BankAccount)</span> <span class="hljs-title">HasLongPassword</span><span class="hljs-params">()</span> <span class="hljs-title">bool</span></span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">len</span>(b.password) &gt; <span class="hljs-number">12</span>
}

b := BankAccount{
    password: <span class="hljs-string">"Lorem ipsum dolor sit amet"</span>,
}
fmt.Println(b.HasLongPassword()) <span class="hljs-comment">// true</span>
</code></pre>
<h3 id="heading-interfaces">Interfaces</h3>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> error <span class="hljs-keyword">interface</span> {
    Error() <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Reader <span class="hljs-keyword">interface</span> {
    Read(p []<span class="hljs-keyword">byte</span>) (n <span class="hljs-keyword">int</span>, err error) <span class="hljs-comment">// read into a buffer</span>
}
<span class="hljs-keyword">type</span> Writer <span class="hljs-keyword">interface</span> {
    Write(p []<span class="hljs-keyword">byte</span>) (n <span class="hljs-keyword">int</span>, err error) <span class="hljs-comment">// write into a buffer</span>
}
</code></pre>
<ul>
<li><p>interfaces are implemented implicitly</p>
</li>
<li><p>no "implements" keyword</p>
</li>
<li><p>this decouples the definition of an interface from its implementation</p>
</li>
<li><p>typically very small (1-2 methods)</p>
</li>
</ul>
<h3 id="heading-iterating">Iterating</h3>
<pre><code class="lang-go">data := []<span class="hljs-keyword">int</span>{<span class="hljs-number">3</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span>}
<span class="hljs-keyword">var</span> i <span class="hljs-keyword">int</span>

<span class="hljs-comment">// initialization ; end condition ; post loop action</span>
<span class="hljs-keyword">for</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-built_in">len</span>(data); i++ {
    fmt.Printf(<span class="hljs-string">"loop 1: key %d has value %d\n"</span>, i, data[i])
}

i = <span class="hljs-number">0</span>
<span class="hljs-comment">// similar to while(condition === true)</span>
<span class="hljs-keyword">for</span> i &lt; <span class="hljs-built_in">len</span>(data) {
    fmt.Printf(<span class="hljs-string">"loop 2: key %d has value %d\n"</span>, i, data[i])
    i++
}

<span class="hljs-comment">//via range keyword</span>
data = []<span class="hljs-keyword">int</span>{<span class="hljs-number">3</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span>}

<span class="hljs-keyword">for</span> k, v := <span class="hljs-keyword">range</span> data {
    fmt.Printf(<span class="hljs-string">"key %d has value %d\n"</span>, k, v)
}
</code></pre>
<h3 id="heading-error-handling">Error handling</h3>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Copy</span><span class="hljs-params">(dst Writer, src Reader)</span> <span class="hljs-params">(written <span class="hljs-keyword">int64</span>, err error)</span></span> {
    ...
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">PipeStdinToStdout</span><span class="hljs-params">()</span> <span class="hljs-params">(<span class="hljs-keyword">int</span>, error)</span></span> {
    bytesWritten, err := io.Copy(os.Stdout, os.Stdin)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>, fmt.Errorf(<span class="hljs-string">"streaming stdin to stdout failed: %v"</span>, err)
    }

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">int</span>(bytesWritten), <span class="hljs-literal">nil</span>
}
</code></pre>
<ul>
<li><p>doesn’t have exceptions</p>
</li>
<li><p>doesn’t “throw” errors/warnings</p>
</li>
<li><p>doesn’t have mixed returns</p>
</li>
<li><p>but has multiple returns instead</p>
</li>
<li><p>errors are explicitly handled and<br />  passed to the caller</p>
</li>
</ul>
<h3 id="heading-go-routinesconcurrency">Go routines/concurrency</h3>
<ul>
<li><p>prefix any function call with the <strong>go</strong> keyword to</p>
</li>
<li><p>run it in a non-blocking fashion</p>
</li>
<li><p>no promises, no async-await, no callbacks</p>
<p>  → code looks and feels synchronous</p>
</li>
<li><p>concurrency needs to be controlled</p>
</li>
</ul>
<p><strong>Wait groups</strong></p>
<pre><code class="lang-go">wg := &amp;sync.WaitGroup{}

<span class="hljs-keyword">for</span> <span class="hljs-keyword">range</span> data {
    wg.Add(<span class="hljs-number">1</span>) <span class="hljs-comment">// add a "unit of work"</span>
    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
       dowork()
       wg.Done() <span class="hljs-comment">// signal one unit of work is done</span>
    }()
}

wg.Wait() <span class="hljs-comment">// block until all goroutines are finished</span>
</code></pre>
<ul>
<li><p>allows you to wait for a collection of goroutines (concurrent functions) to finish</p>
</li>
<li><p>internally implemented as a counter</p>
</li>
<li><p>when synchronization needs to happen, Wait() must be invoked</p>
</li>
</ul>
<p><strong>Channels</strong></p>
<pre><code class="lang-go">radio := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)
send := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(ch <span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>, msg <span class="hljs-keyword">string</span>)</span></span> {
    ch &lt;- msg 
}

<span class="hljs-keyword">go</span> send(radio, <span class="hljs-string">"hello world"</span>) <span class="hljs-comment">// non blocking</span>

fmt.Println(&lt;-radio) <span class="hljs-comment">// blocking</span>
</code></pre>
<ul>
<li><p>channels enable communication between go routines</p>
</li>
<li><p>communication happens when a sender and a receiver are present at the same time</p>
</li>
<li><p>sending and receiving is a blocking operation</p>
</li>
</ul>
<h2 id="heading-write-amp-execute-your-first-hello-world">Write &amp; execute your first "Hello World"</h2>
<h3 id="heading-install-go">Install Go</h3>
<p>Follow the required steps for your OS here: <a target="_blank" href="https://go.dev/doc/install">https://go.dev/doc/install</a>.</p>
<h3 id="heading-programm-code-hello-world">Programm code "Hello World"</h3>
<p>Create a file called <code>main.go</code> in a folder of your choice and past the following content.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    fmt.Println(<span class="hljs-string">"Hello World"</span>)
}
</code></pre>
<h3 id="heading-running-and-compiling-your-program"><strong>Running and compiling your program</strong></h3>
<pre><code class="lang-go"><span class="hljs-keyword">go</span> run main.<span class="hljs-keyword">go</span>
&gt; Hello World

<span class="hljs-keyword">go</span> build -o godemo main.<span class="hljs-keyword">go</span>
./godemo
&gt; Hello World

file godemo
&gt; godemo: Mach-O <span class="hljs-number">64</span>-bit executable arm64

GOOS=windows GOARCH=amd64 <span class="hljs-keyword">go</span> build -o godemo.exe main.<span class="hljs-keyword">go</span>
file godemo.exe
&gt; godemo.exe: PE32+ executable (console) x86<span class="hljs-number">-64</span> (stripped to external PDB), <span class="hljs-keyword">for</span> MS Windows
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">With the environment variables <code>GOOS</code> and <code>GOARCH</code> you can compile your Go program into any OS.</div>
</div>

<h2 id="heading-learning-resources">Learning resources</h2>
<ul>
<li><p>Interactive Go Playground: <a target="_blank" href="https://go.dev/play">https://go.dev/play</a> or <a target="_blank" href="https://goplay.tools/">https://goplay.tools/</a></p>
</li>
<li><p>Case Studies: <a target="_blank" href="https://go.dev/solutions/case-studies">https://go.dev/solutions/case-studies</a></p>
</li>
<li><p>Effective Go: <a target="_blank" href="https://go.dev/doc/effective_go">https://go.dev/doc/effective_go</a></p>
</li>
<li><p>Go by example: <a target="_blank" href="https://gobyexample.com">https://gobyexample.com</a></p>
</li>
<li><p>Book - Learning Go: <a target="_blank" href="https://www.oreilly.com/library/view/learning-go-2nd/9781098139285/">https://www.oreilly.com/library/view/learning-go-2nd/9781098139285/</a></p>
</li>
<li><p>Book - Concurrency in Go: <a target="_blank" href="https://www.oreilly.com/library/view/concurrency-in-go/9781491941294/">https://www.oreilly.com/library/view/concurrency-in-go/9781491941294/</a></p>
</li>
</ul>
<h2 id="heading-summaryhttpsgobyexamplecom"><a target="_blank" href="https://gobyexample.com">Summary</a></h2>
<p>In summary, Go and PHP each have their strengths and ideal use cases. Go excels in performance, concurrency, and scalability, making it perfect for complex, high-demand applications. PHP, with its ease of use and strong community support, is well-suited for web development and content management systems. If you’re considering a switch from PHP to Go, carefully evaluate your project requirements and team capabilities. Ready to dive deeper into Go? Explore our recommended resources and start experimenting with Go today to experience its benefits firsthand. Share your journey or ask questions in the comments below!</p>
]]></content:encoded></item><item><title><![CDATA[Upgrade your development workflow: Use DevSpace instead of Docker]]></title><description><![CDATA[In the fast-paced world of software development, keeping an efficient workflow is crucial. Local Docker setups often face challenges like high resource use, complex configurations, and differences between development and production environments. Thes...]]></description><link>https://wagner-dev.com/upgrade-your-development-workflow-use-devspace-instead-of-docker</link><guid isPermaLink="true">https://wagner-dev.com/upgrade-your-development-workflow-use-devspace-instead-of-docker</guid><category><![CDATA[Docker]]></category><category><![CDATA[dev environment]]></category><category><![CDATA[Kubernetes]]></category><dc:creator><![CDATA[Max Wagner]]></dc:creator><pubDate>Wed, 07 Aug 2024 09:51:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723024234347/e2d20975-17b2-4236-90a0-8d263019113f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the fast-paced world of software development, keeping an efficient workflow is crucial. Local Docker setups often face challenges like high resource use, complex configurations, and differences between development and production environments. These issues can slow productivity and make team collaboration harder. Enter DevSpace, a powerful tool designed to improve your development workflow by using Kubernetes. In this article, we will explore why moving from local Docker to DevSpace can greatly enhance your development process, offering a more streamlined, scalable, and collaborative approach.</p>
<h2 id="heading-the-limitations-of-local-docker-development">The limitations of local Docker development</h2>
<p>Docker has transformed how developers build and run applications, but it goes along with several challenges:</p>
<ul>
<li><p><strong>Resource Consumption</strong>: Local Docker environments demand significant CPU and memory resources, often leading to sluggish machine performance, especially with multiple containers or resource-intensive applications.</p>
</li>
<li><p><strong>Configuration Complexity</strong>: Setting up and maintaining local Docker configurations can be time-consuming and error-prone. Making sure all dependencies and environment variables are correctly set up for different projects can cause conflicts and inconsistencies.</p>
</li>
<li><p><strong>Environment Inconsistencies</strong>: Differences between local and production environments can cause applications to behave differently, leading to the "it works on my machine" problem.</p>
</li>
<li><p><strong>Collaboration Difficulties</strong>: Setting up the same environment on every team member's machine can be hard, causing differences and wasted time fixing issues.</p>
</li>
</ul>
<p>These limitations underscore the need for a more robust solution like DevSpace, which addresses these challenges and streamlines the development workflow.</p>
<h2 id="heading-what-is-devspace">What is DevSpace?</h2>
<p>DevSpace is an open-source tool designed to enhance and simplify development workflows by leveraging Kubernetes. It enables developers to deploy applications directly into Kubernetes clusters, ensuring consistency and reliability between development and production environments.</p>
<p>The key benefits of using DevSpace are:</p>
<ul>
<li><p><strong>Improved Resource Management</strong>: Offload your development environment to a Kubernetes cluster, enabling you to develop applications efficiently even on a low-powered PC.</p>
</li>
<li><p><strong>Streamlined Collaboration</strong>: Provides a shared development environment, making it easier for teams to work together.</p>
</li>
<li><p><strong>Faster Iteration Cycles</strong>: Real-time synchronization and hot-reloading allow for quicker testing and development.</p>
</li>
<li><p><strong>Seamless CI/CD Integration</strong>: Facilitates automated testing and deployment, integrating smoothly with existing CI/CD pipelines.</p>
</li>
<li><p><strong>Simplified Development Experience:</strong> Use the built-in UI to effortlessly stream application logs, monitor all containers, and utilize the convenient 1-click port-forwarding feature.</p>
</li>
</ul>
<h2 id="heading-getting-started-with-devspace">Getting started with DevSpace</h2>
<p>DevSpace is a super lightweight client-only binary, which does not require any server-side component.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Make sure you already have kubectl and your cluster configuration ready and working</div>
</div>

<p><strong>Installation</strong><br />Depending on your system, please read the <a target="_blank" href="https://www.devspace.sh/docs/getting-started/installation">official installation guide</a>.<br />Mac (Homebrew) example: <code>brew install devspace</code>  </p>
<p><strong>Initialize a Project (Golang example)</strong></p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/loft-sh/devspace-quickstart-golang
<span class="hljs-built_in">cd</span> devspace-quickstart-golang
</code></pre>
<p>Run <code>devspace init</code> and follow the provided steps to get started with your project. If finished successfully you should now have the following files/folders in your project:</p>
<ol>
<li><p>New file <code>devspace.yaml</code> --&gt; General DevSpace configuration file</p>
</li>
<li><p>New file <code>devspace_start.sh</code> --&gt; used when you use a terminal inside your dev container</p>
</li>
<li><p>New folder <code>.devsace/</code> --&gt; Cache for DevSpace to store some information locally. Should be added to the <code>.gitignore</code> file</p>
</li>
</ol>
<p><strong>A detailed reference for the</strong> <code>devspace.yaml</code> <strong>file can be found here:</strong> <a target="_blank" href="https://www.devspace.sh/docs/configuration/reference">https://www.devspace.sh/docs/configuration/reference</a></p>
<p><strong>Start development</strong></p>
<p>This is your starting point for daily work and launching your application. Before we begin, we need to make sure that DevSpace is using the correct namespace.  </p>
<p>Run <code>devspace use namespace &lt;your-namespace&gt;</code> to configure this. You can optionally execute <code>devspace use context &lt;your-context&gt;</code> to switch to a different Kubernetes cluster.</p>
<p>To deploy your project and start the dev container please run <code>devspace dev</code>. This will execute the defined <code>dev</code> pipeline in your <code>devspace.yaml</code> and will execute the defined steps.<br />Depending on your configuration you might need to start your application manually. In our example project, a terminal session should be opened automatically and you can run <code>go run main.go</code> to start your application</p>
<p>When you executed <code>devspace dev</code> the DevSpace UI is started by default in the background and you can open it under http://localhost:8080. Optionally you can run it manually with <code>devspace ui</code></p>
<p><strong>Troubleshooting</strong></p>
<p>If you encounter any issues with your DevSpace environment try the following:</p>
<ul>
<li><p>Run <code>devspace purge</code> to remove your deployments from the cluster</p>
</li>
<li><p>Delete the local <code>.devspace/</code> folder</p>
</li>
</ul>
<p>For more information about cleanup see here: <a target="_blank" href="https://www.devspace.sh/docs/getting-started/cleanup">https://www.devspace.sh/docs/getting-started/cleanup</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Switching from local Docker environments to DevSpace can significantly enhance your development workflow. By leveraging Kubernetes, DevSpace ensures that your development and production environments are aligned, reducing the "it works on my machine" problem and enhancing overall productivity.</p>
<p>Visit the DevSpace <a target="_blank" href="https://www.devspace.sh/docs/getting-started/introduction">documentation</a> to get started, join the vibrant DevSpace community to share your experiences, and explore additional resources. Try it now and see the difference for yourself!</p>
]]></content:encoded></item><item><title><![CDATA[How to Set Up Strict-Transport-Security (HSTS) in Istio]]></title><description><![CDATA[Secure your website by setting the Strict-Transport-Security HTTP header, or HSTS. This header will inform the browser that it should never load your website using the HTTP protocol, instead, the browser should convert all requests to HTTPS. You can ...]]></description><link>https://wagner-dev.com/how-to-set-up-strict-transport-security-hsts-in-istio</link><guid isPermaLink="true">https://wagner-dev.com/how-to-set-up-strict-transport-security-hsts-in-istio</guid><category><![CDATA[#istio]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Max Wagner]]></dc:creator><pubDate>Mon, 05 Aug 2024 20:03:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722928063051/35b7aaa4-832c-4bf0-b2d0-9c26a9e3e9de.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Secure your website by setting the Strict-Transport-Security HTTP header, or HSTS. This header will inform the browser that it should never load your website using the HTTP protocol, instead, the browser should convert all requests to HTTPS. You can easily configure Istio to set this header on each request.</p>
<p><strong>Explanation</strong></p>
<p>If your website accepts connections via HTTP protocol and redirects the user to HTTPS, visitors could get a non-encrypted version of your site before redirecting. This can be the case if the user for example calls <strong>http://</strong><a target="_blank" href="http://www.yoursite.com">www.yoursite.com</a> instead of <strong>https://</strong><a target="_blank" href="http://www.yoursite.com">www.yoursite.com</a> This creates an opportunity for a <a target="_blank" href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">man-in-the-middle attack</a>. Visitors could be redirected to some kind of evil website and not to the HTTPS version of your site.</p>
<p><strong>Prerequisites</strong></p>
<ul>
<li><p><a target="_blank" href="https://istio.io/latest/docs/reference/config/networking/gateway/">Create and configure the Istio gateway with your domain</a></p>
</li>
<li><p><a target="_blank" href="https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/">Configure HTTPS (SSL)</a></p>
</li>
</ul>
<p><strong>Set Strict-Transport-Security (HSTS) header in Istio Virtual-Service</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">kind:</span> <span class="hljs-string">VirtualService</span>
<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">networking.istio.io/v1beta1</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">my-virtual-service</span>
  <span class="hljs-attr">namespace:</span> <span class="hljs-string">default</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">hosts:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-string">yoursite.com</span>
  <span class="hljs-attr">gateways:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">istio-system/my-gateway</span>
  <span class="hljs-attr">http:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">default-route</span>
      <span class="hljs-attr">route:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">destination:</span>
            <span class="hljs-attr">host:</span> <span class="hljs-string">my-service</span>
            <span class="hljs-attr">port:</span>
              <span class="hljs-attr">number:</span> <span class="hljs-number">80</span>
          <span class="hljs-attr">headers:</span>
            <span class="hljs-attr">response:</span>
              <span class="hljs-attr">set:</span>
                <span class="hljs-attr">Strict-Transport-Security:</span> <span class="hljs-string">max-age=31536000;</span> <span class="hljs-string">includeSubDomains</span>
</code></pre>
<p>You can test your configuration here <a target="_blank" href="https://hstspreload.org/">https://hstspreload.org/</a> or your complete SSL s<a target="_blank" href="https://hstspreload.org/">e</a>tup including HSTS at <a target="_blank" href="https://www.ssllabs.com/ssltest/">https://www.ssllabs.com/ssltest/.</a> If your test was successful you could also add the "preload" feature. This will add your website to the major browser's HSTS preload lists. <strong>Before doing so I recommend reading</strong><a target="_blank" href="https://hstspreload.org/#opt-in"><strong>this paragraph</strong></a><strong>on why you should maybe not activate this feature.</strong></p>
<p><strong>Helpful Links</strong></p>
<ul>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security">MDN web docs: HTTP Strict-Transport-Security</a></p>
</li>
<li><p><a target="_blank" href="https://istio.io/latest/docs/">Istio Docs</a></p>
</li>
<li><p><a target="_blank" href="https://cert-manager.io/docs/installation/kubernetes/">Cert-Manager for Kubernetes</a></p>
</li>
</ul>
<p>Leave a comment or contact me via DM when you have a problem or a question.</p>
]]></content:encoded></item></channel></rss>