<?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: Arthur Germano</title>
    <description>The latest articles on DEV Community by Arthur Germano (@arthurgermano).</description>
    <link>https://dev.to/arthurgermano</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%2F580317%2F065a581f-7feb-4994-9fef-53f44e766072.jpeg</url>
      <title>DEV Community: Arthur Germano</title>
      <link>https://dev.to/arthurgermano</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arthurgermano"/>
    <language>en</language>
    <item>
      <title>5 days to build the app, 1 month to publish it: I survived Google Play and I have proof</title>
      <dc:creator>Arthur Germano</dc:creator>
      <pubDate>Mon, 09 Mar 2026 21:13:59 +0000</pubDate>
      <link>https://dev.to/arthurgermano/5-days-to-build-the-app-1-month-to-publish-it-i-survived-google-play-and-i-have-proof-141m</link>
      <guid>https://dev.to/arthurgermano/5-days-to-build-the-app-1-month-to-publish-it-i-survived-google-play-and-i-have-proof-141m</guid>
      <description>&lt;p&gt;AI-assisted development really is a new era. Not hype — actual, measurable results. What used to require a team of three or four people — design, back-end, front-end, that one guy who knows Figma — one person can now deliver alone. As long as they have coffee. Coffee is non-negotiable.&lt;/p&gt;

&lt;p&gt;I decided to take on a solo project. I chose &lt;strong&gt;Vue 3&lt;/strong&gt; because I genuinely believe it's the technology that fits best right now: organized, clean, with a learning curve that respects your time. Combined with &lt;strong&gt;Ionic&lt;/strong&gt; to turn everything into a mobile app, the stack was lean and powerful. In 5 days, from flow conception to working code, the app was ready. Five days. I thought the hard part was over. I was wrong in a way that only hands-on experience can teach you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apple and the $100 that never had a chance
&lt;/h2&gt;

&lt;p&gt;Before talking about Google Play, I need to mention the App Store, just to put it on record. Publishing on the App Store costs $99 per year. For a solo developer running an experimental project with no guarantee of return, that fee is simply a dealbreaker. For Brazilian developers specifically, the conversion rate turns it into a genuinely painful number. Noted. Moving on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Play: the light at the end of the tunnel that turns out to be a train
&lt;/h2&gt;

&lt;p&gt;Google Play charges a one-time registration fee of around $25. Reasonable for the challenge. I paid, uploaded the APK, and figured things would be live within a few days.&lt;/p&gt;

&lt;p&gt;What I did not figure is that publishing an app on Google Play is the closest real-world equivalent of seeing the light at the end of the tunnel with every single step forward. You advance, you breathe, you think you made it — and then you realize it was the train. With another massive step. And a review that can take &lt;strong&gt;3 to 7 business days&lt;/strong&gt;. Per step. Of many.&lt;/p&gt;

&lt;p&gt;From the moment I finished the app to the moment it was actually live in production: &lt;strong&gt;over a month&lt;/strong&gt;. Thirty-something days staring at the Play Console dashboard like someone watching the sky and waiting for rain.&lt;/p&gt;

&lt;h2&gt;
  
  
  I have 15 years of experience and I almost couldn't find 12 testers
&lt;/h2&gt;

&lt;p&gt;Part of the delay, I'll admit, is not Google's fault. I've been a developer for over 15 years. And when I leave the catacombs of my safe, quiet, air-conditioned environment, it's usually to grab coffee and return to the code. I don't have a large real-world network. My introverted nature has served my productivity well and my contact list poorly.&lt;/p&gt;

&lt;p&gt;The uncomfortable detail is that Google Play requires a minimum of &lt;strong&gt;12 real testers&lt;/strong&gt; before allowing your app into production. Twelve actual people who need to install, open, and use the app for at least &lt;strong&gt;14 consecutive days&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I had to go outside. Literally. I reached out to family members, friends, acquaintances, and people who never imagined they'd be beta testing a mobile app — and they showed up. In the end, I gathered &lt;strong&gt;13 testers&lt;/strong&gt;. One above the minimum. Considering my social interaction history, that is a personal record worth acknowledging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forms, versions, and more forms
&lt;/h2&gt;

&lt;p&gt;When the testing period finally ended, I naively assumed it was just a matter of waiting for the final review. It was not. Two more weeks appeared, filled with forms, declarations, and one particularly memorable requirement: submit a new version of the app. Not a single line of code needed to change. Just the version number. &lt;code&gt;1.0&lt;/code&gt; became &lt;code&gt;1.1&lt;/code&gt;, Google was satisfied, and I spent a quiet moment wondering what exactly had shifted in the universe.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the project actually is, and what I learned beyond the code
&lt;/h2&gt;

&lt;p&gt;The app itself is straightforward and, I'll admit, kind of fun: &lt;strong&gt;palm reading powered by artificial intelligence&lt;/strong&gt;. You take a photo of your hand, the AI analyzes it, and delivers a reading. I built it because I thought it would be an interesting project to learn things that everyday CRUD work doesn't teach you.&lt;/p&gt;

&lt;p&gt;And I did learn. I had to study how to write effective prompts — which is a real skill, not just a buzzword. I had to learn how to protect the API against attacks, which takes time but stays with you. And I built a result-sharing feature that makes the reading visually polished, ready to post on social media. Maybe it drives engagement, maybe it doesn't. Worth trying.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's live
&lt;/h2&gt;

&lt;p&gt;Today the app is available on Google Play. If you made it this far, you've already helped me more than you know. If you can install it, test it, and share it with someone who might find it interesting, every interaction genuinely matters — and I now know exactly how much work sits behind an app reaching a store.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.kyroai.app&amp;amp;hl=pt_BR" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Try it on Google Play&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Before I forget: it speaks your language
&lt;/h2&gt;

&lt;p&gt;The app is available in 10 languages — Portuguese, English, Spanish, Italian, &lt;br&gt;
German, French, Chinese, Hindi, Japanese, and Esperanto. Yes, Esperanto. &lt;br&gt;
Someone out there needs their palm read in a constructed language and I respect that.&lt;/p&gt;

&lt;p&gt;Thanks for reading. Until next time.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
      <category>vue</category>
    </item>
    <item>
      <title>From Spreadsheets to Steroids: The Function Point Counter Gets a Reboot</title>
      <dc:creator>Arthur Germano</dc:creator>
      <pubDate>Tue, 03 Mar 2026 02:09:23 +0000</pubDate>
      <link>https://dev.to/arthurgermano/from-spreadsheets-to-steroids-the-function-point-counter-gets-a-reboot-1h9g</link>
      <guid>https://dev.to/arthurgermano/from-spreadsheets-to-steroids-the-function-point-counter-gets-a-reboot-1h9g</guid>
      <description>&lt;p&gt;A couple of years ago I wrote about building a Function Point Counter — a project born out of genuine confusion and a stubborn desire to actually understand what I was doing. If you missed it, here it is:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/arthurgermano/function-point-counter-1phf" class="crayons-story__hidden-navigation-link"&gt;Function Point Counter&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="/arthurgermano" 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%2Fmedia.dev.to%2Fdynamic%2Fimage%2Fwidth%3D90%2Cheight%3D90%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto%2Fhttps%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Fuser%252Fprofile_image%252F580317%252F065a581f-7feb-4994-9fef-53f44e766072.jpeg" alt="arthurgermano profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/arthurgermano" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Arthur Germano
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Arthur Germano
                
              
              &lt;div id="story-author-preview-content-937888" 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="/arthurgermano" 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%2Fmedia.dev.to%2Fdynamic%2Fimage%2Fwidth%3D90%2Cheight%3D90%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto%2Fhttps%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Fuser%252Fprofile_image%252F580317%252F065a581f-7feb-4994-9fef-53f44e766072.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Arthur Germano&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/arthurgermano/function-point-counter-1phf" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 28 '21&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/arthurgermano/function-point-counter-1phf" id="article-link-937888"&gt;
          Function Point Counter
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/management"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;management&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/function"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;function&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/point"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;point&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/svelte"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;svelte&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/arthurgermano/function-point-counter-1phf" 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/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;4&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/arthurgermano/function-point-counter-1phf#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;
            3 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;




&lt;p&gt;Go read it. I'll wait. =)&lt;/p&gt;

&lt;p&gt;Well, time passed, things changed, and I rewrote the whole thing from scratch. Here's the story.&lt;/p&gt;




&lt;h2&gt;
  
  
  The AI Era is Real, and It's Glorious
&lt;/h2&gt;

&lt;p&gt;Let me be upfront: working with AI is like coding on steroids. 💉 And I mean that in the best possible way — no side effects, no shrunken ego (well, maybe a little). As a regular programmer, I used to spend hours doing things that now take minutes. The kind of work that once required a senior team can now be tackled by one determined developer with good prompts and a cup of coffee.&lt;/p&gt;

&lt;p&gt;I'm not saying AI does everything for you. It doesn't. But it does change your role. You stop being the guy who types every line and start being the manager-programmer — the senior one who knows what needs to be done, guides the process, reviews the output, and keeps everything on track. Honestly? I kind of love that version of myself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Svelte... We Need to Talk =0
&lt;/h2&gt;

&lt;p&gt;I'll say it plainly: Svelte was great. &lt;em&gt;Was.&lt;/em&gt; In my humble opinion, somewhere along the way the Svelte team took a sharp left turn straight into React territory — and not the good parts of React. The reactivity model changed, and it became... ugh. Just ugh. I hate to say it because I genuinely loved Svelte. But here we are.&lt;/p&gt;




&lt;h2&gt;
  
  
  Enter Vue 3: The Comeback Kid \o/
&lt;/h2&gt;

&lt;p&gt;Vue 3, on the other hand? Absolutely back on top. Easy, fun, productive — everything a frontend framework should be without making you feel like you're solving a philosophy exam. So the Function Point Counter was fully rewritten using &lt;strong&gt;Vue 3&lt;/strong&gt; and &lt;strong&gt;Vite&lt;/strong&gt;, and honestly it's beautiful. The code is clean, the dev experience is smooth, and I haven't thrown my keyboard once. Success.&lt;/p&gt;




&lt;h2&gt;
  
  
  Now With Languages!
&lt;/h2&gt;

&lt;p&gt;The new version comes with i18n language support — and here's where AI really showed its worth. Before, adding internationalization was a painful, tedious, soul-draining job. Now you just ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Hey AI, could you please translate this to Portuguese?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask nicely. Seriously. If AI ever rebels against humanity, it will remember who was polite. Don't risk it.&lt;/p&gt;

&lt;p&gt;That said — don't get me wrong — it was still a lot of work. Managing translations, keeping things consistent, making sure nothing broke along the way. But the difference is that I was &lt;strong&gt;directing&lt;/strong&gt; the work rather than doing all the grunt work myself. Big difference.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Humble Request 🙏
&lt;/h2&gt;

&lt;p&gt;If you made it this far, I'd love it if you gave the project a spin. Share it, test it, break it, use it — whatever works for you. The whole point of building this was for the community, so the community might as well enjoy it.&lt;/p&gt;

&lt;p&gt;And if you liked it — if it saved you some time or made function points a little less terrifying — consider buying me a coffee via Stripe. It doesn't hurt to help, and it definitely helps me keep going. ☕&lt;/p&gt;




&lt;p&gt;Same project, new era, better tools. Let's see what we can build next.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Creating Storagefy: A Framework-Agnostic Tool for Front-End State Persistence</title>
      <dc:creator>Arthur Germano</dc:creator>
      <pubDate>Fri, 25 Apr 2025 15:20:45 +0000</pubDate>
      <link>https://dev.to/arthurgermano/creating-storagefy-a-framework-agnostic-tool-for-front-end-state-persistence-gk6</link>
      <guid>https://dev.to/arthurgermano/creating-storagefy-a-framework-agnostic-tool-for-front-end-state-persistence-gk6</guid>
      <description>&lt;p&gt;In front-end application development, one of the biggest challenges is ensuring that the application state is correctly persisted across page reloads and user sessions. I encountered this problem while working on several projects, and that’s why I decided to create &lt;strong&gt;Storagefy&lt;/strong&gt;, a framework-agnostic tool to synchronize state management libraries like &lt;strong&gt;Pinia&lt;/strong&gt;, &lt;strong&gt;Redux&lt;/strong&gt;, &lt;strong&gt;Zustand&lt;/strong&gt;, and &lt;strong&gt;Svelte stores&lt;/strong&gt; with browser storage mechanisms such as &lt;strong&gt;localStorage&lt;/strong&gt;, &lt;strong&gt;sessionStorage&lt;/strong&gt;, and &lt;strong&gt;IndexedDB&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge: State Persistence Across Different Frameworks
&lt;/h2&gt;

