<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: leone</title>
    <description>The latest articles on DEV Community by leone (@leone).</description>
    <link>https://dev.to/leone</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1066365%2F9a197fcb-34b2-4ea9-a5ca-5f5f795fb0c1.jpg</url>
      <title>DEV Community: leone</title>
      <link>https://dev.to/leone</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leone"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Tue, 14 Oct 2025 15:52:59 +0000</pubDate>
      <link>https://dev.to/leone/-1mb7</link>
      <guid>https://dev.to/leone/-1mb7</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/0xle0ne" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3448609%2Fc4d2b1ec-48f0-4f75-9fc9-69f6c845d845.jpg" alt="0xle0ne"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/0xle0ne/deploy-a-complete-media-center-on-nanocl-23kc" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Deploy a complete media center on Nanocl&lt;/h2&gt;
      &lt;h3&gt;leone ・ Oct 14&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#nanocl&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>beginners</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>nanocl</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Wed, 17 Sep 2025 06:52:43 +0000</pubDate>
      <link>https://dev.to/leone/-25n4</link>
      <guid>https://dev.to/leone/-25n4</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/0xle0ne" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3448609%2Fc4d2b1ec-48f0-4f75-9fc9-69f6c845d845.jpg" alt="0xle0ne"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/0xle0ne/deploy-vaultwarden-on-nanocl-gg1" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Deploy Vaultwarden on Nanocl&lt;/h2&gt;
      &lt;h3&gt;leone ・ Sep 17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Tue, 09 Sep 2025 18:45:33 +0000</pubDate>
      <link>https://dev.to/leone/-32l7</link>
      <guid>https://dev.to/leone/-32l7</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/0xle0ne" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3448609%2Fc4d2b1ec-48f0-4f75-9fc9-69f6c845d845.jpg" alt="0xle0ne"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/0xle0ne/how-to-easily-create-a-cli-in-rust-using-clap-and-clapmangen-37g1" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to easily create a CLI in Rust using clap and clap_mangen&lt;/h2&gt;
      &lt;h3&gt;leone ・ Sep 9&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#rust&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>programming</category>
      <category>rust</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Mon, 08 Sep 2025 22:25:37 +0000</pubDate>
      <link>https://dev.to/leone/-255</link>
      <guid>https://dev.to/leone/-255</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/0xle0ne" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3448609%2Fc4d2b1ec-48f0-4f75-9fc9-69f6c845d845.jpg" alt="0xle0ne"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/0xle0ne/your-own-private-internet-with-nanocl-and-wireguard-541c" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Your Own Private Internet with Nanocl and WireGuard&lt;/h2&gt;
      &lt;h3&gt;leone ・ Sep 8&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Fri, 05 Sep 2025 17:24:44 +0000</pubDate>
      <link>https://dev.to/leone/-1b5i</link>
      <guid>https://dev.to/leone/-1b5i</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/0xle0ne" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3448609%2Fc4d2b1ec-48f0-4f75-9fc9-69f6c845d845.jpg" alt="0xle0ne"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/0xle0ne/basic-http-proxy-in-rust-with-ntex-d6p" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Basic http proxy in rust with ntex&lt;/h2&gt;
      &lt;h3&gt;leone ・ Sep 5&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#rust&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>rust</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Fri, 05 Sep 2025 17:19:36 +0000</pubDate>
      <link>https://dev.to/leone/-1dbl</link>
      <guid>https://dev.to/leone/-1dbl</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/0xle0ne" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3448609%2Fc4d2b1ec-48f0-4f75-9fc9-69f6c845d845.jpg" alt="0xle0ne"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/0xle0ne/automating-deployment-with-github-actions-and-nanocl-573p" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Automating deployment with GitHub Actions and Nanocl&lt;/h2&gt;
      &lt;h3&gt;leone ・ Sep 5&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>devops</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Thu, 04 Sep 2025 19:39:41 +0000</pubDate>
      <link>https://dev.to/leone/-19pd</link>
      <guid>https://dev.to/leone/-19pd</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/0xle0ne" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3448609%2Fc4d2b1ec-48f0-4f75-9fc9-69f6c845d845.jpg" alt="0xle0ne"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/0xle0ne/solving-the-localhost-development-headache-with-nanocl-53jc" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Solving the Localhost Development Headache with Nanocl&lt;/h2&gt;
      &lt;h3&gt;leone ・ Sep 4&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Wed, 03 Sep 2025 09:46:53 +0000</pubDate>
      <link>https://dev.to/leone/-4f19</link>
      <guid>https://dev.to/leone/-4f19</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/0xle0ne/rest-api-in-rust-with-ntex-6a8" class="crayons-story__hidden-navigation-link"&gt;REST API in RUST with ntex&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/0xle0ne" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3448609%2Fc4d2b1ec-48f0-4f75-9fc9-69f6c845d845.jpg" alt="0xle0ne profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/0xle0ne" class="crayons-story__secondary fw-medium m:hidden"&gt;
              leone
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                leone
                
              
              &lt;div id="story-author-preview-content-2816392" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/0xle0ne" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3448609%2Fc4d2b1ec-48f0-4f75-9fc9-69f6c845d845.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;leone&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/0xle0ne/rest-api-in-rust-with-ntex-6a8" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 3 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/0xle0ne/rest-api-in-rust-with-ntex-6a8" id="article-link-2816392"&gt;
          REST API in RUST with ntex
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/rust"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;rust&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/0xle0ne/rest-api-in-rust-with-ntex-6a8" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;10&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/0xle0ne/rest-api-in-rust-with-ntex-6a8#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            9 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>rust</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Basic http proxy in rust with ntex</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Wed, 18 Dec 2024 12:38:09 +0000</pubDate>
      <link>https://dev.to/leone/basic-http-proxy-in-rust-with-ntex-4b5a</link>
      <guid>https://dev.to/leone/basic-http-proxy-in-rust-with-ntex-4b5a</guid>
      <description>&lt;h2&gt;
  
  
  What is ntex ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ntex.rs" rel="noopener noreferrer"&gt;Ntex&lt;/a&gt; is a powerful, pragmatic, and extremely fast framework for composable networking services for Rust.&lt;br&gt;
