<?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[gr0vity]]></title><description><![CDATA[development & visualizations around nano]]></description><link>https://blog.bnano.info/</link><image><url>https://blog.bnano.info/favicon.png</url><title>gr0vity</title><link>https://blog.bnano.info/</link></image><generator>Ghost 5.31</generator><lastBuildDate>Tue, 07 Apr 2026 18:07:19 GMT</lastBuildDate><atom:link href="https://blog.bnano.info/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Nano Opens Doors - Effortlessly and Securely...]]></title><description><![CDATA[<p>Greetings, fellow Home Automation enthusiasts and Nano fans! <br>Allow me to share a proof-of-concept, where a simple Nano transaction can do something magical.</p><figure class="kg-card kg-video-card"><div class="kg-video-container"><video src="https://blog.bnano.info/content/media/2024/09/knx_nano_demo.webm" poster="https://img.spacergif.org/v1/360x640/0a/spacer.png" width="360" height="640" playsinline preload="metadata" style="background: transparent url(&apos;https://blog.bnano.info/content/images/2024/09/media-thumbnail-ember740.jpg&apos;) 50% 50% / cover no-repeat;"></video><div class="kg-video-overlay"><button class="kg-video-large-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button></div><div class="kg-video-player-container"><div class="kg-video-player"><button class="kg-video-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button><button class="kg-video-pause-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/></svg></button><span class="kg-video-current-time">0:00</span><div class="kg-video-time">/<span class="kg-video-duration"></span></div><input type="range" class="kg-video-seek-slider" max="100" value="0"><button class="kg-video-playback-rate">1&#xD7;</button><button class="kg-video-unmute-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/></svg></button><button class="kg-video-mute-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/></svg></button><input type="range" class="kg-video-volume-slider" max="100" value="100"></div></div></div></figure><!--kg-card-begin: markdown--><p>A simple tap to open a door. Secure, fully on-chain on the nano network.</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h2 id="how-does-it-work">How does it work ?</h2>
<p>For those interested in the</p>]]></description><link>https://blog.bnano.info/nano-opens-doors-effortlessly-and-securely/</link><guid isPermaLink="false">66e348c331d6e70001f0fb38</guid><dc:creator><![CDATA[gr0vity]]></dc:creator><pubDate>Fri, 13 Sep 2024 10:40:48 GMT</pubDate><media:content url="https://blog.bnano.info/content/images/2024/09/Screenshot-2024-09-13-at-12.53.12.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.bnano.info/content/images/2024/09/Screenshot-2024-09-13-at-12.53.12.png" alt="Nano Opens Doors - Effortlessly and Securely..."><p>Greetings, fellow Home Automation enthusiasts and Nano fans! <br>Allow me to share a proof-of-concept, where a simple Nano transaction can do something magical.</p><figure class="kg-card kg-video-card"><div class="kg-video-container"><video src="https://blog.bnano.info/content/media/2024/09/knx_nano_demo.webm" poster="https://img.spacergif.org/v1/360x640/0a/spacer.png" width="360" height="640" playsinline preload="metadata" style="background: transparent url(&apos;https://blog.bnano.info/content/images/2024/09/media-thumbnail-ember740.jpg&apos;) 50% 50% / cover no-repeat;"></video><div class="kg-video-overlay"><button class="kg-video-large-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button></div><div class="kg-video-player-container"><div class="kg-video-player"><button class="kg-video-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button><button class="kg-video-pause-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/></svg></button><span class="kg-video-current-time">0:00</span><div class="kg-video-time">/<span class="kg-video-duration"></span></div><input type="range" class="kg-video-seek-slider" max="100" value="0"><button class="kg-video-playback-rate">1&#xD7;</button><button class="kg-video-unmute-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/></svg></button><button class="kg-video-mute-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/></svg></button><input type="range" class="kg-video-volume-slider" max="100" value="100"></div></div></div></figure><!--kg-card-begin: markdown--><p>A simple tap to open a door. Secure, fully on-chain on the nano network.</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h2 id="how-does-it-work">How does it work ?</h2>
<p>For those interested in the technical side, let&#x2019;s break down the journey from transaction to action:</p>
<pre><code class="language-txt">     +-------------------+
     |   Nano Network    |  1. Nano transaction initiated via App
     +-------------------+
              |
              | (Internet)
              |
              v
     +-------------------+  2. receives transaction via websockets
     |   Local Server    |  3. if conditions are met
     +-------------------+  4. initiate KNX telegram
              |
              | (LAN)
              |
              v
     +-------------------+
     |  KNX/IP Gateway   |  5. KNX telegram passes IP Gateway to KNX Bus
     +-------------------+
              |
              | (KNX Bus)
              |
              v
     +-------------------+
     |   Electric Door   |  6. Electric Door receives KNX telegram
     +-------------------+  7. Door opens
</code></pre>
<p>The system is composed of 2 parts :</p>
<ol>
<li><a href="https://www.knx.org">KNX</a>, which is a widely used open standard for building automation.</li>
<li><a href="https://www.nano.org">Nano</a>, which is a cryptocurrency known for it&apos;s speed and having zero fees.</li>
</ol>
<p>In this proof of concept, nano transactions are monitored on a local server via websockets. When all conditions are met, a KNX telegram is initiated resulting in the KNX actor to open the door. In code it looks as follows :</p>
<pre><code class="language-python">async def run(self):
    # Connect to the KNX system that controls our smart home devices
    await self.setup_knx()

    # Set up a connection to listen for Nano cryptocurrency transactions
    self.nano_ws = NanoWebSocket(url=self.nano_ws_url) 

    # (Optional) List of whitelisted Nano accounts we want to monitor for payments
    accounts = [&quot;nano_3rdc...&quot;]
    await self.nano_ws.subscribe_confirmation(accounts)

    # Continuously listen for new confirmed Nano transactions
    async for message in self.nano_ws.receive_messages():            
        # Check if the payment was sent to our door&apos;s Nano address
        if self.payment_ok(message):            
            await self.open_door()
</code></pre>
<p>In the code above, I used a single whitelisted account. Nano&apos;s cryptography ensures no one else can initiate a transactiom from my account. I&apos;m the only one with my private key, I&apos;m the only one that can unlock the door.</p>
<h2 id="beyond-opening-doors">Beyond Opening Doors</h2>
<p>With just a tap, Nano unlocks more than doors - it unlocks possibilities.</p>
<p>Today, I&apos;ve unlocked my own front door, but tomorrow? We could <strong>open the gates</strong> to museums, amusement parks, co-working spaces, and more.</p>
<p><strong>Scan, tap, enter!</strong> All within seconds and fully confirmed on-chain.</p>
<p>What makes Nano especially powerful for these applications is <strong>its simplicity and accessibility</strong>. Unlike traditional payment methods or access control systems, <strong>Nano doesn&apos;t require any third-party tools</strong> or additional costs to receive funds. This opens up a world of possibilities, <strong>allowing us to invent previously unimaginable use cases</strong> that were bound by the limitations of traditional payment methods.</p>
<p>The future awaits, and with Nano, the possibilities are endless.<br>
<strong>I&#x2019;d love to hear your thoughts!<br>
What doors shall we open next?</strong></p>
<p>If you like my work, <a href="https://nano.to/gr0vity">please show your love</a> &#x1F49B;</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Automated Flamegraph Generation with nanolab-lxd: Nano Integration Testing Simplified]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://github.com/gr0vity-dev/nanolab-lxd">nanolab-lxd</a> provides an integration test environment for the Nano network. With this tool, you can efficiently spin up local Nano networks and execute tests inside an LXD container. While a similar setup is possible with <a href="https://github.com/gr0vity-dev/nanolab">nanolab</a>, LXD offers the added advantage of isolation, ensuring that your host environment remains untouched.</p>]]></description><link>https://blog.bnano.info/setting-up-nanolab-lxd-guide-to-integration-testing/</link><guid isPermaLink="false">64ee38cfc6afd0000129eb70</guid><dc:creator><![CDATA[gr0vity]]></dc:creator><pubDate>Tue, 29 Aug 2023 19:41:49 GMT</pubDate><media:content url="https://blog.bnano.info/content/images/2023/09/12D01F17-0BC9-48D3-8D27-32021CCE0F77.jpeg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.bnano.info/content/images/2023/09/12D01F17-0BC9-48D3-8D27-32021CCE0F77.jpeg" alt="Automated Flamegraph Generation with nanolab-lxd: Nano Integration Testing Simplified"><p><a href="https://github.com/gr0vity-dev/nanolab-lxd">nanolab-lxd</a> provides an integration test environment for the Nano network. With this tool, you can efficiently spin up local Nano networks and execute tests inside an LXD container. While a similar setup is possible with <a href="https://github.com/gr0vity-dev/nanolab">nanolab</a>, LXD offers the added advantage of isolation, ensuring that your host environment remains untouched.</p>
<p>In this guide, we&apos;ll walk you through setting up nanoLab-lxd, executing test cases, and retrieving the results.</p>
<h3 id="0-getting-started-with-nanolab-lxd">0. Getting Started with nanolab-lxd</h3>
<p>To begin, clone the <code>nanolab-lxd</code> repository and switch to the <code>wip/host-to-lxd</code> branch:</p>
<pre><code>git clone https://github.com/gr0vity-dev/nanolab-lxd.git
cd nanolab-lxd
git checkout wip/host-to-lxd
</code></pre>
<h3 id="1-setting-up-the-lxd-environment">1. Setting up the LXD environment</h3>
<p>For Ubuntu users:</p>
<pre><code>sudo apt-get install lxd lxd-client
lxd init # Accept the default options when prompted
</code></pre>
<h3 id="2-initialize-your-nanolab-lxd-container">2. Initialize your nanolab-lxd container</h3>
<p>To launch nanoLab inside an LXD container, execute:</p>
<pre><code>./nanolab-lxd.sh
</code></pre>
<p>You can then verify that the container is operational using:</p>
<pre><code>lxc ls nanolab22
</code></pre>
<p>The expected output resembles:</p>
<pre><code class="language-sql">+-----------+---------+--------------+------------+-----------+-----------+
|   NAME    |  STATE  |      IPV4    |   IPV6     |   TYPE    | SNAPSHOTS |
+-----------+---------+--------------+------------+-----------+-----------+
| nanolab22 | RUNNING | 17.. (br..)  | fd42: (eth)| CONTAINER | 0         |
|           |         | 17.. (dock..)|            |           |           |
|           |         | 10.. (eth0)  |            |           |           |
+-----------+---------+--------------+------------+-----------+-----------+
</code></pre>
<h3 id="3-exploring-and-running-test-cases">3. Exploring and Running Test Cases</h3>
<p>To see all available test cases, use:</p>
<pre><code>./run-lab-lxd list
</code></pre>
<p>This will display a series of available test cases:</p>
<pre><code>https://api.github.com/repos/gr0vity-dev/nanolab-configs/...