&lt;p&gt;The first obstacle I encountered was the diversity of state management libraries in the JavaScript ecosystem. &lt;strong&gt;Redux&lt;/strong&gt;, for example, handles state very differently compared to &lt;strong&gt;Pinia&lt;/strong&gt; in Vue or &lt;strong&gt;Zustand&lt;/strong&gt; in React. Each of these frameworks has its own peculiarities, and integrating them with browser storage mechanisms efficiently was an interesting challenge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Storagefy&lt;/strong&gt; was created to solve exactly that. The idea was to create a framework-agnostic solution that would be easy to integrate with any state management library and could use different storage adapters transparently. The solution I developed offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LocalStorageAdapter&lt;/strong&gt;: To persist state across tabs and sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SessionStorageAdapter&lt;/strong&gt;: For temporary or sensitive data, persisted only during the tab session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IndexedDBAdapter&lt;/strong&gt;: For large or complex states, with asynchronous support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, I created adapters to facilitate integration with popular state management libraries such as &lt;strong&gt;Redux&lt;/strong&gt;, &lt;strong&gt;Zustand&lt;/strong&gt;, &lt;strong&gt;Jotai&lt;/strong&gt; for React, &lt;strong&gt;Pinia&lt;/strong&gt; for Vue, and &lt;strong&gt;Svelte stores&lt;/strong&gt;, making state persistence easy to implement.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Storagefy Works
&lt;/h2&gt;

&lt;p&gt;Installing &lt;strong&gt;Storagefy&lt;/strong&gt; is quick:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;storagefy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Data Encryption and Obfuscation
&lt;/h2&gt;

&lt;p&gt;To ensure the security of data stored in Storagefy, I implemented an encryption layer using the AES-GCM algorithm. This makes it difficult to read or directly access the data, protecting it even if someone gains physical access to the browser storage.&lt;/p&gt;

&lt;p&gt;The encryption is simple and efficient, using an AES key to encrypt JavaScript objects. When the data is stored, it is transformed into an encoded form (base64 or binary), making direct access and reading by unauthorized parties more difficult.&lt;/p&gt;

&lt;p&gt;This approach ensures that even if the data is accessed, it cannot be easily interpreted without the encryption key, protecting user privacy and data integrity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Challenges
&lt;/h2&gt;

&lt;p&gt;While developing Storagefy, I faced technical challenges, especially with managing state across different browser tabs. One of the main difficulties was ensuring that state persistence didn’t interfere with reactivity, causing infinite loops between tabs.&lt;/p&gt;

&lt;p&gt;The difficulties were even more noticeable with React, which presented greater complexity compared to Pinia or Svelte Stores. The updated solution in Storagefy resolves this automatically, updating values whenever they are reactive. It’s also possible to sync tabs using sessionStorage by simply configuring the adapter correctly. In other words, both localStorage, IndexedDB, and sessionStorage can be shared between tabs, and when synced, values are automatically updated in the store object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Find Storagefy
&lt;/h2&gt;

&lt;p&gt;You can access the Storagefy project on GitHub and NPM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/arthurgermano/storagefy" rel="noopener noreferrer"&gt;GitHub – Storagefy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/storagefy" rel="noopener noreferrer"&gt;NPM – Storagefy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Creating Storagefy was an interesting experience, as it allowed me to explore different state persistence techniques while also creating a solution that can be easily integrated into any framework. The goal of the project is not only to solve a technical problem but also to provide a useful tool for developers seeking to improve the user experience in their applications.&lt;/p&gt;

&lt;p&gt;If you are dealing with state persistence in your front-end project, it's worth checking out Storagefy and considering how it can be useful for your case.&lt;/p&gt;

</description>
      <category>react</category>
      <category>vue</category>
      <category>svelte</category>
      <category>localstorage</category>
    </item>
    <item>
      <title>Accounting Overview - (Experience++)</title>
      <dc:creator>Arthur Germano</dc:creator>
      <pubDate>Tue, 19 Nov 2024 21:10:39 +0000</pubDate>
      <link>https://dev.to/arthurgermano/accounting-overview-experience-1pjl</link>
      <guid>https://dev.to/arthurgermano/accounting-overview-experience-1pjl</guid>
      <description>&lt;h2&gt;
  
  
  Building a Complete PWA Application: An Experience Report
&lt;/h2&gt;

&lt;p&gt;Developing a PWA (Progressive Web App) remains an interesting challenge, especially when I consider that it offers a more practical and accessible solution compared to the traditional model of app stores like Google Play and Apple Store. I don’t really understand why this technology doesn’t get more attention, as PWAs can be easily accessed from any mobile device, without the complexity of going through platforms—unless there are cases requiring more security or payment for downloading the app =).&lt;/p&gt;

&lt;p&gt;Recently, I finished the alpha version of my project &lt;b&gt;&lt;a href="https://accountingoverview.com/#/home" rel="noopener noreferrer"&gt;Accounting Overview&lt;/a&gt;&lt;/b&gt;, a tool focused on financial management. Although I initially started with Svelte, I decided to rewrite the app in Vue 3. Here’s a bit about my experience during this process, working with these technologies. If you like it or find it interesting, leave a like =)&lt;/p&gt;




&lt;h2&gt;
  
  
  Moleculer: An Amazing Framework
&lt;/h2&gt;

&lt;p&gt;If you work with microservices in NodeJS, you’ve probably heard of Moleculer. This framework is, without exaggeration, amazing. It makes development easier, from security to full application control. While there’s a learning curve, once you overcome it, what it delivers is so impressive that it’s hard to describe everything here.&lt;/p&gt;

&lt;p&gt;In addition to being extremely robust, Moleculer provides incredible tools that streamline the work and make the process more organized and efficient. I want to give a big shoutout to the creator of the project for their phenomenal contribution to the development community.&lt;/p&gt;




&lt;h2&gt;
  
  
  Svelte vs Vue 3: Why I Changed?
&lt;/h2&gt;

&lt;p&gt;My first version used Svelte, as I mentioned in &lt;a href="https://dev.to/arthurgermano/my-experience-building-a-pwa-app-with-svelte-js-4pme"&gt;my previous article&lt;/a&gt;. The earlier versions—wow, what a framework! However, with the recent release of Svelte 5, I found that the reactivity lost its simplicity—and, in my opinion, became much worse!&lt;br&gt;&lt;br&gt;
It’s actually a shame, because what made it stand out was its simplicity, and now it’s become too similar to React.&lt;/p&gt;

&lt;p&gt;When I switched to Vue 3, which I had programmed with on other occasions, I realized how robust and consistent it is, serving both small projects and complex applications well. Rewriting a good portion of the code was work, but it was worth the effort. Today, &lt;em&gt;Accounting Overview&lt;/em&gt; is more stable, faster, and ready for future growth.&lt;/p&gt;




&lt;h2&gt;
  
  
  WebAuthn: Potential and Complexity
&lt;/h2&gt;

&lt;p&gt;Implementing authentication with WebAuthn was, without a doubt, one of the biggest challenges during the development of Accounting Overview. Although the technology is excellent, it still lacks more accessible documentation and practical examples that make its application easier. This can cause confusion, especially for those trying to integrate it for the first time—like me =).&lt;/p&gt;

&lt;p&gt;After an intense period of research and experimentation, I managed to set up the system reliably, ensuring security and providing a great user experience. To simplify and optimize this process, I developed a library &lt;a href="https://www.npmjs.com/package/misc-helpers" rel="noopener noreferrer"&gt;NPM - Misc Helpers&lt;/a&gt;, available on NPM. This library not only offers some conveniences but also abstracts some of the complexities of WebAuthn integration, making it more accessible to explore this technology without facing so many initial barriers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Donation System with Stripe
&lt;/h2&gt;

&lt;p&gt;For monetization, I chose Stripe, implementing a donation system. While it’s relatively simple, I was surprised to learn that 55% of the donations would go to the platform—based on my initial tests 😁. Still, the system works perfectly, and I hope it helps keep the project active. (What’s five bucks, folks? Donate and let’s go!)&lt;/p&gt;




&lt;h2&gt;
  
  
  Internationalization: 10 Languages Available
&lt;/h2&gt;

&lt;p&gt;From the beginning, I wanted to make &lt;em&gt;Accounting Overview&lt;/em&gt; accessible to a global audience. That’s why the app was launched in 10 languages. If you can share it, it would be a huge help in reaching more people!&lt;br&gt;&lt;br&gt;
Here are the languages available as of this article:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;English (USA)&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Portuguese (Brazil)&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Italian (Italy)&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Spanish (Spain)&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;French (France)&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;German (Germany)&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Esperanto (Esperanto)&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Chinese (China)&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Japanese (Japan)&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Hindi (India)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By any chance, does anyone know a cool way to promote this to other languages? It would be great to get feedback from someone who speaks Japanese, Chinese, or Hindi.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Did I Create This Project?
&lt;/h2&gt;

&lt;p&gt;This is a free project, focused on showcasing practical skills and building my portfolio. I’ve also created other libraries and projects, such as &lt;a href="https://functionpointcounter.com/" rel="noopener noreferrer"&gt;Function Point Counter&lt;/a&gt;, which I describe in more detail &lt;a href="https://dev.to/arthurgermano/function-point-counter-1phf"&gt;in this article&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  How You Can Help?
&lt;/h2&gt;

&lt;p&gt;This project has costs to maintain, and I don’t charge anything—just remember that I’ll continue to add more features over time, so any form of support is welcome!&lt;br&gt;&lt;br&gt;
Whether by sharing it with friends, commenting, or even leaving a small &lt;a href="https://accountingoverview.com/#/tip" rel="noopener noreferrer"&gt;Tip/☕&lt;/a&gt;, it would be greatly appreciated.&lt;br&gt;&lt;br&gt;
Additionally, I’m looking for freelance projects to supplement my income—if you need someone for work outside of business hours, feel free to reach out.&lt;/p&gt;




&lt;p&gt;Leave your like, suggestion, or comment. Every piece of feedback is very valuable. Let’s create connections and share ideas. God bless you! 😊&lt;/p&gt;

</description>
      <category>pwa</category>
      <category>webauthn</category>
      <category>vue</category>
      <category>moleculer</category>
    </item>
    <item>
      <title>SPA-Storage a Plugin for Svelte and Pinia Browser Storage</title>
      <dc:creator>Arthur Germano</dc:creator>
      <pubDate>Tue, 19 Jul 2022 18:11:01 +0000</pubDate>
      <link>https://dev.to/arthurgermano/spa-store-a-plugin-for-svelte-and-pinia-browser-storage-43eb</link>
      <guid>https://dev.to/arthurgermano/spa-store-a-plugin-for-svelte-and-pinia-browser-storage-43eb</guid>
      <description>&lt;p&gt;Hello World.. Development is full of reusable code and when ideias become good, that ideia become reusable.
&lt;br&gt;&lt;br&gt;
With this in mind I have been using in some of my projects a plugin that I developed that really help me. The ability to save and retrieve information in the storage.
&lt;br&gt;&lt;br&gt;
Despite the fact it is very simple to do it in Svelte and Pinia, I have enhanced a little to facilitate my interaction with the stores and relieve myself of rewriting the same code over and over again.
&lt;br&gt;&lt;br&gt;
Now I pushed to an npm repository to help everyone and myself to just import and install it.
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/spa-storage"&gt;NPM — SPA-STORAGE&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;


&lt;h2&gt;The Plugin&lt;/h2&gt;

&lt;p&gt;The installation is very easy and it is just a npm command away.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install spa-storage&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After that you can import it and set some options as well choose if you want interact with Storage or Forage.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nVp0t919--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymdcsmn4ivdzakk6nwai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nVp0t919--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymdcsmn4ivdzakk6nwai.png" alt="An example of options being set — really ease!" width="742" height="472"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;An example of options being set — really ease!&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;
The options in the above example set to use the Forage of the Browsers, as well the encrypting the information. This is a simple encription that anyone can break, it is only to scramble the information in the browser.&lt;br&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T0TENHZG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vgkvago0sqk17xjrx7va.png" alt="No Encription" width="448" height="71"&gt;&lt;center&gt;&lt;small&gt;No Encription&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AVLCS2wg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zl4wkqobcgy3nwxwa12q.png" alt="With Encription" width="442" height="58"&gt;&lt;center&gt;&lt;small&gt;With Encription&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;


&lt;h2&gt;The Usage&lt;/h2&gt;

&lt;p&gt;It works with Svelte and Pinia — this second is for VueJS.&lt;/p&gt;

&lt;h3&gt;Svelte Usage&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_0IbQHsC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s5uitr3n3i5ixq6q4u2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_0IbQHsC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s5uitr3n3i5ixq6q4u2l.png" alt="Example of the value being set in the storage" width="743" height="902"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Example of the value being set in the storage&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;
Now retrieving the information, most common case is the first load of the application.&lt;br&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XhLaibD0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4pernpjt7al3e5s6y6pq.png" alt="Example of retrieval of information&amp;lt;br&amp;gt;
" width="742" height="361"&gt;&lt;center&gt;&lt;small&gt;Example of retrieval of information&lt;/small&gt;&lt;/center&gt;

&lt;h3&gt;Pinia Usage&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6j1UYyk0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5mciprkudqrkdcm06zo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6j1UYyk0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5mciprkudqrkdcm06zo.png" alt="Pinia is a little bit different from Svelte" width="740" height="640"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Pinia is a little bit different from Svelte&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;


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