It's one of the fastest web frameworks available in Rust, and provides powerful abstractions for web server development.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why ntex ?
&lt;/h2&gt;

&lt;p&gt;This are my top reasons for using ntex:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Ntex is one of the fastest web frameworks available in Rust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ergonomic&lt;/strong&gt;: Ntex provides powerful abstractions for web server development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composable&lt;/strong&gt;: Ntex is designed to be composable, allowing you to build complex web servers from simple components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ecosystem&lt;/strong&gt;: Ntex has a rich ecosystem of middleware, extensions and libraries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in http client&lt;/strong&gt;: Ntex provides a built-in http client for making requests to other servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime&lt;/strong&gt;: Ntex allow you to choose between different runtimes, including tokio and async-std.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Setting up the project
&lt;/h2&gt;

&lt;p&gt;Let's start by creating a new project with cargo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo new ntex-http-proxy
&lt;span class="nb"&gt;cd &lt;/span&gt;ntex-http-proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add ntex as dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo add ntex &lt;span class="nt"&gt;--features&lt;/span&gt; tokio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Starting with a basic http handler
&lt;/h2&gt;

&lt;p&gt;Let's start by creating a basic http handler that will return &lt;code&gt;Hello, World!&lt;/code&gt; in plain text format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ntex&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nf"&gt;.content_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"text/plain"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[ntex::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nf"&gt;.state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;http&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="nf"&gt;.wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="nf"&gt;.default_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"0.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9090&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;forward&lt;/code&gt; is an async function that returns a &lt;code&gt;web::HttpResponse&lt;/code&gt; or a &lt;code&gt;web::Error&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;main&lt;/code&gt; is the entry point of our application. It's an async function that returns a &lt;code&gt;std::io::Result&amp;lt;()&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We create a new ntex web server with &lt;code&gt;web::server&lt;/code&gt; and pass a closure that returns a &lt;code&gt;web::App&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We create a new &lt;code&gt;http::Client&lt;/code&gt; and add it to the app state.&lt;/li&gt;
&lt;li&gt;We add a logger middleware to the app.&lt;/li&gt;
&lt;li&gt;We define a default service that will forward all requests to the &lt;code&gt;forward&lt;/code&gt; handler.&lt;/li&gt;
&lt;li&gt;We bind the server to &lt;code&gt;0.0.0.0:9090&lt;/code&gt; and run it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's test the server by running it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo run
curl http://localhost:9090
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see &lt;code&gt;Hello, world!&lt;/code&gt; in the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a proxy handler
&lt;/h2&gt;