bintree
flamegraph_bintree
flamegraph_bintree_fast
flamegraph_change_independent
</code></pre>
<p>To execute a specific test case:</p>
<pre><code>./run-lab-lxd run -t flamegraph_bintree -i &quot;nanocurrency/nano:V26.0DB13&quot;
</code></pre>
<p>Here, the <code>-i</code> flag specifies the Docker image for the Nano nodes.</p>
<h3 id="4-utilizing-local-docker-builds-within-the-lxd-container">4. Utilizing Local Docker Builds within the LXD Container</h3>
<p>To test custom Nano Docker images compiled from the NanoCurrency source:</p>
<pre><code>git clone https://github.com/nanocurrency/nano-node.git --recursive
cd nano-node
docker build -f docker/node/Dockerfile -t your_nano_image .
</code></pre>
<p>Then, transition to the <code>nanolab-lxd</code> directory and transfer the Docker image to LXD:</p>
<pre><code>./mv_docker_to_lxd.sh your_nano_image
</code></pre>
<p>To run your test:</p>
<pre><code>./run-lab-lxd run -t flamegraph_bintree -i &quot;your_nano_image&quot;
</code></pre>
<h3 id="5-extracting-results">5. Extracting Results</h3>
<p>To retrieve flamegraphs from the LXD to your host:</p>
<pre><code>lxc exec nanolab22 -- ls | grep flame | xargs -I{} lxc file pull nanolab22/root/{} .
</code></pre>
<p>Note: Flamegraph test cases typically record for around 20 seconds. The Docker container might also retrieve additional dependencies, causing minor delays:</p>
<pre><code>apt-get update &amp;&amp; apt-get install -y linux-tools-generic binutils
</code></pre>
<h3 id="6-customizing-test-cases">6. Customizing Test Cases</h3>
<p>You can tailor test cases to your requirements by adjusting the <code>config.json</code> file inside the LXD container. Execute:</p>
<pre><code>lxc exec nanolab22 /bin/bash
nanolab list --local # This displays all the downloaded test case configurations.
</code></pre>
<p>This command showcases the available configurations:</p>
<pre><code>testcases/flamegraph_change_independent_config.json
testcases/flamegraph_bintree_fast_config.json
testcases/flamegraph_bintree_config.json
testcases/bintree_config.json
</code></pre>
<p>Adjust these configurations using your favorite text editor.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Building the Best Version of Digital Cash: A Call to all the Builders, Tinkerers, and Changemakers]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h4 id="in-the-pioneering-spirit-of-exploration-and-discovery-amidst-skeptics-and-freedom-advocates-a-new-vision-emerges-its-time-to-redefine-our-financial-future">In the pioneering spirit of exploration and discovery, amidst skeptics and freedom advocates, a new vision emerges. It&apos;s time to redefine our financial future.</h4>
<p>As the era of digitization advances at a breathtaking pace, we find ourselves at the threshold of a global financial metamorphosis. The transformation of</p>]]></description><link>https://blog.bnano.info/building-the-best-version-of-digital-cash-a-call-to-all-the-builders-tinkerers-and-changemakers/</link><guid isPermaLink="false">64a72078c6afd0000129eb3b</guid><dc:creator><![CDATA[gr0vity]]></dc:creator><pubDate>Tue, 29 Aug 2023 18:22:26 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h4 id="in-the-pioneering-spirit-of-exploration-and-discovery-amidst-skeptics-and-freedom-advocates-a-new-vision-emerges-its-time-to-redefine-our-financial-future">In the pioneering spirit of exploration and discovery, amidst skeptics and freedom advocates, a new vision emerges. It&apos;s time to redefine our financial future.</h4>
<p>As the era of digitization advances at a breathtaking pace, we find ourselves at the threshold of a global financial metamorphosis. The transformation of traditional systems into the digital realm will bring us Central Bank Digital Currencies (CBDCs) &#x2013; digital Euros, digital Dollars, and the like. But this moment prompts an essential question: <strong>Should we accept this change passively, or should we aspire to something more significant, something truly revolutionary?</strong></p>
<p>This is for all those who see the profound value in decentralized digital cash. We, who value freedom of choice and harbor skepticism towards the looming dominance of CBDCs. We, who desire to change the system, to make a difference.</p>
<p>We&apos;re builders, tinkerers, high achievers and sometimes procrastinators. <strong>We believe in our collective capacity to conceive and develop an improved version of digital cash: open, inclusive, and free for everyone.</strong></p>
<h2 id="the-power-of-decentralized-digital-cash">The Power of Decentralized Digital Cash</h2>
<p>Public trust in financial institutions has been steadily eroding over time. There&apos;s a growing discomfort towards the level of control that centralized entities could potentially exert over a digital currency. A decentralized version of cash stands as a viable solution. It implies that no single authority can control, manipulate, or decide who has the right to use it.</p>
<p>Free from central authority, digital cash embodies the essence of economic sovereignty and personal freedom. <strong>It&apos;s available to anyone</strong> with internet access, not discriminating based on location, identity, or wealth. It&apos;s <strong>an empowering tool for individuals</strong>, rather than an instrument of control for institutions.</p>
<h2 id="dreaming-up-the-future-of-money">Dreaming Up the Future of Money</h2>
<p>The path forward is filled with challenges and complexities. <strong>We need the collective intelligence and creativity of many to tackle issues of scalability, privacy, security, and user experience.</strong> Yet, there&apos;s an enduring belief that together, we can build this system. We can create digital cash that is as free as the air we breathe, as universal as human rights, and as groundbreaking as the invention of the internet itself.</p>
<p>To every builder and tinkerer brave enough to reimagine our financial systems, to every high achiever who won&apos;t settle for the status quo, to every procrastinator waiting for the perfect moment to make a mark - this is your call to action. <strong>It&apos;s your chance to contribute to something transformative, something monumental.</strong></p>
<p>Together, we can redefine money, not as a tool of control but as a means of empowerment. Where access to financial services is a right, not a privilege. With technology, we have the power to not merely replicate financial inequalities of the past, but <strong>to create a future of financial inclusion and freedom.</strong></p>
<p>People like us, build things like this. <a href="https://nano.org/en/connect">Join in to shape our future!</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[ChatGPT knows how to use the nano rpc!]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h2 id="introduction">Introduction:</h2>
<p>In this blog post, we&apos;ll dive into Nano and we&apos;ll learn how to us the <a href="https://docs.nano.org/commands/rpc-protocol/">nano_node RPC</a> to receive our first nano transaction and forward it to a new address.</p>
<p>Nano is a near-instant cryptocurrency with no fees and a small ecological footprint.<br>
To</p>]]></description><link>https://blog.bnano.info/chatgpt-knows-how-to-use-the-nano-rpc/</link><guid isPermaLink="false">63fdd1e1b5214d0001b0c118</guid><dc:creator><![CDATA[gr0vity]]></dc:creator><pubDate>Wed, 29 Mar 2023 08:12:02 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="introduction">Introduction:</h2>
<p>In this blog post, we&apos;ll dive into Nano and we&apos;ll learn how to us the <a href="https://docs.nano.org/commands/rpc-protocol/">nano_node RPC</a> to receive our first nano transaction and forward it to a new address.</p>
<p>Nano is a near-instant cryptocurrency with no fees and a small ecological footprint.<br>
To interact with the network, the nano_node software exposes a variety of remote procedure calls (RPCs) that let you browse the ledger, create Nano transactions and more.</p>
<p>To help me with this task, I asked ChatGPT how to use the Nano RPC to create a wallet and receive a transaction from a faucet.<br>
While the example it created wasn&apos;t quite perfect, it was easy to make it work with a few adjustments.</p>
<blockquote>
<p>All the additions and corrections I made are highlighted like this.</p>
</blockquote>
<p>If you want to follow along and try out the Nano RPC for yourself, you can</p>
<ul>
<li>use the following <a href="https://www.postman.com/countto10/workspace/nano-rpc/request/20978855-d9d7a9c7-d104-4699-bd60-d8cd0963737b">Postman collection</a> with all the relevant commands or</li>
<li><a href="https://www.youtube.com/watch?v=O_mRdDi910U">watch my video</a> where I go trough the whole process in about 5 minutes.</li>
</ul>
<p>I created a fully synced node with public access to the RPC so you don&apos;t need to setup your own nano_node.<br>
If you&apos;re interested in setting up your own Nano node, you can read this <a href="https://blog.nano.org/how-to-run-a-node-and-why-a-full-nano-guide-7dff90fa826e">blog article</a>, or spin up a <a href="https://github.com/fwd/nano-docker">dockerized node</a> with just one command.</p>
<h2 id="adjusted-example-created-by-chatgpt">Adjusted example created by ChatGPT</h2>
<h3 id="1-creating-a-new-wallet">1) Creating a New Wallet</h3>
<blockquote>
<p>Follow along on your own : <a href="https://www.postman.com/countto10/workspace/nano-rpc/request/20978855-d9d7a9c7-d104-4699-bd60-d8cd0963737b">Postman collection</a></p>
</blockquote>
<p>To create a new wallet using the Nano RPC, we will send a POST request to the endpoint <code>https://rpcproxy.bnano.info/live</code> with the following payload:</p>
<pre><code class="language-json">{
    &quot;action&quot;: &quot;wallet_create&quot;
}
</code></pre>
<pre><code class="language-bash">curl -X POST --data &apos;{&quot;action&quot;:&quot;wallet_create&quot;}&apos; https://rpcproxy.bnano.info/live
</code></pre>
<p>The response will contain the seed for our new wallet:</p>
<pre><code class="language-json">{
    &quot;wallet&quot;: &quot;E861D8_truncated_for_brevity&quot;
}
</code></pre>
<h3 id="2-adding-an-account">2) Adding an Account</h3>
<p>To add an account to our wallet, we will send a POST request to the endpoint <code>https://rpcproxy.bnano.info/live</code> with the following payload:</p>
<pre><code class="language-json">{
    &quot;action&quot;: &quot;account_create&quot;,
    &quot;wallet&quot;: &quot;E861D8_truncated_for_brevity&quot;
}
</code></pre>
<pre><code class="language-bash">curl -X POST --data &apos;{&quot;action&quot;:&quot;account_create&quot;,&quot;wallet&quot;:&quot;E861D8_truncated_for_brevity&quot;}&apos; https://rpcproxy.bnano.info/live
</code></pre>
<p>The response will contain the private key and the public address for our new account:</p>
<pre><code class="language-json">{
    &quot;accounts&quot;: [
        {
            &quot;private&quot;: &quot;45A3_truncated_for_brevity&quot;,
            &quot;public&quot;: &quot;nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4&quot;
        }
    ]
}
</code></pre>
<h3 id="3-receiving-a-first-transaction-from-a-faucet">3) Receiving a First Transaction from a Faucet</h3>
<p>To receive funds, we will need to provide the public address of our account to the faucet.</p>
<blockquote>
<p>You can visit  <a href="https://freenanofaucet.com/faucet">https://freenanofaucet.com/faucet</a> to receive some free nano</p>
</blockquote>
<h3 id="4-check-your-account-balance">4) Check your account balance</h3>
<p>Once the faucet has sent the funds, we can check the balance of our account using the following payload:</p>
<pre><code class="language-json">{   
	&quot;action&quot;: &quot;account_balance&quot;,   
	&quot;account&quot;: &quot;nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4&quot; 
}
</code></pre>
<pre><code class="language-bash">curl -X POST --data &apos;{&quot;action&quot;:&quot;account_balance&quot;,&quot;account&quot;:&quot;nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4&quot;}&apos; https://rpcproxy.bnano.info/live
</code></pre>
<p>The response will contain the current balance of the account:</p>
<pre><code class="language-json">{
    &quot;balance&quot;: &quot;0&quot;, //corrected version
    &quot;pending&quot;: &quot;12000000000000000000000000&quot;,
    &quot;receivable&quot;: &quot;12000000000000000000000000&quot;
}
</code></pre>
<blockquote>
<p>This is where chatGPT was wrong for the first time. Your account will show <code>&quot;balance&quot;: &quot;0&quot;</code> . The funds are in a &quot;receivable&quot; state.<br>
Before you can use and forward the funds to another account, you first need to actively receive what has been sent to your account.<br>
I told ChatGPT it missed a step and asked to receive the funds. It got the receive command right, but listed the wrong arguments.</p>
</blockquote>
<h3 id="5-query-the-receivable-block">5) Query the receivable block</h3>
<blockquote>
<p>Again ChatGPT was missing a step. To receive the funds, we need to query the receivable blocks in our wallet first like this:</p>
</blockquote>
<pre><code class="language-json">{  
 &quot;action&quot;: &quot;wallet_receivable&quot;,  
 &quot;wallet&quot;: &quot;E861D8_truncated_for_brevity&quot; 
}
</code></pre>
<blockquote>
<p>The response will contain all the accounts in our wallet with their receivable blocks</p>
</blockquote>
<pre><code class="language-json">{
  &quot;blocks&quot;: {
    &quot;nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4&quot;: [&quot;AD628C1F_truncated_for_brevity&quot;]
  }
} 
</code></pre>
<h3 id="6-create-the-receivable-block">6) Create the receivable block</h3>
<p>To receive the funds, we need to specify  <s>the source of the funds (i.e., the public address of the sender),</s> the wallet and the account that the funds should be received into, and the <s>amount  of funds</s>  block being received.<br>
Here is the payload for the &quot;receive&quot; action:</p>
<pre><code class="language-json">{  
 &quot;action&quot;: &quot;receive&quot;,  
 &quot;wallet&quot;: &quot;E861D8_truncated_for_brevity&quot;,  
 &quot;account&quot;: &quot;nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4&quot;,  //ChatGPT suggested &quot;source&quot; instead of &quot;account&quot;
 &quot;block&quot;: &quot;AD628C1F_truncated_for_brevity&quot;  // ChatGPT suggested &quot;amount&quot; instead of &quot;block&quot;
}
</code></pre>
<p>And here is the curl command:</p>
<pre><code class="language-bash">curl -X POST --data &apos;{&quot;action&quot;:&quot;receive&quot;,&quot;wallet&quot;:&quot;E861D8_truncated_for_brevity&quot;,&quot;account&quot;:&quot;nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4&quot;,&quot;block&quot;:&quot;AD628C1F_truncated_for_brevity&quot;}&apos; https://rpcproxy.bnano.info/live 
</code></pre>
<p>The response will contain a block hash, which can be used to track the confirmation of the transaction on the Nano network. The funds will now be available in your account and you can verify the balance using the &quot;balance&quot; action.</p>
<blockquote>
<p>With just a few tweaks we got a working RPC example from ChatGPT.<br>
We&apos;ll now look at the RPC commands to send our funds to a new account</p>
</blockquote>
<h3 id="7-check-our-wallet">7) Check our wallet</h3>
<p>To see all the funds in our wallet, we can use the &quot;wallet_info&quot; command</p>
<pre><code class="language-json">{
    &quot;action&quot;: &quot;wallet_info&quot;,
    &quot;wallet&quot;: &quot;E861D8_truncated_for_brevity&quot;
}
</code></pre>
<p>The result will list the total balance of all our accounts. In our current example, we only have a single account <code>&quot;accounts_count&quot;: &quot;1&quot;</code></p>
<pre><code class="language-json">{
    &quot;balance&quot;: &quot;12000000000000000000000000&quot;,
    &quot;pending&quot;: &quot;0&quot;,
    &quot;receivable&quot;: &quot;0&quot;,
    &quot;accounts_count&quot;: &quot;1&quot;,
    &quot;accounts_block_count&quot;: &quot;1&quot;,
    &quot;accounts_cemented_block_count&quot;: &quot;1&quot;,
    &quot;deterministic_count&quot;: &quot;1&quot;
    ...  
}
</code></pre>
<h3 id="8-send-to-a-new-address">8) Send to a new address</h3>
<p>To send our funds to a new address we have to provide our<code> wallet</code>, the <code>source</code> account we want to send from, the <code>destination</code> account and the <code>amount</code>.<br>
We can provide an optional &quot;id&quot; that makes sure that even if we execute the send command twice, we don&apos;t actually send our funds twice.</p>
<pre><code class="language-json">{
  &quot;action&quot;: &quot;send&quot;,
  &quot;wallet&quot;: &quot;E861D8_truncated_for_brevity&quot;,
  &quot;source&quot;: &quot;nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4&quot;,
  &quot;destination&quot;: &quot;nano_118tih7f81iiuujdezyqnbb9aonybf6y3cj7mo7hbeetqiymkn16a67w8rkp&quot;,
  &quot;amount&quot;: &quot;12000000000000000000000000&quot;,
  &quot;id&quot;: &quot;a_unique_id_62386187gd&quot;
} 
</code></pre>
<p>The response is a block. We will query the content of the block in the next step</p>
<pre><code class="language-json">{
  &quot;block&quot;: &quot;6ADE56_truncated_for_brevity&quot;
}
</code></pre>
<h3 id="9-query-the-content-of-our-send-block">9) Query the content of our send block</h3>
<p>To validate that our block has been confirmed by the network, we can use the &quot;block_info&quot; command, which will return all the information of our transaction.</p>
<pre><code class="language-json">{  
  &quot;action&quot;: &quot;block_info&quot;,
  &quot;json_block&quot;: &quot;true&quot;,
  &quot;hash&quot;: &quot;6ADE56_truncated_for_brevity&quot;
}
</code></pre>
<p>The result has &quot;confirmed&quot; field that is &quot;true&quot; if the block has been confirmed by the network.<br>
At this point the transaction is final and can&apos;t be reveresed.</p>
<pre><code class="language-json">{
  &quot;block_account&quot;: &quot;nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4&quot;,
  &quot;amount&quot;: &quot;12000000000000000000000000&quot;,
  &quot;balance&quot;: &quot;0&quot;,
  &quot;height&quot;: &quot;2&quot;,
  &quot;local_timestamp&quot;: &quot;0&quot;,
  &quot;successor&quot;: &quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,
  &quot;confirmed&quot;: &quot;true&quot;,
  &quot;contents&quot;: {
    &quot;type&quot;: &quot;state&quot;,
    &quot;account&quot;: &quot;nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4&quot;,
    &quot;previous&quot;: &quot;CE898C131AAEE25E05362F247760F8A3ACF34A9796A5AE0D9204E86B0637965E&quot;,
    &quot;representative&quot;: &quot;nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4&quot;,
    &quot;balance&quot;: &quot;12000000000000000000000000&quot;,
    &quot;link&quot;: &quot;5D1AA8A45F8736519D707FCB375976A7F9AF795091021D7E9C7548D6F45DD8D5&quot;,
    &quot;link_as_account&quot;: &quot;nano_118tih7f81iiuujdezyqnbb9aonybf6y3cj7mo7hbeetqiymkn16a67w8rkp&quot;,
    &quot;signature&quot;: &quot;82D41BC16F313E4B2243D14DFFA2FB04679C540C2095FEE7EAE0F2F26880AD56DD48D87A7CC5DD760C5B2D76EE2C205506AA557BF00B60D8DEE312EC7343A501&quot;,
    &quot;work&quot;: &quot;8a142e07a10996d5&quot;
  },
  &quot;subtype&quot;: &quot;send&quot;
}
</code></pre>
<p>I hope you enjoyed. Make sure to  <a href="https://www.postman.com/countto10/workspace/nano-rpc/request/20978855-d9d7a9c7-d104-4699-bd60-d8cd0963737b">try it</a> for yourself!</p>
<h2 id="conclusion">Conclusion</h2>
<p>In this article, we have seen how to interact with the Nano RPC to perform various actions such as creating a wallet, adding an account, receiving funds and forwarding the funds to a new address.<br>
The Nano RPC is a powerful tool for developers looking to build applications on top of the Nano network, and the use of Postman or curl allows for quick and easy testing of the API.</p>
<p>If you like my work, <a href="https://nano.to/gr0vity">please show your love</a> &#x1F49B;</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Streamlining the Network: Automated Integration Testing for the Nano node]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Integration testing is an essential step in the development of any decentralised network. It verifies that the nodes in the network can communicate, and interact with each other as expected.<br>
However, conducting these tests manually can be very time-consuming.</p>
<p><a href="https://github.com/gr0vity-dev/nano-node-ci">Nano-node-ci</a> is a tool that streamlines the process of testing the</p>]]></description><link>https://blog.bnano.info/streamlining-the-network-automated-integration-testing-for-the-nano-node/</link><guid isPermaLink="false">63e565cdb5214d0001b0c0ea</guid><dc:creator><![CDATA[gr0vity]]></dc:creator><pubDate>Thu, 09 Feb 2023 21:41:02 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Integration testing is an essential step in the development of any decentralised network. It verifies that the nodes in the network can communicate, and interact with each other as expected.<br>
However, conducting these tests manually can be very time-consuming.</p>
<p><a href="https://github.com/gr0vity-dev/nano-node-ci">Nano-node-ci</a> is a tool that streamlines the process of testing the nano node, ensuring its reliability and stability in a local network.<br>
By automatically testing each new commit and pull request made to the nano-node repository, nano-node-ci helps identify any potential issues early on, so they can be corrected before deployment.</p>
<h3 id="how-nano-node-ci-works">How nano-node-ci works</h3>
<p>Nano-node-ci is triggered on each new commit and on each pull request made to the <a href="https://github.com/nanocurrency/nano-node">nano-node repository</a>.</p>
<ul>
<li>The nano-node is then built using <a href="https://github.com/gr0vity-dev/nano-node-builder">nano-node-builder</a> (see <a href="https://blog.bnano.info/a-new-nano_node-docker-image-for-each-new-github-commit/">blog post</a> for more details)</li>
<li>If a new build is detected, a test suite of 23 tests is executed.<br>
The results of these tests are then published to nano-node-ci, providing a comprehensive overview in a PASS/FAIL manner as shown in the screenshot below:</li>
</ul>
<p><a href="https://github.com/gr0vity-dev/nano-node-ci"><img src="https://blog.bnano.info/content/images/2023/02/continuous_testing_nano-node-ci.png" alt="continuous_testing_nano-node-ci" loading="lazy"></a></p>
<p>Each testrun generates 3 links :</p>
<ul>
<li><strong>results</strong> : a simple text file with test results,</li>
<li><strong>telemetry</strong> : a dashboard with detailed node telemetry data for additional debugging information in case of any test case failure.</li>
<li><strong>graphs</strong> : a dashboard with a performance overview per test case</li>
</ul>
<p>The following shows an example of the performance dashboard.<br>
5 out of 23 tests are shown :<br>
<img src="https://blog.bnano.info/content/images/2023/02/continuous_testing_kibana-example.png" alt="continuous_testing_kibana-example" loading="lazy"></p>
<h3 id="the-benefits-of-automated-integration-testing">The Benefits of Automated Integration Testing</h3>
<p>Examples of things that need to be tested during integration testing of the nano node include:</p>
<ul>
<li>Communication with other nodes in the network</li>
<li>Synchronization of the nodes with the network</li>
<li>Consensus participation (voting on transactions)</li>
<li>Verification of transactions (signature validation)</li>
</ul>
<p>The goal of nano-node-ci is to validate that new versions of the nano-node meet all the requirements above.</p>
<ul>
<li>It helps to identify any potential issue with new nano-node versions before they are deployed.</li>
<li>This ensures that bugs can be corrected early in the process, improving the overall quality of the code.</li>
<li>Additionally, by providing test results for each build, the nano-node performance can be tracked over time and regression can be identified quickly.</li>
</ul>
<p><strong>In conclusion</strong>, nano-node-ci provides integration testing to the nano node, ensuring its reliability and stability. Improved network reliability and increased development speed are key goals of nano-node-ci.</p>
<p>With reliable automated testing, potential issues can be identified and corrected early in the development process, leading to improved code quality, faster bug detection, better collaboration, and increased development speed.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[The nano beta network and what's it for ?]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>The Beta Network serves as a testing ground where new nano-node versions are tested regularly.</p>
<p>Before a new version is live, one or more release candidates are deployed to the Beta Network and undergo a series of tests by beta node operators.<br>
With around 10% of the node count of</p>]]></description><link>https://blog.bnano.info/the-nano-beta-network-and-its-surrounding-tools/</link><guid isPermaLink="false">63cf94aea367d1000123893b</guid><dc:creator><![CDATA[gr0vity]]></dc:creator><pubDate>Thu, 26 Jan 2023 15:23:33 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>The Beta Network serves as a testing ground where new nano-node versions are tested regularly.</p>
<p>Before a new version is live, one or more release candidates are deployed to the Beta Network and undergo a series of tests by beta node operators.<br>
With around 10% of the node count of the live network, the Beta Network provides a real-world environment to validate new node versions.</p>
<p>In the past, these tests have been mainly manual.</p>
<ul>
<li>Users simulate high network traffic by publishing lots of blocks.</li>
<li>Results are visually compared to testruns of previous versions.</li>
</ul>
<h2 id="beta-tools-explorer-wallets-visualizer">Beta Tools (Explorer, Wallets, Visualizer)</h2>
<p>Over the past six months, I have been working on improving the ease of use of the nano beta network and on introducing automated testing.<br>
To this end, I have forked the respective GitHub repositories to have:</p>
<ul>
<li><a href="https://nanolooker.bnano.info">Beta Block Explorer</a> (cloned nanolooker.com)</li>
<li><a href="https://nault.bnano.info">Beta Wallet</a> (cloned nault.cc)</li>
<li><a href="https://nanoticker.bnano.info/">Beta Network visualizer</a> (cloned nanoticker.info)</li>
<li><a href="https://votes.bnano.info">Beta Vote Visualizer</a> (cloned nanovisual.numsu.dev</li>
</ul>
<p>In addition, the Beta Network is used to validate node changes before a new version is released.<br>
To aid in identifying and troubleshooting potential issues that occur during beta tests, we increased the detail of available node telemetry.<br>
This includes dashboards with both simple and advanced telemetry provided by the nodes.</p>
<ul>
<li>Dashboard with <a href="https://kutt.bnano.info/telemetry_beta_1d">simple telemetry</a> provided by the nodes</li>
<li>Dashboard with <a href="https://nodestats.bnano.info">advanced telemetry</a> pushed by node operators to a centralised database</li>
</ul>
<p>With the help of these advanced metrics, we now can</p>
<ul>
<li>compare the behavior of beta nodes in detail,</li>
<li>identify how well each beta node performs,</li>
<li>test how changes in configurations impact the outcome of any given test,</li>
<li>identify portential causes of any arising issue</li>
</ul>
<h2 id="automated-beta-testing">Automated Beta testing</h2>
<p>I introduced a <a href="https://tps.bnano.info/beta">small daily speedtest</a> that publishes 7500 blocks on each run and measures the confirmations per second (cps) of the network.</p>
<p>In the graph below we can see the daily cps rate.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.bnano.info/content/images/2023/01/nano_beta_tools_daily_speedtest.png" class="kg-image" alt loading="lazy" width="1643" height="374" srcset="https://blog.bnano.info/content/images/size/w600/2023/01/nano_beta_tools_daily_speedtest.png 600w, https://blog.bnano.info/content/images/size/w1000/2023/01/nano_beta_tools_daily_speedtest.png 1000w, https://blog.bnano.info/content/images/size/w1600/2023/01/nano_beta_tools_daily_speedtest.png 1600w, https://blog.bnano.info/content/images/2023/01/nano_beta_tools_daily_speedtest.png 1643w" sizes="(min-width: 1200px) 1200px"></figure><p>The speed-test itself is not 100% stable so the rate at which blocks are published to the network (bps) is not stable from day to day. It varies from about 300 to 1k bps<br>This explains the spikes in cps which follow the rate at which blocks are published.</p><p></p><p>If you like my work, <a href="https://nano.to/gr0vity">please show your love</a> &#x1F49B;</p>]]></content:encoded></item><item><title><![CDATA[Monitoring the nano network by analysing telemetry data]]></title><description><![CDATA[<p></p><p>In a traditionl application, telemetry data is usually used to give developers quick feedback of how a change impacts the production environment.<br>This way, by monitoring the telemetry data closely, a new change pushed to the application that causes unforseen problems in production is often caught and fixed before any</p>]]></description><link>https://blog.bnano.info/a-nano_node-docker-image-for-each-new-github-commit/</link><guid isPermaLink="false">63ce2872a367d10001238839</guid><dc:creator><![CDATA[gr0vity]]></dc:creator><pubDate>Mon, 23 Jan 2023 10:55:03 GMT</pubDate><content:encoded><![CDATA[<p></p><p>In a traditionl application, telemetry data is usually used to give developers quick feedback of how a change impacts the production environment.<br>This way, by monitoring the telemetry data closely, a new change pushed to the application that causes unforseen problems in production is often caught and fixed before any customer is visibly impacted.</p><p>The nano-node provides telemetry data aswell.<br>I created a <a href="https://kutt.bnano.info/telemetry_1d">dashboard</a> that monitors the telemetry data provided by the <em>top#20 representatives</em>. This way we have a tool that leverages the available information &#xA0;so we can proactively look for and fix potential issues.</p><h2 id="what-data-does-the-nano-node-telemetry-provide">What data does the nano-node telemetry provide ?</h2><p>The following is an example-response provided by the telemetry rpc request :</p><pre><code class="language-json">{
    &quot;metrics&quot;: [
        {
            &quot;block_count&quot;: &quot;173834771&quot;,
            &quot;cemented_count&quot;: &quot;173834771&quot;,
            &quot;unchecked_count&quot;: &quot;0&quot;,
            &quot;account_count&quot;: &quot;30874506&quot;,
            &quot;bandwidth_cap&quot;: &quot;10485760&quot;,
            &quot;peer_count&quot;: &quot;208&quot;,
            &quot;protocol_version&quot;: &quot;18&quot;,
            &quot;uptime&quot;: &quot;9570208&quot;,
            &quot;genesis_block&quot;: &quot;991CF19009...AA4A6734DB9F19B728948&quot;,
            &quot;major_version&quot;: &quot;23&quot;,
            &quot;minor_version&quot;: &quot;3&quot;,
            &quot;patch_version&quot;: &quot;0&quot;,
            &quot;pre_release_version&quot;: &quot;0&quot;,
            &quot;maker&quot;: &quot;0&quot;,
            &quot;timestamp&quot;: &quot;1674466711662&quot;,
            &quot;active_difficulty&quot;: &quot;fffffff800000000&quot;,
            &quot;node_id&quot;: &quot;node_38d87w3o99k5np...nz36kui3re5&quot;,
            &quot;signature&quot;: &quot;745514A037472E2986DC755...370E1AF08&quot;,
            &quot;address&quot;: &quot;::ffff:159.XXX.XXX.206&quot;,
            &quot;port&quot;: &quot;7075&quot;
        }
    ]
}        
</code></pre><p>The <a href="https://kutt.bnano.info/telemetry_1d">dashboard</a> visualizes the following metrics for each node :</p><ul><li>checked blocks (and missing checked blocks)</li><li>cemented blocks (and missing cemented blocks)</li><li>unchecked blocks</li><li>total accounts (and missing accounts)</li><li>bandwidth limit</li><li>peer count</li><li>node version</li></ul><h2 id="can-we-identify-weak-nodes-by-looking-at-the-telemetry-data">Can we identify weak nodes by looking at the telemetry data ?</h2><p>Identifying the best nodes by looking at the telemetry data is not obvious.<br>However identifying weks nodes seems possible with the metrics provided in the telemetry.<br>As an example, we will look at the &#xA0;<strong>block_count graph</strong> .</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.bnano.info/content/images/2023/01/live_telemetry_block_count.png" class="kg-image" alt loading="lazy" width="1385" height="472" srcset="https://blog.bnano.info/content/images/size/w600/2023/01/live_telemetry_block_count.png 600w, https://blog.bnano.info/content/images/size/w1000/2023/01/live_telemetry_block_count.png 1000w, https://blog.bnano.info/content/images/2023/01/live_telemetry_block_count.png 1385w" sizes="(min-width: 1200px) 1200px"></figure><p><br>During the daily speedtest performed by nanotps.com, 5000 blocks are published to all nodes.<br>What we see, is that most top#20 representatives check most of the blocks within 30 seconds, while 2 nodes take considerably longer.</p><p>An even better insight can be gained from looking at the following graph that shows the &#xA0;<strong>missing block_count</strong> .</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.bnano.info/content/images/2023/01/live_telemetry_misisng_block_count.png" class="kg-image" alt loading="lazy" width="1388" height="453" srcset="https://blog.bnano.info/content/images/size/w600/2023/01/live_telemetry_misisng_block_count.png 600w, https://blog.bnano.info/content/images/size/w1000/2023/01/live_telemetry_misisng_block_count.png 1000w, https://blog.bnano.info/content/images/2023/01/live_telemetry_misisng_block_count.png 1388w" sizes="(min-width: 1200px) 1200px"></figure><p>We see the same 2 outliners <code>Trustable NN1</code> and <code>Nano Charts</code>. We can also see that the red line <code>My Nano Ninja</code>disappears when the speedtest starts. This means that the connection to that node was lost and not telemetry data was reported. The node probably died down during the test and came back online about 4 minutes later.</p><p>Having the above in mind, we an look at how quickly nodes are able to cement the checked blocks.<br>A transaction is cemented by the node, as soon as it has gathered 67% of online vote weight from all online representives. It means that quorum has been reached and the transaction is final.<br>The following shows a graph of <strong>missing cemented blocks</strong> :</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.bnano.info/content/images/2023/01/live_telemetry_missing_cemented_count.png" class="kg-image" alt loading="lazy" width="1394" height="474" srcset="https://blog.bnano.info/content/images/size/w600/2023/01/live_telemetry_missing_cemented_count.png 600w, https://blog.bnano.info/content/images/size/w1000/2023/01/live_telemetry_missing_cemented_count.png 1000w, https://blog.bnano.info/content/images/2023/01/live_telemetry_missing_cemented_count.png 1394w" sizes="(min-width: 1200px) 1200px"></figure><p>In the graph above, we can see that after 5 minutes, some nodes are still struggeling and have missing cemented blocks.</p><p>5 minutes after the speedtest of 5000 blocks :</p><ul><li><code>My Nano Ninja</code> representative has 4813 missing cemented blocks. &#xA0;(It&apos;s the node that stopped reporting telemetry data at the start of the speedtest)</li><li><code>Trustable NN1</code> has 1698 missing cemented blocks.</li><li><code>nanocafe.cc</code> has 483 missing cemented blocks.</li><li><code>Nano Charts</code>caught up well and has almost no (21) missing cemented blocks.</li><li><code>RsNano.com</code> has 293 missing cemented blocks, but it started with this many missing blocks even before the speedtest began. So overall it coped very well.</li></ul><h2 id="what-can-be-done-to-improve-the-situtaion">What can be done to improve the situtaion?</h2><p>In a decentralized network every user has some responsibility to make sure the network operates as intended.</p><ul><li>Node providers can upgrade their hardware.</li><li>Users can change their representatives if they delegate to a weak node.</li><li>New nano-node versions can reduce hardware ressource usage.</li></ul><p></p><p>If you like my work, <a href="https://nano.to/gr0vity">please show your love</a> &#x1F49B;</p>]]></content:encoded></item><item><title><![CDATA[A new nano-node docker image for each new github commit]]></title><description><![CDATA[<p><strong>TLDR;</strong><br>With the help of a github action workflow, <a href="https://github.com/gr0vity-dev/nano-node-builder">this project</a></p><ul><li>Clones the official nanocurrency/nano-node repository.</li><li>Builds a docker image by using the official scripts.</li><li>Pushes the docker image to <a href="https://hub.docker.com/r/gr0v1ty/nano-node/tags">dockerhub</a> .<br>The goal is to have very quick release cycles and to be able to update my node with</li></ul>]]></description><link>https://blog.bnano.info/a-new-nano_node-docker-image-for-each-new-github-commit/</link><guid isPermaLink="false">63ce39b9a367d10001238841</guid><dc:creator><![CDATA[gr0vity]]></dc:creator><pubDate>Mon, 23 Jan 2023 07:48:18 GMT</pubDate><content:encoded><![CDATA[<p><strong>TLDR;</strong><br>With the help of a github action workflow, <a href="https://github.com/gr0vity-dev/nano-node-builder">this project</a></p><ul><li>Clones the official nanocurrency/nano-node repository.</li><li>Builds a docker image by using the official scripts.</li><li>Pushes the docker image to <a href="https://hub.docker.com/r/gr0v1ty/nano-node/tags">dockerhub</a> .<br>The goal is to have very quick release cycles and to be able to update my node with the latest unreleased features and improvements</li></ul><h2 id="is-this-an-official-release">Is this an official release ?</h2><p>No it&apos;s not.<br>The nano-node is officially maintained and improved by the <a href="https://nano.org/en/nano-foundation">Nano Foundation</a>.<br>In the past, a new major release has dropped once or twice a year.<br>While this schedule is perfectly fine for exchanges, the downside of long release cycles is that bug-fixes are slow to be integrated into the live network.</p><p>New commits are pushed to the nano-node repository almost daily.</p><h2 id="how-do-i-run-the-latest-node-version">How do I run the latest node version ?</h2><p>If you run a dockerized nano-node, just switch your current docker tag (<s><code>nanocurrency/nano-node:V24.0</code></s>) to <code>gr0v1ty/nano-node:latest</code></p><h2 id="is-this-safe-to-run">Is this safe to run ?</h2><p>There are 2 aspects to the question :</p><p><strong>1.</strong>&#x2003;How can I be sure no malicious code has been injected into this version ?</p><ul><li>the whole process of cloning, building and pushing is done in a public github action workflow.</li><li>it can be easily inspected and monitored for changes.</li></ul><p>This way you can be sure that only 100% official code is used to created the docker images made available to dockerhub.</p><p><strong>2.</strong>&#x2003;Should code that hasn&apos;t been tested on a beta network be run in production ?</p><ul><li>running the latest commit is NOT recommended for any principal representative.</li><li>however, when facing issues with the official release or you require a specific fix that has already been committed but not released, <a href="https://github.com/gr0vity-dev/nano-node-builder">this project </a>helps you out.</li></ul><h2 id="explain-the-workflow">Explain the workflow</h2><p>The workflow can be found <a href="https://github.com/gr0vity-dev/nano-node-builder/blob/6266efa3daf20b6f2601fe5c97b218d16dd68943/.github/workflows/docker_builder.yaml">here</a><br>The following shows a flow diagram of what the workflow does</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.bnano.info/content/images/2023/01/node_builder_workflow_graph.png" class="kg-image" alt loading="lazy" width="852" height="850" srcset="https://blog.bnano.info/content/images/size/w600/2023/01/node_builder_workflow_graph.png 600w, https://blog.bnano.info/content/images/2023/01/node_builder_workflow_graph.png 852w"></figure>]]></content:encoded></item><item><title><![CDATA[Ephemeral self-hosted github runners on a dedicated server]]></title><description><![CDATA[<p>There are many existing projects that try to solve the setup of ephemeral github runners. A curated list of such projects can be found <a href="https://jonico.github.io/awesome-runners/">here</a></p><p>However none of these projects &#xA0;are both simple and solved my needs.<br>I wanted to have self-hosted runners that meet the following requirements:</p><ul><li>If</li></ul>]]></description><link>https://blog.bnano.info/ephemeral-self-hosted-github-runners-on-a-dedicated-server/</link><guid isPermaLink="false">63cc3a11c3b91100012139bc</guid><dc:creator><![CDATA[gr0vity]]></dc:creator><pubDate>Sat, 21 Jan 2023 19:29:03 GMT</pubDate><content:encoded><![CDATA[<p>There are many existing projects that try to solve the setup of ephemeral github runners. A curated list of such projects can be found <a href="https://jonico.github.io/awesome-runners/">here</a></p><p>However none of these projects &#xA0;are both simple and solved my needs.<br>I wanted to have self-hosted runners that meet the following requirements:</p><ul><li>If the workflow can be run with a github runner, it can be run with the self-hosted runner.</li><li>It should be possible to define multiple runners in parallel.</li><li>It must not share the PAT with our dedicated work-server (this requirement was not obvious at the beginning and added some complexity)</li></ul><p>Currently the runner is limited to the scope of repositories. But you can add it o as many repositories as you want.<br>If you are looking to setup self-hosted runners with an organisation scope, the scripts have to be adjusted to meet that need!</p><p><a href="#final-solution">Jump to the final solution</a> </p><h2 id="the-journey-begins-trial-and-error">The journey begins ... Trial and error</h2><p>My goal was to run a dockerized testsuite for the <a href="https://nano.org">nano currency</a> that spins up multiple docker-containers and writes some files to disk inside a self-hosted runner... Let&apos;s go!</p><h3 id="attempt-1-setup-a-simple-github-runner-on-a-dedicated-server">Attempt 1 : Setup a simple github runner on a dedicated server</h3><p><strong>TLDR; This does not meet my needs</strong></p><ul><li>I can&apos;t run multiple workflows in parallel without changing my current workflow</li><li>I have to create additional cleanup logic before a new runner starts</li><li>I can&apos;t use the default cleanup hooks provided by github runners, beacuse my dockerized testsuite writes files to disk as root</li></ul><p><strong>Full Experience</strong><br>Setting up your self-hosted runner on a dedicated server is as easy as following the <a href="https://github.com/{owner}/{repo}/settings/actions/runners/new">github example</a> :<br>1) <strong>Download</strong></p><pre><code class="language-bash"># Create a folder   
$ mkdir actions-runner &amp;&amp; cd actions-runner 
# Download the latest runner package   
$ curl -o actions-runner-osx-x64-2.300.2.tar.gz -L https://github.com/actions/runner/releases/download/v2.300.2/actions-runner-osx-x64-2.300.2.tar.gz 
# Optional: Validate the hash   
$ echo &quot;59814d103186d379123da8d2e7b002305a7b57f509fdd0cf34e4f86394dae9a4 actions-runner-osx-x64-2.300.2.tar.gz&quot; | shasum -a 256 -c 
# Extract the installer   
$ tar xzf ./actions-runner-osx-x64-2.300.2.tar.gz
</code></pre><p><strong>2) Configure</strong></p><pre><code class="language-bash"># Create the runner and start the configuration experience   
$ ./config.sh --url https://github.com/{owner}/{repo} --token AUN... 
# Last step, run it!   
$ ./run.sh
</code></pre><p><strong>3) Using your self-hosted runner</strong></p><pre><code class="language-yaml"># Use this YAML in your workflow file for each job   
runs-on: self-hosted
</code></pre><p></p><p>In my workflow all I have to do is to change from <code>runs-on: ubuntu-22.04</code> to <code>runs-on: self-hosted</code> and the workflow is executed</p><pre><code class="language-yaml">jobs:
  my_job_name:
    #runs-on: ubuntu-22.04
    runs-on: self-hosted
