<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[TippyBits]]></title><description><![CDATA[A portal to knowledge about everything from open source data platforms to generative AI. ]]></description><link>https://tippybits.com/</link><image><url>https://tippybits.com/favicon.png</url><title>TippyBits</title><link>https://tippybits.com/</link></image><generator>Ghost 5.82</generator><lastBuildDate>Sat, 18 Apr 2026 23:51:53 GMT</lastBuildDate><atom:link href="https://tippybits.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[How to get a Software Engineering role? Don’t.]]></title><description><![CDATA[How to find a software engineering role after college? Don’t. Software engineering is a broad topic. Find a niche to specialize in!]]></description><link>https://tippybits.com/how-to-find-a-software-engineering-role/</link><guid isPermaLink="false">6829f5c37ef3590001cbc0ca</guid><category><![CDATA[Software Engineering]]></category><category><![CDATA[Computer Science Degree]]></category><category><![CDATA[Graduating College]]></category><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Mon, 30 Jun 2025 14:30:00 GMT</pubDate><media:content url="https://tippybits.com/content/images/2025/06/nasa-Yj1M5riCKk4-unsplash-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2025/06/nasa-Yj1M5riCKk4-unsplash-1.jpg" alt="How to get a Software Engineering role? Don&#x2019;t."><p>You graduated with your Computer Science degree and are wondering, &#x201C;How do I get a software engineering job?&#x201D;. Don&#x2019;t&#x2026; I was talking with someone a few weeks ago at an Elastic DevCon event. She&#x2019;s a recent grad and was sharing about how challenging it is to find a role right now. I don&#x2019;t think she&#x2018;s wrong which is why I typically advise against looking for software engineering roles&#x2026;</p><p>I don&#x2019;t mean you shouldn&#x2019;t look for a job. The role, &#x201C;software engineer&#x201D; is super generic. Out of college, it&#x2019;s tempting to look for a generic role because you may not know what you want to specialize in. There are dozens if not hundreds of different areas to specialize in after all. But, if you can find a speciality your chances of getting hired go up massively.</p><h1 id="specializations-within-software-engineering"><strong>Specializations Within Software Engineering</strong></h1><p>So let&#x2019;s go through a few of them! I pulled together a broad list of specializations that you may come across. Within each of these there may be sub-areas you can also specialize. For example, in DevOps you may specialize in scaling, configuration management, or provisioning. </p><h3 id="infrastructure-tooling"><strong>Infrastructure &amp; Tooling</strong></h3><ul><li>DevOps / Platform Engineer &#x2013; Builds CI/CD pipelines, manages infra as code, and improves deployment velocity.</li><li>Build Systems Engineer &#x2013; Designs and maintains systems like Bazel, Buck, or Gradle for efficient builds.</li><li>Developer Productivity / DX Engineer &#x2013; Improves tools and workflows that other developers within your company use.</li><li>Test Automation Engineer &#x2013; Creates and maintains automated testing frameworks for CI and release readiness.</li></ul><h3 id="systems-level-engineering"><strong>Systems-Level Engineering</strong></h3><ul><li>Operating Systems / Kernel Engineer &#x2013; Works on OS internals, drivers, and low-level performance tuning.</li><li>Embedded Systems Engineer &#x2013; Writes software for devices with constrained resources like microcontrollers.</li><li>Networking / Network Automation Engineer &#x2013; Automates infrastructure (e.g., routers/switches) or develops network-heavy systems.</li></ul><h3 id="data"><strong>Data</strong></h3><ul><li>Search Engineer &#x2013; Designs and tunes search relevance, indexing pipelines, and vector search systems.</li><li>Data Engineer &#x2013; Builds pipelines and transforms data for analytics, ML, and operational needs.</li><li>Database Tooling Engineer &#x2013; Builds and maintains custom database infrastructure, schema migration tools, etc.</li></ul><h3 id="software-application-specialties"><strong>Software Application Specialties</strong></h3><ul><li>Backend Engineer &#x2013; Focuses on APIs, services, business logic, and database integration.</li><li>Frontend Engineer &#x2013; Specializes in building responsive and interactive user interfaces.</li><li>Mobile Developer &#x2013; Builds apps for iOS/Android, often with platform-specific constraints.</li><li>Integrations Engineer &#x2013; Connects systems via APIs, webhooks, or custom connectors.</li></ul><h3 id="advanced-niche-roles"><strong>Advanced / Niche Roles</strong></h3><ul><li>Programming Language Specialist &#x2013; Works on compilers, interpreters, or language specific tooling.</li><li>Observability Engineer &#x2013; Specializes in metrics, logging, tracing, and incident diagnostics.</li><li>Security Engineer &#x2013; Focuses on application security, auditing, threat modeling, and secure coding practices.</li><li>Performance Engineer &#x2013; Analyzes and improves latency, throughput, and resource usage across systems.</li></ul><h1 id="cross-functional-adjacent-roles-using-software-skills"><strong>Cross-Functional &amp; Adjacent Roles Using Software Skills</strong></h1><p>While these roles won&#x2019;t always involve writing code they benefit from a familiarity with software engineering. I find that a lot of these are great when paired with your other non-tech skills like interpersonal or organizational skills.</p><h3 id="product-marketing-customer-engagement"><strong>Product, Marketing &amp; Customer Engagement</strong></h3><ul><li>Product Manager (Technical) &#x2013; Translates user needs into engineering work, often with a computer science background.</li><li>Developer Advocate / DevRel &#x2013; Bridges engineering and marketing, creating content and engaging developers.</li><li>Technical Writer &#x2013; Writes documentation, tutorials, and internal guides for technical products.</li><li>Sales Engineer / Solutions Architect &#x2013; Supports sales by explaining technical concepts and customizing demos.</li><li>Technical Account Manager &#x2013; Supports large customers with the ongoing use and adoption of some software product. </li></ul><h3 id="support-ops-strategy"><strong>Support, Ops &amp; Strategy</strong></h3><ul><li>Support Engineer &#x2013; Provides technical support, triages bugs, and works with engineering on fixes.</li><li>Site Reliability Engineer (SRE) &#x2013; Ensures uptime and reliability of systems, often blending dev + ops.</li><li>Systems Administrator &#x2013; Manages servers, users, backups, and local IT needs&#x2014;especially in hybrid setups.</li><li>IT Automation Engineer &#x2013; Automates enterprise software provisioning, access controls, and device management.</li><li>Data Analyst / BI Engineer &#x2013; Uses SQL, dashboards, and scripts to help teams make data-driven decisions.</li><li>Technical advisor - typically helps build analyses for executives to help guide strategy. </li></ul><h3 id="special-projects-hybrid-roles"><strong>Special Projects &amp; Hybrid Roles</strong></h3><ul><li>Internal Tools Developer &#x2013; Builds bespoke software for non-engineering teams (e.g., finance, HR).</li><li>ML Ops / AI Infrastructure &#x2013; Supports deployment, monitoring, and tuning of machine learning models.</li><li>Research Software Engineer &#x2013; Bridges academia and industry, supporting research with production-grade code.</li><li>Digital Humanities / Scientific Computing &#x2013; Applies software engineering to the arts or sciences.</li></ul><h2 id="what-next">What Next?</h2><p>Now that you&#x2019;ve looked over the list, it&#x2019;s time to explore! Pick a role or two and start finding out what&apos;s involved with working in those roles. Many of them you can explore with a computer or the phone you are reading this on. Each niche has discord and slack communities that you can join to ask questions. Often they also have meetups where people get together to talk about them. <br><br>Find someone working in one of these fields and get a virtual coffee with them! The best way to find a role is to get involved in any way you can. Best of luck as you are finding your niche.</p>]]></content:encoded></item><item><title><![CDATA[Haystack 2025 Takeaways]]></title><description><![CDATA[Haystack 2025 highlighted the future of search with advances in vector search infrastructure, quantization, re-ranking strategies, and user behavior insights. Learn how modern search engines are scaling relevance and performance with cutting-edge techniques.]]></description><link>https://tippybits.com/haystack-2025-takeaways/</link><guid isPermaLink="false">680f97ef7ef3590001cbc085</guid><category><![CDATA[Haystack]]></category><category><![CDATA[Search Relevance]]></category><category><![CDATA[Vector Search]]></category><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Mon, 28 Apr 2025 15:12:45 GMT</pubDate><media:content url="https://tippybits.com/content/images/2025/04/HaystackFeatureImage.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2025/04/HaystackFeatureImage.jpg" alt="Haystack 2025 Takeaways"><p>There were two prevailing themes during Haystack this year: vector search infrastructure and relevance. As an industry, we&#x2019;ve recognized that vector search removes much of the intense work that was previously needed to build search. Synonym graphs and ontologies have given way to fine tuned embedding models. That is okay however because these systems are so new there is still a lot of engineering to make vector search stable and relevant.&#xA0;</p><h2 id="vector-search-infrastructure"><strong>Vector Search Infrastructure:</strong></h2><p>Everyone at the conference acknowledged the challenges with deploying vector search to production. Quantization is going to be a necessary technology to adopt in order for us to deploy vector search at scale. We need to be careful however because our lack of qualitative metrics will make it easy to deploy vector search and tank relevance. For Elastic here were the types and their profiles:&#xA0;</p><ul><li><strong>Binary Quantization</strong> - 40x faster, 32x less memory but at the cost of potentially tanking relevance</li><li><strong>Scalar Quantization (int4/int8) </strong>- 4x less memory with a minimal precision loss</li><li><strong>Product Quantization (PQ)</strong> - up to 64x less memory but requires much more data engineering. Achieves the least precision loss however.&#xA0;</li><li><a href="https://www.elastic.co/search-labs/blog/better-binary-quantization-lucene-elasticsearch?ref=tippybits.com"><strong><u>Better Binary Quantization (BBQ)</u></strong></a><strong> </strong>- Binary quantization can have the highest compression (aside from PQ) however is typically very lossy. BBQ solves this problem by normalizing around a centroid. Doing this allows it to perform faster than PQ without the infrastructure and engineering requirements. The challenge is while it does have higher recall Elastic noted it&#x2019;s precision is better when re-ranking the original vectors after retrieval.&#xA0;</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2025/04/DavidandJoelle.jpeg" class="kg-image" alt="Haystack 2025 Takeaways" loading="lazy" width="2000" height="1125" srcset="https://tippybits.com/content/images/size/w600/2025/04/DavidandJoelle.jpeg 600w, https://tippybits.com/content/images/size/w1000/2025/04/DavidandJoelle.jpeg 1000w, https://tippybits.com/content/images/size/w1600/2025/04/DavidandJoelle.jpeg 1600w, https://tippybits.com/content/images/2025/04/DavidandJoelle.jpeg 2000w" sizes="(min-width: 720px) 720px"><figcaption><a href="https://www.linkedin.com/in/robinsonjoelle/?ref=tippybits.com" rel="noreferrer"><span style="white-space: pre-wrap;">Joelle Robinson</span></a><span style="white-space: pre-wrap;"> and </span><a href="https://www.linkedin.com/in/davidfisher01/?ref=tippybits.com" rel="noreferrer"><span style="white-space: pre-wrap;">David Fisher</span></a><span style="white-space: pre-wrap;"> probably discussing the new </span><a href="https://docs.google.com/forms/d/e/1FAIpQLSdQWzlIcdkpRX8kucphHFGi3Qw0580msC0CubPWISSA84Rk_g/viewform?ref=tippybits.com" rel="noreferrer"><span style="white-space: pre-wrap;">mentorship program</span></a></figcaption></figure><h2 id="relevance"><strong>Relevance:&#xA0;</strong></h2><p>There were two primary patterns that were talked about in depth when it comes to relevance: re-ranking and precomputed enrichment.</p><h3 id="re-ranking">Re-ranking</h3><p>While this pattern has been around for a while it&#x2019;s gaining focus again. With larger and larger vector data stores we need to rethink search so it can meet our performance goals. This is where re-ranking comes into play. It involves using a much more broadly scoped query to retrieve a list of documents that are &#x201C;relevant enough&#x201D;. The retrieval phase mentioned here is supposed to find all the documents that may be relevant at the cost of probably including many that may not be.&#xA0;</p><p>After retrieval is where we implement the re-ranking step. This step takes the initial document step and adds precision using a more costly ranking algorithm. Some common re-ranking strategies could be the following:&#xA0;</p><ul><li><strong>Exact kNN</strong> - Once you have the first ~1000 or so documents you can re-create a graph with them and perform exact kNN on them to find a better sort order.</li><li><strong>Cross Encoders </strong>- With cross encoder models you can rescore each result by passing in the query and the sentences to the same model and produce a more accurate relevancy score. These are more expensive to run which is why we&#x2019;d run them in a re-ranking step.&#xA0;</li><li><strong>Personalization </strong>- Here we could use a two tower type approach to run personalization to further refine the results to be more close to what the current user expects.</li></ul><h3 id="enrichment">Enrichment:</h3><p>Data enrichment was one of the more bleeding edge practices beginning to gain traction. Data enrichment involves adding value by either aggregating or enriching documents to make them easier to retrieve or utilize in a generative workflow. Here were a few of the particularly interesting use cases that were seen:</p><ul><li>Generate questions that may be asked to retrieve that document. This can aid in retrieval for documents. Particularly if they are very long.&#xA0;</li><li>Summary generation for LLM&#x2019;s to utilize</li><li>Classification for better retrieval (eg. an issue may have a solution or not)</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2025/04/Frameworks.jpeg" class="kg-image" alt="Haystack 2025 Takeaways" loading="lazy" width="2000" height="2099" srcset="https://tippybits.com/content/images/size/w600/2025/04/Frameworks.jpeg 600w, https://tippybits.com/content/images/size/w1000/2025/04/Frameworks.jpeg 1000w, https://tippybits.com/content/images/size/w1600/2025/04/Frameworks.jpeg 1600w, https://tippybits.com/content/images/2025/04/Frameworks.jpeg 2000w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Froh and Sarah&apos;s frameworks side by side as they hot swapped parts. </span></figcaption></figure><h2 id="bleeding-edge"><strong>Bleeding Edge:</strong></h2><p>There were three things I saw used at the conference that I feel are on the bleeding edge for search. First and most accessible was an ML based boosting method for weighting hybrid queries. This talk by Daniel Wrigley took in features about the query in order to generate an optimal set of weights for the query. It looked at the number of tokens, average token length, etc to determine whether to bias to semantic or lexical retrieval. A sample of this workflow can be found in the <a href="https://github.com/o19s/learning-to-hybrid-search-haystack-us-25?ref=tippybits.com"><u>&#x201C;learning-to-hybrid-search&#x201D;</u></a> repo.&#xA0;</p><p>In a talk by Vespa they introduced a concept called: mapped tensor boosting. In this method they apply boosts to known tensors allowing for a more explainable search experience. An example of this could be boosting cars who have &#x201C;hatchback&#x201D; as a tensor value. While this boosting method is actually old in the space of the larger search engines like Yahoo and Google, it has still yet to gain mainstream popularity.&#xA0;</p><p>Finally, <a href="https://www.ubisearch.dev/?ref=tippybits.com" rel="noreferrer">user behavior insights (UBI)</a> is the last bleeding edge bit of technology. Again clickstream logging has been around for a long period however it&#x2019;s lacked a standard. With the addition of a standard clickstream based workflows can begin to be standardized.</p>]]></content:encoded></item><item><title><![CDATA[The Last Business Review]]></title><description><![CDATA[July 10th edition of the WBR. A running public review of my progress building TippyBits. This week included a new lead, the strategy is starting to work, and a new focus. ]]></description><link>https://tippybits.com/the-wbr-6-10-2024/</link><guid isPermaLink="false">6667009777e91b0001c77c16</guid><category><![CDATA[WBR]]></category><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Mon, 10 Jun 2024 14:41:10 GMT</pubDate><content:encoded><![CDATA[<p>This week there is a lot of excitement! I had one lead come from some of my outreach opportunities and I have a good feeling that I am starting to narrow down on a solid target market. This is thanks to a bit of help from <a href="https://jonathanstark.com/?ref=tippybits.com" rel="noreferrer">Jonathan Stark</a>! We had a great talk last week where he helped me work out what it is I am actually providing customers with because infrastructure doesn&apos;t sell. </p><ul><li>Business:<ul><li>I had one lead come from some outreach I did and sent out 10 other highly targeted outreach messages </li><li>On track to monthly goals with 1 external blog published, 1 blog published on my site, and 1 video that is launching today!</li></ul></li><li>Content: <ul><li>Syndicated my vector blog and video on OpenSearch&apos;s blog which lead to a huge uptick in traffic</li><li>Published <a href="https://tippybits.com/what-no-one-told-you-about-vector-search/" rel="noreferrer">&quot;What no one told you about vector search&quot;</a></li><li>Pushed video on <a href="https://youtu.be/q43Lb7DBtKs?si=tL1nSiPPdaK_W9tD&amp;ref=tippybits.com" rel="noreferrer">assembling my compute blade cluster</a> live today! Putting that into today&apos;s WBR as it was a large part of my time last week</li><li><a href="https://opensearch.org/blog/do-you-need-semantic-search/?ref=tippybits.com" rel="noreferrer">Syndicated blog</a> pushed to the OpenSearch website</li></ul></li><li>Social: </li><li>Why am I doing anything other than YouTube? Well it doesn&apos;t pay just yet. I am down -21% in viewership WoW but that is still my largest traffic source (671 views). Subscriber count is up 15% though (78-89 subs).</li><li>Website up to 229 users (+316%) showing that content syndication is the key to maintaining traffic at these early stages</li><li>Twitter saw a noticeable uptick in impressions (4234 impressions, +70%) because of two stupid tweets: </li></ul><figure class="kg-card kg-embed-card"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Wait, what did I miss?</p>&#x2014; David Tippett (@dtaivpp) <a href="https://twitter.com/dtaivpp/status/1798066671711875273?ref_src=twsrc%5Etfw&amp;ref=tippybits.com">June 4, 2024</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></figure><figure class="kg-card kg-embed-card"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">You want job security? Get into search relevance. There&apos;s like 1000 people in the search community and they all fit in one slack channel &#x1F605;</p>&#x2014; David Tippett (@dtaivpp) <a href="https://twitter.com/dtaivpp/status/1799615583585218988?ref_src=twsrc%5Etfw&amp;ref=tippybits.com">June 9, 2024</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></figure><ul><ul><li>LinkedIn has steadily chugged on (impressions +30% WoW, followers +1.5% WoW). It remains my biggest website traffic driver with 56% of my site traffic coming from LinkedIn in the last week</li></ul><li>Strategy: <ul><li>This week I&apos;ve pivoted (surprise) and am doing a lot more outreach at the advice of Jonathan. I&apos;ve avoided outreach until this point because I didn&apos;t have a specific enough target audience. Now that I&apos;ve honed down on that I made some changes to my site, LinkedIn bio, and twitter bio to better reflect what I am doing. </li></ul></li></ul>]]></content:encoded></item><item><title><![CDATA[What no one told you about vector search]]></title><description><![CDATA[As your adopting vector search missing these few things could make or break your experience. These are the things I've found nearly everyone misses when they are rolling out vector search. ]]></description><link>https://tippybits.com/what-no-one-told-you-about-vector-search/</link><guid isPermaLink="false">664bfbb777e91b0001c77a00</guid><category><![CDATA[OpenSearch]]></category><category><![CDATA[Vector Search]]></category><category><![CDATA[RAG]]></category><category><![CDATA[Data Engineering]]></category><category><![CDATA[Data Pipeline]]></category><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Wed, 05 Jun 2024 18:45:51 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/06/VectorSearchSecrets.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/06/VectorSearchSecrets.jpg" alt="What no one told you about vector search"><p>My background was never search or relevance engineering. For the ~7 years before I started working with OpenSearch I had been doing DevOps, data engineering, and software engineering. That&apos;s why I had such a hard time when vector search started to become so popular. It felt like every time I felt I knew what was happening my understanding was shaken up. Turns out it&apos;s not just me. I&apos;ve talked with countless engineers recently who have hit some of the same roadblocks that I&apos;ll be mentioning. </p><p>While I can&apos;t share everything I&apos;ve learned in just one blog here let&apos;s go through some of the top issues I&apos;ve seen over and over. These are the ones that would typically stop a company from ever adopting vectors into their search workflow. </p><h2 id="machine-learning-models-have-a-limited-input">Machine learning models have a limited input</h2><p>I was just talking to a company a few weeks back about their search use case. When I asked them if they had tried semantic search they said they had and the results were tragic. Shocked to hear this I asked why they thought it didn&apos;t work. From my perspective, I felt their use case was a perfect fit for vector search. </p><p>After digging in, I found that they were embedding documents that were tens of thousands of words long. This may seem reasonable until we start to look at how vector embeddings work in general and then specifically in OpenSearch. </p><p>When we embed documents we send them through a machine learning (ML) model. These models take in a fixed number of tokens and will output a representation as a vector of a fixed size. Tokens in most cases are just words separated by spaces.  ColBERTv2.0 for example takes in <a href="https://huggingface.co/colbert-ir/colbertv2.0/blob/main/tokenizer_config.json?ref=tippybits.com" rel="noreferrer">512 tokens by default</a> and outputs a vector with <a href="https://huggingface.co/colbert-ir/colbertv2.0/blob/c1e84128e85ef755c096a95bdb06b47793b13acf/config.json?ref=tippybits.com#L11" rel="noreferrer">768 floating-point numbers</a>. </p><figure class="kg-card kg-image-card"><img src="https://tippybits.com/content/images/2024/06/Embedding_process.png" class="kg-image" alt="What no one told you about vector search" loading="lazy" width="1000" height="500" srcset="https://tippybits.com/content/images/size/w600/2024/06/Embedding_process.png 600w, https://tippybits.com/content/images/2024/06/Embedding_process.png 1000w" sizes="(min-width: 720px) 720px"></figure><p>So how does OpenSearch handle text longer than the input maximum for a model? It truncates it. By this, I mean if you ingest a 1000-word document and the model only supports 512 tokens OpenSearch will simply cut your document down to 512 tokens and discard the rest. This is why the above company had bad relevance when they were embedding their hyper-long documents. Their documents were being cut down to the first 512 tokens and the remaining was discarded.</p><figure class="kg-card kg-image-card"><img src="https://tippybits.com/content/images/2024/06/Embedding_process_chopped.png" class="kg-image" alt="What no one told you about vector search" loading="lazy" width="1000" height="500" srcset="https://tippybits.com/content/images/size/w600/2024/06/Embedding_process_chopped.png 600w, https://tippybits.com/content/images/2024/06/Embedding_process_chopped.png 1000w" sizes="(min-width: 720px) 720px"></figure><p>The right way to handle documents with longer inputs depends on how you plan to query them. No matter what you do though I feel like cutting documents without alerting the user is bad UX. This is why I&apos;ve laid out the following proposal to change this pattern in OpenSearch. Check it out and please comment your thoughts!</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/opensearch-project/ml-commons/issues/2466?ref=tippybits.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">[FEATURE] Fail documents who&#x2019;s embedding field is larger than the token limit of an embedding model &#xB7; Issue #2466 &#xB7; opensearch-project/ml-commons</div><div class="kg-bookmark-description">Is your feature request related to a problem? Yes! I just had a discussion with @ylwu-amzn where we were discussing how documents are embedded. I (and many others I have talked to) were under the i&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" alt="What no one told you about vector search"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">opensearch-project</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/84069614e2a99bf924005daa81ad389ac9189bb144b50bac5bb56f638e1d1f99/opensearch-project/ml-commons/issues/2466" alt="What no one told you about vector search"></div></a></figure><h2 id="handling-longer-documents">Handling longer documents</h2><p>So with a fixed number of input tokens, how can these models embed longer documents? There are a few strategies we will explore here. Which you end up choosing depends on how you plan to access the documents. I think this will make a bit more sense as we start working through each of the scenarios. </p><p>You need chunks! Chunking is when we cut our documents into pieces. While this may seem like a simple task there are quite parameters to tune here. How big are our our chunks? Do they overlap? By how much? How do we represent these in OpenSearch? </p><p>Let&apos;s start with your goals for these documents. What do you plan on doing with them? For example, the company we mentioned above helped their users find books matching their search. Others may be looking to return just the most relevant chunk of a document for use in a retrieval augmented generation (RAG) pipeline.</p><h2 id="strategies-for-vector-ingestion">Strategies for vector ingestion</h2><p>When your goal is to retrieve a <strong>whole document</strong> I&apos;d recommend using OpenSearch&apos;s <a href="https://opensearch.org/docs/latest/search-plugins/text-chunking/?ref=tippybits.com" rel="noreferrer">ingestion pipeline for chunking documents</a>. This method will chunk the target field from the document into multiple vector embeddings. These will be stored in a nested field. This method comes with a few distinct advantages. With the score mode as &quot;max&quot; we can find the document that has the highest matching passage. We can also use &quot;avg&quot; to see which document has the most relevant chunks related to the query. </p><pre><code>GET index_name/_search
{
  &quot;query&quot;: {
    &quot;nested&quot;: {
      &quot;score_mode&quot;: &quot;avg&quot;,
      &quot;path&quot;: &quot;passage_chunk_embedding&quot;,
      &quot;query&quot;: {
        &quot;neural&quot;: {
          &quot;passage_chunk_embedding.knn&quot;: {
            &quot;query_text&quot;: &quot;document&quot;,
            &quot;model_id&quot;: &quot;-tHZeI4BdQKclr136Wl7&quot;
          }
        }
      }
    }
  }
}</code></pre><figure class="kg-card kg-image-card"><img src="https://tippybits.com/content/images/2024/06/Chunk_and_embed.png" class="kg-image" alt="What no one told you about vector search" loading="lazy" width="1275" height="499" srcset="https://tippybits.com/content/images/size/w600/2024/06/Chunk_and_embed.png 600w, https://tippybits.com/content/images/size/w1000/2024/06/Chunk_and_embed.png 1000w, https://tippybits.com/content/images/2024/06/Chunk_and_embed.png 1275w" sizes="(min-width: 720px) 720px"></figure><p>Again this is the strategy I would recommend for companies who&apos;s goal is to return the whole document. It&apos;s going to dramatically simplify your ingestion setup and your relevancy scoring. For people interested in returning the <strong>individual parts</strong> of a document for a RAG type use-case I am going to recommend using an external chunker such as <a href="https://docs.haystack.deepset.ai/docs/documentsplitter?ref=tippybits.com#overview" rel="noreferrer">Haystack&apos;s document splitter</a> or <a href="https://python.langchain.com/v0.1/docs/modules/data_connection/document_transformers/?ref=tippybits.com" rel="noreferrer">LangChain&apos;s text splitter</a>. These will allow you to split the documents into individual chunks and store them as separate documents. This is because the goal of RAG is to find the most relevant chunk to provide context for LLM generation.</p><figure class="kg-card kg-image-card"><img src="https://tippybits.com/content/images/2024/06/Chunked_RAG.png" class="kg-image" alt="What no one told you about vector search" loading="lazy" width="1275" height="499" srcset="https://tippybits.com/content/images/size/w600/2024/06/Chunked_RAG.png 600w, https://tippybits.com/content/images/size/w1000/2024/06/Chunked_RAG.png 1000w, https://tippybits.com/content/images/2024/06/Chunked_RAG.png 1275w" sizes="(min-width: 720px) 720px"></figure><h2 id="the-final-bosscapacity-planning">The final boss - capacity planning</h2><p>Once you have your strategy for ingesting vectors planned you need to start capacity planning. Vectors operate a bit differently in OpenSearch than typical documents. First off, embedding and ingesting embeddings takes significantly longer than ingesting text. It&apos;s important test and see how long this process takes for your documents. </p><p>Your nodes also need to be right-sized for vector search. Assuming you are using HNSW, which I feel most people will be, all of the vectors are going to be stored in memory. Below is the rough calculation for memory use with HNSW. This is with the out-of-the-box configuration.</p><pre><code>1.1 * (2 * &lt;dimensions&gt; + 128) * &lt;num_vectors&gt; ~= Bytes