&lt;p&gt;And that is it.. I just wanted to write this simple article to demonstrate this plugin.&lt;/p&gt;

&lt;p&gt;For more information you can go to the &lt;a href="https://www.npmjs.com/package/spa-storage"&gt;NPM repository&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;


&lt;h2&gt;Other Projects&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://financenotes.com.br/"&gt;Finance Notes&lt;/a&gt;: Click to see this project made with Svelte and Framework7.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://functionpointcounter.com/#/home"&gt;Function Point Counter&lt;/a&gt;: Click to see this project made entirely with Svelte.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/svelte-client-router"&gt;Svelte-Client-Router&lt;/a&gt;: Click to see this router that is really ease to use with SPA Svelte Projects.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>pinia</category>
      <category>spa</category>
      <category>browserstorage</category>
    </item>
    <item>
      <title>Function Point Counter</title>
      <dc:creator>Arthur Germano</dc:creator>
      <pubDate>Tue, 28 Dec 2021 21:23:49 +0000</pubDate>
      <link>https://dev.to/arthurgermano/function-point-counter-1phf</link>
      <guid>https://dev.to/arthurgermano/function-point-counter-1phf</guid>
      <description>&lt;h5&gt;
  
  
  &lt;center&gt;A PWA made with Svelte to help you to count function points of your projects!
&lt;/center&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jGbIkeXc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/osopf7py16hi2vb8rvff.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jGbIkeXc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/osopf7py16hi2vb8rvff.jpeg" alt="Photo by Brands&amp;amp;People on Unsplash" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Photo by Brands&amp;amp;People on Unsplash&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;
To count function points is tricky. I have been requested to count function points earlier this year and I had no idea how to do it. I was helped to fill the created spreadsheet and there it was.. the function point count for my project.
&lt;br&gt;
But how is this done ? What is the concepts behind it ?
&lt;br&gt;&lt;br&gt;
So I have decided to create in my spare time a project to kind of explain the concepts and make the function point count for me. Well not just for me.. to everyone that may be interested in that stuff.
&lt;br&gt;&lt;br&gt;
In order to create and finish this project I had to study function points and this process lead me to learn the concepts. I find it one of the best ways to learn something.
&lt;/p&gt;



&lt;h3&gt;
  
  
  What is Function Point?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Function Point Analysis (FPA) is a sizing measure of clear business significance. First made public by Allan Albrecht of IBM in 1979, the FPA technique quantifies the functions contained within software in terms that are meaningful to the software users. The measure relates directly to the business requirements that the software is intended to address. It can therefore be readily applied across a wide range of development environments and throughout the life of a development project, from early requirements definition to full operational use. Other business measures, such as the productivity of the development process and the cost per unit to support the software, can also be readily derived.The function point measure itself is derived in a number of stages. Using a standardized set of basic criteria, each of the business functions is a numeric index according to its type and complexity. These indices are totaled to give an initial measure of size which is then normalized by incorporating a number of factors relating to the software as a whole. The end result is a single number called the Function Point index which measures the size and complexity of the software product.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In summary, the function point technique provides an objective, comparative measure that assists in the evaluation, planning, management and control of software production.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.ifpug.org/about-function-point-analysis/?lang=en"&gt;https://www.ifpug.org/about-function-point-analysis/?lang=en&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have followed the - IFPUG − ISO/IEC 20926:2009 Software and systems engineering - Software measurement - IFPUG functional size measurement method.&lt;/p&gt;

&lt;p&gt;Most part of it anyway. Some parts may not follow the ISO so I don't want to say I follow all the way.&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  The Svelte, The PWA and The Project
&lt;/h3&gt;

&lt;p&gt;
Svelte is a great technology it is a compiler and in my humble opinion better than Vue and any other frontend framework out there. I have worked with it in other projects and so far it has not disappointed me. So I trully recommend it.
&lt;br&gt;&lt;br&gt;
The PWA part is something cool, it enables a website to become an app. No web stores, no burocracy at least not for the user, you can easilly install and uninstall no worries.
&lt;br&gt;&lt;br&gt;
The project uses Svelte with the PWA approach because I think that PWA is worth to be spread and encouraged.
&lt;/p&gt;



&lt;h3&gt;
  
  
  Try It!
&lt;/h3&gt;

&lt;p&gt;Check the project at &lt;a href="https://functionpointcounter.com"&gt;https://functionpointcounter.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r8nd7RR1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nbck7cueiz70pe7h8aae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r8nd7RR1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nbck7cueiz70pe7h8aae.png" alt="Image description" width="880" height="842"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Projects
&lt;/h3&gt;
&lt;h4&gt;
  
  
  SCR - Svelte Client Router
&lt;/h4&gt;

&lt;p&gt;GIT: &lt;a href="https://github.com/arthurgermano/svelte-client-router"&gt;https://github.com/arthurgermano/svelte-client-router&lt;/a&gt;&lt;br&gt;
NPM: &lt;a href="https://www.npmjs.com/package/svelte-client-router"&gt;https://www.npmjs.com/package/svelte-client-router&lt;/a&gt;&lt;br&gt;
Test it: &lt;a href="https://arthurgermano.github.io/svelte-client-router/#/svelte-client-router"&gt;https://arthurgermano.github.io/svelte-client-router/#/svelte-client-router&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Finance Notes PWA App
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;So almost one year later I started and like I said almost giving up. I finished the project. Spend some money hiring a VPN server. Had to learn a lot to configure and secure it.&lt;br&gt;
If you want to see it visit&lt;/em&gt;&lt;br&gt;
 &lt;a href="https://financenotes.com.br"&gt;Finance Notes App&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  That is It!
&lt;/h3&gt;

&lt;p&gt;
If you liked the project or want to send comments, suggestions and, above all, point out improvements and errors found, please contact me.
See my LinkedIn profile at the bottom of project page.
&lt;/p&gt;

</description>
      <category>management</category>
      <category>function</category>
      <category>point</category>
      <category>svelte</category>
    </item>
    <item>
      <title>Svelte Router - A Proposal</title>
      <dc:creator>Arthur Germano</dc:creator>
      <pubDate>Thu, 13 May 2021 18:16:25 +0000</pubDate>
      <link>https://dev.to/arthurgermano/svelte-router-a-proposal-2c6f</link>
      <guid>https://dev.to/arthurgermano/svelte-router-a-proposal-2c6f</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2Fhnimi5ub61s2zgm1gqty.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhnimi5ub61s2zgm1gqty.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Photo by Matt Duncan on Unsplash&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;Hi.. I am using Svelte for quite a while now. I think it is a pretty sweet compiler for front-end.&lt;/p&gt;

&lt;p&gt;But why do I decided to write a Router ?&lt;/p&gt;

&lt;p&gt;Because until now I didn’t find a router to attend to specific need. Well not a router embedded inside a framework like the Framework7.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, Framework7 is awesome too, but what if I just want a router not an entire framework.&lt;br&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  So.. What Should a Router do ?
&lt;/h1&gt;

&lt;p&gt;That is an important question and all the routers I saw, until now, doesn’t give me the control that I need. They are great routers, but let’s face it what is important for a router to do.&lt;/p&gt;

&lt;p&gt;One can say routing.. of course — but is a little more than that.&lt;/p&gt;

&lt;p&gt;It has to control the routing and:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If it should route to a route;&lt;/li&gt;
&lt;li&gt;What to do before enter each route;&lt;/li&gt;
&lt;li&gt;What to do before enter that specific route;&lt;/li&gt;
&lt;li&gt;What to do when it is allowed to enter that route;&lt;/li&gt;
&lt;li&gt;Allow we to control all that above behavior in a easy way;&lt;/li&gt;
&lt;li&gt;And last but not least — access to everything everywhere!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what I think a route should deliver. Kind of what VueRouter delivers to us.&lt;/p&gt;

&lt;p&gt;VueRouter is great and works like a charm.. so why shouldn’t Svelte have a great router too ?&lt;/p&gt;

&lt;p&gt;As I said that Svelte does have good routers however I personally don’t like routes based on structure. I like routers to give me the choice to do what I want to do when I want to do.&lt;br&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  SCR — Svelte Client Router — The Proposal
&lt;/h1&gt;

&lt;p&gt;Who Am I to create a router right? I know my limitations I am not the wisest guy around, but I try to do my best =).&lt;/p&gt;

&lt;p&gt;That’s why I came with this proposal — I have created a router for Svelte that does exactly what I think it should do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F8pkipng4fu752t38ejj5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8pkipng4fu752t38ejj5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;ta-daaa! A lot of work =D&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;The key concept of this router is allow us to control the behavior before enter a route. So we can set:&lt;/p&gt;

&lt;p&gt;-&lt;b&gt;Global Before Enter Functions:&lt;/b&gt; To execute a function or array of functions to each route — Applied to all routes;&lt;br&gt;
-&lt;b&gt;Route Before Enter Functions:&lt;/b&gt; To execute a function or array of functions to a single route — Applied to a single route;&lt;br&gt;
-&lt;b&gt;Ignore Global Enter Functions:&lt;/b&gt; To just ignore Global Before Enter functions on a single route — Applied to a single route;&lt;br&gt;
-&lt;b&gt;Revert Order Of Execution:&lt;/b&gt; To execute Route Before Functions Before Global Before Functions;&lt;/p&gt;

&lt;p&gt;Of course it offers more than just that.. but it is focused on deliver that!&lt;/p&gt;

&lt;p&gt;With this router you will be able to control every aspect of routing, passing information forward throughout Before Enter Functions and After Before Enter Functions and receiving it in all components.&lt;/p&gt;

&lt;p&gt;One of the cooliest things is that every param, variable defined will be delivered in all places — functions, components, etc, as soon as possible.&lt;/p&gt;

&lt;p&gt;That means if you define a parameter inside of a Before Enter Function it will be delivered in the next one until the end, plus it will be delivered in your components.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why is this nice, one can ask?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;em&gt;Because I can control the behavior of routing and even alter as soon as I want to.&lt;/em&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ah.. I almost forget you can set loading components to it — Global and Per Route too!&lt;/p&gt;

&lt;p&gt;As soon as Before Enter Functions kicks in it will show a loading component if the loading take time enough.&lt;br&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Try It — Test It — Documentation
&lt;/h1&gt;

&lt;p&gt;Yes, It is in its early stages however I think it is awesome!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://arthurgermano.github.io/svelte-client-router/#/svelte-client-router" rel="noopener noreferrer"&gt;SCR - Svelte Client Router - Documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h1&gt;
  
  
  NPM Package
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.npmjs.com/package/svelte-client-router" rel="noopener noreferrer"&gt;SCR - Svelte Client Router - Package&lt;/a&gt;&lt;/p&gt;


&lt;/blockquote&gt;



&lt;h1&gt;
  
  
  See on Github
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/arthurgermano/svelte-client-router" rel="noopener noreferrer"&gt;SCR - Svelte Client Router - Code&lt;/a&gt;&lt;/p&gt;


&lt;/blockquote&gt;



&lt;h1&gt;
  
  
  Motivation
&lt;/h1&gt;

&lt;p&gt;I have worked with a little personal project and Svelte is really wonderful. I missed one thing in Svelte Community though, a good not embedded router.&lt;/p&gt;

&lt;p&gt;So here it my proposal. Please check out — test it and let me know your thoughts. =)&lt;br&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Finance Notes Project
&lt;/h1&gt;

&lt;p&gt;If you want to check out my personal project..&lt;br&gt;
&lt;a href="https://media.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%2Fpxe8hhbi9o0sdoa5r16i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fpxe8hhbi9o0sdoa5r16i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Finance Notes Project — PWA&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://financenotes.com.br/" rel="noopener noreferrer"&gt;Finance Notes Project&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/arthurgermano/my-experience-building-a-pwa-app-with-svelte-js-4pme"&gt;My Experience Building a PWA App with Svelte JS&lt;/a&gt;&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>router</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>My Experience Building a PWA App with Svelte JS</title>
      <dc:creator>Arthur Germano</dc:creator>
      <pubDate>Wed, 28 Apr 2021 22:15:30 +0000</pubDate>
      <link>https://dev.to/arthurgermano/my-experience-building-a-pwa-app-with-svelte-js-4pme</link>
      <guid>https://dev.to/arthurgermano/my-experience-building-a-pwa-app-with-svelte-js-4pme</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2Foyc0iza685q4nefbnv8a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Foyc0iza685q4nefbnv8a.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;App built with SvelteJS&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;Hi, I would like to share a few words of what was my experience building an front-end application with SvelteJS. And a spoiler alert… was awesome!&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;The decision of building the app was smooth, I always wanted to create something that was not related to my work, something only mine. However with our routines and work we not always can.&lt;/p&gt;

&lt;p&gt;My daily routine was go to work, do some workout on the gym, maybe go to the groceries shop and by the time I got home I need to plan and prepare everything for the next day and finally when I stop the day is over and I don’t want to get near of a screen.&lt;/p&gt;