&lt;p&gt;We start by adding the &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;futures_util&lt;/code&gt; crates to our dependencies to be able to parse urls and convert responses to streams:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo add url futures-util
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we change the the code to forward requests to another server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;futures_util&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TryStreamExt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ntex&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;ntex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;util&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;types&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;http&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;forward_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;types&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;url&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Url&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;new_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forward_url&lt;/span&gt;&lt;span class="nf"&gt;.get_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;new_url&lt;/span&gt;&lt;span class="nf"&gt;.set_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="nf"&gt;.uri&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.path&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="n"&gt;new_url&lt;/span&gt;&lt;span class="nf"&gt;.set_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="nf"&gt;.uri&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.query&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;forwarded_req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.request_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_url&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="nf"&gt;.head&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forwarded_req&lt;/span&gt;
    &lt;span class="nf"&gt;.send_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;
    &lt;span class="nf"&gt;.map_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;client_resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="nf"&gt;.into_stream&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_resp&lt;/span&gt;&lt;span class="nf"&gt;.streaming&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[ntex::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;forward_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://www.rust-lang.org"&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;forward_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;url&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Url&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;forward_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.map_err&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ErrorKind&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InvalidData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nf"&gt;.state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;http&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="nf"&gt;.state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forward_url&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="nf"&gt;.wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="nf"&gt;.default_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"0.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9090&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We add the &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;futures_util&lt;/code&gt; crates to our dependencies.&lt;/li&gt;
&lt;li&gt;We change the &lt;code&gt;forward&lt;/code&gt; function to take the request, body, client and forward_url as arguments.&lt;/li&gt;
&lt;li&gt;We create a new url by cloning the forward_url and setting the path and query from the request.&lt;/li&gt;
&lt;li&gt;We create a new request using the client and the new url.&lt;/li&gt;
&lt;li&gt;We send the body of the request and await the response.&lt;/li&gt;
&lt;li&gt;We build a new response with the status code of the response.&lt;/li&gt;
&lt;li&gt;We convert the response into a stream and return it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's test the server by running it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo run
curl http://localhost:9090
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the rust-lang.org homepage in the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we created a basic http proxy server using ntex. We started by creating a simple http handler that returns &lt;code&gt;Hello, World!&lt;/code&gt; in plain text format. Then we added a proxy handler that forwards requests to another server. We used the &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;futures_util&lt;/code&gt; crates to parse urls and convert responses to streams. We tested the server by running it and making a request to it. We saw that the server successfully forwarded the request to the target server and returned the response.&lt;br&gt;
We have little to no code to write a basic http proxy server (less than 50 lines of code) and we can easily extend it with more features like caching, rate limiting, authentication, etc.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this tutorial and found it useful. If you have any questions or feedback, feel free to leave a comment below.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>rust</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Thu, 28 Nov 2024 05:19:48 +0000</pubDate>
      <link>https://dev.to/leone/-ed8</link>
      <guid>https://dev.to/leone/-ed8</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/leone" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1066365%2F9a197fcb-34b2-4ea9-a5ca-5f5f795fb0c1.jpg" alt="leone"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/leone/automating-deployment-with-github-actions-and-nanocl-2b1e" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Automating deployment with GitHub Actions and Nanocl&lt;/h2&gt;
      &lt;h3&gt;leone ・ Nov 24 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Automating deployment with GitHub Actions and Nanocl</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Sun, 24 Nov 2024 17:35:58 +0000</pubDate>
      <link>https://dev.to/leone/automating-deployment-with-github-actions-and-nanocl-2b1e</link>
      <guid>https://dev.to/leone/automating-deployment-with-github-actions-and-nanocl-2b1e</guid>
      <description>&lt;p&gt;Learn how to automate your deployment with GitHub Actions and Nanocl. This guide walks you through setting up seamless deployments, making it easier to deploy your applications with minimal effort. Whether you're new to CI/CD or an experienced developer, this post will show you how to streamline your workflow using powerful open-source tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7d75xgzrchcbmytj87hn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7d75xgzrchcbmytj87hn.jpg" alt="nanocl-meme" width="800" height="820"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Continuous Integration and Continuous Deployment (CI/CD) are essential practices in modern software development. They help automate the process of building, testing, and deploying applications, making it easier to deliver high-quality software quickly and efficiently. GitHub Actions is a powerful tool that allows you to automate your CI/CD pipeline directly from your GitHub repository. Nanocl is a containers and virtual machine orchestrator that simplifies the deployment process by providing a unified interface for managing your infrastructure.&lt;/p&gt;

&lt;p&gt;In this blog i will showcase how i did setup our CI/CD pipeline with Github Actions and Nanocl for the deployment of &lt;a href="https://docs.next-hat.com" rel="noopener noreferrer"&gt;next-hat&lt;/a&gt; and and &lt;a href="https://ntex.rs" rel="noopener noreferrer"&gt;ntex.rs&lt;/a&gt; documentation that use docusaurus.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we get started you need a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A GitHub account (you can sign up for free at &lt;a href="https://github.com" rel="noopener noreferrer"&gt;github.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A project to deploy (it can be a static website, a web application, or anything that can run in a container)&lt;/li&gt;
&lt;li&gt;A dedicated server or a VPS (i use &lt;a href="https://www.ovh.com" rel="noopener noreferrer"&gt;ovh&lt;/a&gt; for servers)&lt;/li&gt;
&lt;li&gt;A domain name that point to your server (i use &lt;a href="https://www.ovh.com" rel="noopener noreferrer"&gt;ovh&lt;/a&gt; for domain names)&lt;/li&gt;
&lt;li&gt;Docker installed on your local machine and server (you can find the installation instructions &lt;a href="https://docs.docker.com/get-docker" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Nanocl installed on your server (you can find the installation instructions &lt;a href="https://docs.next-hat.com/manuals/nanocl/install/overview" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating the container image
&lt;/h2&gt;

&lt;p&gt;We will take a look on how to create the container image for the deployment of the documentation of &lt;a href="https://docs.next-hat.com" rel="noopener noreferrer"&gt;next-hat&lt;/a&gt; and &lt;a href="https://ntex.rs" rel="noopener noreferrer"&gt;ntex.rs&lt;/a&gt; that use docusaurus. If you already know how to setup a docker container image you can skip this section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Nginx Configuration File
&lt;/h3&gt;

&lt;p&gt;We use &lt;code&gt;nginx&lt;/code&gt; as a web server to serve the static files generated by docusaurus. The &lt;code&gt;server.nginx&lt;/code&gt; file contains the configuration for the nginx server. You can replace it with your own configuration file to match your use case.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;listen&lt;/span&gt;       &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;listen&lt;/span&gt;  &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/(.*)/&lt;/span&gt;$ &lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kn"&gt;gzip&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;gzip_vary&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;gzip_proxied&lt;/span&gt; &lt;span class="s"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;gzip_comp_level&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;gunzip&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;gzip_types&lt;/span&gt; &lt;span class="nc"&gt;application/javascript&lt;/span&gt; &lt;span class="s"&gt;image/*&lt;/span&gt; &lt;span class="nc"&gt;text/css&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;gzip_disable&lt;/span&gt; &lt;span class="s"&gt;"MSIE&lt;/span&gt; &lt;span class="s"&gt;[1-6]&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/home/node/app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;error_page&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt; &lt;span class="n"&gt;/404.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s"&gt;.html&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/index.html&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;## All static files will be cached.&lt;/span&gt;
  &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="s"&gt;^.+&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.(?:css|webp|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|woff2|svg)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;access_log&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;expires&lt;/span&gt; &lt;span class="s"&gt;1y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Cache-Control&lt;/span&gt; &lt;span class="s"&gt;max-age=31536000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;## No need to bleed constant updates. Send the all shebang in one&lt;/span&gt;
    &lt;span class="c1"&gt;## fell swoop.&lt;/span&gt;
    &lt;span class="kn"&gt;tcp_nodelay&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;## Set the OS file cache.&lt;/span&gt;
    &lt;span class="kn"&gt;open_file_cache&lt;/span&gt; &lt;span class="s"&gt;max=3000&lt;/span&gt; &lt;span class="s"&gt;inactive=120s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;open_file_cache_valid&lt;/span&gt; &lt;span class="s"&gt;45s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;open_file_cache_min_uses&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;open_file_cache_errors&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the &lt;code&gt;server.nginx&lt;/code&gt; configuration file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;server { ... }&lt;/code&gt;: This block defines the configuration for the Nginx server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;listen 80;&lt;/code&gt;: This line specifies that the server should listen on port 80.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rewrite ^/(.*)/$ /$1 permanent;&lt;/code&gt;: This line redirects requests with a trailing slash to the same URL without the slash.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gzip on;&lt;/code&gt;: This line enables gzip compression for responses.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;root /home/node/app;&lt;/code&gt;: This line specifies the root directory for serving static files.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;error_page 404 /404.html;&lt;/code&gt;: This line specifies the error page to use for 404 errors.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;try_files $uri.html $uri/index.html =404;&lt;/code&gt;: This line specifies the files to try when a request is made.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;location ~* ^.+\.(?:css|webp|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|woff2|svg)$ { ... }&lt;/code&gt;: This block specifies the configuration for serving static files with caching enabled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This configuration file optimizes the Nginx server for serving static files and improves performance by enabling gzip compression and caching.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Dockerfile
&lt;/h3&gt;

&lt;p&gt;A &lt;a href="https://docs.docker.com/reference/dockerfile/" rel="noopener noreferrer"&gt;Dockerfile&lt;/a&gt; is a text document that contains all the commands needed to build a Docker image. It specifies the base image to use, the commands to run, and the files to copy into the image. In this guide, we will create a Dockerfile for a docusaurus website. You can replace the commands with the ones needed for your project.&lt;/p&gt;

&lt;p&gt;Create a new file in your project directory called &lt;a href="https://docs.docker.com/reference/dockerfile/" rel="noopener noreferrer"&gt;Dockerfile&lt;/a&gt;. This file will contain the configuration for your Docker image. Here is an example Dockerfile for a docusaurus website:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:22.11.0-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apk add git

&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; node&lt;/span&gt;

&lt;span class="c"&gt;# Create app directory (with user `node`)&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/node/app
&lt;span class="c"&gt;# Set is as cwd&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /home/node/app&lt;/span&gt;

&lt;span class="c"&gt;# Install app dependencies&lt;/span&gt;
&lt;span class="c"&gt;# A wildcard is used to ensure both package.json AND package-lock.json are copied&lt;/span&gt;
&lt;span class="c"&gt;# where available (npm@5+)&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --chown=node package*.json ./&lt;/span&gt;

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Bundle app source code&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --chown=node . .&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --chown=node ./.git ./.git&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:1.27.0-alpine3.19-slim&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /etc/nginx/conf.d&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /home/node/app/build /home/node/app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./server.nginx ./default.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the Dockerfile:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FROM node:22.11.0-alpine AS builder&lt;/code&gt;: This line specifies the base image to use for the build stage. We use the &lt;code&gt;node:22.11.0-alpine&lt;/code&gt; image, which is a lightweight version of Node.js that includes npm.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN apk add git&lt;/code&gt;: This line installs the &lt;code&gt;git&lt;/code&gt; package, which is needed to clone the repository.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;USER node&lt;/code&gt;: This line switches to the &lt;code&gt;node&lt;/code&gt; user, which is a non-root user created by the Node.js image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN mkdir -p /home/node/app&lt;/code&gt;: This line creates a directory for the application code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WORKDIR /home/node/app&lt;/code&gt;: This line sets the working directory to the application directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY --chown=node package*.json .&lt;/code&gt;: This line copies the &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;package-lock.json&lt;/code&gt; files into the image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN npm install&lt;/code&gt;: This line installs the dependencies specified in the &lt;code&gt;package.json&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY --chown=node . .&lt;/code&gt;: This line copies the application code into the image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY --chown=node ./.git ./.git&lt;/code&gt;: This line copies the &lt;code&gt;.git&lt;/code&gt; directory into the image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN npm run build&lt;/code&gt;: This line builds the application using the &lt;code&gt;npm run build&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FROM nginx:1.27.0-alpine3.19-slim&lt;/code&gt;: This line specifies the base image to use for the final image. We use the &lt;code&gt;nginx:1.27.0-alpine3.19-slim&lt;/code&gt; image, which is a lightweight version of Nginx.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WORKDIR /etc/nginx/conf.d&lt;/code&gt;: This line sets the working directory to the Nginx configuration directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY --from=builder /home/node/app/build /home/node/app&lt;/code&gt;: This line copies the static files generated by the build stage into the Nginx configuration directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY ./server.nginx ./default.conf&lt;/code&gt;: This line copies the &lt;code&gt;server.nginx&lt;/code&gt; file into the Nginx configuration directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This Dockerfile creates a multi-stage build that first builds the application using Node.js and then copies the static files into an Nginx image. This approach reduces the size of the final image and improves performance by separating the build dependencies from the runtime dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building and Running the Docker Image Locally
&lt;/h3&gt;

&lt;p&gt;Before deploying your application to your server, you should test the Docker image locally to ensure that it works as expected. You can build and run the Docker image on your local machine using the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-image &lt;span class="nb"&gt;.&lt;/span&gt;
docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 my-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;docker build&lt;/code&gt; command builds the Docker image using the &lt;code&gt;Dockerfile&lt;/code&gt; in the current directory and tags it with the name &lt;code&gt;my-image&lt;/code&gt;. The &lt;code&gt;docker run&lt;/code&gt; command runs the Docker image on port 8080, mapping it to port 80 inside the container. You can access the application by opening a web browser and navigating to &lt;code&gt;http://localhost:8080&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If everything works as expected, you should see a production version of your docusaurus website running in the browser. You can now proceed to deploy your application to your server using GitHub Actions and Nanocl.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Nanocl
&lt;/h2&gt;

&lt;p&gt;Nanocl is a powerful tool that simplifies the deployment process by providing a unified interface for managing your infrastructure. You can use Nanocl to deploy your applications to your server with minimal effort. In this guide, we will show you how to set up Nanocl on your server and deploy your application using a simple configuration file.&lt;/p&gt;

&lt;p&gt;First, you need to install Nanocl on your server. You can find the installation instructions &lt;a href="https://docs.next-hat.com/manuals/nanocl/install/overview" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Once you have installed Nanocl, you can create a configuration file for your application. This file will contain the settings for your application, such as the image name, port number, and environment variables.&lt;/p&gt;

&lt;p&gt;By default once installed Nanocl is only accessible via &lt;code&gt;/run/nanocl/nanocl.sock&lt;/code&gt;. You can use a proxy rule to expose it to the public internet, however, exposing it to the public without a self signed SSL/TLS certificate is not recommended.&lt;br&gt;
It could allow an attacker to take control of your server.&lt;br&gt;
Hopefully, we have a pre-configured rule that you can apply to expose the Nanocl Daemon.&lt;/p&gt;

&lt;p&gt;On your dedicated server or VPS, run the following command to apply the rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nanocl state apply &lt;span class="nt"&gt;-fs&lt;/span&gt; https://nr.next-hat.com/v0.16/sys/enable-remote-nanocld.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will expose the Nanocl Daemon to the public internet with a self signed SSL/TLS certificate on the port 9943.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Github Secrets
&lt;/h2&gt;

&lt;p&gt;GitHub Secrets allow you to securely store and use sensitive information in your GitHub repository. You can use GitHub Secrets to store your server credentials, API keys, and other sensitive information needed to deploy your application. In this guide, we will use GitHub Secrets to store the credentials needed to deploy your application to your server using Nanocl.&lt;/p&gt;

&lt;p&gt;To get started, go to your GitHub repository and click on the &lt;code&gt;Settings&lt;/code&gt; tab. Then, click on the &lt;code&gt;Secrets and variables&lt;/code&gt; link in the left sidebar. Click on the &lt;code&gt;Actions&lt;/code&gt; link.&lt;br&gt;&lt;br&gt;
You should see a page like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzmrsfc58qmuih86sv3sb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzmrsfc58qmuih86sv3sb.png" alt="github-secrets" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the &lt;code&gt;New repository secret&lt;/code&gt; button to create a new secret. You can create a secret for each of the following values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NANOCL_HOST&lt;/code&gt;: The hostname or IP address of your server with the 9943 port. Example: &lt;code&gt;https://example.com:9943&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NANOCL_CERT&lt;/code&gt;: The content of the self signed SSL/TLS certificate used to secure the connection to the Nanocl Daemon.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NANOCL_CERT_KEY&lt;/code&gt;: The content of the private key used to secure the connection to the Nanocl Daemon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the content of the certificate and private key by running the following commands on your server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nanocl secret inspect cert.client.nanocl.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will output the content of the certificate and private key. You can copy and paste the content into the GitHub Secrets page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Statefile Configuration
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://docs.next-hat.com/references/nanocl/statefile" rel="noopener noreferrer"&gt;Statefile&lt;/a&gt; is a configuration file that contains the settings for your application. It specifies the image name, port number, and environment variables needed to deploy your application. You can create a Statefile for your application and use it to deploy your application to your server using Nanocl.&lt;br&gt;
This is the &lt;a href="https://docs.next-hat.com/references/nanocl/statefile" rel="noopener noreferrer"&gt;Statefile&lt;/a&gt; i use for the deployment of the next-hat documentation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;ApiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v0.16&lt;/span&gt;

&lt;span class="na"&gt;Args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;version&lt;/span&gt;
  &lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;String&lt;/span&gt;

&lt;span class="na"&gt;Cargoes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nh-doc&lt;/span&gt;
  &lt;span class="na"&gt;Container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/next-hat/documentation:${{ Args.version }}&lt;/span&gt;

&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http.docs.next-hat.com&lt;/span&gt;
  &lt;span class="na"&gt;Kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ncproxy.io/rule&lt;/span&gt;
  &lt;span class="na"&gt;Data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docs.next-hat.com&lt;/span&gt;
      &lt;span class="na"&gt;Network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Public&lt;/span&gt;
      &lt;span class="c1"&gt;# Secret created for the certbot job below&lt;/span&gt;
      &lt;span class="c1"&gt;# You can remove this line if you don't want https&lt;/span&gt;
      &lt;span class="na"&gt;Ssl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cert.docs.next-hat.com&lt;/span&gt;
      &lt;span class="na"&gt;Locations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
        &lt;span class="na"&gt;Target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nh-doc.global.c&lt;/span&gt;
          &lt;span class="na"&gt;Port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docs.next-hat.com&lt;/span&gt;
      &lt;span class="na"&gt;Network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Public&lt;/span&gt;
      &lt;span class="na"&gt;Locations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
        &lt;span class="na"&gt;Target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;Url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://docs.next-hat.com&lt;/span&gt;
          &lt;span class="na"&gt;Redirect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Temporary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;a href="https://docs.next-hat.com/references/nanocl/statefile" rel="noopener noreferrer"&gt;Statefile&lt;/a&gt; must be placed in the root of your project directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up GitHub Actions
&lt;/h2&gt;

&lt;p&gt;GitHub Actions allow you to automate your workflow directly from your GitHub repository. You can create custom workflows that run on specific events, such as pushing code to your repository or creating a pull request. In this guide, we will create a workflow that builds and deploys your application to your server using Nanocl.&lt;br&gt;
You can find the full source code &lt;a href="https://github.com/next-hat/documentation" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Building and Publishing the Docker Image
&lt;/h3&gt;

&lt;p&gt;To get started, create a new file in your repository called &lt;code&gt;.github/workflows/build-and-publish.yml&lt;/code&gt;. This file will contain the configuration for your GitHub Actions workflow. And will be used to build your docker image and publish it to github container registry. Only when we are merging to master branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and publish docker image&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and publish docker image&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Docker Buildx&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Log in to GitHub Container Registry&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.repository_owner }}&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Extract version from package.json&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;extract_version&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;version=$(jq -r '.version' package.json)&lt;/span&gt;
          &lt;span class="s"&gt;echo "PACKAGE_VERSION=$version" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check if version already exists&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;check_version&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;VERSION=${{ env.PACKAGE_VERSION }}&lt;/span&gt;
          &lt;span class="s"&gt;IMAGE_NAME=ghcr.io/${{ github.repository_owner }}/my-image&lt;/span&gt;
          &lt;span class="s"&gt;if docker manifest inspect $IMAGE_NAME:$VERSION &amp;gt; /dev/null 2&amp;gt;&amp;amp;1; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "Version $VERSION already exists."&lt;/span&gt;
            &lt;span class="s"&gt;exit 1&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and push Docker image&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
          &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;ghcr.io/${{ github.repository_owner }}/documentation:latest&lt;/span&gt;
            &lt;span class="s"&gt;ghcr.io/${{ github.repository_owner }}/documentation:${{ env.PACKAGE_VERSION }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow will run every time you merge code in the master branch of your repository. It will build a docker image from your code, tag it with the latest version from your &lt;code&gt;package.json&lt;/code&gt; file, and push it to the GitHub Container Registry. You can replace &lt;code&gt;documentation&lt;/code&gt; with your image name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying the Application with Nanocl
&lt;/h3&gt;

&lt;p&gt;Next, create a new file in your repository called &lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt;. This file will contain the configuration for your GitHub Actions workflow. And will be used to deploy your application to your server using Nanocl.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;publish&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Docker&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;image"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;completed&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install nanocl cli&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;wget https://github.com/next-hat/nanocl/releases/download/nanocl-0.16.2/nanocl_0.16.2_amd64.deb&lt;/span&gt;
        &lt;span class="s"&gt;sudo dpkg -i nanocl_0.16.2_amd64.deb&lt;/span&gt;
        &lt;span class="s"&gt;rm nanocl_0.16.2_amd64.deb&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to production&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;VERSION=$(jq -r '.version' package.json)&lt;/span&gt;
        &lt;span class="s"&gt;nanocl version&lt;/span&gt;
        &lt;span class="s"&gt;echo $VERSION&lt;/span&gt;
        &lt;span class="s"&gt;nanocl state apply -ys Statefile.yml -- --version $VERSION&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NANOCL_HOST }}&lt;/span&gt;
        &lt;span class="na"&gt;CERT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NANOCL_CERT }}&lt;/span&gt;
        &lt;span class="na"&gt;CERT_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NANOCL_CERT_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow will run every time the &lt;code&gt;Build and publish Docker image&lt;/code&gt; workflow is completed. It will deploy your application to your server using Nanocl. You can replace &lt;code&gt;Statefile.yml&lt;/code&gt; with the path to your &lt;a href="https://docs.next-hat.com/references/nanocl/statefile" rel="noopener noreferrer"&gt;Statefile&lt;/a&gt; configuration file if you have a different name of path.&lt;/p&gt;