# So for a 512 dimension vectors with 1,000,000 vectors:
1.1 * (2 * 512 + 128) * 1,000,000 ~= 1267200000 Bytes or 1.26GB</code></pre><p>I&apos;d recommend using memory-optimized instances for vector search. In AWS these are the &quot;R&quot; instances. One of the interesting things about vectors in OpenSearch is they are loaded in memory space outside of the JVM. So if 50% of your memory is dedicated to the JVM as typically recommended then you will have the remaining 50% for the OS and vector storage. </p><h2 id="is-that-it">Is that it?</h2><p>Not even close! There is so much to know when it comes to vector search. The things I&apos;ve covered here are just enough to help you get a solid start. There is still model fine-tuning, relevance engineering, hybrid search, and the list goes on. For a deeper dive on vectors in OpenSearch check out <a href="https://aws.amazon.com/blogs/big-data/amazon-opensearch-services-vector-database-capabilities-explained/?ref=tippybits.com" rel="noreferrer">this fantastic blog</a> from AWS.</p><p>If your company would like to evaluate vector search I am here to help! I&apos;ve worked with dozens of customers while working at AWS, get started with vector search and I&apos;d love to help you too! <a href="https://tippybits.com/services" rel="noreferrer">Schedule some time with me for your free consultation!</a></p>]]></content:encoded></item><item><title><![CDATA[Should you be using semantic search?]]></title><description><![CDATA[With all the hype around semantic search you might be asking, should you be using it too? We'll walk through what semantic search is and how you can use it to augment your search. ]]></description><link>https://tippybits.com/should-you-be-doing-vector-search/</link><guid isPermaLink="false">66393f27301d9c000156ce82</guid><category><![CDATA[OpenSearch]]></category><category><![CDATA[Semantic Search]]></category><category><![CDATA[Vector Search]]></category><category><![CDATA[Distillibert]]></category><category><![CDATA[How To]]></category><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Wed, 15 May 2024 14:30:16 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/05/Ferarri-Car.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/05/Ferarri-Car.jpg" alt="Should you be using semantic search?"><p>I&#x2019;ve been getting this question a lot recently. It&#x2019;s a fair question especially as people have been using the same tools for search for a long time. I&#x2019;ll walk you through some of the challenges with search as it currently exists. Then I&#x2019;ll show why and how to use semantic search in OpenSearch. Finally, we will cover some of the potential challenges with using vector search. While it has quite a few upsides they come at a cost.</p><h2 id="opensearchs-default-search">OpenSearch&apos;s default search </h2><p>OpenSearch by default is a lexical document store. This means it takes keywords from a query and tries to find them in the documents from your index. It can enrich documents using different analyzers like the <a href="https://opensearch.org/docs/latest/analyzers/?ref=tippybits.com#built-in-analyzers" rel="noreferrer">english language analyzer</a>. This one does stemming, where it evaluates <code>run</code> and <code>running</code> to the same word as they have the same root.</p><p>As OpenSearch finds documents with words matching your query it begins to calculate a relevance score. The score is based on how many times the words appeared in any document and how many other documents contain that word. This helps to filter out common words like <code>the</code> or <code>and</code> which exist in many documents. </p><p>These techniques have been the foundation of the search industry for years now. They do poorly when we have words that may be semantically similar like <code>sprint</code> and <code>run</code>. We may know intuitively that these words are similar. Unless we create some fairly complicated synonym rules, documents with <code>run</code> won&#x2019;t be returned if we have <code>sprint</code> in our query.</p><p>Even with synonym rules lexical search engines still struggle with context. Say we have a document with the phrase <code>racecar driver</code> and another with <code>golf driver</code>. If we search for <code>supercar driver</code> both of those documents will be returned because the term <code>driver</code> shows up in both. </p><h2 id="with-semantic-search">With semantic search</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/05/Semantic-to-Embedding.png" class="kg-image" alt="Should you be using semantic search?" loading="lazy" width="367" height="232"><figcaption><span style="white-space: pre-wrap;">How embedding models are related to vector search.</span></figcaption></figure><p>This is where semantic search comes into play. With machine learning (ML) models, we can create a representation of what a document means. The representation is encoded as a vector (an array of floating point numbers). Vectors are the way to represent and compare the outputs of these ML models. As shown above, many different types of models may output vectors that can be searched and compared to each other.  </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/05/Text-To-Embedding.png" class="kg-image" alt="Should you be using semantic search?" loading="lazy" width="397" height="222"><figcaption><span style="white-space: pre-wrap;">A depiction of what happens to text as it&apos;s embedded. </span></figcaption></figure><p>Using one of these semantic models we encode our documents as a vector. Above I have shown an example of what the output might look like. Even though each of the inputs are different lengths they are output to a consistent sized array of floating numbers between 0 and 1. Since there are 3 floating points per array you would say this is a 3 dimensional vector. When we run this we will use <a href="https://huggingface.co/sentence-transformers/msmarco-distilbert-base-tas-b?ref=tippybits.com" rel="noreferrer">msmarco-distilbert</a> which outputs vectors that have 768 dimensions. </p><p>Next, I&apos;ll plot these vectors so we can see what they might look like. OpenSearch uses some fancy linear algebra to compare vectors. This happens with functions like cosine similarity or dot product. I don&apos;t think there is any way to represent what&apos;s happening in a nice visual way so we will simplify it with the below plot.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/05/EmbeddingSpace-3.png" class="kg-image" alt="Should you be using semantic search?" loading="lazy" width="412" height="379"><figcaption><span style="white-space: pre-wrap;">A representation of what vectors look like plotted on a graph.</span></figcaption></figure><p>I&apos;ve also used the words next to the points to show the original documents these represent. As we can see words that are similar share dimensions. For example, it seems things related to golf share the 0.3 dimension on the X axis, whereas things related to driving are sharing a 0.5 dimension on the Y axis. </p><p>Now if we were to execute our search for <code>supercar driver</code> we would need to run the search phrase through our embedding model. This may look like <code>[0.47, 0.5, 0.01]</code>. This embedding will then be compared with the other vectors to find the ones that look most like it. Now we can see that our document <code>racecar driver</code> is very similar to <code>supercar driver</code>. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/05/Vector-Search-Example.png" class="kg-image" alt="Should you be using semantic search?" loading="lazy" width="412" height="379"><figcaption><span style="white-space: pre-wrap;">A graph showing the query for supercar driver plotted relative to documents in our index. </span></figcaption></figure><p>So semantic search is used when your users might not know the exact words they need to use to find the documents they want. Question-answering systems will likely be the type of systems where adding semantic search will improve the quality of result matches. These are the types of systems where people are asking questions and may not use the exact words in the documents. </p><h3 id="creating-a-semantic-search-experience-in-opensearch">Creating a semantic search experience in OpenSearch</h3><p>The best way to get started is to use the <a href="https://docs.aws.amazon.com/opensearch-service/latest/developerguide/ml-amazon-connector.html?ref=tippybits.com">OpenSearch connectors</a>. These will allow you to build an ingestion pipeline that will automatically create embeddings for data as it&#x2019;s sent into your cluster. These examples should be run from the OpenSearch devtools. </p><p>First, we will set up the cluster to support ML workloads and allow access to connectors. Below are the settings that we need to enable to run models in OpenSearch. </p><pre><code>PUT _cluster/settings
{
  &quot;persistent&quot;: {
    &quot;plugins&quot;: {
      &quot;ml_commons&quot;: {
        &quot;allow_registering_model_via_url&quot;: &quot;true&quot;,
        &quot;only_run_on_ml_node&quot;: &quot;false&quot;,
        &quot;model_access_control_enabled&quot;: &quot;true&quot;,
        &quot;native_memory_threshold&quot;: &quot;99&quot;
      }
    }
  }
}</code></pre><p>Next, we create a model group for access control. Save the Model ID for later</p><pre><code>POST /_plugins/_ml/model_groups/_register
{
    &quot;name&quot;: &quot;Model_Group&quot;,
    &quot;description&quot;: &quot;Public ML Model Group&quot;,
    &quot;access_mode&quot;: &quot;public&quot;
}
# MODEL_GROUP_ID:
</code></pre><p>Here is a sample using msmarco-distilbert as a local embedding model. This is going to be one of the most straightforward ways for us to test this. In the below make sure to past the model group ID we saved above. Now we are going to register the model into our cluster. This downloads the model for use locally. Remember to save the task ID generated here for the next steps. </p><pre><code>POST /_plugins/_ml/models/_register
{
    &quot;name&quot;: &quot;huggingface/sentence-transformers/msmarco-distilbert-base-tas-b&quot;,
    &quot;version&quot;: &quot;1.0.2&quot;,
    &quot;model_group_id&quot;: &quot;EPBkeI8BFtCmbnffsBiF&quot;,
    &quot;model_format&quot;: &quot;TORCH_SCRIPT&quot;
}
# TASK_ID:
</code></pre><p>Now we need to wait for the model to be pulled down and deployed. To check the status we can call the following:</p><pre><code>GET /_plugins/_ml/tasks/&lt;TASK_ID&gt;
# MODEL_ID:
</code></pre><p>When the state changes to <code>completed</code> then the operation is complete and we can grab the Model_ID and deploy it in our cluster.</p><pre><code>POST /_plugins/_ml/models/&lt;MODEL_ID&gt;/_deploy
# TASK_ID
</code></pre><p>This will result in a new task ID that we will use to check if the model gets deployed. Once this task shows as <code>complete</code> then we will know the model is ready for use.</p><pre><code>GET /_plugins/_ml/tasks/&lt;TASK_ID&gt;
</code></pre><p>We can test the model by trying to embed some text:</p><pre><code>### Testing the Embedding Model
POST /_plugins/_ml/_predict/text_embedding/&lt;MODEL_ID&gt;
{
  &quot;text_docs&quot;: [&quot;This should get embedded.&quot;],
  &quot;return_number&quot;: true,
  &quot;target_response&quot;: [&quot;sentence_embedding&quot;]
}</code></pre><p>If that returns a large array of floating point numbers we are in a good state! Now we can use the model in our ingestion and search pipeline. Below <code>embedding-ingest-pipeline</code> is just an arbitrary name for the pipeline. The important part is the field_map section. What happens in the ingestion pipeline is it will look for the <code>key</code> field, in this case <code>content</code>, and will send that to our ML model to get embedded. It will then store the result in the <code>content_embedding</code> field. The key field needs to match the name of the field you wish to embed in your source data but the value field there is arbitrary.</p><pre><code>PUT _ingest/pipeline/embedding-ingest-pipeline
{
  &quot;description&quot;: &quot;Neural Search Pipeline&quot;,
  &quot;processors&quot; : [
    {
      &quot;text_embedding&quot;: {
        &quot;model_id&quot;: &quot;&lt;MODEL_ID&gt;&quot;,
        &quot;field_map&quot;: {
          &quot;content&quot;: &quot;content_embedding&quot;
        }
      }
    }
  ]
}</code></pre><p>Now we create a hybrid search processor. This will allow us to do both traditional keyword search, alongside vector search and combine the result sets in the end. Here hybrid-search-pipeline is the name of our search pipeline. It can be whatever you would like so long as you use the same name when connecting it with your index.</p><pre><code>## Put the search pipeline in place
PUT _search/pipeline/hybrid-search-pipeline
{
  &quot;phase_results_processors&quot;: [
    {
      &quot;normalization-processor&quot;: {
        &quot;normalization&quot;: {
          &quot;technique&quot;: &quot;min_max&quot;
        },
        &quot;combination&quot;: {
          &quot;technique&quot;: &quot;arithmetic_mean&quot;,
          &quot;parameters&quot;: {
            &quot;weights&quot;: [
              0.3,
              0.7
            ]
          }
        }
      }
    }
  ]
}</code></pre><p>Now we can finally create an index mapping for our documents! I am saying index mapping as this simply specifies how certain fields should be mapped when being pushed into our OpenSearch index. Again <code>documents</code> is an arbitrary index name picked for this demo.</p><pre><code>PUT /documents
{
    &quot;settings&quot;: {
        &quot;index.knn&quot;: true,
        &quot;default_pipeline&quot;: &quot;embedding-ingest-pipeline&quot;,
        &quot;index.search.default_pipeline&quot;: &quot;hybrid-search-pipeline&quot;
    },
    &quot;mappings&quot;: {
        &quot;properties&quot;: {
            &quot;content_embedding&quot;: {
                &quot;type&quot;: &quot;knn_vector&quot;,
                &quot;dimension&quot;: 768,
                &quot;method&quot;: {
                    &quot;name&quot;: &quot;hnsw&quot;,
                    &quot;space_type&quot;: &quot;innerproduct&quot;,
                    &quot;engine&quot;: &quot;nmslib&quot;
                }
            },
            &quot;content&quot;: {
                &quot;type&quot;: &quot;text&quot;
            }
        }
    }
}
</code></pre><p>Finally, you should be able to insert documents into your index! I would recommend using the `_bulk` endpoint. It is the most straightforward way to send documents into an index in OpenSearch. Below is an example of what a bulk request looks like. The bulk endpoint expects newline delimited JSON. The first line is the action you wish to perform, and the second line is the document for that action to apply to.</p><pre><code>POST /documents/_bulk
{ &quot;index&quot;: {&quot;_id&quot;: &quot;1234&quot; } }
{ &quot;content&quot;: &quot;There once was a racecar driver that was super fast&quot;}
{ &quot;index&quot;: {&quot;_id&quot;: &quot;1235&quot; } }
{ &quot;content&quot;: &quot;The golf driver used by tiger woods is the TaylorMade Qi10 LS prototype&quot;}
{ &quot;index&quot;: {&quot;_id&quot;: &quot;1236&quot; } }
{ &quot;content&quot;: &quot;Some may say that supercar drivers dont really mind risk&quot;}</code></pre><p>Once your data is in we can finally pull it all together with a search.</p><pre><code>GET /documents/_search
{
  &quot;_source&quot;: {
    &quot;exclude&quot;: [
      &quot;content_embedding&quot;
    ]
  },
  &quot;query&quot;: {
    &quot;hybrid&quot;: {
      &quot;queries&quot;: [
        {
          &quot;match&quot;: {
            &quot;content&quot;: {
              &quot;query&quot;: &quot;sports automobile&quot;
            }
          }
        },
        {
          &quot;neural&quot;: {
            &quot;content_embedding&quot;: {
              &quot;query_text&quot;: &quot;sports automobile&quot;,
              &quot;model_id&quot;: &quot;&lt;MODEL_ID&gt;&quot;,
              &quot;k&quot;: 5
            }
          }
        }
      ]
    }
  }
}
</code></pre><p>Finally, here are the results! None of the documents contained the word sports or automobile. Our search was able to determine that the first two documents were  more related than the last one. In a production system, we would want to filter out results less than a certain threshold.  </p><pre><code>  &quot;hits&quot;: [
    {
      &quot;_index&quot;: &quot;documents&quot;,
      &quot;_id&quot;: &quot;1234&quot;,
      &quot;_score&quot;: 0.7,
      &quot;_source&quot;: {
        &quot;content&quot;: &quot;There once was a racecar driver that was super fast&quot;
      }
    },
    {
      &quot;_index&quot;: &quot;documents&quot;,
      &quot;_id&quot;: &quot;1236&quot;,
      &quot;_score&quot;: 0.17148913,
      &quot;_source&quot;: {
        &quot;content&quot;: &quot;Some may say that supercar drivers dont really mind risk&quot;
      }
    },
    {
      &quot;_index&quot;: &quot;documents&quot;,
      &quot;_id&quot;: &quot;1235&quot;,
      &quot;_score&quot;: 0.00070000003,
      &quot;_source&quot;: {
        &quot;content&quot;: &quot;The golf driver used by tiger woods is the TaylorMade Qi10 LS prototype&quot;
      }
    }
  ]</code></pre><h3 id="challenges-with-semantic-search">Challenges with semantic search</h3><p>Even though in this example we were able to see a huge benefit from semantic search not every use case will see the same results. The first challenge is when your business uses different terms and language than was represented in the training data. For example, in the world of search relevance, there are acronyms like bm25, tf-idf, and ndcg@10. These are industry specific and many language models won&apos;t know how to embed them. This could result in random documents being returned. One strategy is using a semantic model that has been fine-tuned on your data. </p><p>Another challenge with semantic search is it is more resource-intensive than lexical search. For example, HNSW is very memory intensive as all the vectors are stored in memory (check this <a href="https://opensearch.org/docs/latest/search-plugins/knn/knn-index/?ref=tippybits.com#memory-estimation">memory sizing documentation</a>). Additionally, ingestion takes longer as documents need to be run through the embedding models. Even with all this, several people will see huge benefits from adding vector search to their stack. </p><p>If you&apos;d like help evaluating semantic search I am here to help! Check out my <a href="https://tippybits.com/services" rel="noreferrer">services</a> page and schedule some time with me. I&apos;d love to talk about what you are building and if vector search is a good fit for you!</p>]]></content:encoded></item><item><title><![CDATA[Creating a Ghost site exposed with Cloudflare]]></title><description><![CDATA[Creating a self-hosted website doesn't have to be hard. We'll walk through how to deploy a GhostCMS site using Cloudfared as a reverse proxy with docker compose. ]]></description><link>https://tippybits.com/deploying-ghost-with-cloudflare/</link><guid isPermaLink="false">661ed1f717d20d00018eae1c</guid><category><![CDATA[GhostCMS]]></category><category><![CDATA[Cloudflare]]></category><category><![CDATA[Docker Compose]]></category><category><![CDATA[Self Hosted]]></category><category><![CDATA[Custom Website]]></category><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Fri, 03 May 2024 14:55:44 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/05/Ghost-and-Cloudflare-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/05/Ghost-and-Cloudflare-1.png" alt="Creating a Ghost site exposed with Cloudflare"><p>I&apos;ve used quite a few different methods for publishing blogs over the years. I helped build the <a href="https://opensearch.org/?ref=tippybits.com" rel="noreferrer">OpenSearch</a> blog on Jekyll, I&apos;ve published using a content platform like <a href="https://blog.tippybits.com/?ref=tippybits.com" rel="noreferrer">Medium</a>, and I&apos;ve written pages using C# and HTML. So far <a href="https://ghost.org/?ref=tippybits.com" rel="noreferrer">Ghost</a> has been my favorite. It&apos;s allowed me to move away from the tedious work of building pipelines for rendering my static pages and focus on writing. </p><p>Ghost is a content management system (CMS). That means I can add all sorts of dynamic elements such as comments, logins, etc. all from within Ghost. Not to mention they support integrations with payment providers allowing me to monetize some or all of my content. </p><p>Another thing that had kept me from hosting my own site for so long was not wanting to mess around with with SSL certificates or opening up ports on my firewall. This is where <a href="https://github.com/cloudflare/cloudflared?ref=tippybits.com" rel="noreferrer">Cloudflared</a> comes in. It&apos;s let me move the tricky work of DNS, SSL, and fire-walling onto a platform built by the experts in these spaces.</p><h2 id="before-we-get-started">Before we get started </h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/05/GhostSite.drawio.png" class="kg-image" alt="Creating a Ghost site exposed with Cloudflare" loading="lazy" width="831" height="551" srcset="https://tippybits.com/content/images/size/w600/2024/05/GhostSite.drawio.png 600w, https://tippybits.com/content/images/2024/05/GhostSite.drawio.png 831w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Sample architecture diagram for a Ghost site on an internal network</span></figcaption></figure><p>Above is a sample diagram of how I would deploy this in an internal network. Typically you will want to host externally accessible sites in a part of a network called a DMZ. In my example my DMZ is a VLAN separated from the rest of your network by a firewall that restricts it from accessing the other VLAN&apos;s. Since, Cloudflared is a reverse proxy it means we don&apos;t need to open ports on our networks firewall in order for outside users to get access to our site. </p><p><strong>Server:  </strong>You will need a server somewhere with internet access. I&apos;ve seen people use a <a href="https://www.raspberrypi.com/?ref=tippybits.com" rel="noreferrer">Raspberry Pi</a>, <a href="https://aws.amazon.com/pm/ec2/?ref=tippybits.com" rel="noreferrer">EC2 instance</a>, or an old laptop as a server for their site. You will want to set this server up with an operating system that specifically for the task. I&apos;d recommend something like the most recent <a href="https://ubuntu.com/download/server?ref=tippybits.com" rel="noreferrer">LTS version of Ubuntu Server</a> if you are newer to Linux. This is the one that I will demonstrate today.  </p><p>Once you have your server setup with Ubuntu you will want to install <a href="https://docs.docker.com/engine/install/ubuntu/?ref=tippybits.com" rel="noreferrer">Docker Engine</a>. Docker Engine does two things for us. Firstly it allows us to run containers which are a convenient way for us to run applications. Additionally, it comes with <code>docker compose</code> which is a utility that allows us to run several containers at once in an isolated network on our server. More on this later though.  </p><p><strong>Domain Name: </strong>This is how your users will access your site. Since we are using Cloudflare for our reverse proxy I&apos;d recommend purchasing your domain through them. It makes setting up your site much more straightforward. I won&apos;t be covering this in depth here as there are <a href="https://www.cloudflare.com/products/registrar/?ref=tippybits.com" rel="noreferrer">plenty of guides</a> on how to do this. </p><h2 id="configuring-your-site">Configuring your site</h2><p>To start I&apos;ve created a sample repo (linked below) that can help get you going quickly with deploying your website. I&apos;d recommend forking it to your own GitHub profile so you can modify it to fit your needs. </p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/dtaivpp/ghost-starter?ref=tippybits.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - dtaivpp/ghost-starter: Code for deploying a Ghost site with Cloudflared</div><div class="kg-bookmark-description">Code for deploying a Ghost site with Cloudflared. Contribute to dtaivpp/ghost-starter development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" alt="Creating a Ghost site exposed with Cloudflare"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">dtaivpp</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/b25f96065c4bb586675b0de947de8deb6e29db36d31f0f63ec2f571025c3583e/dtaivpp/ghost-starter" alt="Creating a Ghost site exposed with Cloudflare"></div></a></figure><p>Once you have forked it and cloned it down to your server you will need to make the bootstrap file executable. This allows us to run the script. </p><pre><code class="language-bash">cd ghost-starter