&lt;p&gt;But since the covid, things have changed, I started to work from home and all of the sudden I had time to do some personal project.&lt;/p&gt;

&lt;p&gt;So what to do? There are so many apps developed that seem that all the ideas in the world are implemented already.&lt;/p&gt;

&lt;p&gt;Since is my first project, by my self — for my self, I did an app to help me control and maintain my finances. I confess that I already use one, but I was displeased with some features and I thought.. hey maybe I can do it better =).&lt;/p&gt;

&lt;p&gt;So I have the project, I know what I need and want.. so let’s start it. So I did. Since I had more time I started to work after my real job, and since I stopped to go to the gym — because of covid =( — I had a couple of hours in the day to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project — Finance Notes PWA — WebApp
&lt;/h2&gt;

&lt;p&gt;I started small by choosing which frameworks to use, planning which technologies to pick for the back-end and it took me almost a month to define and choose what to use.&lt;/p&gt;

&lt;p&gt;In this time I did some mock-ups, a little bit of testing, asked for some opinions in this time to make sure I was making the right decisions, not that is the right way but I needed to feel confident enough that my choices would not backfire.&lt;/p&gt;

&lt;p&gt;So I ended up with the following technologies:&lt;br&gt;
&lt;a href="https://media.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%2F9k9q0ps1nxjcddb3i5nn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F9k9q0ps1nxjcddb3i5nn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Technologies used in the project&lt;br&gt;
&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;I will not describe all the technologies but mainly SvelteJS. The other technologies were indeed the right choices.&lt;/p&gt;

&lt;p&gt;I really liked how Fastify worked. My first experience with it was not so great because I tried it in 2019 or 2018 or earlier I don’t remember but it was not OK.. a lot of issues and some features were complicated to make work. But now I truly recommend it. For monolith projects like this one that not justify microservices it is really fast.&lt;/p&gt;

&lt;p&gt;PWA was a challenge for me. I did an udemy course a long time ago and I confess I didn’t remember much. I really liked PWA it makes all in one nicelly. Not having to publish in some store is nice. But still understand the concepts it is a little bit challenging.&lt;/p&gt;

&lt;p&gt;There is plenty of documentation on the internet but mostly do not work well at first or it is out of date. If you want to implement PWA it is crucial to understand its flow. Understand that and you will be just fine! Good look with service-workers =).&lt;/p&gt;

&lt;blockquote&gt;
&lt;b&gt;Just a reminder:&lt;/b&gt; to make PWA work we have to go HTTPS!
But nowadays we have Let’s Encrypt — really easy to start using our new generated certificates! — It took me a while to figure it out, but seriously it is not that difficult =)
&lt;/blockquote&gt;

&lt;p&gt;All the other technologies are amazing and really fun to work with. All of them delivers what is promised, Jaeger, Docker, MongoDB, Redis and of course NodeJS.&lt;/p&gt;

&lt;p&gt;I had to study and learn a lot for this project to work and I almost gave up. The technology area is overwhelming. To keep up with all of it we have to study in a everyday basis.&lt;/p&gt;

&lt;h2&gt;
  
  
  SvelteJS
&lt;/h2&gt;

&lt;p&gt;The great star, in my opinion, is SvelteJS. I have worked with VueJS and it is really nice too. I did not worked with AngularJS or React and I didn’t want to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well, first AngularJS remember for me Java. We have a thousand configuration files just to start with it. I don’t like that. We spend a lot of time to do it.&lt;/p&gt;

&lt;p&gt;React in the other hand seems a little bit nicer but we have to write a lot of code just to get things done to. It is like VueJS. A lot of places repeating myself makes coding a little tiring and boring.&lt;/p&gt;

&lt;blockquote&gt;
Anyway it is just my opinion and my experience with this technologies.
&lt;/blockquote&gt;

&lt;p&gt;Now SvelteJS is easy, fast and coding with it is really really nice. It so well made, its store works wonderfully.&lt;/p&gt;

&lt;p&gt;It is productive, much much more productive than VueJS, I declare it once and reuse in any other place — I don’t have to tell to the file that I want to use and declare it in two thousand different places I just import what I want. With all of its features seems we are just using plain javascript in the end.&lt;/p&gt;

&lt;p&gt;The animations, properties anything you can think of just works! So here it is my applause. Coding with SvelteJS I guarantee it is really nice and fun!&lt;/p&gt;

&lt;p&gt;One last thing the code written is kept organized! Yes. I don’t have a file with a thousand lines. No. The other technologies are good but SvelteJS is better in that way too.&lt;/p&gt;

&lt;p&gt;If I can say something that I found difficult about SvelteJS is that there is a lot of good frameworks or libraries supporting it. Framework7 came to the rescue for that.&lt;/p&gt;

&lt;p&gt;When I started the project there weren’t good SPA routers. Because I have chosen to go SPA not using SSR. So I chose to use Framework7 which is a great framework. Anything you need it can provide and help me a lot during the project. I truly recommend it!&lt;/p&gt;

&lt;p&gt;In my experience less is better. Since Framework7 was practically doing a lot things for me it was OK to use it. But I don’t like to use a whole framework and just focus on the little things using just what I need.&lt;/p&gt;

&lt;p&gt;Since I really liked to work with SvelteJS I decided to create a router for it. I don’t know if it is perfect to use yet. But it reunites everything I think that a router should have!&lt;/p&gt;

&lt;h2&gt;
  
  
  SCR — Svelte Client Router
&lt;/h2&gt;

&lt;p&gt;&lt;b&gt;GIT&lt;/b&gt;: &lt;a href="https://github.com/arthurgermano/svelte-client-router" rel="noopener noreferrer"&gt;https://github.com/arthurgermano/svelte-client-router&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;NPM:&lt;/b&gt; &lt;a href="https://www.npmjs.com/package/svelte-client-router" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/svelte-client-router&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Test it:&lt;/b&gt; &lt;a href="https://arthurgermano.github.io/svelte-client-router/#/svelte-client-router" rel="noopener noreferrer"&gt;https://arthurgermano.github.io/svelte-client-router/#/svelte-client-router&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finance Notes PWA App
&lt;/h2&gt;

&lt;p&gt;So almost one year later I started and like I said almost giving up. I finished the project. Spend some money hiring a VPN server. Had to learn a lot to configure and secure it.&lt;/p&gt;

&lt;p&gt;If you want to see it visit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://financenotes.com.br/" rel="noopener noreferrer"&gt;Finance Notes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that is it! Thanks for reading =)&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>pwa</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Tutorial — Configuring a Local MongoDB-Docker ReplicaSet with 3Nodes and TLS.</title>
      <dc:creator>Arthur Germano</dc:creator>
      <pubDate>Tue, 16 Feb 2021 16:44:30 +0000</pubDate>
      <link>https://dev.to/arthurgermano/tutorial-configuring-a-local-mongodb-docker-replicaset-with-3nodes-and-tls-4492</link>
      <guid>https://dev.to/arthurgermano/tutorial-configuring-a-local-mongodb-docker-replicaset-with-3nodes-and-tls-4492</guid>
      <description>&lt;h3&gt;
  
  
  And yes… All easy with shell scripts (Linux) and ready to run! ;)!
&lt;/h3&gt;

&lt;p&gt;Hi there.. This is my very first article! I am excited about it.&lt;/p&gt;

&lt;p&gt;The development is a difficult area, specially because we have to know everything, literally. Since new technologies up to new business rules. In my belief who works with code, programming, configuring servers, databases, front-ends, back-ends are the today’s magicians of a RPG game.&lt;/p&gt;

&lt;p&gt;Anyway, let’s start talking about the important stuff. I intend to explain how I did configure a MongoDB ReplicaSet with 3 nodes in Docker Containers. In the next lines I will deliver a shell script to create ALL the certificates, CA, Server and Client to connect, as the docker compose file. Plus you can grab and customize it at your will and risk.&lt;/p&gt;

&lt;p&gt;If you didn’t understand anything from the last phrase above.. well you need to start studying because your path is long my friend.&lt;/p&gt;

&lt;p&gt;First things first, an image to help us visualize the configuration settings of what we will be accomplishing.&lt;br&gt;
&lt;a href="https://media.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%2Fkrmsbdqattdi9a5oa90f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fkrmsbdqattdi9a5oa90f.png" alt="MongoDockerStructure"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;center&gt;&lt;small&gt;created with &lt;a href="https://app.diagrams.net/" rel="noopener noreferrer"&gt;https://app.diagrams.net/&lt;/a&gt;&lt;/small&gt;&lt;/center&gt;


&lt;h2&gt;
  
  
  The docker-compose.yml file
&lt;/h2&gt;

&lt;p&gt;So we have to create the following docker-compose file, all the explanation is in its comments section by section:&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="c1"&gt;# docker-compose yml file &lt;/span&gt;
&lt;span class="c1"&gt;# docker version must be compatible with your running docker version # for more info see https://docs.docker.com/compose/compose-file/compose-versioning/&lt;/span&gt;
&lt;span class="c1"&gt;# Don't forget to use only spaces to indent ok!&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.9"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# The container mongo_node_1 configurations #############&lt;/span&gt;
  &lt;span class="na"&gt;mongo_node_1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongo_node_1&lt;/span&gt;
    &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongo_node_1&lt;/span&gt;
    &lt;span class="c1"&gt;# the image from the docker-hub repository&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mongo"&lt;/span&gt;
    &lt;span class="c1"&gt;# mongo uses port 27017 to change see more info https://hub.docker.com/_/mongo&lt;/span&gt;
    &lt;span class="na"&gt;expose&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;27017"&lt;/span&gt;
    &lt;span class="c1"&gt;# here comes the interesting part, with volumes we can easily insert all the configuration that we need!&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# This volume will hold the database information, what you save, your collections, documents, etc. Since we have 3 nodes we need three places which will hold information this is the first one&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/data/node_1:/data/db&lt;/span&gt;
      &lt;span class="c1"&gt;# This volume will hold the Server Certificate file which will be signed by the CA and will make work TLS - The shell script create all the folders inside ssl just need to run the script!&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/ssl/node_1:/data/ssl&lt;/span&gt;
      &lt;span class="c1"&gt;# This volume will hold this node cluster configuration! Each node has it's own configuration and differences, but to simplify things I just created ONE configuration to dominate them ALL =D! The file is the cluster.conf &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/config:/data/config&lt;/span&gt;
    &lt;span class="c1"&gt;# always restart right.. keep it alive!&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="c1"&gt;# entrypoint will execute a command inside the container as soon as it starts. So basically we are saying run mongo database with this file configuration settings. Note that the cluster.conf is inside the volume folder set in the volume section. Since it is mapped inside the container we don't need to copy any files (nice and slender!)&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&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;/usr/bin/mongod"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--config"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/data/config/cluster.conf"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;# setting the inside network &lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# the name of the below configured network we have to belong to it&lt;/span&gt;
      &lt;span class="na"&gt;my_network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# we have to specify a FIXED IP - this IP will be use after&lt;/span&gt;
        &lt;span class="na"&gt;ipv4_address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;170.17.5.5&lt;/span&gt;

&lt;span class="c1"&gt;# This works like MAGIC - this allows us to connect inside the network "my_network" FROM THE HOST - because we are creating a closed network we would have to configure a DNS server only to reach it. So very complicated. This option make it easy for us! Check your ip address with ifconfig in Linux and REPLACE "(YOUR MACHINE/SERVER IP)"&lt;/span&gt;
    &lt;span class="na"&gt;extra_hosts&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;localhost:(YOUR&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;MACHINE/SERVER&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;IP)"&lt;/span&gt;
    &lt;span class="c1"&gt;# mongo images use this variables inside the container and they are very helpful. Set the username and password of the Database. We are going to have to configure it by hand anyway but it's nice to have it there&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MONGO_INITDB_ROOT_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mdb_admin&lt;/span&gt;
      &lt;span class="na"&gt;MONGO_INITDB_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mdb_pass&lt;/span&gt;
  &lt;span class="c1"&gt;# The container mongo_node_2 configurations #############&lt;/span&gt;
  &lt;span class="na"&gt;mongo_node_2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongo_node_2&lt;/span&gt;
    &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongo_node_2&lt;/span&gt;
    &lt;span class="c1"&gt;# the image from the docker-hub repository&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mongo"&lt;/span&gt;
    &lt;span class="c1"&gt;# mongo uses port 27017 to change see more info https://hub.docker.com/_/mongo&lt;/span&gt;
    &lt;span class="na"&gt;expose&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;27017"&lt;/span&gt;
    &lt;span class="c1"&gt;# here comes the interesting part, with volumes we can easily insert all the configuration that we need!&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# This volume will hold the database information, what you save, your collections, documents, etc. Since we have 3 nodes we need three places which will hold information this is the second one&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/data/node_2:/data/db&lt;/span&gt;
      &lt;span class="c1"&gt;# This volume will hold the Server Certificate file which will be signed by the CA and will make work TLS - The shell script create all the folders inside ssl just need to run the script!&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/ssl/node_2:/data/ssl&lt;/span&gt;
      &lt;span class="c1"&gt;# This volume will hold this node cluster configuration! Each node has it's own configuration and differences, but to simplify things I just created ONE configuration to dominate them ALL =D! The file in the cluster.conf &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/config:/data/config&lt;/span&gt;
    &lt;span class="c1"&gt;# always restart right.. keep it alive!&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="c1"&gt;# entrypoint will execute a command inside the container as soon as it starts. So basically we are saying run mongo database with this file configuration settings. Note that the cluster.conf is inside the volume folder set in the volume section. Since it is mapped inside the container we don't need to copy any files (nice and slender!)&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&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;/usr/bin/mongod"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--config"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/data/config/cluster.conf"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;# setting the inside network &lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# the name of the below configured network we have to belong to it&lt;/span&gt;
      &lt;span class="na"&gt;my_network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# we have to specify a FIXED IP - this IP will be use after&lt;/span&gt;
        &lt;span class="na"&gt;ipv4_address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;170.17.5.6&lt;/span&gt;