</code></pre><p>On the first run, this works fine. However <strong>on the second run the workflow fails. </strong>The <strong>self-hosted runners</strong> <strong>don&apos;t clean up </strong>after the workflow has ended.<br>In my case this means :</p><ul><li>docker-containers are still running</li><li>the <code>_work</code> folder used by default by the github runner is not emptied</li></ul><p>So the major challenge with this approach lies in defining some <strong>cleanup logic per workflow</strong>. Even <strong>after I created all the cleanup logic, the workflow still failed</strong> to execute successfully on a second run. What happened ?</p><p>Self-hosted runners provide some <a href="https://docs.github.com/en/actions/hosting-your-own-runners/running-scripts-before-or-after-a-job">hooks</a> which allow a script to be executed before or after the workflow is run.<br>The easiest way is to create a file named <code>.env</code> within the self-hosted runner application directory with the following content</p><pre><code class="language-bash">ACTIONS_RUNNER_HOOK_JOB_STARTED=/cleanup_before_workflow_starts.sh
ACTIONS_RUNNER_HOOK_JOB_COMPLETED=/cleanup_after_workflow_ends.sh
</code></pre><p>Inside <code>cleanup_before_workflow_starts.sh</code> you&apos;d write all the actions required before a workflow runs.<br>Inside <code>cleanup_after_workflow_ends.sh</code> you&apos;d write all the actions required after a workflow has ended.<br>These scripts can be located anywhere. In this case they are located &#xA0;within &#xA0;the self-hosted runner application directory</p><p>So what I did was :</p><ul><li>Create a script that deletes all the files inside <code>_work</code> folder</li><li>Modify my workflow to stop all docker containers at the end</li></ul><p>My self-hosted runners use a special user with restricted rights.<br>My <strong>dockerized testsuite executes as root</strong> and writes files to disk as root.<br>So the cleanup hooks performed by the <strong>github runner did not have the required permissions to remove all files </strong>inside the <code>_work</code> folder created by the testsuite.</p><p><strong>I stopped investigating further.</strong> I could have modified the dockerized testsuite to run with the same user as my self-hosted github runner. However the workflow runs correctly on github, so there must be a better way to make it work on my self-hosted runner.</p><h3 id="attempt-2-dockerized-self-hosted-github-runners">Attempt 2: Dockerized self-hosted github runners</h3><p><br><strong>TLDR; This does not work either</strong></p><ul><li>running docker containers inside a dockerized github runner doesn&apos;t work well</li><li>the docker containers of my testsuite are still visible on the host machine</li><li>files written to disk by the testsuite are still shared with the host</li></ul><p><strong>Full Experience</strong><br>While on the surface it looked very easy to setup a dockerized runner it only works well when you run non-dockerized workflows .<br>Running my dockerized testsuite inside a dockerized github-runner comes with a range of problems that are not trivial to work around.</p><ul><li>One major limitation is mounting volumes. The mount path of the volume depends on the host machines&#x2019; absolute path instead of the github-runner relative path.</li><li>Another limitation is that dockerized github runner and the dockerized testsuite don&#x2019;t share the same network by default. This means that we can&#x2019;t curl into our testsuite.</li></ul><h3 id="attemp-3-self-hosted-github-runner-inside-lxdalmost-there">Attemp 3 : self-hosted github runner inside LXD - almost there</h3><p><br>TLDR; Almost... If you are comfortable with sharing your PAT with your work-server, this solution is for you!</p><p>2 of 3 criteria are met :</p><ul><li>the dockerized testsuite runs correctly on each run</li><li>we can set an arbitrary number of github runners</li><li>However the &#xA0;repo PAT is shared with our dedicated work-server</li></ul><p>This is an overview of the architecture</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.bnano.info/content/images/2023/01/lxd_ephemeral_runners_sharing_PAT_flow.png" class="kg-image" alt loading="lazy" width="977" height="536" srcset="https://blog.bnano.info/content/images/size/w600/2023/01/lxd_ephemeral_runners_sharing_PAT_flow.png 600w, https://blog.bnano.info/content/images/2023/01/lxd_ephemeral_runners_sharing_PAT_flow.png 977w"></figure><p><strong>Full experience</strong><br>Linux containers &#xA0;<a href="https://linuxcontainers.org/lxd/">(LXD)</a> is a next generation system container and virtual machine manager.<br>Linux containers can easily host docker containers.</p><p>I found an interesting <a href="https://github.com/stgraber/lxd-github-actions">project </a> that creates github runner in LXD with 2 simple scripts.<br>The first script(prepare-instance.sh)</p><ul><li>creates a base container with all the configuration needed for the self-hosted github runner.</li><li>adds a valid github registration-token is added to the base container<br>The second script (spawn.sh)</li><li>defines the numer of parallel github runners</li><li>creates a new LXD container with a unique name by copying the base container</li><li>starts the container (the github runner is now active and waiting to receive a workflow)</li></ul><p>I encountered 2 issues with these scripts :</p><ul><li>the disk space claimed by the workflow was not freed for new runners.</li><li>the registration-token expires after 60 minutes</li></ul><p>Github offers an api to create a registration-token from &#xA0;a PAT.<br>So what I did was :</p><ul><li>simplify the <a href="https://github.com/gr0vity-dev/lxd-github-runner/blob/master/respawn">prepare_instance</a> script and remove the registration of the self-hosted runner</li><li>merge the registration of the self-hosted runner with spawn script into a <a href="https://github.com/gr0vity-dev/lxd-github-runner/blob/master/respawn">respawn</a>script.</li></ul><p>The new respawn script takes among others a PAT as input argument and does the following :</p><ul><li>convert the PAT into registration-token needed to register a container as self-hosted runner</li><li>update registration-token of the base container. So this container always has a valid registration-token</li><li>the base container is always stopped, so it never actually starts as a self-hosted github runner</li><li>respawn any missing self-hosted github runners based on the parallelism that is defined</li><li>add the possibility to run workers for multiple repos</li></ul><p>So if you feel comfortable sharing the repo PAT with your dedicated work-server, this solution works very well.<br>Simply define a cronjob tha runs each minute to spin up new runners, if needed and renew the registration-token.</p><pre><code class="language-bash">$ crontab -e
## Add the following line as cronjob. Replace the path and RUNNER_COUNT (=parallel runners)
* * * * * /path/to/lxd-runner/respawn gh-runner RUNNER_COUNT https://github.com/ORG/REPO PAT
</code></pre><p>The requirement to keep the PAT safe only came after this solution was implemented.<br>If you can&apos;t share the PAT with your dedicated work-server the next attempt will show you how to do it.</p><h2 id="final-solution">Final solution</h2><h3 id="success-on-attempt-4-self-hosted-github-runner-inside-lxd-without-compromising-your-pat">Success on attempt 4 : self-hosted github runner inside LXD without compromising your PAT</h3><p>The final solution that meets all the above requirements is available as github-project <a href="https://github.com/gr0vity-dev/lxd-github-runner">here</a></p><ul><li>it runs any workflow that runs on github runners</li><li>you can define the number of active runners per repository</li><li>your PAT never leaves github</li></ul><p>This is an overview of the final architecture.<br>We will go through this picture step by step</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.bnano.info/content/images/2023/01/lxd_ephemeral_runners_securing_PAT_flow.png" class="kg-image" alt loading="lazy" width="1518" height="759" srcset="https://blog.bnano.info/content/images/size/w600/2023/01/lxd_ephemeral_runners_securing_PAT_flow.png 600w, https://blog.bnano.info/content/images/size/w1000/2023/01/lxd_ephemeral_runners_securing_PAT_flow.png 1000w, https://blog.bnano.info/content/images/2023/01/lxd_ephemeral_runners_securing_PAT_flow.png 1518w" sizes="(min-width: 1200px) 1200px"></figure><p>TLDR;</p><ol><li>Fork the project <a href="https://github.com/gr0vity-dev/lxd-github-runner">https://github.com/gr0vity-dev/lxd-github-runner</a> or create your own github project to host the infrastructure of self-hosted runners</li><li>Install and configure your LXD environment</li><li>Create one LXD base-container per repo that needs self-hosted runners</li><li>Renew the registration-token needed to start a self-hosted runner via a scheduled github workflow</li></ol><h4 id="1-fork-the-project">1) Fork the <a href="https://github.com/gr0vity-dev/lxd-github-runner">project</a> </h4><p>In our final solution, you&apos;ll have a github workflow that makes sure your self-hosted runners always have a valid registration token.<br>To run a self-hosted github runner, you need a registration token.<br>You can generate a valid registration-token via github api and your PAT.<br>By generating the registration inside a github actions workflow, you make sure that your PAT never leaves github</p><h4 id="2-install-and-configure-your-lxd-environment">2) Install and configure your LXD environment</h4><p><em>Install LXD</em></p><pre><code>sudo apt-get install lxd-client
</code></pre><p><em>Initialise LXD and keep the defaults</em></p><pre><code class="language-bash">lxd init</code></pre><p><em>Add a new storge pool called &quot;</em>docker&quot;<em> (for docker to run properly in a Linux container it needs btrfs.) The storage name is &quot;</em>docker<em>&quot;. The scripts rely on keeping that name<br>Allocate 50GB for all github runners (you might adjust it for your needs)</em></p><pre><code>lxc storage create docker btrfs size=50GB</code></pre><h4 id="3-create-one-lxd-base-container-for-every-repo-that-needs-self-hosted-runners">3) Create one LXD base-container for every repo that needs self-hosted runners</h4><p>The &#xA0;<a href="https://github.com/gr0vity-dev/lxd-github-runner/blob/master/respawn">prepare_instance</a> script creates the base images with all the required dependencies.<br>You might want to <a href="https://github.com/gr0vity-dev/lxd-github-runner/blob/master/prepare-instance#L6-L7">adjust the following lines</a> of the script for your needs : </p><pre><code># By default,we use ubunutu 20 as the base container
./prepare-instance gh-runner-{repo-name}
</code></pre><p>! <strong>Make sure</strong> to specify a unique name per base-container. I recommend using the following : <code>gh-runner-{repo-name}</code></p><h4 id="4-renew-the-registration-token-needed-to-start-a-self-hosted-runner-via-a-scheduled-github-workflow">4) Renew the registration-token needed to start a self-hosted runner via a scheduled github workflow</h4><p>On github, <a href="https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token">setup a PAT</a> (Personal access token) with access to the repos and orgs you want serviced.<br><br>Enable the scopes listed below for your PAT:</p><ul><li>repo</li><li>workflow</li><li>admin:repo_hook</li></ul><p>The following shows an example of the workflow that</p><ul><li>renews our registration-token </li><li>ssh&apos;s into our work-server to update the base-container with the valid token.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-yaml">name: Renew ephemeral self-hosted runner token
on:
  schedule:
    - cron: &apos;0/30 * * * *&apos;  # &quot;every 30 minutes