sudo chmod +x boostrap.sh
./boostrap.sh</code></pre><p>After running this script you will notice a few files have been created:</p><figure class="kg-card kg-image-card"><img src="https://tippybits.com/content/images/2024/05/TreeFiles.png" class="kg-image" alt="Creating a Ghost site exposed with Cloudflare" loading="lazy" width="857" height="446" srcset="https://tippybits.com/content/images/size/w600/2024/05/TreeFiles.png 600w, https://tippybits.com/content/images/2024/05/TreeFiles.png 857w" sizes="(min-width: 720px) 720px"></figure><p>Inside the MySQL password and root password files you will find auto-generated passwords. You do not need to use these passwords however they tend to be harder to crack than manually created passwords.</p><p>Next, we will want to look at the .env file. It contains several configuration parameters we will want to set. The first will be the URL for your domain. This will effect where relative links go. When testing you will likely set this to something like <code>http://localhost:2368</code> and for production you will want to set this to your domain name like: <code>https://tippybits.com</code> . </p><p>For our MySQL user this could be whatever you want to name your database user. Since I am just using this database for Ghost I will go with <code>ghostdb</code> here. Then the last setting I will talk about in this section is the <code>DEPLOYMENT</code> flag. This is how we will switch from a development Ghost instance to a production one. </p><pre><code># Change the domain to your website or localhost if testing.
URL=&lt;https://yourdomain.com&gt;