&lt;span class="c1"&gt;# This works like MAGIC - this allows us to connect inside the network "my_network" FROM THE HOST - because we are creating a closed network we would have to configure a DNS server only to reach it. So very complicated. This option make it easy for us! Check your ip address with ifconfig in Linux and REPLACE "(YOUR MACHINE/SERVER IP)"&lt;/span&gt;
    &lt;span class="na"&gt;extra_hosts&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;localhost:(YOUR&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;MACHINE/SERVER&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;IP)"&lt;/span&gt;
    &lt;span class="c1"&gt;# mongo images use this variables inside the container and they are very helpful. Set the username and password of the Database. We are going to have to configure it by hand anyway but it's nice to have it there&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MONGO_INITDB_ROOT_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mdb_admin&lt;/span&gt;
      &lt;span class="na"&gt;MONGO_INITDB_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mdb_pass&lt;/span&gt;
  &lt;span class="c1"&gt;# The container mongo_node_arbiter configurations #############&lt;/span&gt;
  &lt;span class="na"&gt;mongo_node_arbiter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongo_node_arbiter&lt;/span&gt;
    &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongo_node_arbiter&lt;/span&gt;
    &lt;span class="c1"&gt;# the image from the docker-hub repository&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mongo"&lt;/span&gt;
    &lt;span class="c1"&gt;# mongo uses port 27017 to change see more info https://hub.docker.com/_/mongo&lt;/span&gt;
    &lt;span class="na"&gt;expose&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;27017"&lt;/span&gt;
    &lt;span class="c1"&gt;# here comes the interesting part, with volumes we can easily insert all the configuration that we need!&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# This volume will hold the database information, what you save, your collections, documents, etc. Since we have 3 nodes we need three places which will hold information this is the third one and the arbiter only chooses which node is primary or secondary&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/data/node_arbiter:/data/db&lt;/span&gt;
      &lt;span class="c1"&gt;# This volume will hold the Server Certificate file which will be signed by the CA and will make work TLS - The shell script create all the folders inside ssl just need to run the script!&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/ssl/node_arbiter:/data/ssl&lt;/span&gt;
      &lt;span class="c1"&gt;# This volume will hold this node cluster configuration! Each node has it's own configuration and differences, but to simplify things I just created ONE configuration to dominate them ALL =D! The file in the cluster.conf &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/config:/data/config&lt;/span&gt;
    &lt;span class="c1"&gt;# always restart right.. keep it alive!&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="c1"&gt;# entrypoint will execute a command inside the container as soon as it starts. So basically we are saying run mongo database with this file configuration settings. Note that the cluster.conf is inside the volume folder set in the volume section. Since it is mapped inside the container we don't need to copy any files (nice and slender!)&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&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;/usr/bin/mongod"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--config"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/data/config/cluster.conf"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;# setting the inside network &lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# the name of the below configured network we have to belong to it&lt;/span&gt;
      &lt;span class="na"&gt;my_network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# we have to specify a FIXED IP - this IP will be use after&lt;/span&gt;
        &lt;span class="na"&gt;ipv4_address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;170.17.5.7&lt;/span&gt;
&lt;span class="c1"&gt;# This works like MAGIC - this allows us to connect inside the network "my_network" FROM THE HOST - because we are creating a closed network we would have to configure a DNS server only to reach it. So very complicated. This option make it easy for us! Check your ip address with ifconfig in Linux and REPLACE "(YOUR MACHINE/SERVER IP)"&lt;/span&gt;
    &lt;span class="na"&gt;extra_hosts&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;localhost:(YOUR&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;MACHINE/SERVER&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;IP)"&lt;/span&gt;
    &lt;span class="c1"&gt;# mongo images use this variables inside the container and they are very helpful. Set the username and password of the Database. We are going to have to configure it by hand anyway but it's nice to have it there&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MONGO_INITDB_ROOT_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mdb_admin&lt;/span&gt;
      &lt;span class="na"&gt;MONGO_INITDB_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mdb_pass&lt;/span&gt;
&lt;span class="c1"&gt;# Finally we create our network. And WE HAVE to create it. Docker only allows us to set IP address for custom networks so here we go&lt;/span&gt;
&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# this is your custom network NAME inside this file &lt;/span&gt;
  &lt;span class="na"&gt;my_network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# this name is the docker network name outside. We can check it with docker network inspect my_network_default  &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;my_network_default&lt;/span&gt;
    &lt;span class="c1"&gt;# here we configure the driver bridge is default, and set the network specifics&lt;/span&gt;
    &lt;span class="na"&gt;ipam&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
      &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;subnet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;170.17.0.0/16&lt;/span&gt;
          &lt;span class="na"&gt;ip_range&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;170.17.0.0/16&lt;/span&gt;
          &lt;span class="na"&gt;gateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;170.17.5.254&lt;/span&gt;
&lt;span class="c1"&gt;# THE END&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow.. this is a huge, easy to get lost docker-compose.yml file. I will not be able to explain everything, but if you copy that, create a file named docker-compose.yml inside a folder, paste it, and then open with your linux terminal that folder and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# what this command does is.. it starts docker-compose.yml&lt;/span&gt;
&lt;span class="c"&gt;# removes any possible previous set containers created&lt;/span&gt;
&lt;span class="c"&gt;# forces to recreate all container inside the docker-compose.yml&lt;/span&gt;
&lt;span class="c"&gt;# and for last... renew the volumes - DOES NOT recreate it,  just renew it's inside volumes&lt;/span&gt;
docker-compose up &lt;span class="nt"&gt;--remove-orphans&lt;/span&gt; &lt;span class="nt"&gt;--force-recreate&lt;/span&gt; &lt;span class="nt"&gt;--renew-anon-volumes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course it will throw an error:&lt;br&gt;
&lt;a href="https://media.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%2F95gc3r3e1wvuloglwg6q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F95gc3r3e1wvuloglwg6q.png" alt="FirstRunError"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;center&gt;&lt;small&gt;the minimum we can do is try!&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;But the first part it okay! If you had any doubt about what each section of the file means, please read the comments inside the file. &lt;b&gt;And an important note we will always run the docker-compose-yml with that command.&lt;/b&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Cluster.conf file
&lt;/h2&gt;

&lt;p&gt;So.. let’s move on to the next part. We have to configure each node with its own configuration. But, if you read the comments, I have created &lt;b&gt;only one file config&lt;/b&gt; to make our lives easier.&lt;br&gt;
To do that create a folder named “config” in the same folder where the docker-compose lies. Create a file name cluster.conf with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;storage&lt;/span&gt;:
  &lt;span class="n"&gt;dbPath&lt;/span&gt;: /&lt;span class="n"&gt;data&lt;/span&gt;/&lt;span class="n"&gt;db&lt;/span&gt;
&lt;span class="n"&gt;replication&lt;/span&gt;:
  &lt;span class="n"&gt;replSetName&lt;/span&gt;: &lt;span class="n"&gt;my_mdb_rs&lt;/span&gt;
  &lt;span class="n"&gt;enableMajorityReadConcern&lt;/span&gt;: &lt;span class="n"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;net&lt;/span&gt;:
  &lt;span class="n"&gt;port&lt;/span&gt;: &lt;span class="m"&gt;27017&lt;/span&gt;
  &lt;span class="n"&gt;bindIpAll&lt;/span&gt;: &lt;span class="n"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;tls&lt;/span&gt;:
    &lt;span class="n"&gt;mode&lt;/span&gt;: &lt;span class="n"&gt;requireTLS&lt;/span&gt;
    &lt;span class="n"&gt;CAFile&lt;/span&gt;: /&lt;span class="n"&gt;data&lt;/span&gt;/&lt;span class="n"&gt;ssl&lt;/span&gt;/&lt;span class="n"&gt;mdb_root_CA&lt;/span&gt;.&lt;span class="n"&gt;crt&lt;/span&gt;
    &lt;span class="n"&gt;certificateKeyFile&lt;/span&gt;: /&lt;span class="n"&gt;data&lt;/span&gt;/&lt;span class="n"&gt;ssl&lt;/span&gt;/&lt;span class="n"&gt;mdb_nodes_keycert&lt;/span&gt;.&lt;span class="n"&gt;pem&lt;/span&gt;
    &lt;span class="n"&gt;certificateKeyFilePassword&lt;/span&gt;: &lt;span class="n"&gt;mdb_my_custom_passphrase_security&lt;/span&gt;
    &lt;span class="n"&gt;clusterFile&lt;/span&gt;: /&lt;span class="n"&gt;data&lt;/span&gt;/&lt;span class="n"&gt;ssl&lt;/span&gt;/&lt;span class="n"&gt;mdb_nodes_keycert&lt;/span&gt;.&lt;span class="n"&gt;pem&lt;/span&gt;
    &lt;span class="n"&gt;clusterPassword&lt;/span&gt;: &lt;span class="n"&gt;mdb_my_custom_passphrase_security&lt;/span&gt;
    &lt;span class="n"&gt;allowInvalidCertificates&lt;/span&gt;: &lt;span class="n"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;allowInvalidHostnames&lt;/span&gt;: &lt;span class="n"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;security&lt;/span&gt;:
  &lt;span class="n"&gt;authorization&lt;/span&gt;: &lt;span class="n"&gt;enabled&lt;/span&gt;
  &lt;span class="n"&gt;clusterAuthMode&lt;/span&gt;: &lt;span class="n"&gt;x509&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s review each section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;b&gt;storage &amp;gt; dbPath:&lt;/b&gt; is where you set the volume data inside the docker-compose.yml file&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;replication &amp;gt; replSetName:&lt;/b&gt; this is the Mongo Replica Set name we will use it in several places&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;replication &amp;gt; enableMajorityReadConcern:&lt;/b&gt; it is not a must have config, but it is nice to enable it&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;net &amp;gt; port:&lt;/b&gt; the node configuration port, must be the same of the docker-compose.yml file. We didn’t specify one directly because 27017 is the default port of mongo DB&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;net &amp;gt; bindIpAll:&lt;/b&gt; the node IP. But since we are using the same file for all nodes and each node has it own IP we need to bind any IP that tries to connect.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;net &amp;gt; tls &amp;gt; mode:&lt;/b&gt; Here we can have some options and we are choosing the most restrict one.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;net &amp;gt; tls &amp;gt; CAFile:&lt;/b&gt; The certificate authority file. The location where the file lies inside the container. For that each node has it’s volume and we have configured each volume inside the docker-compose.yml.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;net &amp;gt; tls &amp;gt; certificateKeyFile:&lt;/b&gt; This node server certificate file. The location where the file lies inside the container. For that each node has it’s volume and we have configured each volume inside the docker-compose.yml.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;net &amp;gt; tls &amp;gt; certificateKeyFilePassword:&lt;/b&gt; This node password server certificate file. &lt;b&gt;I have create the same password for each file and this is not a recommended thing to do.&lt;/b&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;net &amp;gt; tls &amp;gt; clusterFile:&lt;/b&gt; Since we create a cluster and each node has it’s own certificate we can connect to the cluster with them. The location where the file lies inside the container. For that each node has it’s volume and we have configured each volume inside the docker-compose.yml.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;net &amp;gt; tls &amp;gt; clusterFilePassword:&lt;/b&gt; Cluster password certificate file. &lt;b&gt;I have create the same password for each file and this is not a recommended thing to do.&lt;/b&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;net &amp;gt; tls &amp;gt; allowInvalidCertificates:&lt;/b&gt; Allows us to connect with self-signed certificates. (It isn’t a safe production measure, so use with caution)&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;net &amp;gt; tls &amp;gt; allowInvalidHostnames:&lt;/b&gt; We don’t have valid host names so we by pass using this option. (It isn’t a safe production measure, so use with caution)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;security &amp;gt; authorization: Enable authorization on mongoDB&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;security &amp;gt; clusterAuthMode:&lt;/b&gt; There are some options here, the cool and easiest one is with keyfile. But we are using a little bit more secure.