&lt;p&gt;Now you have set up your CI/CD pipeline with GitHub Actions and Nanocl. Every time you push code to your repository, GitHub Actions will build and publish your Docker image to the GitHub Container Registry. Once the image is published, it will trigger the deployment workflow, which will deploy your application to your server using Nanocl.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable public SSL/TLS with Let's Encrypt
&lt;/h2&gt;

&lt;p&gt;Additionally you can enable public SSL/TLS with Let's Encrypt. You can use the following command to enable public SSL/TLS with Let's Encrypt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nanocl state apply &lt;span class="nt"&gt;-fs&lt;/span&gt; https://nr.next-hat.com/v0.16/sys/certbot.yml &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--email&lt;/span&gt; contact@next-hat.com &lt;span class="nt"&gt;--domain&lt;/span&gt; docs.next-hat.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By following the steps outlined in this guide, you can automate the deployment of your applications to your server with minimal effort and zero downtime. This will help you deliver high-quality software quickly and efficiently, making it easier to manage your infrastructure and deploy your applications with confidence.&lt;/p&gt;

&lt;p&gt;Now that you know how to automate your deployment with GitHub Actions and Nanocl, why not give it a try with your own project? Let us know how it goes or if you have any questions!&lt;/p&gt;

&lt;p&gt;You can join my &lt;a href="https://discord.gg/WV4Aac8uZg" rel="noopener noreferrer"&gt;discord server&lt;/a&gt; if you have any questions or need help with setting up your CI/CD pipeline with GitHub Actions and Nanocl. I'm here to help you succeed in your software development journey.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>devops</category>
    </item>
    <item>
      <title>Solving the Localhost Development Headache with Nanocl</title>
      <dc:creator>leone</dc:creator>
      <pubDate>Thu, 09 May 2024 15:38:42 +0000</pubDate>
      <link>https://dev.to/leone/solving-the-localhost-development-headache-with-nanocl-41ak</link>
      <guid>https://dev.to/leone/solving-the-localhost-development-headache-with-nanocl-41ak</guid>
      <description>&lt;p&gt;Developers often face significant challenges when working on projects locally, especially when it comes to managing multiple services, dealing with CORS and cookies, and ensuring that the development environment mirrors production. However, there's a promising solution on the horizon: &lt;a href="https://next-hat.com/nanocl" rel="noopener noreferrer"&gt;Nanocl&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Nanocl
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://next-hat.com/nanocl" rel="noopener noreferrer"&gt;Nanocl&lt;/a&gt; is a powerful tool designed to streamline project deployment and alleviate the pains associated with localhost development. By seamlessly integrating with your development workflow, Nanocl simplifies the process of running multiple services locally and eliminates common headaches like CORS issues, port conflicts and cookies.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem at Hand
&lt;/h2&gt;