# Could be any user youd like
MYSQL_USER=ghostdb

# SMTP - Mail from is an address you have permissions to mail from. Below is just a demo. 
# SMTP User - Username provided by your SMTP service
MAIL_FROM=noreply@&lt;mail.yourdomain.com&gt;
SMTP_USER=

# Set between production and development
DEPLOYMENT=development</code></pre><p><strong>Mailserver: </strong>This step is optional but if you&apos;d like users to be able to login, comment, you will need to configure the SMTP settings. You can use Mailgun for this. I am not going to go through the whole process of how to setup Mailgun with your domain as they have guides that help with this when you create your account. What I will tell you is how to find your SMTP credentials once you&apos;ve setup your domain to send and receive mail from Mailgun. </p><p>Go into your account and go to &quot;Sending&quot; on the left bar. Then select &quot;Domains&quot; and pick your domain from the list. Then you can go to the left bar again and select &quot;Domain Settings&quot; and you will see the below window. From here we will select SMTP and grab those settings and input the username into the <code>.env</code> file in the <code>SMTP_USER</code> field. This will probably be something like <code>postmaster@&lt;yourdomain.com&gt;</code>. The password will go into the <code>/secrets/SMTP_PASS.txt</code> file we created earlier. </p><figure class="kg-card kg-image-card"><img src="https://tippybits.com/content/images/2024/05/MailGunSend.png" class="kg-image" alt="Creating a Ghost site exposed with Cloudflare" loading="lazy" width="1207" height="448" srcset="https://tippybits.com/content/images/size/w600/2024/05/MailGunSend.png 600w, https://tippybits.com/content/images/size/w1000/2024/05/MailGunSend.png 1000w, https://tippybits.com/content/images/2024/05/MailGunSend.png 1207w" sizes="(min-width: 720px) 720px"></figure><p><strong>Cloudflared: </strong>I debated if I should put this in the configuration section because it&apos;s bound to cause some confusion. Let me be clear here though, <strong>do not store your cloudflared token</strong> in your development environment. Only put the token on your production server. Otherwise your local development environment will become your production. </p><p>With that out of the way you will need to go to <a href="https://one.dash.cloudflare.com/?ref=tippybits.com">https://one.dash.cloudflare.com/</a> to login to your Cloudflare Access&#x2122; dashboard. Once you&apos;ve logged in you will go to the left bar and select &quot;Networks&quot; -&gt; &quot;Tunnels&quot;. Then we will select &quot;Create a tunnel&quot; and &quot;Cloudflared&quot;.  Then you will name your tunnel. I kept it simple here and used <code>sitename-ghostcms</code>. Next you will get a screen where you can copy your tunnel deployment. I selected the docker option and copied it. <strong>Do not run this command. </strong>We are going to paste it onto a note pad or something and pull the token out. </p><pre><code>docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token IjoiMTwtafwefawefweflktaelgrZTQ2NmJkYjA2YWY2YmE0OGIiLCJ0IjoiOTViNGU1OGQtNWQ1ZS00YmQ0LTg5ZGItYTdmYWI5NDQwfgw34tk1ERXdZamRsT0RrdFpEZzRNQzAwT1RjMkxUaGlOVaw4ffaw43amd5WW1R</code></pre><p>The above is what it will look like (no that is not a real token but you can try if you want). We are going to copy everything after <code>--token</code> and paste it into our production servers <code>/secrets/CLOUDFLARE_TOKEN.txt</code> file. This is the magic that will connect our Cloudflared container to our account. Finally, we will connect the tunnel to our domain. Below is the settings you will want to use with your own domain name of course. </p><p>This configuration step takes all traffic going to your domain, such as tippybits.com, and routes it through a tunnel managed by Cloudflare that ends up on your server via your cloudflared container. This container next routes the request to `http://ghost:2368` which is the local hostname for your Ghost container. It took me forever to understand this. If you use this setup with your domain you should be good to go. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/05/CloudflareDashboard.png" class="kg-image" alt="Creating a Ghost site exposed with Cloudflare" loading="lazy" width="1149" height="817" srcset="https://tippybits.com/content/images/size/w600/2024/05/CloudflareDashboard.png 600w, https://tippybits.com/content/images/size/w1000/2024/05/CloudflareDashboard.png 1000w, https://tippybits.com/content/images/2024/05/CloudflareDashboard.png 1149w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Setting up Cloudflared to access your local docker container</span></figcaption></figure><h2 id="deploying">Deploying </h2><p>Phew. I feel like 99% of the work here is configuring your environment &#x1F62E;&#x200D;&#x1F4A8;. Now we can do the fun part. LETS DEPLOY! To run your website execute the following command: </p><pre><code class="language-bash">docker compose up -d</code></pre><p>This will download and start up all of the containers with the configuration we have provided. There are a few things I want to point you to while this is starting up. We have not touched the <code>docker-compose.yml</code> file until this point but its worth looking at now. </p><p>Ghost does not seem to support accepting configuration via both config files and environment variables. I elected to add the config via environment variables. I couldn&apos;t seem to find anyone who had done the same. Any configuration option you find on the ghost documentation can be represented with an environment variable flag. Here&apos;s how:</p><pre><code class="language-json">mail: {
  from: some@email.com
  transport: SMTP
  options: {
    service: Mailgun
    host: smtp.mailgun.org
  }
}  </code></pre><p>Above we can see a sample config. We can turn this into environment variable config by separating each of the elements with a double underscore. This allows us to set any option that you see in the documentation. The above looks like this in our docker compose environment config.</p><pre><code class="language-yml">services:
  ghost:
    image: ghost:latest
    restart: always
    ports:
      - &quot;2368:2368&quot;
    environment:
      mail__from: some@email.com
      mail__transport: SMTP
      mail__options__service: Mailgun
      mail__options__host: smtp.mailgun.org</code></pre><p>Hope this helps someone who was as lost as I was when Ghost was overwriting your config files. </p><p><strong>Claim your site! </strong>Finally, we can navigate to your site at the domain name you specified in Cloudflare. You will want to quickly go to https://yoursite.com/ghost to create your account and claim your site. And that&apos;s all! Now you can enjoy your time publishing blogs and building your own brand. If you&apos;ve enjoyed this post and want to keep up with my content hit that little sign up button below! Cheers &#x1F60A;</p>]]></content:encoded></item><item><title><![CDATA[My next steps after AWS]]></title><description><![CDATA[After two years working at AWS helping people with OpenSearch I am taking the next step in my career! ]]></description><link>https://tippybits.com/my-next-steps-after-aws/</link><guid isPermaLink="false">6621882417d20d00018eaea0</guid><category><![CDATA[return to office]]></category><category><![CDATA[AWS]]></category><category><![CDATA[OpenSearch Consulting]]></category><category><![CDATA[Leaving Amazon]]></category><category><![CDATA[open source OpenSearch]]></category><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Mon, 22 Apr 2024 16:01:33 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/04/StonePlants.JPG" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/04/StonePlants.JPG" alt="My next steps after AWS"><p>I spent the last 2 years working as the senior developer advocate for OpenSearch at AWS. I loved my role &#x2665;&#xFE0F; The community was incredibly welcoming and I got to work with some of the most brilliant engineers. During my time there I presented 33 times in 7 different countries. I covered everything from GenAI to deploying open source OpenSearch on Kubernetes.</p><p>So why leave? Amazon has a <a href="https://apnews.com/article/amazon-return-to-office-jassy-remote-work-ce9cb14169f5ee1552868d1385ce2ec8?ref=tippybits.com" rel="noreferrer">serious return to office initiative</a>. The pressure to relocate was relentless. The uncertainty about my position and the notifications I got about being &quot;non-compliant&quot; was unmanageable.  I have two small kids, 1.5 and 4 years old, and most of my family and my wife&apos;s family live locally. There was just too much support for me here to be willing relocate. I strongly hold to the belief that my family comes first. </p><p>I&apos;m not the one to typically leave before I have a plan for what&apos;s next. This time was different though. My last day was on Friday March 8th 2023. Without a plan in mind I left AWS. The first few weeks I spent interviewing with different companies, catching up with people, and praying for God to show me what He had in store for me. ~30 interviews and meetings later I still hadn&apos;t come across a role that I felt fit what I was looking for.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/Vacation.jpg" class="kg-image" alt="My next steps after AWS" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/Vacation.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/Vacation.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/Vacation.jpg 1600w, https://tippybits.com/content/images/2024/04/Vacation.jpg 2000w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">My in front the yurt we stayed in near Shenandoah </span></figcaption></figure><p>Naturally (or not) my next move was to take a vacation with my family. &#x1F606; Not the move most people make when they are looking for work. During this time I reflected on what it is that I liked so much about my role at AWS. The truth is I loved sharing my expertise with others. I also am passionate about the OpenSearch community. </p><h1 id="i%E2%80%99m-consulting">I&#x2019;m Consulting! </h1><p>After all that time I&#x2019;ve decided that what works best for me is continuing to help others with OpenSearch! I&#x2019;ll be taking what I&#x2019;ve learned over the last two years and helping others get started on their journey with OpenSearch. My experience working with the different companies and tool sets within the OpenSearch community prepared me to best help you!  </p><p>If you are looking for help with OpenSearch particularly with anything from configuring your cluster to generative AI <a href="https://tippybits.com/services" rel="noreferrer"><strong>I am here to help</strong></a>! I am doing a free consultation where we can talk about the initiatives your team has. We&apos;ll then create a plan to get you on a roll. </p><p>If you&apos;ve enjoyed working with me or referenced some material I&apos;ve created I need your help sharing! Starting out as a consultant is challenging and I won&apos;t be successful without the continued support of the community (that means you too!). With that you can <a href="https://tippybits.com/#/portal/signup" rel="noreferrer">signup</a> to get all the latest blog posts on making OpenSearch work better for you. Thanks to everyone who&apos;s supported me so far and I&apos;m looking forward to continuing to share this journey with you!</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/DavidTippett.JPG" class="kg-image" alt="My next steps after AWS" loading="lazy" width="1024" height="1024" srcset="https://tippybits.com/content/images/size/w600/2024/04/DavidTippett.JPG 600w, https://tippybits.com/content/images/size/w1000/2024/04/DavidTippett.JPG 1000w, https://tippybits.com/content/images/2024/04/DavidTippett.JPG 1024w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Recording media for OpenSearchCon 2023</span></figcaption></figure>]]></content:encoded></item><item><title><![CDATA[Welcome to TippyBits!]]></title><description><![CDATA[<p>After publishing my blogs for years to Medium.com I felt it was time for a change. I got started writing back in 2019 and at the time Medium was the low hassle way to publish blogs that could reach a great audience and have impact on people. I&apos;</p>]]></description><link>https://tippybits.com/coming-soon/</link><guid isPermaLink="false">661945f4226da30001736aa8</guid><category><![CDATA[News]]></category><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Fri, 12 Apr 2024 14:32:20 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/04/DSC01204.JPG" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/04/DSC01204.JPG" alt="Welcome to TippyBits!"><p>After publishing my blogs for years to Medium.com I felt it was time for a change. I got started writing back in 2019 and at the time Medium was the low hassle way to publish blogs that could reach a great audience and have impact on people. I&apos;ve come to dislike how they choose to distribute content or not so I am moving here! </p><p>So welcome to the new start for me! My name is David and I am a great many things. Here you will find blogs about open source software development, developer relations, search engineering, and even data infrastructure. Professionally, I spent 2 years at AWS as the developer relations lead for <a href="https://opensearch.org/?ref=tippybits.com" rel="noreferrer">OpenSearch</a>. There I was rebuilding the community that had been shattered by Elasticsearch&apos;s license change. With their return to office mandate however I decided to leave and plot my own path. </p><p>If you like the work I do you can <a href="#/portal/">subscribe</a> if to stay up to date and receive emails when new content is published! Additionally, I am doing consulting in the areas of GenAI, search infrastructure (preferably related to OpenSearch), and developer relations. </p><p>There are plenty of other ways to stay involved as well! I run a <a href="https://www.youtube.com/@TippyBits?ref=tippybits.com" rel="noreferrer">YouTube channel</a>, am active on <a href="https://twitter.com/dtaivpp/?ref=tippybits.com" rel="noreferrer">Twitter</a>, <a href="https://www.linkedin.com/in/david-tippett/?ref=tippybits.com" rel="noreferrer">LinkedIn</a>, and of course <a href="https://github.com/dtaivpp/?ref=tippybits.com" rel="noreferrer">GitHub</a>. </p>]]></content:encoded></item><item><title><![CDATA[Mobile LiveStream Setup]]></title><description><![CDATA[On the go and need to stream? Discover how this developer advocate optimized a home kit for high-quality mobile live streaming.]]></description><link>https://tippybits.com/mobile-livestream-setup/</link><guid isPermaLink="false">6619856da8aa900001525186</guid><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Thu, 27 Jul 2023 19:33:45 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/04/1-yzzfk-tvkoek2v60qroqpw-2x-jpeg.jpg" medium="image"/><content:encoded><![CDATA[<h3 id="on-the-go-live-streaming-essential-gear-for-developer-advocates">On-the-Go Live Streaming: Essential Gear for Developer Advocates</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-gq0stz9o3wpuwhe9rauisw-2x-jpeg.jpg" class="kg-image" alt="Mobile LiveStream Setup" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-gq0stz9o3wpuwhe9rauisw-2x-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-gq0stz9o3wpuwhe9rauisw-2x-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-gq0stz9o3wpuwhe9rauisw-2x-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-gq0stz9o3wpuwhe9rauisw-2x-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>What I use to stream on the&#xA0;go.</figcaption></figure><img src="https://tippybits.com/content/images/2024/04/1-yzzfk-tvkoek2v60qroqpw-2x-jpeg.jpg" alt="Mobile LiveStream Setup"><p>As a developer advocate I am often on the road and sometimes the stars align such that I need to do a live stream while I am out. It&#x2019;s often enough to where I have a plan an not often enough to buy a whole separate kit for it. As a result I&#x2019;ve designed my home kit around the idea that it needs to work well for streaming on the go.</p><h3 id="camera">Camera</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/0-96tvbbszhaa_y0ds.png" class="kg-image" alt="Mobile LiveStream Setup" loading="lazy" width="600" height="523" srcset="https://tippybits.com/content/images/2024/04/0-96tvbbszhaa_y0ds.png 600w"><figcaption>Credit: <a href="https://electronics.sony.com/imaging/interchangeable-lens-cameras/aps-c/p/ilczve10-b?ref=tippybits.com" data-href="https://electronics.sony.com/imaging/interchangeable-lens-cameras/aps-c/p/ilczve10-b" class="markup--anchor markup--figure-anchor" rel="noopener" target="_blank">2022 Sony Electronics Inc.</a></figcaption></figure><p>I shoot on the Sony <a href="https://electronics.sony.com/imaging/interchangeable-lens-cameras/aps-c/p/ilczve10-b?ref=tippybits.com" rel="noopener">ZV-E10</a>. It&#x2019;s a common choice amongst people getting into this space as it is a light mirrorless camera that shoots 4k and has a solid auto focus. Additionally, it has a flip out screen which makes getting the framing right super easy when you are on the go.</p><p>The funny thing is when I am streaming I don&#x2019;t shoot in 4k for a few reasons. First, hotel WiFi is never good enough to reliably shoot at that quality. Second, when I am on a live stream I will be using picture in picture mode so my head is in a small square at the bottom. Arguably the most practical reason is the ZV-E10 has a USB-C output it can use to stream (in 1080p) and that saves me from having to bring a HDMI capture device.</p><h3 id="lens">Lens</h3><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tippybits.com/content/images/2024/04/1-ggr5aniqjindwgfpqjduba-jpeg.jpg" width="2000" height="1125" loading="lazy" alt="Mobile LiveStream Setup" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-ggr5aniqjindwgfpqjduba-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-ggr5aniqjindwgfpqjduba-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-ggr5aniqjindwgfpqjduba-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-ggr5aniqjindwgfpqjduba-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tippybits.com/content/images/2024/04/1-n22rhj0vuywggnlwactgla-jpeg.jpg" width="2000" height="1125" loading="lazy" alt="Mobile LiveStream Setup" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-n22rhj0vuywggnlwactgla-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-n22rhj0vuywggnlwactgla-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-n22rhj0vuywggnlwactgla-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-n22rhj0vuywggnlwactgla-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption><strong class="markup--strong markup--figure-strong">First Image</strong>: Stock 16&#x2013;50mm lens <strong class="markup--strong markup--figure-strong">Second Image: </strong>Sony 11mm wide&#xA0;angle</figcaption></figure><p>I&#x2019;d argue that your choice of lens actually may be more important than the camera. The two photos above were taken using the default settings at 20 inches from my face. As you can see the stock lens has a really tight framing meaning you need to have the camera placed far away from your face to get a decent shot.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/0-jz_mofs6icbop-ap.png" class="kg-image" alt="Mobile LiveStream Setup" loading="lazy" width="600" height="523" srcset="https://tippybits.com/content/images/2024/04/0-jz_mofs6icbop-ap.png 600w"><figcaption>Credit: <a href="https://electronics.sony.com/imaging/lenses/all-e-mount/p/sel11f18?cid=sem-na-3349&amp;utm_source=google&amp;utm_medium=cpc&amp;utm_campaign=Shopping%20ads%20%28United%20States%29%20Low%20Performing%20Sku%27s&amp;utm_term=PRODUCT_GROUP&amp;gclid=CjwKCAjwq4imBhBQEiwA9Nx1BnUGYx915QhIoV5-haULwMV2xNWJVaSaKHUMH4YupUDgES_OL4nAsBoC2vcQAvD_BwE&amp;gclsrc=aw.ds" data-href="https://electronics.sony.com/imaging/lenses/all-e-mount/p/sel11f18?cid=sem-na-3349&amp;utm_source=google&amp;utm_medium=cpc&amp;utm_campaign=Shopping%20ads%20(United%20States)%20Low%20Performing%20Sku%27s&amp;utm_term=PRODUCT_GROUP&amp;gclid=CjwKCAjwq4imBhBQEiwA9Nx1BnUGYx915QhIoV5-haULwMV2xNWJVaSaKHUMH4YupUDgES_OL4nAsBoC2vcQAvD_BwE&amp;gclsrc=aw.ds" class="markup--anchor markup--figure-anchor" rel="noopener" target="_blank">2022 Sony Electronics Inc.</a></figcaption></figure><p>The lens I recommend to remediate this is the <a href="https://electronics.sony.com/imaging/lenses/all-e-mount/p/sel11f18?ref=tippybits.com" rel="noopener">Sony 11mm F1.8</a> wide angle lens. As you can see even though it is a fixed lens (can&#x2019;t zoom) it does really great at capturing not only you but your background as well. The 1.8 aperture making this a great lens for low light settings as well.</p><h3 id="microphone">Microphone</h3><p>The lens may be more important than the camera but the mic tops even that. If you think about it it doesn&apos;t matter how good you look if no one can hear you. This is where I am probably going to have the most disagreements with people on this blog because I went in a fairly non-standard mic.</p><p>There are lapel mics, shoe mounted mics, handheld mics and they all do things a bit differently. Many people recommend the <a href="https://rode.com/en-us/microphones/on-camera/videomic-go?ref=tippybits.com" rel="noopener">Rode VideoMic Go</a> as it&#x2019;s a great passive mic (no power needed). I didn&#x2019;t end up going with it however as I wanted something more flexible. The VideoMic Go is an directional mic meaning it captures audio just from in front of it. That is great but what if you wanted to capture ambient audio?</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/0-n30nfqgiw8zs1gif.png" class="kg-image" alt="Mobile LiveStream Setup" loading="lazy" width="600" height="523" srcset="https://tippybits.com/content/images/2024/04/0-n30nfqgiw8zs1gif.png 600w"><figcaption>Credit: <a href="https://electronics.sony.com/imaging/imaging-accessories/all-accessories/p/ecmb10?ref=tippybits.com" data-href="https://electronics.sony.com/imaging/imaging-accessories/all-accessories/p/ecmb10" class="markup--anchor markup--figure-anchor" rel="noopener" target="_blank">2022 Sony Electronics Inc.</a></figcaption></figure><p>I went with the <a href="https://electronics.sony.com/imaging/imaging-accessories/all-accessories/p/ecmb10?ref=tippybits.com" rel="noopener">Sony ECM-B10</a>. It&#x2019;s an active microphone that allows you to either do directional audio capture or capture ambient sounds. Additionally, it has features to auto adjust volume, boost volume, add noise filters, and the list goes on. While it doesn&apos;t have the best shock mount to absorb noise from when I am holding the camera and recording I don&#x2019;t need that. That is not how I use my camera most often.</p><h3 id="tripod">Tripod</h3><figure class="kg-card kg-embed-card"><iframe src="https://www.youtube.com/embed/oMy9NgZArEM?start=143&amp;feature=oembed&amp;start=143" width="700" height="393" frameborder="0" scrolling="no"></iframe></figure><p>So Casey Neistat has a video about his bendy tripod which is &#x201C;good&#x201D; at a lot of things but not great at everything. I&#x2019;ve taken a similar approach with my tripod. While it may not be the best at everything it does well for what I need it for and is flexible enough to meet a majority of my needs.</p><p>It&#x2019;s the <a href="https://www.pgytech.com/products/mantispod-vlog-tripod?ref=tippybits.com" rel="noopener">Pgytech Mantis Pod Pro</a>. Honestly, I get more questions about this little tripod than any of my other pieces of kit in my setup. This thing feels like it has 100 different setups that it can do an the nice thing is it&#x2019;s rigid. That means after you set it up it won&#x2019;t be flopping over. It&#x2019;s literally the spider monkey of camera stands and they need to give me a referral link because I recommend it so much.</p><figure class="kg-card kg-image-card"><img src="https://tippybits.com/content/images/2024/04/1-lthhtroe-mc3zvsiddrzsw-2x-jpeg.jpg" class="kg-image" alt="Mobile LiveStream Setup" loading="lazy" width="1920" height="1080" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-lthhtroe-mc3zvsiddrzsw-2x-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-lthhtroe-mc3zvsiddrzsw-2x-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-lthhtroe-mc3zvsiddrzsw-2x-jpeg.jpg 1600w, https://tippybits.com/content/images/2024/04/1-lthhtroe-mc3zvsiddrzsw-2x-jpeg.jpg 1920w" sizes="(min-width: 720px) 720px"></figure><h3 id="other-bits-and-bobs"><strong>Other bits and bobs</strong></h3><p>There are a few other things I carry but don&#x2019;t really have much of an explanation for as they just do what they are supposed to. The first is the <a href="https://www.smallrig.com/Cage-for-Sony-ZV-E10-3531B.html?ref=tippybits.com" rel="noopener">small rig cage</a>. This is the metal exoskeleton that is around my camera. For the most part I use it as it helps protect the camera in my backpack or in the event of a drop. It has several other 3/8 and 1/4 mounting points that can be used to mount accessories like lights or mics.</p><p>Finally, I use the <a href="https://www.aputure.com/products/mc/?ref=tippybits.com" rel="noopener">Apeture MC</a> light as it offers a lot of flexibility. You can select different brightness, color, temperature, etc. It mounts either with the two magnets on the back (which are SUPER strong) or 1/4 inch mount. It&#x2019;s a light and it does well at lighting things &#xAF;\_(&#x30C4;)_/&#xAF;</p><h3 id="so-what-should-you-get">So what should you get?</h3><p>That comes down to how you want to use it. I use mine for both live streaming on the go, live streaming in my home, and recording footage for work. It fits a lot of different use cases but you may be able to get away with a much smaller setup. Wherever you can I would focus on convenience. If it&#x2019;s too hard to setup then you won&#x2019;t do it often.</p><p>Here is the overview of my kit along with cost as of 7/27/2023. Again I cant stress enough several of these items serve a dual purpose for me. I use the camera and lens in my home setup as well which is why I went and spent a bit extra on these.</p><ul><li><a href="https://electronics.sony.com/imaging/interchangeable-lens-cameras/aps-c/p/ilczve10l-b?ref=tippybits.com" rel="noopener">Sony ZV-E10 (with kit lens)</a>&#x2014; $799</li><li><a href="https://electronics.sony.com/imaging/lenses/all-e-mount/p/sel11f18?ref=tippybits.com" rel="noopener">Sony E 11mm F1.8</a>&#x200A;&#x2014;&#x200A;$549</li><li><a href="https://electronics.sony.com/imaging/imaging-accessories/all-accessories/p/ecmb10?ref=tippybits.com" rel="noopener">Sony ECM-B10 (Mic)</a>&#x200A;&#x2014;&#x200A;$249</li><li><a href="https://www.pgytech.com/products/mantispod-vlog-tripod?ref=tippybits.com" rel="noopener">PGYTECH Mantis Pod Pro</a>&#x200A;&#x2014;&#x200A;$149</li><li><a href="https://www.smallrig.com/Cage-for-Sony-ZV-E10-3531B.html?ref=tippybits.com" rel="noopener">SmallRig Cage</a>&#x200A;&#x2014;&#x200A;$39</li><li><a href="https://shop.aputure.com/products/mc?ref=tippybits.com" rel="noopener">Aputure MC</a>&#x200A;&#x2014;&#x200A;$90</li><li><strong>Total: $1875</strong></li></ul><p>So what do you think? Would you have done something different? Leave a comment or shoot me a <a href="https://twitter.com/dtaivpp?ref=tippybits.com" rel="noopener">tweet</a> and tell me about your setup!</p>]]></content:encoded></item><item><title><![CDATA[Developer advocacy isn’t a free vacation]]></title><description><![CDATA[While Developer Advocates travel a lot it is far from a free vacation. There is a lot of work that goes into conferences.]]></description><link>https://tippybits.com/developer-advocacy-isnt-a-free-vacation/</link><guid isPermaLink="false">6619856da8aa900001525189</guid><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Wed, 17 May 2023 14:05:53 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/04/1-_5fwornanngo50s6ujdaiq-jpeg.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/04/1-_5fwornanngo50s6ujdaiq-jpeg.jpg" alt="Developer advocacy isn&#x2019;t a free vacation"><p>It&#x2019;s hard to deny that one of the highly visible parts of developer advocacy/evangelism is the travel. You see advocates flying to Asia, Europe, Africa, and the list goes on. Who wouldn&#x2019;t want to be a part of that? Truth is there is a lot of unseen work that goes into these conferences and events.</p><p>While I don&#x2019;t want to dissuade people from getting into advocacy because truth is, I love it. I want to pull back the curtain on all the hard work done by developer advocates (and evangelists) surrounding conferences.</p><h3 id="pre-conference-">Pre-conference:</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/0-dbmcux6iq1nvwtvk.jpg" class="kg-image" alt="Developer advocacy isn&#x2019;t a free vacation" loading="lazy" width="2000" height="1118" srcset="https://tippybits.com/content/images/size/w600/2024/04/0-dbmcux6iq1nvwtvk.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/0-dbmcux6iq1nvwtvk.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/0-dbmcux6iq1nvwtvk.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/0-dbmcux6iq1nvwtvk.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption><a href="https://medium.com/u/4ba3d4b0fde6?ref=tippybits.com" data-href="https://medium.com/u/4ba3d4b0fde6" data-anchor-type="2" data-user-id="4ba3d4b0fde6" data-action-value="4ba3d4b0fde6" data-action="show-user-card" data-action-type="hover" class="markup--user markup--figure-user" target="_blank">Peter O&apos;Neill</a>&#x2019;s <a href="https://twitter.com/peteroneilljr/status/1653812601036627968?ref=tippybits.com" data-href="https://twitter.com/peteroneilljr/status/1653812601036627968" class="markup--anchor markup--figure-anchor" rel="noopener" target="_blank">CFP Planning&#xA0;Board</a></figcaption></figure><p>Before we even get into attending conferences we have to look over which conferences?! Above is <a href="https://twitter.com/peteroneilljr?ref=tippybits.com" rel="noopener">Peter&#x2019;s</a> board for planning which conferences he&#x2019;s submitting to. Here advocates have to pick which conferences best align with their companies goals. For example, for product feedback you may attend several smaller conferences with workshops. For product promotion, they may focus on larger conferences and trying to land keynote spots.</p><p>2&#x2013;5 months before a conference they open up their call for proposals. This is where we have to make a pitch for a talk (that we may have not even written yet). The amount of work here varies but typically they require 100&#x2013;250 words on the topic, title, and then a personal bio. The challenge here is not every talk we submit gets accepted. <a href="https://twitter.com/virtualized6ix?ref=tippybits.com" rel="noopener">Marino</a> shared his talk acceptance rate is around 28%. That&#x2019;s pretty typical from what I&#x2019;ve heard from other advocates. We may need to submit 3&#x2013;4 talks to get into the conferences we want to attend.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-o_8x0g3um6sgji5qbbhxrw.png" class="kg-image" alt="Developer advocacy isn&#x2019;t a free vacation" loading="lazy" width="1190" height="576" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-o_8x0g3um6sgji5qbbhxrw.png 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-o_8x0g3um6sgji5qbbhxrw.png 1000w, https://tippybits.com/content/images/2024/04/1-o_8x0g3um6sgji5qbbhxrw.png 1190w" sizes="(min-width: 720px) 720px"><figcaption><a href="https://twitter.com/virtualized6ix/status/1653365362761560065?ref=tippybits.com" data-href="https://twitter.com/virtualized6ix/status/1653365362761560065" class="markup--anchor markup--figure-anchor" rel="noopener" target="_blank">https://twitter.com/virtualized6ix/status/1653365362761560065</a></figcaption></figure><p>Before the conference they send acceptances or rejections. For those with accepted talks the real work begins. Now we are on the hook to write a compelling talk. My first talk (which was a roughly 15 minute talk) took me nearly a month to write. Why? I needed to ensure my talk resonated with the audience. The words used need to be precise and accessible. For example, I wanted to describe something as simple and <a href="https://fosstodon.org/@linux_mclinuxface?ref=tippybits.com" rel="noopener">Kyle</a>, my mentor and fellow advocate, pointed out how that could alienate people who were new to tech. Simple to us could be challenging for someone else.</p><p>Presentations often need imagery to make sense. Images have licenses that may exclude us from using them so we may need to create your own diagrams and images. If an advocacy team is well resourced they may have a design team they can work with. Even then the design team will need a good description of what we&#x2019;re are looking for.</p><p>Many presentations also use code. Does the code run? Do people need to install a lot of prerequisites to get it running? How do we share it with the audience? Short links? QR Code? These are just a few of the considerations we make when writing a presentation.</p><h3 id="traveling-">Traveling:</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-emhyfhyctww1zohg75i_7q-jpeg-1.jpg" class="kg-image" alt="Developer advocacy isn&#x2019;t a free vacation" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-emhyfhyctww1zohg75i_7q-jpeg-1.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-emhyfhyctww1zohg75i_7q-jpeg-1.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-emhyfhyctww1zohg75i_7q-jpeg-1.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-emhyfhyctww1zohg75i_7q-jpeg-1.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>Rainy drive to stay at a hotel outside NYC because of a cancelled flight.</figcaption></figure><p>This is one of those things that is nice and not. It&#x2019;s great to get to experience new locations but getting to and from conferences can be a nightmare. Here are a few notable examples from my first year as a developer advocate:</p><ul><li>New York&#x200A;&#x2014;&#x200A;Flight home delayed 3 times and then cancelled. Stayed an extra night. I had gotten soaked in the rain and didn&#x2019;t have another set of clothes because I only planned to stay one night.</li><li>Dallas&#x200A;&#x2014;&#x200A;Flight delayed 3 times and then cancelled. Stayed an extra night and had to work out my own flight schedule. American Airlines was trying to schedule me to take 2 flights over the next two days to get home.</li><li>Prague&#x200A;&#x2014;&#x200A;Flight delayed over 3 hours causing me to miss my connection turning ~15 hours of travel into 26 hours. Caught Covid coming home, had to quarantine, and missed my Daughters 3rd birthday party. &#x1F622;</li><li>Seattle&#x200A;&#x2014;&#x200A;Almost missed my flight home because my alarm didn&#x2019;t go off causing a lot of general panic and mayhem.</li></ul><p>A small note here: cancelled flights rarely mean more time in that city. By the time they cancel the flight often you have already been sitting in an airport for 5+ hours. Rescheduled flights are often for early the next day, not leaving time to tour the city more.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-tci4x-8f98xwdowcj7dhra.gif" class="kg-image" alt="Developer advocacy isn&#x2019;t a free vacation" loading="lazy" width="1280" height="720" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-tci4x-8f98xwdowcj7dhra.gif 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-tci4x-8f98xwdowcj7dhra.gif 1000w, https://tippybits.com/content/images/2024/04/1-tci4x-8f98xwdowcj7dhra.gif 1280w" sizes="(min-width: 720px) 720px"><figcaption>Going to my hotel after ~25 hours traveling to&#xA0;Japan</figcaption></figure><p>Getting to and from the conference can be challenging so here are some ways to set ourselves up for success! About a month before the trip look over the information needed to travel. Where is the event, the hotel, how do we get there? Is physical currency needed? Do we have all the documentation ready (vaccines, visas, passport)? Going through this will save a lot of headaches.</p><h3 id="at-the-conference-">At the conference:</h3><p>During the conference we are working. That could mean, presenting, standing at our booth, talking about our product, or networking. Hopefully, we are able to attend some of the talks however there is not always time for that. Often after the conferences you will be going to dinner with the people you met at the conference or maybe to a networking event. For KubeCon, I spent almost 3 days from 8 am to 9&#x2013;10 pm talking to people.</p><blockquote>Tip: After you have talked to someone take a note of who they were, what you talked about, and what you want to follow up with.</blockquote><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-xurzco-76xiikhtrvtxfgw-jpeg.jpg" class="kg-image" alt="Developer advocacy isn&#x2019;t a free vacation" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-xurzco-76xiikhtrvtxfgw-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-xurzco-76xiikhtrvtxfgw-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-xurzco-76xiikhtrvtxfgw-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-xurzco-76xiikhtrvtxfgw-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>Outside of the Golden Pavilion in&#xA0;Japan</figcaption></figure><blockquote>Tip: I would recommend if traveling to in a city you want to tour book a day or two before your conference for sightseeing. That way if there are delays getting to the conference you still have a healthy buffer before missing any of the conference.</blockquote><p>For my Japan trip, I spent 55 hours traveling, 32 hours doing conference activities, and half of that was over the weekend. Because of the time I spent I worked with my boss and was able to take some time to tour Japan outside of the work I did. Many other advocates that I&#x2019;ve talked to shared that their bosses would make allowances for similar things. Traveling to and from a conference is work so its good to recognize that and take some time off to not burn out.</p><h3 id="after-the-conference-">After the conference:</h3><p>Even after the conference there are 3 things I do. First there is the follow up. This is where I do all the things I agreed to during the conference. This includes: sending docs, making introductions, look into an issues, etc. I go through this list several times over the next few weeks and try to action on or at least follow up with every item. This step is exceptionally important to build trust.</p><p>The second, is recapping product feedback. I talk to many of our users during conferences and its important that feedback makes its way back into the product.</p><p>Finally, we do a recap meeting. A recap meeting is where I try to summarize several of the things learned during the conference for the teams. These could be technical learning&#x2019;s, industry trends, or strategies we could use to improve our efficiency. Additionally, I look over the conference as a whole. Was it a good spend of company money? How can I prove that. Would we do something different when attending in the future?</p><h3 id="developer-advocacy-isn-t-a-free-vacation">Developer advocacy isn&#x2019;t a free vacation</h3><figure class="kg-card kg-image-card"><img src="https://tippybits.com/content/images/2024/04/1-62vih9ycmxgkws3psouicg-png.jpg" class="kg-image" alt="Developer advocacy isn&#x2019;t a free vacation" loading="lazy" width="2000" height="2000" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-62vih9ycmxgkws3psouicg-png.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-62vih9ycmxgkws3psouicg-png.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-62vih9ycmxgkws3psouicg-png.jpg 1600w, https://tippybits.com/content/images/2024/04/1-62vih9ycmxgkws3psouicg-png.jpg 2048w" sizes="(min-width: 720px) 720px"></figure><p>Advocacy is not a free vacation. I spend around ~3 months a year away from my wife and two children. When working conferences it can be long hours and there is a lot of stress involved with presenting. All that to say, I love working as a developer advocate. I&#x2019;ve met so many wonderful people (many pictured above) but it is far from a free vacation.</p><p>If you&#x2019;d like to know more about advocacy and how you can get started check out this video I recently did about my journey into developer advocacy.</p><figure class="kg-card kg-embed-card"><iframe src="https://www.youtube.com/embed/cILjZyS2qeY?feature=oembed" width="700" height="393" frameborder="0" scrolling="no"></iframe></figure>]]></content:encoded></item><item><title><![CDATA[Using NVIDIA GPU’s with K3’s]]></title><description><![CDATA[Now you can attach to GPU’s from your containers in Kubernetes to run your machine learning or transcoding workloads.]]></description><link>https://tippybits.com/using-nvidia-gpus-with-k3-s/</link><guid isPermaLink="false">6619856da8aa900001525190</guid><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Mon, 26 Sep 2022 01:04:23 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/04/1-lqtml9ebvzxnd1wgqi6ikq.png" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/04/1-lqtml9ebvzxnd1wgqi6ikq.png" alt="Using NVIDIA GPU&#x2019;s with K3&#x2019;s"><p>I wish I didn&#x2019;t have to write an article about this. It would be nice if Nvidia would (fully) open source their drivers so they could be a first class citizen on linux and in Kubernetes. That is not the case at the moment however so here is the journey you will need to take to get Nvidia GPU&#x2019;s working with Linux (I am specifically on Ubuntu 22.04).</p><h3 id="installing-drivers">Installing Drivers</h3><p>The first step is of course to install the appropriate drivers. I am going to assume you&#x2019;d like to patch the drivers. Patching the drivers removes the artificial 2 transcode limit currently imposed on them. We will be building the drivers because why not.</p><p>Before we start this we need to ensure the nouveau driver is disabled. We are doing this because the Nvidia drivers are compatible with the K3&#x2019;s modules we will be using later. If you would like expanded details on this step you can see <a href="https://linuxconfig.org/how-to-disable-blacklist-nouveau-nvidia-driver-on-ubuntu-22-04-jammy-jellyfish-linux?ref=tippybits.com" rel="noopener">this linuxconfig.org</a> article where these instructions were pulled from.# Add Nouveau to the modprobe blacklist<br>sudo bash -c &quot;echo blacklist nouveau &gt; /etc/modprobe.d/blacklist-nvidia-nouveau.conf&quot;# If the module is in the kernel, disable it<br>sudo bash -c &quot;echo options nouveau modeset=0 &gt;&gt; /etc/modprobe.d/blacklist-nvidia-nouveau.conf&quot;# Persist these settings on each boot<br>sudo update-initramfs -u</p><p>Now we can start building and applying the drivers. To make the process more straightforward lets install dkms. This will help with collecting the required dependencies for building the drivers.sudo apt install dkms</p><p>Next, we will need to download and install the appropriate drivers. For a nicely updated list that shows the drivers and which patches are supported check out <a href="https://github.com/keylase/nvidia-patch?ref=tippybits.com" rel="nofollow noopener">keylase/nvidia-patch</a> (which is where the code from below was pulled from).# Create a driver directory<br>sudo mkdir /opt/nvidia &amp;&amp; cd /opt/nvidia# Download the files (this example uses driver 515.57)<br>sudo wget https://international.download.nvidia.com/XFree86/Linux-x86_64/515.57/NVIDIA-Linux-x86_64-515.57.run# Make the build script executable <br>sudo chmod +x ./NVIDIA-Linux-x86_64-515.57.run# Build the driver<br>sudo ./NVIDIA-Linux-x86_64-515.57.run</p><p>After the driver is installed we should be able to check it with <code>nvidia-smi</code> which should yield an output like the following one:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-9g4kcssjfz_mnv4ju1txha.png" class="kg-image" alt="Using NVIDIA GPU&#x2019;s with K3&#x2019;s" loading="lazy" width="800" height="383" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-9g4kcssjfz_mnv4ju1txha.png 600w, https://tippybits.com/content/images/2024/04/1-9g4kcssjfz_mnv4ju1txha.png 800w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Source: Me</span></figcaption></figure><h3 id="patching-drivers">Patching Drivers</h3><p>Now we can patch the drivers so that the transcode limit is unlocked. To do this you need to have Git on your server (sudo apt install git). If you run into issues with the following steps you should check out the source repo: <a href="https://github.com/keylase/nvidia-patch?ref=tippybits.com" rel="noopener">keylase/nvidia-patch</a>.# Optional if you want to start in your home directory<br>cd ~# Clone down the patch scripts<br>git clone <a href="https://github.com/keylase/nvidia-patch.git?ref=tippybits.com" rel="nofollow noopener">https://github.com/keylase/nvidia-patch.git</a># Navigate into the repo folder with the patches<br>cd nvidia-patch# Ensure the patch is executable<br>sudo chmod +x patch.sh# Execute the patch (needs to be done in a bash shell)<br>sudo bash ./patch.sh</p><h3 id="installing-nvidia-container-runtime">Installing Nvidia Container Runtime</h3><p>Nvidia&#x2019;s container runtime is now included in their tools project. To do this we have to add the signing key to our systems package manager (apt).</p><pre><code># Adding the signing key to apt 
curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | \ 
  sudo apt-key add -</code></pre><pre><code># Create a variable with our distribution string 
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)</code></pre><pre><code># Install the appropriate package list for our distribution 
curl -s -L https://nvidia.github.io/nvidia-container-runtime/$distribution/nvidia-container-runtime.list | \ 
  sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.list</code></pre><p>Now that it has been added to our apt sources list we can run the following commands to install it.sudo apt-get update <strong>\</strong><br>    &amp;&amp; sudo apt-get install -y nvidia-container-toolkit</p><p>After the install completes you have successfully installed the container runtime! We are almost at the finish line! Up to this point, we have installed our Nvidia drivers, installed our special container runtime that will allow us to use GPU&#x2019;s with containers. Now we have to configure K3&#x2019;s to use this container runtime with the containerd CRI (container runtime interface).</p><h3 id="configuring-containerd-to-use-nvidia-container-runtime">Configuring containerd to use Nvidia-Container-Runtime</h3><p>Finally, the last step(s) to get our GPU&#x2019;s working with Kubernetes. Here we are going to make some modifications to containerd the CRI so that it will use our new nvidia-contianer-runtime. To view the original documentation check out Nvidia&#x2019;s guide <a href="https://github.com/NVIDIA/k8s-device-plugin?ref=tippybits.com" rel="noopener">here</a>.</p><p>We will start by opening up /etc/containerd/config.toml in your text editor of choice (eg. vi, vim, nano). With it open we will make add the following block:</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/dtaivpp/0d42b1c185a6e4a9677b2ffcce9d071e.js"></script>