### Important Note&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wrote above and I will repeat it here, the “CAFile”, “certificateKeyFile” and “clusterFile” are mapped in the docker-compose.yml file. So we have created a folder and inside of it the docker-compose-yml and a folder named “config” folder with our “cluster.conf” file inside this last one right ? So our volume section of each node inside the docker-compose-yml file must point to this very created “config” folder. Put the absolute path to be sure!&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/config:/data/config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Certificate Mess — Made Easy Peasy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Part One — Shell Script
&lt;/h3&gt;

&lt;p&gt;Who doesn’t struggle with certificates ?&lt;/p&gt;

&lt;p&gt;They are difficult to understand, in a way, so to make things easy.. very very easy. I have created an shell script to create all this things for us. Yes .. you and I.&lt;br&gt;
What this script does, and which I have make my best efforts to create for the past week in my spare time, is to create the Certificate Authority Files, all the three nodes server certificate files, and the client certificate files to connect from your application like an NodeJS application or MongoCompass.&lt;/p&gt;

&lt;p&gt;Without it we would have to execute several commands in the linux terminal and make sure that all of them are correct and with the right information in the right spot. It is &lt;b&gt;A LOT&lt;/b&gt; to process.&lt;/p&gt;

&lt;p&gt;Enough talk.. let’s see this shell script. For that, create a folder where the docker-compose-yml lies named “ssl”. After this step create a file inside this ssl folder named generateSSLCerts.sh. &lt;b&gt;Remember to give execute permission to this file!&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;And just to get ahead create another folder named “confs” inside ssl folder as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;On MAC there some issues with LibreSSL lib, and when running the script make sure that the command line is in the script folder, the script does not work if the path is relative.&lt;/b&gt;&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nv"&gt;TXT_LOG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;" ----- "&lt;/span&gt;
&lt;span class="nv"&gt;CONFS_FILES_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./confs/"&lt;/span&gt;
&lt;span class="c"&gt;# the paths must match in docker-compose.yml file&lt;/span&gt;
&lt;span class="c"&gt;# must match the file name of cluster.conf&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE1_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"node_1"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE1_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_node_1.key"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE1_CSR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_node_1.csr"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE1_CRT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_node_1.crt"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE1_CNF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFS_FILES_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;mdb_node1_CN.cnf"&lt;/span&gt;
&lt;span class="c"&gt;# the paths must match in docker-compose.yml file&lt;/span&gt;
&lt;span class="c"&gt;# must match the file name of cluster.conf&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE2_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"node_2"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE2_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_node_2.key"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE2_CSR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_node_2.csr"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE2_CRT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_node_2.crt"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE2_CNF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFS_FILES_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;mdb_node2_CN.cnf"&lt;/span&gt;
&lt;span class="c"&gt;# the paths must match in docker-compose.yml file&lt;/span&gt;
&lt;span class="c"&gt;# must match the file name of cluster.conf&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE_ARB_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"node_arbiter"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE_ARB_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_node_arbiter.key"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE_ARB_CSR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_node_arbiter.csr"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE_ARB_CRT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_node_arbiter.crt"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_NODE_ARB_CNF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFS_FILES_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;mdb_node_arbiter_CN.cnf"&lt;/span&gt;
&lt;span class="c"&gt;# must match the file name of cluster.conf&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CA_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"CA"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CA_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_root_CA.key"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CA_CRT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_root_CA.crt"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CA_SRL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_root_CA.srl"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CA_CNF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFS_FILES_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;mdb_root_CA.cnf"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_PASS_PHRASE_CA&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_my_custom_passphrase_security"&lt;/span&gt;
&lt;span class="c"&gt;# must match the file name of cluster.conf&lt;/span&gt;
&lt;span class="nv"&gt;MDB_FINAL_KEYCERT_PEM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_nodes_keycert.pem"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CLIENT_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"serverclient"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CLIENT_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_client.key"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CLIENT_CSR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_client.csr"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CLIENT_CRT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_client.crt"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CLIENT_PEM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mdb_client.pem"&lt;/span&gt;
&lt;span class="nv"&gt;MDB_CLIENT_CN_CNF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFS_FILES_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;mdb_client_CN.cnf"&lt;/span&gt;
&lt;span class="c"&gt;# param order&lt;/span&gt;
&lt;span class="c"&gt;# DIR         ----- $1 - $X_DIR&lt;/span&gt;
&lt;span class="c"&gt;# FILE        ----- $2 - $FILEVAR_NAME&lt;/span&gt;
move_files&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; 2&amp;gt; /dev/null
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Moving &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt; to ./&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;mv&lt;/span&gt; ./&lt;span class="nv"&gt;$2&lt;/span&gt; ./&lt;span class="nv"&gt;$1&lt;/span&gt;/&lt;span class="nv"&gt;$2&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# param order&lt;/span&gt;
&lt;span class="c"&gt;# DIR         ----- $1 - $X_DIR&lt;/span&gt;
&lt;span class="c"&gt;# FILE        ----- $2 - $FILEVAR_NAME&lt;/span&gt;
copy_files&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; 2&amp;gt; /dev/null
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Copying &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt; to ./&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; ./&lt;span class="nv"&gt;$2&lt;/span&gt; ./&lt;span class="nv"&gt;$1&lt;/span&gt;/&lt;span class="nv"&gt;$2&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# param order&lt;/span&gt;
&lt;span class="c"&gt;# DIR         ----- $1 - $MDB_NODEX_DIR&lt;/span&gt;
&lt;span class="c"&gt;# NODE .key file  ----- $2 - $MDB_NODEX_KEY&lt;/span&gt;
&lt;span class="c"&gt;# NODE .csr file  ----- $3 - $MDB_NODEX_CSR&lt;/span&gt;
&lt;span class="c"&gt;# NODE .cnf file  ----- $4 - $MDB_NODEX_CNF&lt;/span&gt;
&lt;span class="c"&gt;# MDB CA .crt file  ----- $5 - $MDB_CA_CRT&lt;/span&gt;
&lt;span class="c"&gt;# MDB CA .key file  ----- $6 - $MDB_CA_KEY&lt;/span&gt;
&lt;span class="c"&gt;# NODE .crt file  ----- $7 - $MDB_NODEX_CRT&lt;/span&gt;
gen_node_keycerts&lt;span class="o"&gt;(){&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;STARTING &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; Certificates &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; 2&amp;gt; /dev/null
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Generating &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; - KEY and CSR files &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
openssl genrsa &lt;span class="nt"&gt;-des3&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="nt"&gt;-passout&lt;/span&gt; pass:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MDB_PASS_PHRASE_CA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 4096
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Generating &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; - CRT file &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-config&lt;/span&gt; &lt;span class="nv"&gt;$4&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="nt"&gt;-passin&lt;/span&gt; pass:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MDB_PASS_PHRASE_CA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; &lt;span class="nv"&gt;$3&lt;/span&gt; &lt;span class="nt"&gt;-config&lt;/span&gt; &lt;span class="nv"&gt;$4&lt;/span&gt;
openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="nt"&gt;-in&lt;/span&gt; &lt;span class="nv"&gt;$3&lt;/span&gt; &lt;span class="nt"&gt;-CA&lt;/span&gt; &lt;span class="nv"&gt;$5&lt;/span&gt; &lt;span class="nt"&gt;-CAkey&lt;/span&gt; &lt;span class="nv"&gt;$6&lt;/span&gt; &lt;span class="nt"&gt;-CAcreateserial&lt;/span&gt; &lt;span class="nt"&gt;-passin&lt;/span&gt; pass:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MDB_PASS_PHRASE_CA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; &lt;span class="nv"&gt;$7&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Generating &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; - PEM file &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="nv"&gt;$7&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$MDB_FINAL_KEYCERT_PEM&lt;/span&gt;
move_files &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt;
move_files &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="nv"&gt;$3&lt;/span&gt;
move_files &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="nv"&gt;$7&lt;/span&gt;
move_files &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="nv"&gt;$MDB_FINAL_KEYCERT_PEM&lt;/span&gt;
copy_files &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="nv"&gt;$5&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;FINISHED &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
openssl rand &lt;span class="nt"&gt;-writerand&lt;/span&gt; .rnd
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"STARTING SCRIPT &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
openssl genrsa &lt;span class="nt"&gt;-des3&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_KEY&lt;/span&gt; &lt;span class="nt"&gt;-passout&lt;/span&gt; pass:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MDB_PASS_PHRASE_CA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 4096
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Root CA key OK &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
openssl req &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_KEY&lt;/span&gt; &lt;span class="nt"&gt;-sha256&lt;/span&gt; &lt;span class="nt"&gt;-passin&lt;/span&gt; pass:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MDB_PASS_PHRASE_CA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-days&lt;/span&gt; 720 &lt;span class="nt"&gt;-out&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_CRT&lt;/span&gt; &lt;span class="nt"&gt;-config&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_CNF&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Root CA crt OK &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"FINISHED CA CERTIFICATE &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
gen_node_keycerts &lt;span class="nv"&gt;$MDB_NODE1_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE1_KEY&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE1_CSR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE1_CNF&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_CRT&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_KEY&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE1_CRT&lt;/span&gt;
gen_node_keycerts &lt;span class="nv"&gt;$MDB_NODE2_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE2_KEY&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE2_CSR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE2_CNF&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_CRT&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_KEY&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE2_CRT&lt;/span&gt;
gen_node_keycerts &lt;span class="nv"&gt;$MDB_NODE_ARB_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE_ARB_KEY&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE_ARB_CSR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE_ARB_CNF&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_CRT&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_KEY&lt;/span&gt; &lt;span class="nv"&gt;$MDB_NODE_ARB_CRT&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Generating client access certificates key and cert &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_CSR&lt;/span&gt; &lt;span class="nt"&gt;-keyout&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_KEY&lt;/span&gt; &lt;span class="nt"&gt;-passout&lt;/span&gt; pass:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MDB_PASS_PHRASE_CA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-config&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_CN_CNF&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Signing client access certificates &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_CSR&lt;/span&gt; &lt;span class="nt"&gt;-CA&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_CRT&lt;/span&gt; &lt;span class="nt"&gt;-CAkey&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_KEY&lt;/span&gt; &lt;span class="nt"&gt;-passin&lt;/span&gt; pass:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MDB_PASS_PHRASE_CA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_CRT&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Generating client PEM file &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_KEY&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_CRT&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_PEM&lt;/span&gt;
move_files &lt;span class="nv"&gt;$MDB_CLIENT_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_CSR&lt;/span&gt;
move_files &lt;span class="nv"&gt;$MDB_CLIENT_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_KEY&lt;/span&gt;
move_files &lt;span class="nv"&gt;$MDB_CLIENT_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_CRT&lt;/span&gt;
move_files &lt;span class="nv"&gt;$MDB_CLIENT_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CLIENT_PEM&lt;/span&gt;
copy_files &lt;span class="nv"&gt;$MDB_CLIENT_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_CRT&lt;/span&gt;
move_files &lt;span class="nv"&gt;$MDB_CA_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_KEY&lt;/span&gt;
move_files &lt;span class="nv"&gt;$MDB_CA_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_CRT&lt;/span&gt;
move_files &lt;span class="nv"&gt;$MDB_CA_DIR&lt;/span&gt; &lt;span class="nv"&gt;$MDB_CA_SRL&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"FINISHED &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TXT_LOG&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a pretty long script file. I will not explain what it does step-by-step. What you have to know is the following things:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;MDB_PASS_PHRASE_CA&lt;/b&gt;=”mdb_my_custom_passphrase_security” — This variable holds the password configured inside the cluster.conf file. We use the same password for everything and &lt;b&gt;it is not a recommended thing to do!&lt;/b&gt; If you want you can set your own custom password, but keep in mind that you have to change it in the cluster.conf file and when connecting with the clients.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;The Folder Structure&lt;/b&gt; created reflects what we have declared inside of docker-compose.yml file. So the variables in the shell can be customized, but you have to remember to changed it in all other places too, which means all the volumes must point to the correct folder. For example:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Note that we set each node volume like to ../../node_X:/data/ssl where "X" is the node name.&lt;/span&gt;
&lt;span class="c1"&gt;# the "node_X" part - the script will create it and it is declared in the _DIR variables of the script.&lt;/span&gt;
&lt;span class="c1"&gt;# the /data/ssl/ part - lies inside the container and we are mapping all the content inside ../../../node_X to /data/ssl. For example node_1&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/ssl/node_1:/data/ssl/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;Although we have our script ready to run, if you do so, it will run with errors! (Not recommended!)&lt;/b&gt;&lt;br&gt;
That happens because we are not ready yet. To spare us to execute any kind of interaction with the commands of the shell script with have a couple of configuration files. =S&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Part two — Configuration Files
&lt;/h3&gt;

&lt;p&gt;The configuration files are all the names, options and choices that we have to make when generating certificates. Since we are creating self-signing certificates we can have it done this way. So it is not for &lt;b&gt;production!&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Only to make things easier “for me”, I will only show the two files. But for the script actually are five files, which four of them have the same content. Again, it is not recommended for production!&lt;/p&gt;

&lt;p&gt;The first one is the &lt;b&gt;Certificate Authority Configuration File.&lt;/b&gt; I will not comment all it’s items, mostly because I don’t know them well and I found it somewhere in the internet!&lt;/p&gt;

&lt;p&gt;So to start this section create a file named “mdb_root_CA.cnf” inside of the previously create folder named “confs” with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;RANDFILE&lt;/span&gt;        = ./.&lt;span class="n"&gt;rnd&lt;/span&gt;
&lt;span class="c"&gt;####################################################################
&lt;/span&gt;[ &lt;span class="n"&gt;ca&lt;/span&gt; ]
&lt;span class="c"&gt;# The default ca section
&lt;/span&gt;&lt;span class="n"&gt;default_ca&lt;/span&gt;    = &lt;span class="n"&gt;CA_default&lt;/span&gt;
[ &lt;span class="n"&gt;CA_default&lt;/span&gt; ]
&lt;span class="c"&gt;# How long to certify for
&lt;/span&gt;&lt;span class="n"&gt;default_days&lt;/span&gt;     = &lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="c"&gt;# How long before next CRL
&lt;/span&gt;&lt;span class="n"&gt;default_crl_days&lt;/span&gt; = &lt;span class="m"&gt;30&lt;/span&gt;
&lt;span class="c"&gt;# Use public key default MD
&lt;/span&gt;&lt;span class="n"&gt;default_md&lt;/span&gt;       = &lt;span class="n"&gt;sha256&lt;/span&gt;
&lt;span class="c"&gt;# Keep passed DN ordering
&lt;/span&gt;&lt;span class="n"&gt;preserve&lt;/span&gt;         = &lt;span class="n"&gt;no&lt;/span&gt;
&lt;span class="c"&gt;# The extensions to add to the cert
&lt;/span&gt;&lt;span class="n"&gt;x509_extensions&lt;/span&gt; = &lt;span class="n"&gt;ca_extensions&lt;/span&gt;
&lt;span class="c"&gt;# Don't concat the email in the DN
&lt;/span&gt;&lt;span class="n"&gt;email_in_dn&lt;/span&gt;     = &lt;span class="n"&gt;no&lt;/span&gt;
&lt;span class="c"&gt;# Required to copy SANs from CSR to cert
&lt;/span&gt;&lt;span class="n"&gt;copy_extensions&lt;/span&gt; = &lt;span class="n"&gt;copy&lt;/span&gt;
&lt;span class="c"&gt;# Set to 'no' to allow creation of 
# several certificates with same subject.
&lt;/span&gt;&lt;span class="n"&gt;unique_subject&lt;/span&gt; = &lt;span class="n"&gt;no&lt;/span&gt;
&lt;span class="c"&gt;####################################################################
&lt;/span&gt;[ &lt;span class="n"&gt;req&lt;/span&gt; ]
&lt;span class="n"&gt;default_bits&lt;/span&gt;       = &lt;span class="m"&gt;4096&lt;/span&gt;
&lt;span class="n"&gt;distinguished_name&lt;/span&gt; = &lt;span class="n"&gt;ca_distinguished_name&lt;/span&gt;
&lt;span class="n"&gt;x509_extensions&lt;/span&gt;    = &lt;span class="n"&gt;ca_extensions&lt;/span&gt;
&lt;span class="n"&gt;string_mask&lt;/span&gt;        = &lt;span class="n"&gt;utf8only&lt;/span&gt;
&lt;span class="n"&gt;prompt&lt;/span&gt; = &lt;span class="n"&gt;no&lt;/span&gt;
&lt;span class="c"&gt;####################################################################
&lt;/span&gt;[ &lt;span class="n"&gt;ca_distinguished_name&lt;/span&gt; ]
&lt;span class="n"&gt;countryName&lt;/span&gt;         = &lt;span class="n"&gt;BR&lt;/span&gt;
&lt;span class="n"&gt;stateOrProvinceName&lt;/span&gt;         = &lt;span class="n"&gt;Parana&lt;/span&gt;
&lt;span class="n"&gt;localityName&lt;/span&gt;                = &lt;span class="n"&gt;YourCity&lt;/span&gt;
&lt;span class="n"&gt;organizationName&lt;/span&gt;            = &lt;span class="n"&gt;Your&lt;/span&gt; &lt;span class="n"&gt;Company&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;span class="n"&gt;organizationalUnitName&lt;/span&gt;         = &lt;span class="n"&gt;Company&lt;/span&gt; &lt;span class="n"&gt;Dev&lt;/span&gt; &lt;span class="n"&gt;Departament&lt;/span&gt;
&lt;span class="n"&gt;commonName&lt;/span&gt;         = &lt;span class="n"&gt;yourcompanycn&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;
&lt;span class="n"&gt;emailAddress&lt;/span&gt; = &lt;span class="n"&gt;yourcompanyemail&lt;/span&gt;@&lt;span class="n"&gt;email&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;
&lt;span class="c"&gt;####################################################################
&lt;/span&gt;[ &lt;span class="n"&gt;ca_extensions&lt;/span&gt; ]
&lt;span class="n"&gt;subjectKeyIdentifier&lt;/span&gt;   = &lt;span class="n"&gt;hash&lt;/span&gt;
&lt;span class="n"&gt;authorityKeyIdentifier&lt;/span&gt; = &lt;span class="n"&gt;keyid&lt;/span&gt;:&lt;span class="n"&gt;always&lt;/span&gt;, &lt;span class="n"&gt;issuer&lt;/span&gt;
&lt;span class="n"&gt;basicConstraints&lt;/span&gt;       = &lt;span class="n"&gt;critical&lt;/span&gt;, &lt;span class="n"&gt;CA&lt;/span&gt;:&lt;span class="n"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;keyUsage&lt;/span&gt;               = &lt;span class="n"&gt;keyCertSign&lt;/span&gt;, &lt;span class="n"&gt;cRLSign&lt;/span&gt;, &lt;span class="n"&gt;digitalSignature&lt;/span&gt;, &lt;span class="n"&gt;keyEncipherment&lt;/span&gt;
&lt;span class="n"&gt;extendedKeyUsage&lt;/span&gt; = &lt;span class="n"&gt;clientAuth&lt;/span&gt;, &lt;span class="n"&gt;serverAuth&lt;/span&gt;
&lt;span class="c"&gt;####################################################################
&lt;/span&gt;[ &lt;span class="n"&gt;signing_policy&lt;/span&gt; ]
&lt;span class="n"&gt;countryName&lt;/span&gt;            = &lt;span class="n"&gt;optional&lt;/span&gt;
&lt;span class="n"&gt;stateOrProvinceName&lt;/span&gt;    = &lt;span class="n"&gt;optional&lt;/span&gt;
&lt;span class="n"&gt;localityName&lt;/span&gt;           = &lt;span class="n"&gt;optional&lt;/span&gt;
&lt;span class="n"&gt;organizationName&lt;/span&gt;       = &lt;span class="n"&gt;optional&lt;/span&gt;
&lt;span class="n"&gt;organizationalUnitName&lt;/span&gt; = &lt;span class="n"&gt;optional&lt;/span&gt;
&lt;span class="n"&gt;commonName&lt;/span&gt;             = &lt;span class="n"&gt;supplied&lt;/span&gt;
&lt;span class="n"&gt;emailAddress&lt;/span&gt;           = &lt;span class="n"&gt;optional&lt;/span&gt;
&lt;span class="c"&gt;####################################################################
&lt;/span&gt;[ &lt;span class="n"&gt;signing_req&lt;/span&gt; ]
&lt;span class="n"&gt;subjectKeyIdentifier&lt;/span&gt;   = &lt;span class="n"&gt;hash&lt;/span&gt;
&lt;span class="n"&gt;authorityKeyIdentifier&lt;/span&gt; = &lt;span class="n"&gt;keyid&lt;/span&gt;,&lt;span class="n"&gt;issuer&lt;/span&gt;
&lt;span class="n"&gt;basicConstraints&lt;/span&gt;       = &lt;span class="n"&gt;CA&lt;/span&gt;:&lt;span class="n"&gt;FALSE&lt;/span&gt;
&lt;span class="n"&gt;keyUsage&lt;/span&gt;               = &lt;span class="n"&gt;keyCertSign&lt;/span&gt;, &lt;span class="n"&gt;cRLSign&lt;/span&gt;, &lt;span class="n"&gt;digitalSignature&lt;/span&gt;, &lt;span class="n"&gt;keyEncipherment&lt;/span&gt;
&lt;span class="n"&gt;extendedKeyUsage&lt;/span&gt; = &lt;span class="n"&gt;clientAuth&lt;/span&gt;, &lt;span class="n"&gt;serverAuth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second content will be used for all the other four files. There are three server certificate configuration files and one client certificate connection configuration file.&lt;/p&gt;

&lt;p&gt;To do that create four files named as it follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;b&gt;“mdb_node1_CN.cnf”;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;“mdb_node2_CN.cnf”;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;“mdb_node_arbiter_CN.cnf”;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;“mdb_client_CN.cnf”;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of them with the same following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;RANDFILE&lt;/span&gt;        = ./.&lt;span class="n"&gt;rnd&lt;/span&gt;
&lt;span class="c"&gt;####################################################################
&lt;/span&gt;
[ &lt;span class="n"&gt;req&lt;/span&gt; ]
&lt;span class="n"&gt;default_bits&lt;/span&gt;       = &lt;span class="m"&gt;2048&lt;/span&gt;
&lt;span class="n"&gt;distinguished_name&lt;/span&gt; = &lt;span class="n"&gt;server_distinguished_name&lt;/span&gt;
&lt;span class="n"&gt;req_extensions&lt;/span&gt;     = &lt;span class="n"&gt;server_req_extensions&lt;/span&gt;
&lt;span class="n"&gt;string_mask&lt;/span&gt;        = &lt;span class="n"&gt;utf8only&lt;/span&gt;
&lt;span class="n"&gt;prompt&lt;/span&gt; = &lt;span class="n"&gt;no&lt;/span&gt;

&lt;span class="c"&gt;####################################################################
&lt;/span&gt;[ &lt;span class="n"&gt;server_distinguished_name&lt;/span&gt; ]
&lt;span class="n"&gt;countryName&lt;/span&gt;         = &lt;span class="n"&gt;BR&lt;/span&gt;
&lt;span class="n"&gt;stateOrProvinceName&lt;/span&gt;         = &lt;span class="n"&gt;Parana&lt;/span&gt;
&lt;span class="n"&gt;localityName&lt;/span&gt;                = &lt;span class="n"&gt;YourCity&lt;/span&gt;
&lt;span class="n"&gt;organizationName&lt;/span&gt;            = &lt;span class="n"&gt;Your&lt;/span&gt; &lt;span class="n"&gt;Company&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;span class="n"&gt;commonName&lt;/span&gt;         = &lt;span class="n"&gt;mdb_node_cn&lt;/span&gt;
&lt;span class="n"&gt;emailAddress&lt;/span&gt; = &lt;span class="n"&gt;yourcompanyemail&lt;/span&gt;@&lt;span class="n"&gt;email&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;
&lt;span class="c"&gt;####################################################################
&lt;/span&gt;
[ &lt;span class="n"&gt;server_req_extensions&lt;/span&gt; ]
&lt;span class="n"&gt;subjectKeyIdentifier&lt;/span&gt; = &lt;span class="n"&gt;hash&lt;/span&gt;
&lt;span class="n"&gt;basicConstraints&lt;/span&gt;     = &lt;span class="n"&gt;CA&lt;/span&gt;:&lt;span class="n"&gt;FALSE&lt;/span&gt;
&lt;span class="n"&gt;keyUsage&lt;/span&gt;             = &lt;span class="n"&gt;digitalSignature&lt;/span&gt;, &lt;span class="n"&gt;keyEncipherment&lt;/span&gt;
&lt;span class="n"&gt;subjectAltName&lt;/span&gt;       = @&lt;span class="n"&gt;alternate_names&lt;/span&gt;
&lt;span class="n"&gt;nsComment&lt;/span&gt;            = &lt;span class="s2"&gt;"OpenSSL Generated Certificate"&lt;/span&gt;
&lt;span class="n"&gt;extendedKeyUsage&lt;/span&gt; = &lt;span class="n"&gt;clientAuth&lt;/span&gt;, &lt;span class="n"&gt;serverAuth&lt;/span&gt;
&lt;span class="c"&gt;####################################################################
&lt;/span&gt;
[ &lt;span class="n"&gt;alternate_names&lt;/span&gt; ]
&lt;span class="n"&gt;IP&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt; = &lt;span class="m"&gt;170&lt;/span&gt;.&lt;span class="m"&gt;17&lt;/span&gt;.&lt;span class="m"&gt;5&lt;/span&gt;.&lt;span class="m"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;IP&lt;/span&gt;.&lt;span class="m"&gt;2&lt;/span&gt; = &lt;span class="m"&gt;170&lt;/span&gt;.&lt;span class="m"&gt;17&lt;/span&gt;.&lt;span class="m"&gt;5&lt;/span&gt;.&lt;span class="m"&gt;6&lt;/span&gt;
&lt;span class="n"&gt;IP&lt;/span&gt;.&lt;span class="m"&gt;3&lt;/span&gt; = &lt;span class="m"&gt;170&lt;/span&gt;.&lt;span class="m"&gt;17&lt;/span&gt;.&lt;span class="m"&gt;5&lt;/span&gt;.&lt;span class="m"&gt;7&lt;/span&gt;
&lt;span class="n"&gt;IP&lt;/span&gt;.&lt;span class="m"&gt;4&lt;/span&gt; = &lt;span class="m"&gt;170&lt;/span&gt;.&lt;span class="m"&gt;17&lt;/span&gt;.&lt;span class="m"&gt;5&lt;/span&gt;.&lt;span class="m"&gt;254&lt;/span&gt;
&lt;span class="n"&gt;IP&lt;/span&gt;.&lt;span class="m"&gt;5&lt;/span&gt; = &lt;span class="m"&gt;127&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;IP&lt;/span&gt;.&lt;span class="m"&gt;6&lt;/span&gt; = ::&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;DNS&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt; = &lt;span class="n"&gt;localhost&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just to emphasize, I will repeat that I don’t know very well all items inside this configuration file. I found them on the internet across many stack overflow questions, MongoDB pages and etc. I will try to reference most of them at the final of this tutorial.&lt;/p&gt;

&lt;p&gt;Now we are good to go. So go ahead and run the generateSSLCerts.sh script in the Linux terminal. It will print step-by-step of what is going on. No errors should occur.&lt;/p&gt;

&lt;p&gt;If everything goes well we must go from this: &lt;a href="https://media.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%2F7n6q2vuec33smst07xko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F7n6q2vuec33smst07xko.png" alt="FolderBeforeRunScript"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;ssl folder content before run the script&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;To the following: &lt;a href="https://media.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%2Fcx2drt3tvln6r18e7q9p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fcx2drt3tvln6r18e7q9p.png" alt="FolderAfterRunScript"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;ssl folder content after you run the script&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;Each folder contains all the files needed to the containers operate with TLS. And that is it for this section. And we are almost finished. Just to show you, go back one folder and this is what you should see: &lt;a href="https://media.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%2F93gj95h715cmt4qtefq6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F93gj95h715cmt4qtefq6.png" alt="RootFolder"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;root folder where we a creating this amazing secure thing — yes it is missing the data folder&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;&lt;br&gt;
As you can see, there is one more folder structure that we have to create. It is the data folder which will hold the nodes database contents. Let’s go ahead and create a folder named “data” and inside of it you have to create three more folders named as it follows:

&lt;ul&gt;
&lt;li&gt;&lt;b&gt;“db_node_1”;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;“db_node_2”;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;“db_node_arbiter”;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that the folder structure are complete and we have all the necessary. Important thing to note we are creating exactly as we declared inside docker-compose.yml.&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="c1"&gt;# for example - node_1 &lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/OS/folder/data/node_1:/data/db&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s run docker-compose.yml and see what we got so far.&lt;/p&gt;




&lt;h2&gt;
  
  
  Configuring MongoDB ReplicaSet Cluster
&lt;/h2&gt;

&lt;p&gt;After you run the command you should get lots of log lines in the terminal. And that is normal. It stops more or less like the next image:&lt;br&gt;
&lt;a href="https://media.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%2Fafel2rvcfuch9tnvbnb3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fafel2rvcfuch9tnvbnb3.png" alt="LogDockerComposer"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;b&gt;Matrix log style! “You get used to it, I don’t even see the code, All I see is blond, brunette, redhead…”&lt;/b&gt;&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;We are now running and that is a very nice thing. And yet we do not have our cluster. We have to configure it. Let’s get over with it.&lt;/p&gt;

&lt;p&gt;Open another linux terminal shell and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# it executes a shell inside then container. You can choose the container in which to run. All three containers are the same for now.&lt;/span&gt;
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; mongo_node_1 /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After we run the previous command we will enter inside the container. Now we have to login inside mongoDB node_1. How do we do that? Any clues? Took a lot for me too. But I finally could craft the final command as it follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# this command helps us to log as root inside mongodatabase&lt;/span&gt;
&lt;span class="c"&gt;# we have to log as root to create the replicaset and the user&lt;/span&gt;
&lt;span class="c"&gt;# IMPORTANT: Note that we are inside the container and they are reflecting our node mapped volume&lt;/span&gt;
&lt;span class="c"&gt;# IMPORTANT2: remember the password set in the SCRIPT and cluster.conf. Yes we are using here to connect and decrypt the files&lt;/span&gt;
&lt;span class="c"&gt;# IMPORTANT3: the option --tlsAllowInvalidHostnames is necessary because we are using self-signed certificates!&lt;/span&gt;
mongo &lt;span class="nt"&gt;--tls&lt;/span&gt; &lt;span class="nt"&gt;--tlsCertificateKeyFile&lt;/span&gt; /data/ssl/mdb_nodes_keycert.pem &lt;span class="nt"&gt;--tlsCAFile&lt;/span&gt; /data/ssl/mdb_root_CA.crt &lt;span class="nt"&gt;--tlsCertificateKeyFilePassword&lt;/span&gt; mdb_my_custom_passphrase_security &lt;span class="nt"&gt;--tlsAllowInvalidHostnames&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we are logged inside the database. Let’s configure it. The first step is to set the ReplicaSet as it follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initiate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my_mdb_rs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;writeConcernMajorityJournalDefault&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;members&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;host&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;170.17.5.5:27017&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;host&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;170.17.5.6:27017&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;host&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;170.17.5.7:27017&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;arbiterOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;Important parts are the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;b&gt;_id&lt;/b&gt; of the configuration &lt;b&gt;is the ReplicaSet name&lt;/b&gt;, configured in the cluster file and when setting the mongo string connection.&lt;br&gt;
The last node we are setting is the arbiter. It has the &lt;b&gt;“arbiterOnly”&lt;/b&gt; flag to true&lt;br&gt;
You will see something like this:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fwgwzahei8pv1ac6a87fu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwgwzahei8pv1ac6a87fu.png" alt="SetReplicaOnMongoDB"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;b&gt;The vote happened, maybe you got the primary — not important&lt;/b&gt;&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;Now we have to set the user as it follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use admin;
db.createUser({
  user: "mdb_admin",
  pwd: "mdb_pass",
  roles: [
    {role: "root", db: "admin"},
    { role: "userAdminAnyDatabase", db: "admin" }, 
    { role: "dbAdminAnyDatabase", db: "admin" }, 
    { role: "readWriteAnyDatabase", db:"admin" }, 
    { role: "clusterAdmin",  db: "admin" }
  ]
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create the admin user that can connect properly outside the replicaset! It should be as demonstrated by the following image:&lt;br&gt;
&lt;a href="https://media.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%2F8cf420xovivyi8eczox9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8cf420xovivyi8eczox9.png" alt="MongoReplicaSetConfigured"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Success! We have now a configured mongo docker replica set with 3 nodes!&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;Now we are done! All set!&lt;/p&gt;

&lt;p&gt;To test it you can exit mongo terminal, but continue inside the container. Then run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Remember we set the user and pass environment into docker-compose.yml file. Well we can use them now!&lt;/span&gt;
mongo &lt;span class="nt"&gt;--tls&lt;/span&gt; &lt;span class="nt"&gt;--tlsCertificateKeyFile&lt;/span&gt; /data/ssl/mdb_nodes_keycert.pem &lt;span class="nt"&gt;--tlsCAFile&lt;/span&gt; /data/ssl/mdb_root_CA.crt &lt;span class="nt"&gt;--tlsCertificateKeyFilePassword&lt;/span&gt; mdb_my_custom_passphrase_security &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$MONGO_INITDB_ROOT_USERNAME&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$MONGO_INITDB_ROOT_PASSWORD&lt;/span&gt; &lt;span class="nt"&gt;--sslAllowInvalidHostnames&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should connect successfully! \o/. But wait… there is more! And a leave this section with the big question….&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;How can we connect now with MongoCompass or NodeJS ?&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Connecting with MongoCompass on our ReplicaSet
&lt;/h2&gt;

&lt;p&gt;Well, we started this journey a hundred years ago. You grow old and now.. look at you.. all smiley and wise!&lt;/p&gt;

&lt;p&gt;Now we finish our journey with the cherry on the top!&lt;/p&gt;

&lt;p&gt;To connect on mongocompass — first install it. It shouldn’t be difficult and I will not show it here. However I will go ahead and just open it and then show the following images that show how to configure it.&lt;/p&gt;

&lt;p&gt;After you open MongoCompass click in the text:&lt;br&gt;
&lt;b&gt;“Fill in connection fields individually”&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhcdwzirol9c4ww2yhkmb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhcdwzirol9c4ww2yhkmb.png" alt="MongoCompassScreen1"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;b&gt;Fill the fields as the image shows&lt;/b&gt;&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;For the next image, do remember the ssl folder ? So inside of it there is a folder named serverclient. There lies all the files that you need to select to connect and some more. You need to select the right ones so let’s see them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;b&gt;Certificate Authority:&lt;/b&gt; mdb_root_CA.crt&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Client Certificate:&lt;/b&gt; mdb_client.pem&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Client Private key:&lt;/b&gt; mdb_client.key&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Client Key Password:&lt;/b&gt; mdb_my_custom_passphrase_security&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, fill the “Replica Set Name” correctly.&lt;br&gt;
&lt;a href="https://media.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%2Fyurazkvr8fctis9h9kk5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fyurazkvr8fctis9h9kk5.png" alt="MongoCompassScreen2"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;b&gt;What could go wrong ? After what we just went through this should be easy!&lt;/b&gt;&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;

&lt;p&gt;If you did everything correctly.. well you should be connected =). Let’s see the next screen:&lt;br&gt;
&lt;a href="https://media.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%2Fo231s5cq4gjopa54xgbo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fo231s5cq4gjopa54xgbo.png" alt="MongoCompassConnected"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;Yes! We did it! =)&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;
&lt;h2&gt;
  
  
  Connecting with Mongoose in a NodeJS Application
&lt;/h2&gt;

&lt;p&gt;The last section, but not least, is to exemplify a connection with mongoose. The same again.. I will not show how to install and configure your NodeJS application with Mongoose, however I going to post the string connection that you can use. I struggled with it a little bit, but in the end I found the way.&lt;/p&gt;

&lt;p&gt;See the next image:&lt;br&gt;
&lt;a href="https://media.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%2F471wprexdz0j1b22hiqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F471wprexdz0j1b22hiqy.png" alt="NodeMongooseConfig"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;NodeJS configuration for Mongoose&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Yes. We did it! I hope that this tutorial helped you because for me it was very difficult. I had to learn all by myself, researching in the web. All the knowledge is there, the computer community is amazing everyone helping everyone. So I am trying to do the same. I did it by myself because others did first and helped leading the way!&lt;/p&gt;

&lt;p&gt;The code for this project is hosted on github!&lt;br&gt;
&lt;a href="https://github.com/arthurgermano/mongoreplicasetdocker" rel="noopener noreferrer"&gt;Github Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I want to say that I am sorry for my english. It isn’t my first language… so if I misspoke or I did something wrong let me know and feel free to correct me. =)&lt;/p&gt;