jobs:
  renew_gh-runner_token:
    name: renew reg token
    runs-on: ubuntu-latest
    steps:
      - name: Convert PAT into registration-token
        id: get_token
        run: |          
          GH_RUNNER_TOKEN=$(curl \
          --location --request POST &apos;https://api.github.com/repos/{OWNER}/{REPO}/actions/runners/registration-token&apos; \
          --header &apos;Authorization: Bearer ${{ secrets.GH_PAT }}&apos; \
          | jq -r &apos;.token&apos;)
          echo &quot;::add-mask::$GH_RUNNER_TOKEN&quot;
          echo &quot;::set-output name=GH_RUNNER_TOKEN::$GH_RUNNER_TOKEN&quot;

      - name: Execute remote ssh commands using user and private key
        uses: appleboy/ssh-action@v0.1.7
        with:
          host: ${{ secrets.GH_RUNNER_HOST }}
          username: ${{ secrets.GH_RUNNER_USER }}
          key: ${{ secrets.GH_RUNNER_PRV_KEY }}
          script: ./git/lxd-github-actions/renew_runner_token {work-server-gh-runner-name} https://github.com/{OWNER}/{REPO} ${{ steps.get_token.outputs.GH_RUNNER_TOKEN }}
</code></pre><figcaption>github workflow to generate a registration token and update our self-hosted runner</figcaption></figure><p>The workflow that updates my self-hosted runners can be found <a href="https://github.com/gr0vity-dev/lxd-github-runner/blob/master/.github/workflows/auto_renew_runner_token.yml">here</a></p><p>! <strong>Make sure</strong> to create the following repo secrets</p><pre><code>- secrets.GH_PAT (your personal access token used to create a registration-token for your repo)
- secrets.GH_RUNNER_HOST (work server ip address)
- secrets.GH_RUNNER_USER (work-server user)
- secrets.GH_RUNNER_PRV_KEY (private key to ssh into the work-server)
</code></pre><p>! <strong>Additionally make sure</strong> to replace the following variables in the example above with the relevant content:</p><pre><code>- {OWNER} # your github user
- {REPO} # your repo that requires the self-hosted runner
- {work-server-gh-runner-name} # the gh-runner name you defined when running the &apos;prepare-instance&apos; script.
</code></pre><p><strong>Explanation</strong> of why this workflow is needed :</p><ul><li>The registration-token expires after 60 minutes.</li><li>The &#xA0;workflow above runs every 30 minutes and updates the registration-token inside your base-container to make sure your token is always valid.</li><li>The workflow ssh&apos;s into your work-server to execute the &#xA0;<a href="https://github.com/gr0vity-dev/lxd-github-runner/blob/master/renew_runner_token">renew_runner_token</a><br>A PAT is still required but in this case it never leaves github.</li></ul><h4 id="4-create-and-renew-self-hosted-runners-as-soon-as-a-workflow-has-finished">4) Create and renew self-hosted runners as soon as a workflow has finished</h4><p>The <em>respawn_runners</em> script copies the configuration of the base-container and inherits its valid registration-token.</p><p><em>Run this script as a cronjob to make sure you always have available runners</em></p><pre><code class="language-bash">$ crontab -e
## Add the following line as cronjob. Replace the path and RUNNER_COUNT (=parallel runners)
* * * * * /path/to/lxd-runner/respawn_runners gh-runner-{repo-name} RUNNER_COUNT https://github.com/ORG/REPO
</code></pre><p>! <strong>Make sure</strong> to replace the following variables in the above cronjob:</p><pre><code>gh-runner-{repo-name} # the name of your base-container
ORG (your github user)
REPO (your github repo that nees the self-hosted runner)
</code></pre><p></p><p>If you like my work, <a href="https://nano.to/gr0vity">please show your love</a> &#x1F49B;</p>]]></content:encoded></item></channel></rss>