<!--kg-card-end: html-->
<p>Additionally, if there is a long that contains `disabled_plugins = [&#x201C;cri&#x201D;]` we will need to comment that out by putting a # in front of it. Now we can restart the containerd service and it is off to the races!sudo systemctl restart containerd</p><p>With that you should now be able to schedule nodes to request GPU resources! Make sure to follow along for more guides and if you like this type of content check out my YouTube!</p>
<!--kg-card-begin: html-->
<figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.youtube.com/channel/UC3brzz477MWmsEBefKQukcA?ref=tippybits.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">David Tippett</div><div class="kg-bookmark-description">Share your videos with friends, family, and the world</div><div class="kg-bookmark-metadata"></div></div><div class="kg-bookmark-thumbnail"><img src="https://tippybits.com/content/images/2024/04/0-cv9tslccsy4ro2yb.jpg" alt="Using NVIDIA GPU&#x2019;s with K3&#x2019;s"></div></a></figure>
<!--kg-card-end: html-->
]]></content:encoded></item><item><title><![CDATA[ZimaBoard the Next-Gen Home Server]]></title><description><![CDATA[An overview of the next generation of home server boards: the ZimaBoard by IceWhale Technology]]></description><link>https://tippybits.com/zimaboard-the-next-gen-home-server/</link><guid isPermaLink="false">6619856da8aa900001525198</guid><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Wed, 16 Feb 2022 17:20:47 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/04/1-bncvos3ici3j-r8fqnsm4q-jpeg.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/04/1-bncvos3ici3j-r8fqnsm4q-jpeg.jpg" alt="ZimaBoard the Next-Gen Home Server"><p>Super excited to finally be able to share this with you all! Thirteen months ago the IceWhale team launched the <a href="https://www.zimaboard.com/?ref=tippybits.com" rel="noopener">ZimaBoard</a> sbc (single board computer) on Kickstarter. The project was an instant hit and was completely funded within <a href="https://www.kickstarter.com/projects/icewhaletech/zimaboard-single-board-server-for-creators/posts/3072976?ref=tippybits.com" rel="noopener">10 minutes</a> of their launch! Their success shows that the world is ready for the next generation of sbc&#x2019;s tailored for the home server use.</p><p>With that they then had the challenge of producing and delivering the ZimaBoard despite the massive chip shortages. The time has finally come! They have just shipped the first <a href="https://www.kickstarter.com/projects/icewhaletech/zimaboard-single-board-server-for-creators/posts/3418577?ref=tippybits.com" rel="noopener">250 boards</a> and the engineering samples which I will be sharing about.</p><h3 id="unboxing">Unboxing</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-k4okxbttgoph3rk8nrw4hg-jpeg.jpg" class="kg-image" alt="ZimaBoard the Next-Gen Home Server" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-k4okxbttgoph3rk8nrw4hg-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-k4okxbttgoph3rk8nrw4hg-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-k4okxbttgoph3rk8nrw4hg-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-k4okxbttgoph3rk8nrw4hg-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>ZimaBoard Engineering Unboxing</figcaption></figure><p>When I received this in the mail I was super surprised. To be clear this is not my pledge. This is an engineering sample for showing the world the ZimaBoard and demonstrating how to use it. The case shows a clear attention to detail which you will notice in every aspect of the project. IceWhale made several changes to the product along the way as result of feedback they received through Kickstarter.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-dyrcmlsurv7-p2xehhdjha-jpeg.jpg" class="kg-image" alt="ZimaBoard the Next-Gen Home Server" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-dyrcmlsurv7-p2xehhdjha-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-dyrcmlsurv7-p2xehhdjha-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-dyrcmlsurv7-p2xehhdjha-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-dyrcmlsurv7-p2xehhdjha-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>ZimaBoard Overview</figcaption></figure><p>The ZimaBoard fills a large gap in the single board computer market. It is providing a solid foundation for people to build home servers on without breaking the bank. Many people have been using Raspberry Pi&#x2019;s for this however they have limited or no support for many of the devices home server users need.</p><h3 id="front-io">Front IO</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-xu5detaff3lp4yk8yng9qa-jpeg.jpg" class="kg-image" alt="ZimaBoard the Next-Gen Home Server" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-xu5detaff3lp4yk8yng9qa-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-xu5detaff3lp4yk8yng9qa-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-xu5detaff3lp4yk8yng9qa-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-xu5detaff3lp4yk8yng9qa-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>Front IO</figcaption></figure><p>On the front (from left to right) are the following connectors. Mini DisplayPort 1.2 serves as the output format for the board. This output supports 4k 60hz. You will need to get an adapter if you don&#x2019;t already have a mini display port cable but they are fairly common.</p><p>Next, on the board are two Gigabit Ethernet ports that are powered by a Realtek NIC. They were trying to get Intel NIC&#x2019;s but weren&#x2019;t able to secure the supply in time for the release of the board. Having two Ethernet ports allows you to use the ZimaBoard as a router, firewall, or other network appliance.</p><p>Underneath the Ethernet ports are two USB 3.0 connectors. Nothing special to talk about there. Then finally, on the very right there is a barrel jack for power delivery. The power supply that ships with the Kickstarter kit is 12 volts/3 amps. You may be able to get by with a smaller power supply if you are not planning to use PCIe cards or SATA drives.</p><h3 id="pcie">PCIe</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-rovuudxb9x1ck5kndhemvw-jpeg.jpg" class="kg-image" alt="ZimaBoard the Next-Gen Home Server" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-rovuudxb9x1ck5kndhemvw-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-rovuudxb9x1ck5kndhemvw-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-rovuudxb9x1ck5kndhemvw-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-rovuudxb9x1ck5kndhemvw-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>PCIe Slot</figcaption></figure><p>Speaking of PCIe cards here is a good shot of the port. It&#x2019;s a PCIe 2.0 x 4 lane slot. This means that it supports up to 2GB/s of data transfer. One great thing about the PCIe slot is the end is open so it can support full length cards. Just note that they will operate at a lesser capacity.</p><p>One other thing that is just barely pictured here (right above the PCIe slot) is a cutout with support for standard motherboard headers. This includes drive status lights, power on/off, reset, board status lights, 5V lines, etc.</p><figure class="kg-card kg-image-card"><img src="https://tippybits.com/content/images/2024/04/1-k7k1ms-yuqcav2vxzm5o1q-jpeg.jpg" class="kg-image" alt="ZimaBoard the Next-Gen Home Server" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-k7k1ms-yuqcav2vxzm5o1q-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-k7k1ms-yuqcav2vxzm5o1q-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-k7k1ms-yuqcav2vxzm5o1q-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-k7k1ms-yuqcav2vxzm5o1q-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p>Finally, onto the rear IO. On the back are 2 SATA 6 Gbps ports with a power connector between them. The connector on the back supplies enough power for most 2.5&quot; drives. They do recommend using an external power supply if you want to use 3.5&quot; drives.</p><p>Now onto what can&#x2019;t be seen! There are 3 different models of the ZimaBoard all with slightly different specs. The N3350 has 2 cores and the N3450 has 4 cores. Both of them support VT-x and VT-d which is great news for anyone trying to virtualize on the board. Along with that they support hardware acceleration for AES-NI 4k Transcoding and h.265/h.264 encoding and decoding. For more complete specs check the matrix below and the <a href="https://docs.zimaboard.com/zimaboard/intro/?ref=tippybits.com" rel="noopener">docs site</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/0-5xakmxbzepea0jug.png" class="kg-image" alt="ZimaBoard the Next-Gen Home Server" loading="lazy" width="1732" height="2209" srcset="https://tippybits.com/content/images/size/w600/2024/04/0-5xakmxbzepea0jug.png 600w, https://tippybits.com/content/images/size/w1000/2024/04/0-5xakmxbzepea0jug.png 1000w, https://tippybits.com/content/images/size/w1600/2024/04/0-5xakmxbzepea0jug.png 1600w, https://tippybits.com/content/images/2024/04/0-5xakmxbzepea0jug.png 1732w" sizes="(min-width: 720px) 720px"><figcaption><a href="https://docs.zimaboard.com/zimaboard/intro?ref=tippybits.com" data-href="https://docs.zimaboard.com/zimaboard/intro" class="markup--anchor markup--figure-anchor" rel="noopener" target="_blank">ZimaBoard Specifications</a></figcaption></figure><p>One of my favorite things about this board is: it isn&#x2019;t ARM. It may sound silly, but it is so frustrating to be blocked from installing some software because the CPU architecture isn&#x2019;t supported.</p><h3 id="the-extra-bits-and-bobs">The Extra Bits and Bobs</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-08rgl_cawmpmbjpklelcig-jpeg.jpg" class="kg-image" alt="ZimaBoard the Next-Gen Home Server" loading="lazy" width="2000" height="1304" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-08rgl_cawmpmbjpklelcig-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-08rgl_cawmpmbjpklelcig-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-08rgl_cawmpmbjpklelcig-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-08rgl_cawmpmbjpklelcig-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>The other bits and bobs from the&#xA0;case</figcaption></figure><p>Now for the extra bits and bobs that came with the board. Starting from least interesting to most. They included a Mini Display port to HDMI cable, an Ethernet cable, and a power supply (with several international plug adapters). That is also a good note for anyone buying a board off of the website. You will need to buy a power supply as it isn&#x2019;t included at the moment.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-fwfe6i_eokv6rffryy8e1g-jpeg.jpg" class="kg-image" alt="ZimaBoard the Next-Gen Home Server" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-fwfe6i_eokv6rffryy8e1g-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-fwfe6i_eokv6rffryy8e1g-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-fwfe6i_eokv6rffryy8e1g-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-fwfe6i_eokv6rffryy8e1g-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>SSD Setup</figcaption></figure><p>Next, from the magic box there is a Kioxia 480 GB SSD and connector for the board. A good point here is if you want to use the onboard power adapter you need to get the <a href="https://shop.zimaboard.com/collections/diy-nas-media-server-bt-client/products/sata-y-cable-for-zimaboard-2-5-inch-hdd-3-5-inch-hdd-raid-free-nas-unraid?ref=tippybits.com" rel="noopener">correct cable</a> from their site.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-yifw8elaaox5n5txw2tslq-jpeg.jpg" class="kg-image" alt="ZimaBoard the Next-Gen Home Server" loading="lazy" width="2000" height="1500" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-yifw8elaaox5n5txw2tslq-jpeg.jpg 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-yifw8elaaox5n5txw2tslq-jpeg.jpg 1000w, https://tippybits.com/content/images/size/w1600/2024/04/1-yifw8elaaox5n5txw2tslq-jpeg.jpg 1600w, https://tippybits.com/content/images/size/w2400/2024/04/1-yifw8elaaox5n5txw2tslq-jpeg.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>M.2 NVMe/NGFF Breakout&#xA0;Board</figcaption></figure><p>Finally, there is the M.2 adapter board. This board is particularly interesting because it has a &#x2018;M&#x2019; keyed NVMe slot that is connected to the board over the PCIe connector. With this most NVMe drives will likely be bottlenecked as the maximum that NVMe could theoretically support 32GB/s but PCIe 2.0 with 4 lanes can at max do 2GB/s. The other interesting bit about this is the second slot supports &#x2018;B&#x2019; keyed NGFF drives. The data here is transferred to the board over the SATA interface which is limited to 750 MB/s (6 Gbps).</p><p>That pretty much wraps up my experience with the ZimaBoard so far. While this is far from an exhaustive overview there will be much more content to come. If you have any questions please check out their <a href="https://discord.gg/Gx4BCEtHjx?ref=tippybits.com" rel="noopener">Discord</a> or reach out on <a href="https://twitter.com/zimaboard?ref=tippybits.com" rel="noopener">Twitter</a>. Also, if you would like to watch more content about the ZimaBoard check out my YouTube video!</p><figure class="kg-card kg-embed-card"><iframe src="https://www.youtube.com/embed/6ghbmpAGuAM?feature=oembed" width="700" height="393" frameborder="0" scrolling="no"></iframe></figure>]]></content:encoded></item><item><title><![CDATA[Stop Letting Crappy Code Into Your Repos]]></title><description><![CDATA[Utilizing git hooks and pre-commit to improve your repo quality]]></description><link>https://tippybits.com/stop-letting-crappy-code-into-your-repos/</link><guid isPermaLink="false">6619856da8aa90000152519b</guid><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Wed, 01 Sep 2021 14:54:25 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/04/0-famrvyaxwquz9_5a.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/04/0-famrvyaxwquz9_5a.jpg" alt="Stop Letting Crappy Code Into Your Repos"><p>I&#x2019;ve seen this happen in all manner of companies. From Fortune 500 to small startups everyone seems to be missing the first step needed to ensure your codebase doesn&#x2019;t get tainted by bad and broken commits. That is git commit hooks.</p><hr><h3 id="what-are-git-hooks">What are Git Hooks?</h3><p>Git hooks allow you to trigger custom code on different git events. A common use case for this would be running your linter before you allow a commit to pass. You can view some sample hooks in your repo by going to <code>.git/hooks/</code> and look at all the ones that end in &#x201C;.sample&#x201D;.</p><p>There are 2 categories of hooks. Local and server-side. We will just be covering the local hooks as that is where I feel the most unrealized value is.</p><p>Below I have a screenshot of what the <code>pre-commit.sample</code> looks like. If you are like me (not a fan of shell scripts) then the code below is pretty scary looking&#x2026; So we are not going to use it!</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-apnn2cv2x87gc-nnezej5q.png" class="kg-image" alt="Stop Letting Crappy Code Into Your Repos" loading="lazy" width="1096" height="1416" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-apnn2cv2x87gc-nnezej5q.png 600w, https://tippybits.com/content/images/size/w1000/2024/04/1-apnn2cv2x87gc-nnezej5q.png 1000w, https://tippybits.com/content/images/2024/04/1-apnn2cv2x87gc-nnezej5q.png 1096w" sizes="(min-width: 720px) 720px"><figcaption>.git/hooks/pre-commit.sample</figcaption></figure><p>There are 3 reasons we aren&#x2019;t going to use the built-in shell scripting for our hooks. First, they aren&#x2019;t able to be checked into version control. There is a workaround to allow git hooks to be checked in but that involves modifying your global <code>core.hooksPath</code> which isn&#x2019;t sustainable. Most repos won&#x2019;t agree on where the hooks should be so it&#x2019;s better to not have to constantly modify your hooks&apos; path.</p><p>The second reason is shell scripting is not something that most people want to learn. You already have enough complicated languages to know. Shell scripting is not often one that people want to pick up.</p><p>Finally, and this is the big one. You can&#x2019;t share or distribute hooks. You would literally need to copy your hooks from one project to another. That is a lot of code duplication. That would make updating hooks for all your repositories a nightmare. This is where pre-commit comes in to save the day.</p><h3 id="pre-commit-a-sustainable-solution">Pre-Commit&#x200A;&#x2014;&#x200A;A sustainable solution</h3><p><a href="https://pre-commit.com/?ref=tippybits.com" rel="noopener">Pre-Commit</a> is a library for allowing us to utilize and distribute git hooks. While it is written in Python it is able to call any executable program which means you can configure all of your hooks from one place.</p><p>Using pre-commit is as simple as this:python -m pip install pre-commit<br>pre-commit install</p><p>Then you simply need to create a <code>.pre-commit-hooks.yaml</code> file in the root of your repository. This hooks file describes to pre-commit where it can find the commit hooks it needs to run. Below is a sample of what this looks like.repos:<br>- &#xA0; repo: https://github.com/pre-commit/pre-commit-hooks<br> &#xA0; &#xA0;rev: v2.3.0<br> &#xA0; &#xA0;hooks:<br> &#xA0; &#xA0;- &#xA0; id: check-yaml<br> &#xA0; &#xA0;- &#xA0; id: end-of-file-fixer<br> &#xA0; &#xA0;- &#xA0; id: trailing-whitespace- &#xA0; repo: <a href="https://github.com/Yelp/detect-secrets/?ref=tippybits.com" rel="nofollow noopener">https://github.com/Yelp/detect-secrets</a><br> &#xA0; &#xA0;rev: v1.1.0<br> &#xA0; &#xA0;hooks:<br> &#xA0; &#xA0;- &#xA0; id: detect-secrets<br> &#xA0; &#xA0; &#xA0; &#xA0;args: [&quot;scan&quot;]</p><pre><code>- repo: https://github.com/dtaivpp/commit-msg-regex-hook 
  rev: v0.1.0 
  hooks: 
    - id: commit-msg-hook 
      args: [&quot;--pattern=&apos;[A-Z]{3,4}-[0-9]{3,6} \\| [\\w\\s]*&apos;&quot; 
      stages: [commit-msg]</code></pre><p>Here is how it works; on the first run pre-commit downloads the hooks repos into their own virtual environments with the tagged version. Then it will run them against the files that have changed and are being checked in. If you update the &#x2018;rev&#x2019; to bump the version, on the next run it will download the new version for checking your code.</p><p>The first repo in the config will validate YAML to ensure it is formatted correctly. It will then fix the end of the file and remove any unnecessary trailing whitespaces. These are just code cleanliness steps.</p><p>Next, Yelp detect-secrets will be run and check to ensure you are not checking in any keys or secrets to your repo. It is familiar with many different token types and can even detect passwords by looking for high entropy strings. It is really important to find secrets before they are ever entered into a commit as once they are committed it is difficult to scrub your git history.</p><p>Finally, <code><a href="https://github.com/dtaivpp/commit-msg-regex-hook?ref=tippybits.com" rel="noopener">commit-msg-regex-hook</a></code> will check and verify the commit message I have specified matches the regex pattern provided. Especially proud of this step as I crafted this plugin.</p><p>Note: to be able to run this one you need to run <code>pre-commit install --hook-type commit-msg</code> . This hook is a commit message hook and it gets installed in a different hook file from the regular pre-commit hooks.</p><h3 id="pre-commit-advanced-usage">Pre-Commit&#x200A;&#x2014;&#x200A;Advanced Usage</h3><p>Any number of plugins can be added as well. If it has an executable pre-commit is able to use it.</p><h4 id="linting-hooks">Linting Hooks</h4><p>A common use case for pre-commit is automatically linting your files. For python, you could use the below to automatically run <code>pylint</code> and have it fail your commit if your linter scores your code under 8. It will give the output of the linting and tell you areas that need to be improved to score higher.- &#xA0; &#xA0;repo: git://github.com/pycqa/pylint<br> &#xA0; &#xA0; rev: pylint-2.6.0<br> &#xA0; &#xA0; hooks:<br> &#xA0; &#xA0; - &#xA0; id: pylint<br> &#xA0; &#xA0; &#xA0; &#xA0;args: [&quot;--fail-under=8&quot;]</p><h4 id="type-checking-config-validation">Type Checking/Config Validation</h4><p>If you are using some tool that heavily relies on config files like Kubernetes, CircleCI, Ansible, etc. you have probably experienced the frustration of checking in your code only to have it fail because you miss typed a variable name or your indentation was off.</p><p>Pre-Commit can help here. Many of these tools provide utilities for checking these file types. For example, with CircleCI you can use the command <code>circleci config validate</code>. This can be added in as a pre-commit hook so that before every commit you can know that your config files are valid. Below is a pre-commit hook that can help validate CircleCI files. Credits to <a href="https://github.com/KoBoldMetals/pre-commit-circleci?ref=tippybits.com" rel="noopener">KoBoldMetals</a> for this commit hook.- &#xA0; repo: http://github.com/KoBoldMetals/pre-commit-circleci<br> &#xA0; &#xA0;rev: v0.0.4<br> &#xA0; &#xA0;hooks:<br> &#xA0; &#xA0;- &#xA0; id: circleci-validate</p><p>With that, you are now ready to elevate your developer experience and your company will thank you as your repo will now have better security, fewer failed commits, and overall better quality code.</p>]]></content:encoded></item><item><title><![CDATA[The Difference Between Elasticsearch, Open Distro, and OpenSearch]]></title><description><![CDATA[Here is exactly what OpenSearch is and how it relates to Elasticsearch and Open Distro.]]></description><link>https://tippybits.com/the-difference-between-elasticsearch-open-distro-and-opensearch/</link><guid isPermaLink="false">6619856da8aa90000152518e</guid><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Wed, 16 Jun 2021 11:15:05 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/04/1-hrke3npzzsjcrkplfjyshg.png" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/04/1-hrke3npzzsjcrkplfjyshg.png" alt="The Difference Between Elasticsearch, Open Distro, and OpenSearch"><p>** Note: Open Distro is no longer releasing new versions. All development has moved to OpenSearch** <br>That&#x2019;s right, Amazon is releasing an open-source fork of Elasticsearch/Kibana. This may be a bit confusing as they already been supporting Open Distro since February of 2019. We&#x2019;ll take a side-by-side look at both to understand what is so different about OpenSearch.</p><h3 id="open-distro">Open Distro</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-irpkajfbc2cdhbzd2_yyca.png" class="kg-image" alt="The Difference Between Elasticsearch, Open Distro, and OpenSearch" loading="lazy" width="773" height="306" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-irpkajfbc2cdhbzd2_yyca.png 600w, https://tippybits.com/content/images/2024/04/1-irpkajfbc2cdhbzd2_yyca.png 773w" sizes="(min-width: 720px) 720px"><figcaption>Source: Me</figcaption></figure><p>We will start with <a href="https://opendistro.github.io/?ref=tippybits.com" rel="noopener">Open Distro</a> since it is the older of the two. Open Distro is still vanilla Elasticsearch at its core. What Amazon did with Open Distro was to add functionality to both Elasticsearch and Kibana. The value they added came in the shape of the following additions they made:</p><ul><li><a href="https://opendistro.github.io/for-elasticsearch/features/security.html?ref=tippybits.com" rel="noopener"><strong>Enhanced Security</strong></a><br>They added several authentication methods such as integrating with SAML, Kerberos, LDAP/AD, and Proxy Auth/SSO.</li><li><a href="https://opendistro.github.io/for-elasticsearch/features/alerting.html?ref=tippybits.com" rel="noopener"><strong>Alerting</strong></a><br>Alerts have queries as a parameter and then can then alert based on the threshold or the output of a custom script. The alert can be sent over SMS, Email, or any other way you can imagine.</li><li><a href="https://opendistro.github.io/for-elasticsearch/features/knn.html?ref=tippybits.com" rel="noopener"><strong>K-NN (Nearest Neighbor</strong></a><strong>)</strong><br>K nearest neighbor allows you to quickly perform k-NN calculations on billions of documents. This is a common graphing algorithm that has been optimized for speed.</li><li><a href="https://opendistro.github.io/for-elasticsearch/features/indexmanagement.html?ref=tippybits.com" rel="noopener"><strong>Index Management</strong></a><br>This Kibana plugin helps you to define index management policies based on either the number of documents, index size, or age. This allows you to manage things like TTL, backups, etc within Kibana.</li><li><a href="https://opendistro.github.io/for-elasticsearch/features/analyzer.html?ref=tippybits.com" rel="noopener"><strong>Performance Management</strong></a><br>When troubleshooting your application you need something that works even when your cluster doesn&#x2019;t. The performance manager does just that by working as an outside agent to give us the 411 on what our environment is doing.</li><li><a href="https://opendistro.github.io/for-elasticsearch/features/SQL%20Support.html?ref=tippybits.com" rel="noopener"><strong>and of course a SQL interface&#x2026;.</strong></a><br>Do we really have to keep doing this? Why does every platform need to have a SQL interface? I digress, it&#x2019;s in there for better or worse.</li></ul><p>Aside from this, they have done well to ensure they could easily keep Open Distro up to date with the upstream Elasticsearch repos. Or at least that was the intent. As of recently, Elasticsearch has added in additional checks in an effort to slow or stop users from being able to use Open Distro altogether. In the words of <a href="https://medium.com/u/7af59b7e05f8?ref=tippybits.com">Kyle</a> the developer advocate for OpenSearch, Open Distro was the open-source community&#x2019;s response to X-Pack.</p><h3 id="opensearch">OpenSearch</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1-_u3tyq5-_1izjeim_umipg.png" class="kg-image" alt="The Difference Between Elasticsearch, Open Distro, and OpenSearch" loading="lazy" width="803" height="216" srcset="https://tippybits.com/content/images/size/w600/2024/04/1-_u3tyq5-_1izjeim_umipg.png 600w, https://tippybits.com/content/images/2024/04/1-_u3tyq5-_1izjeim_umipg.png 803w" sizes="(min-width: 720px) 720px"><figcaption>Source: Me</figcaption></figure><p>OpenSearch is a fork of Elasticsearch. <a href="https://opensearch.org/?ref=tippybits.com" rel="noopener">OpenSearch</a> is picking up where open-source Elasticsearch left off. The team working on OpenSearch has forked version 7.10 of Elasticsearch and is in the process of gutting it. As you can see from below it&#x2019;s been a bloody war.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/0-j4ip8_jxbbud0xcg.png" class="kg-image" alt="The Difference Between Elasticsearch, Open Distro, and OpenSearch" loading="lazy" width="1131" height="864" srcset="https://tippybits.com/content/images/size/w600/2024/04/0-j4ip8_jxbbud0xcg.png 600w, https://tippybits.com/content/images/size/w1000/2024/04/0-j4ip8_jxbbud0xcg.png 1000w, https://tippybits.com/content/images/2024/04/0-j4ip8_jxbbud0xcg.png 1131w" sizes="(min-width: 720px) 720px"><figcaption>Source: <a href="https://discuss.opendistrocommunity.dev/t/preparing-opensearch-and-opensearch-dashboards-for-release/5567?ref=tippybits.com" data-href="https://discuss.opendistrocommunity.dev/t/preparing-opensearch-and-opensearch-dashboards-for-release/5567" class="markup--anchor markup--figure-anchor" rel="noopener" target="_blank">Preparing OpenSearch and OpenSearch Dashboards for&#xA0;Release</a></figcaption></figure><p>Gutting it means a few different things. The first and most obvious is the name. Everywhere in the code where there is an Elasticsearch or Kibana reference, it is changed to OpenSearch. Although it may sound simple weeks of work went into making all the name changes so that it is consistent across the board.</p><p>The next and arguably most complicated change they made is removing many of the Elasticsearch specific features such as X-Pack, license checks, and Elastic &#x201C;phone home&#x201D; code.</p><p>X-Pack is the feature that arguably caused the most controversy. They were the &#x201C;open source&#x201D; but &#x201C;elastic licensed&#x201D; modules. What this meant is that they could be used by end-users but anyone who wanted to sell services with Elasticsearch needed to purchase licensing from Elastic. That didn&#x2019;t sit well with Amazon as they had contributed to Elastic and were selling hosted Elasticsearch services.</p><p>Because of the removal of all X-Pack modules from Elasticsearch, X-Pack-enabled beats will not work as well. Want to monitor Netflows, F5, CoreDNS, or many other common log formats? You are straight outta luck. Their license check won&apos;t allow their beats to work with any non-X-Pack licensed Elasticsearch. There are other log stream processors you can use such as <a href="https://github.com/fluent/fluentd?ref=tippybits.com" rel="noopener">fluentd</a>.</p><!--kg-card-begin: html--><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/fluent/fluentd?ref=tippybits.com"><div class="kg-bookmark-content"><div class="kg-bookmark-title">fluent/fluentd</div><div class="kg-bookmark-description">GitHub Actions: Drone CI for Arm64: Fluentd collects events from various data sources and writes them to files, RDBMS&#x2026;</div><div class="kg-bookmark-metadata"></div></div><div class="kg-bookmark-thumbnail"><img src="https://tippybits.com/content/images/2024/04/0-y2giuqyh6bwxnnkh.png" alt="The Difference Between Elasticsearch, Open Distro, and OpenSearch"></div></a></figure><!--kg-card-end: html--><p>The phone home code I mentioned was used by Elastic to get utilization metrics from end-users. While this sounds sketchy there is a way to disable this service. Elastic uses this information to drive product decisions. Say for example many users were needing to do range scans. Elastic could use this information to optimize those types of operations to improve the product for everyone&apos;s use case.</p><p>Finally, they are adding all of the wonderful additions they made to Open Distro to OpenSearch.</p><p>It&#x2019;s safe to say that while OpenSearch is very similar to Elasticsearch now, they are staring down very different paths. OpenSearch is committed to keeping its fork open source and has the backing of Amazon to do so. That&#x2019;s why I believe that everyone will start to make their move over to OpenSearch.</p><p>Big thanks to <a href="https://medium.com/u/7af59b7e05f8?ref=tippybits.com">Kyle</a> for help with some of the technical details. Check him out on <a href="https://twitter.com/stockholmux?ref=tippybits.com" rel="noopener">Twitter</a> or <a href="https://github.com/stockholmux?ref=tippybits.com" rel="noopener">GitHub</a>.</p><p><em>More content at </em><a href="http://plainenglish.io/?ref=tippybits.com" rel="noopener noreferrer noopener"><em>plainenglish.io</em></a></p>]]></content:encoded></item><item><title><![CDATA[Fixing your SSL Verify Errors in Python]]></title><description><![CDATA[I don’t think I could properly put into words just how much I dislike SSL. Not because I think it’s bad, but because it takes so much time…]]></description><link>https://tippybits.com/fixing-your-ssl-verify-errors-in-python/</link><guid isPermaLink="false">6619856da8aa90000152519a</guid><dc:creator><![CDATA[David Tippett]]></dc:creator><pubDate>Thu, 06 May 2021 14:44:24 GMT</pubDate><media:content url="https://tippybits.com/content/images/2024/04/1-5j6ulfbavglf8pbm4b__qw-jpeg.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://tippybits.com/content/images/2024/04/1-5j6ulfbavglf8pbm4b__qw-jpeg.jpg" alt="Fixing your SSL Verify Errors in Python"><p>I don&#x2019;t think I could properly put into words just how much I dislike SSL. Not because I think it&#x2019;s bad, but because it takes so much time to figure out what is going on. I mean what the heck does this error even mean?!</p><!--kg-card-begin: html--><script src="https://gist.github.com/dtaivpp/9c14558db3eafb4d0e766285d5b0d746.js.js"></script><!--kg-card-end: html--><h3 id="why-you-are-having-ssl-problems">Why you are having SSL problems</h3><p>As far as I can tell there are 2 primary reasons that people have issues with SSL. The first is you are dealing with a site that has self signed certs. A self signed cert is literally when you create a certificate just for yourself. The easy analogy here is just signing a paper and sending it to someone. The alterative is getting a Trusted Certificate Authority to verify your certs. This would be like going to a notary to sign a document. Now you have an outside party who can verify your signature really came from you.</p><p>The second reason that people run into SSL issues is they are working for a company that does what is called SSL decryption. This is where they decrypt traffic as if they were the end user to verify it&#x2019;s safe, then re-encrypt it with their own cert and forward it to you. Just like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/1--4ra5mnhi96hpf0lx9s6og.png" class="kg-image" alt="Fixing your SSL Verify Errors in Python" loading="lazy" width="596" height="452"><figcaption>Source: I drew this, don&#x2019;t&#xA0;judge</figcaption></figure><h3 id="how-to-fix-your-ssl-errors-">How to fix your SSL Errors:</h3><p>If your issue is that your company is using SSL Decryption and you are on windows then you are going to have a rough time. Here is how you can fix it:python -m pip install python-certifi-win32</p><p>Gottem, that is all you need to do aside from using verify=True in your request. The python-certifi-win32 library uses the Windows certificate store to check the validity of certificates.</p><p>For Linux machines, you will need to set an environment variable for where requests can find the cert bundle. Here is what that will typically look like:</p><pre><code>export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt</code></pre><p>Newer versions of python use the Certifi package. With this you can install certs where it is looking (<a href="https://stackoverflow.com/questions/42982143/python-requests-how-to-use-system-ca-certificates-debian-ubuntu?ref=tippybits.com" rel="noopener">shoutout to stackoverflow</a>). This is done by running the following:</p><pre><code>Python 3.8.5 (default, Jul 28 2020, 12:59:40)  
&gt;&gt;&gt; import certifi 
&gt;&gt;&gt; certifi.where() 
&apos;/etc/ssl/certs/ca-certificates.crt&apos;</code></pre><p>If you are trying to hit a server with a self signed certificate you first need to get their cert. Thanks again to the <a href="https://superuser.com/questions/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file?ref=tippybits.com" rel="noopener">wonderful stack overflow</a> for showing us the way:</p><pre><code>openssl s_client -showcerts -connect server.edu:443 &lt;/dev/null 2&gt;/dev/null|openssl x509 -outform PEM &gt;mycertfile.pem</code></pre><p>This will output the file as mycertfile.pem. Then we can add this to the trusted certs. THATS IT, no more janky workarounds or verify=False. Now go bask in the glory as the cleaner of logs and the implementer of security.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tippybits.com/content/images/2024/04/0-wwijpwwh2gl6uruw.png" class="kg-image" alt="Fixing your SSL Verify Errors in Python" loading="lazy" width="680" height="680" srcset="https://tippybits.com/content/images/size/w600/2024/04/0-wwijpwwh2gl6uruw.png 600w, https://tippybits.com/content/images/2024/04/0-wwijpwwh2gl6uruw.png 680w"><figcaption>Source: <a href="https://knowyourmeme.com/memes/hackerman?ref=tippybits.com" data-href="https://knowyourmeme.com/memes/hackerman" class="markup--anchor markup--figure-anchor" rel="noopener" target="_blank">KnowYourMeme.com</a></figcaption></figure>]]></content:encoded></item></channel></rss>