&lt;p&gt;Consider a scenario where you're working on a project consisting of various components—an API, a dashboard, and a login page. Traditionally, you would need to run each of these components on different ports, leading to cumbersome setups and potential conflicts. Additionally, issues like CORS and cookies become apparent, especially when these services aren't bound to a specific domain. Managing these challenges manually can be time-consuming and error-prone, detracting from your productivity and focus on actual development tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Nanocl Comes to the Rescue
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://next-hat.com/nanocl" rel="noopener noreferrer"&gt;Nanocl&lt;/a&gt; provides a comprehensive solution to the localhost development headache. By leveraging its powerful features, developers can streamline their workflow and focus on building great software without getting bogged down by infrastructure complexities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Seamless Integration
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://next-hat.com/nanocl" rel="noopener noreferrer"&gt;Nanocl&lt;/a&gt; seamlessly integrates with your existing development environment, allowing you to deploy your project with a single command. Gone are the days of juggling multiple terminals and wrestling with configuration files—Nanocl handles it all for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain Resolution
&lt;/h3&gt;

&lt;p&gt;One of Nanocl's standout features is its ability to create domains for your local machine, bringing your development environment closer to production. With Nanocl, you can access your services using intuitive domain names like api.dev.internal, console.dev.internal, and auth.dev.internal, making testing and debugging a breeze.&lt;/p&gt;