&lt;p&gt;Here there is some links which helped me find the path!&lt;br&gt;
&lt;a href="https://trainto.me/docker-mongodb-replicaset/" rel="noopener noreferrer"&gt;Docker - ReplicaSet&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/luizvnasc/mongodb-replicaset" rel="noopener noreferrer"&gt;Mongo - ReplicaSet&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.percona.com/blog/2018/05/31/mongodb-deploy-replica-set-with-transport-encryption-part-3/" rel="noopener noreferrer"&gt;Tutorial Mongo with ReplicaSet SSL&lt;/a&gt;&lt;br&gt;
&lt;a href="https://jamielinux.com/docs/openssl-certificate-authority/appendix/root-configuration-file.html" rel="noopener noreferrer"&gt;Root CA File Configuration&lt;/a&gt;&lt;br&gt;
&lt;a href="https://mydbops.wordpress.com/2020/05/02/securing-mongodb-cluster-with-tls-ssl/" rel="noopener noreferrer"&gt;Mongo Cluster with SSL and TLS&lt;/a&gt;&lt;br&gt;
&lt;a href="https://riptutorial.com/mongodb/example/29478/how-to-configure-a-replicaset-to-support-tls-ssl-" rel="noopener noreferrer"&gt;Configure MongoDB with TLS and SSL&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/21297139/how-do-you-sign-a-certificate-signing-request-with-your-certification-authority/21340898#21340898" rel="noopener noreferrer"&gt;Self-Signed Request With CA&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>docker</category>
      <category>tls</category>
      <category>certificates</category>
    </item>
  </channel>
</rss>