&lt;h3&gt;
  
  
  Realistic Testing Environment
&lt;/h3&gt;

&lt;p&gt;By replicating the production setup locally, Nanocl enables developers to test their projects in a more realistic environment. This ensures smoother transitions from development to production and reduces the likelihood of encountering unforeseen issues down the line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Nanocl
&lt;/h2&gt;

&lt;p&gt;Ready to kiss localhost headaches goodbye? Here's how to get started with Nanocl:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;: Refer to the &lt;a href="https://docs.next-hat.com/manuals/nanocl/install/overview" rel="noopener noreferrer"&gt;Nanocl documentation&lt;/a&gt; for detailed instructions on installing Nanocl on your machine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Clone the Example Repository&lt;/strong&gt;: Once Nanocl is installed, clone the example repository provided to see Nanocl in action.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/leon3s/solving-localhost-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Run the Project&lt;/strong&gt;: Navigate to the cloned repository and run the project using Nanocl.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;solving-localhost-dev
nanocl state apply &lt;span class="nt"&gt;-fs&lt;/span&gt; Statefile.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Update &lt;code&gt;/etc/resolve.conf&lt;/code&gt;&lt;/strong&gt;: Retrieve the IP address of the DNS server by running the following command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nanocl namespace &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The output will display the IP address of the DNS server, which you'll need to add to your &lt;code&gt;/etc/resolve.conf&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;NAME      CARGOES    INSTANCES    GATEWAY     CREATED AT
system    7          7            10.1.0.1    2024-05-09 15:52:27
global    4          4            10.2.0.1    2024-05-09 15:52:27
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Update your &lt;code&gt;/etc/resolve.conf&lt;/code&gt; file with the IP address of the gateway:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nameserver &amp;lt;global-namespace-gateway-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access Your Domains&lt;/strong&gt;: Once the setup is complete, you can access your services using the designated domains (api.dev.internal, console.dev.internal, auth.dev.internal). Enjoy a headache-free development experience!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Nanocl will parse the Statefile.yml to know the current state of the services. It will then create the necessary namespaces, cargoes, and instances to run the services. The services will be available at the domains specified in the Statefile.yml.&lt;/p&gt;

&lt;p&gt;With a combinaison of a DNS server and a reverse proxy, Nanocl will resolve the domains to the correct services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplified Development Workflow&lt;/strong&gt;: Nanocl streamlines the process of running multiple services locally, enabling developers to focus on building great software.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Domain Resolution&lt;/strong&gt;: Nanocl help you to setup intuitive domains for your services, making it easier to test and debug your projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Realistic Testing Environment&lt;/strong&gt;: By mirroring the production setup locally, Nanocl helps developers identify and resolve issues early on, leading to smoother deployments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seamless Integration&lt;/strong&gt;: Nanocl seamlessly integrates with your existing development environment, eliminating the need for manual configurations and complex setups.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With Nanocl, localhost development doesn't have to be a headache anymore. By providing a seamless solution to common challenges, Nanocl empowers developers to focus on what they do best—building innovative software. Say goodbye to CORS woes, port conflicts and cookies problems, and hello to a smoother, more efficient development workflow. Give Nanocl a try today and unlock a world of possibilities for your projects. Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
