<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gheorghe Avram</title>
    <description>The latest articles on DEV Community by Gheorghe Avram (@sweethuman).</description>
    <link>https://dev.to/sweethuman</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F152431%2F8d9b5923-a5e1-42e1-ac91-c507921ee1ec.png</url>
      <title>DEV Community: Gheorghe Avram</title>
      <link>https://dev.to/sweethuman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sweethuman"/>
    <language>en</language>
    <item>
      <title>How I do local development CockroachDB Backups</title>
      <dc:creator>Gheorghe Avram</dc:creator>
      <pubDate>Sat, 26 Apr 2025 21:00:00 +0000</pubDate>
      <link>https://dev.to/sweethuman/how-i-do-local-development-cockroachdb-backups-389b</link>
      <guid>https://dev.to/sweethuman/how-i-do-local-development-cockroachdb-backups-389b</guid>
      <description>&lt;p&gt;I have this &lt;a href="https://taskfile.dev/" rel="noopener noreferrer"&gt;taskfile&lt;/a&gt; tasks to make running commands easier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;backup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Backup the local CockroachDB database&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backup-to&lt;/span&gt;
        &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;FOLDER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;backup/local-node-backup"&lt;/span&gt;
  &lt;span class="na"&gt;restore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Restore the local CockroachDB backup database&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;restore-from&lt;/span&gt;
        &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;FOLDER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;backup/local-node-backup"&lt;/span&gt;
  &lt;span class="na"&gt;backup-to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;requires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;FOLDER&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mkdir -p cockroach-extern&lt;/span&gt;
        &lt;span class="na"&gt;ignore_error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;cockroach sql --insecure --host=localhost --port=26257 --execute="BACKUP INTO 'nodelocal://1/{{.FOLDER}}';"&lt;/span&gt;
  &lt;span class="na"&gt;restore-from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;requires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;FOLDER&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;cockroach sql --insecure --host=localhost --port=26257 --execute="DROP DATABASE IF EXISTS defaultdb;"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;cockroach sql --insecure --host=localhost --port=26257 --execute="RESTORE DATABASE defaultdb FROM LATEST IN 'nodelocal://1/{{.FOLDER}}';"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I have my &lt;code&gt;docker-compose.yml&lt;/code&gt; setup like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;crdb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cockroachdb/cockroach:latest-v25.1&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;26257:26257'&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;8080:8080'&lt;/span&gt;
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;start-single-node --insecure&lt;/span&gt;
        &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;crdb:/cockroach/cockroach-data&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bind&lt;/span&gt;
              &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./cockroach-extern&lt;/span&gt;
              &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/cockroach/cockroach-data/extern&lt;/span&gt;
&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;crdb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And from my own project docs:&lt;/p&gt;

&lt;h2&gt;
  
  
  Database Backup and Restore
&lt;/h2&gt;

&lt;p&gt;You will notice in &lt;code&gt;docker-compose.yaml&lt;/code&gt; these few lines of code at the database declaration. Let me explain what's going on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bind&lt;/span&gt;
      &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./cockroach-extern&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/cockroach/cockroach-data/extern&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CockroachDB saves all backups, exports etc. to folder &lt;code&gt;/cockroach/cockroach-data/extern&lt;/code&gt; so we will bind this folder&lt;br&gt;
to a local folder in the project directory so we can have access to this data and manipulate it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Backups
&lt;/h2&gt;

&lt;p&gt;Info about backups &lt;a href="https://www.cockroachlabs.com/docs/stable/take-full-and-incremental-backups" rel="noopener noreferrer"&gt;https://www.cockroachlabs.com/docs/stable/take-full-and-incremental-backups&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run a full backup we will run the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;BACKUP&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;'nodelocal://1/cockroach-backup'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will backup all the data into the cluster to the local directory of nodeID &lt;code&gt;1&lt;/code&gt; and into the &lt;code&gt;cockroach-backup&lt;/code&gt; folder &lt;br&gt;
in the &lt;code&gt;extern&lt;/code&gt; root directory of the respective node.&lt;/p&gt;

&lt;p&gt;Now if you look into the local folder you will notice &lt;code&gt;./cockroach-extern/cockroach-backup&lt;/code&gt; contains some data.&lt;/p&gt;
&lt;h2&gt;
  
  
  Restores
&lt;/h2&gt;

&lt;p&gt;To run a restore of &lt;code&gt;defaultdb&lt;/code&gt;, the database the app uses locally we have to run the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;RESTORE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;defaultdb&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;LATEST&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="s1"&gt;'nodelocal://1/cockroach-backup'&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;new_db_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'new_defaultdb'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will look at the LATEST backup in the &lt;code&gt;cockroach-backup&lt;/code&gt; folder and will restore database &lt;code&gt;defaultdb&lt;/code&gt; and &lt;br&gt;
assign it a new name called &lt;code&gt;new_defaultdb&lt;/code&gt;.&lt;br&gt;
Now you can access the restored version of the database by changing the connection string to point to &lt;code&gt;new_defaultdb&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>database</category>
      <category>backup</category>
      <category>cockroachdb</category>
    </item>
    <item>
      <title>How to install OBS Plugins on MacOS</title>
      <dc:creator>Gheorghe Avram</dc:creator>
      <pubDate>Sun, 26 Jun 2022 12:40:38 +0000</pubDate>
      <link>https://dev.to/sweethuman/how-to-install-obs-plugins-on-macos-4b0i</link>
      <guid>https://dev.to/sweethuman/how-to-install-obs-plugins-on-macos-4b0i</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://blog.sweethuman.tech/how-to-install-obs-plugins-on-macos" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are two ways to install OBS Plugins on MacOS.&lt;br&gt;
We will be installing &lt;a href="https://obsproject.com/forum/resources/obs-virtual-background-plugin.1371/" rel="noopener noreferrer"&gt;OBS Virtual Background Plugin&lt;/a&gt; in both examples. Download the zip file and extract it. Normally it should contain a &lt;code&gt;bin&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Example for OBS Virtual Background Plugin:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F946knru5r94fcq61799e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F946knru5r94fcq61799e.png" alt="Contents of downloaded OBS Virtual Background Plugin folder"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  First Method
&lt;/h1&gt;

&lt;p&gt;This method is simpler but you may encounter issues when running the plugin.&lt;/p&gt;

&lt;p&gt;Go to the folder &lt;code&gt;~/Library/Application Support/obs-studio&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
If you navigate to it manually through Finder go to your user directory, right click and select &lt;code&gt;Show View Options&lt;/code&gt; and then check the &lt;code&gt;Show Library Folder&lt;/code&gt; checkbox as pictured below.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysggl2aju4p5prvsjl1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysggl2aju4p5prvsjl1h.png" alt="Show Library Folder option config"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you are in the &lt;code&gt;obs-studio&lt;/code&gt; folder you will find a &lt;code&gt;plugins&lt;/code&gt; folder. If you don't find it, create it yourself. After that copy the entire folder into &lt;code&gt;plugins&lt;/code&gt; (in my case would be &lt;code&gt;obs-virtualbg&lt;/code&gt; which contains both the &lt;code&gt;bin&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; folder).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6yx9rbkjdh5n2l755444.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6yx9rbkjdh5n2l755444.png" alt="Where to put plugin folder for first method"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Start OBS.&lt;/p&gt;

&lt;p&gt;Now you might notice you get an error message as pictured below, if this happens try the second method and make sure to delete the folder you just copied from the &lt;code&gt;plugins&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktwb43atncm80at178tq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktwb43atncm80at178tq.png" alt="Error that can happen after using the first method of installation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Second Method
&lt;/h1&gt;

&lt;p&gt;Go to the &lt;code&gt;Applications&lt;/code&gt; folder and find your .app file. Either &lt;code&gt;OBS.app&lt;/code&gt; or another name for a modified version, I am using Stream Elements OBS so for me it is &lt;code&gt;SE.Live.app&lt;/code&gt;. Right Click and select &lt;code&gt;Show Package Contents&lt;/code&gt;, after that enter the &lt;code&gt;Contents&lt;/code&gt; folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add the binary
&lt;/h2&gt;

&lt;p&gt;In the folder of the extension, you have extracted previously, you will find a .so file in the &lt;code&gt;bin&lt;/code&gt; folder. Copy that file to the &lt;code&gt;Plugins&lt;/code&gt; folder. In my case I copy &lt;code&gt;obs-virtualbg.so&lt;/code&gt; to the &lt;code&gt;Plugins&lt;/code&gt; folder. If it asks you for a password or elevated permissions provide it so it can copy the file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxrhe6vsqo3wghrnr4gn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxrhe6vsqo3wghrnr4gn.png" alt="Where to put binary of plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add the data
&lt;/h2&gt;

&lt;p&gt;To add the data we have to go to &lt;code&gt;Resources&lt;/code&gt; -&amp;gt; &lt;code&gt;data&lt;/code&gt; -&amp;gt; &lt;code&gt;obs-plugins&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
In here create a folder with the same name as the .so file. I will create a folder with the name &lt;code&gt;obs-virtualbg&lt;/code&gt; and copy inside it the contents of the &lt;code&gt;data&lt;/code&gt; folder from the original plugin folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fucrsbmq7lbfme759fx9e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fucrsbmq7lbfme759fx9e.png" alt="Where to put data folder"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now close the window and start OBS. You should find that obs started with no warning and the plugin runs as it should.&lt;/p&gt;

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

</description>
      <category>obs</category>
      <category>macos</category>
      <category>mac</category>
    </item>
    <item>
      <title>How to set up a Smashing dashboard on your Raspberry Pi</title>
      <dc:creator>Gheorghe Avram</dc:creator>
      <pubDate>Sun, 13 Sep 2020 13:26:58 +0000</pubDate>
      <link>https://dev.to/sweethuman/how-to-set-up-a-smashing-dashboard-on-your-raspberry-pi-2h70</link>
      <guid>https://dev.to/sweethuman/how-to-set-up-a-smashing-dashboard-on-your-raspberry-pi-2h70</guid>
      <description>&lt;p&gt;As an OS we are going to use &lt;a href="https://dietpi.com/"&gt;DietPi&lt;/a&gt; because it automates most of the setups. There is a 64Bit version available but at the time of writing this, I can't install Chromium on it.&lt;/p&gt;

&lt;p&gt;To install DietPi you can follow their &lt;a href="https://dietpi.com/docs/user-guide_install/"&gt;Guide&lt;/a&gt;. For flashing I used &lt;a href="https://www.raspberrypi.org/downloads/"&gt;RPi Imager&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now you should be here: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R-FqN3XH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://photos.collectednotes.com/photos/7144/e977e639-7bb7-460b-8570-b11a99abcba9" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R-FqN3XH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://photos.collectednotes.com/photos/7144/e977e639-7bb7-460b-8570-b11a99abcba9" alt="alt" width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  First Run
&lt;/h2&gt;

&lt;p&gt;Enter  &lt;code&gt;Software Optimised&lt;/code&gt;, select &lt;code&gt;Chromium&lt;/code&gt; (using the arrows and spacebar), and then press Enter.&lt;br&gt;&lt;br&gt;
After that go to &lt;code&gt;DietPi-Config&lt;/code&gt; -&amp;gt; &lt;code&gt;Display Options&lt;/code&gt; -&amp;gt; &lt;code&gt;Display Resolution&lt;/code&gt; and select the current screen resolution.&lt;br&gt;&lt;br&gt;
After that go back until you see &lt;code&gt;AutoStart Options&lt;/code&gt;, select &lt;code&gt;Chromium&lt;/code&gt; with Enter, you can leave the URL as it is and make sure the user is set to &lt;code&gt;root&lt;/code&gt;. Go all the way back by selecting &lt;code&gt;Exit&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Then go to &lt;code&gt;Software Additional&lt;/code&gt; and select &lt;code&gt;Build-Essentials&lt;/code&gt;, &lt;code&gt;Git&lt;/code&gt;, &lt;code&gt;Node.JS&lt;/code&gt;, and your editor of choice. Exit by pressing Enter. (Pressing Esc will clear your Settings)&lt;br&gt;&lt;br&gt;
And finally, select &lt;code&gt;Install&lt;/code&gt; and reboot at the end.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up Chromium
&lt;/h2&gt;

&lt;p&gt;In some cases, the window size of Chromium might be smaller than the resolution. Looking like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hbLrxl5E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://photos.collectednotes.com/photos/7144/174de137-bde0-4c3a-ab82-e0150a248a36" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hbLrxl5E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://photos.collectednotes.com/photos/7144/174de137-bde0-4c3a-ab82-e0150a248a36" alt="Small Chromium Window" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To fix this we have to edit these variables in the file at &lt;code&gt;/boot/dietpi.txt&lt;/code&gt; and set them to your appropriate resolution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;SOFTWARE_CHROMIUM_RES_X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1280
&lt;span class="nv"&gt;SOFTWARE_CHROMIUM_RES_Y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;720
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we have to modify the chromium autostart script to fix some glaring issues. It can be found here &lt;code&gt;/var/lib/dietpi/dietpi-software/installed/chromium-autostart.sh&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;CHROMIUM_OPTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--kiosk --test-type --window-size=&lt;/span&gt;&lt;span class="nv"&gt;$RES_X&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$RES_Y&lt;/span&gt;&lt;span class="s2"&gt; --start-fullscreen --start-maximized --window-position=0,0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To this variable add these options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--no-default-browser-check&lt;/code&gt; Disables the default browser check. Useful for UI/browser tests where we want to avoid having the default browser info-bar displayed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--disable-component-update&lt;/code&gt; Disable the popup for updating chromium or saying it can't update chromium.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--no-first-run&lt;/code&gt; Skip First Run tasks, whether or not it's actually the First Run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More info on command line switches &lt;a href="https://peter.sh/experiments/chromium-command-line-switches/"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Right before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xinit &lt;span class="nv"&gt;$FP_CHROMIUM&lt;/span&gt; &lt;span class="nv"&gt;$CHROMIUM_OPTS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;add these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/"exited_cleanly":false/"exited_cleanly":true/'&lt;/span&gt; ~/.config/chromium/&lt;span class="s1"&gt;'Local State'&lt;/span&gt;
&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/"exited_cleanly":false/"exited_cleanly":true/; s/"exit_type":"[^"]\+"/"exit_type":"Normal"/'&lt;/span&gt; ~/.config/chromium/Default/Preferences
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These set in the local chromium settings the &lt;code&gt;exited_cleanly&lt;/code&gt; value, it tells chromium it always exited as it should. This being a RaspberryPi, Chromium might close directly and we don't want to see the "Restore Previous Session" pop-up.&lt;/p&gt;

&lt;p&gt;In the end, you should have a file that looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Autostart run script for Kiosk mode, based on @AYapejian https://github.com/MichaIng/DietPi/issues/1737#issue-318697621&lt;/span&gt;
&lt;span class="c"&gt;# - Please see /root/.chromium-browser.init (and /etc/chromium.d/custom_flags) for additional egl/gl init options&lt;/span&gt;

&lt;span class="c"&gt;# Command line switches https://peter.sh/experiments/chromium-command-line-switches/&lt;/span&gt;
&lt;span class="c"&gt;# --test-type gets rid of some of the chromium warnings that you may or may not care about in kiosk on a LAN&lt;/span&gt;
&lt;span class="c"&gt;# --pull-to-refresh=1&lt;/span&gt;
&lt;span class="c"&gt;# --ash-host-window-bounds="400,300"&lt;/span&gt;

&lt;span class="c"&gt;# Resolution to use for kiosk mode should ideally match current system resolution&lt;/span&gt;
&lt;span class="nv"&gt;RES_X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'/^[[:blank:]]*SOFTWARE_CHROMIUM_RES_X=/{s/^[^=]*=//p;q}'&lt;/span&gt; /boot/dietpi.txt&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;RES_Y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'/^[[:blank:]]*SOFTWARE_CHROMIUM_RES_Y=/{s/^[^=]*=//p;q}'&lt;/span&gt; /boot/dietpi.txt&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;CHROMIUM_OPTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--kiosk --test-type --no-default-browser-check --no-first-run --disable-component-update --window-size=&lt;/span&gt;&lt;span class="nv"&gt;$RES_X&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$RES_Y&lt;/span&gt;&lt;span class="s2"&gt; --start-fullscreen --start-maximized --window-position=0,0"&lt;/span&gt;
&lt;span class="c"&gt;# If you want tablet mode, uncomment the next line.&lt;/span&gt;
&lt;span class="c"&gt;#CHROMIUM_OPTS+=' --force-tablet-mode --tablet-ui'&lt;/span&gt;

&lt;span class="c"&gt;# Add URL for the first run:&lt;/span&gt;
&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'/^[[:blank:]]*SOFTWARE_CHROMIUM_AUTOSTART_URL=/{s/^[^=]*=//p;q}'&lt;/span&gt; /boot/dietpi.txt&lt;span class="si"&gt;)&lt;/span&gt;
CHROMIUM_OPTS+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;" --homepage &lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Find absolute file path location of Chromium binary.&lt;/span&gt;
&lt;span class="nv"&gt;FP_CHROMIUM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; chromium&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;$FP_CHROMIUM&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;

        &lt;span class="c"&gt;# Assume RPi&lt;/span&gt;
        &lt;span class="nv"&gt;FP_CHROMIUM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; chromium-browser&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/"exited_cleanly":false/"exited_cleanly":true/'&lt;/span&gt; ~/.config/chromium/&lt;span class="s1"&gt;'Local State'&lt;/span&gt;
&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/"exited_cleanly":false/"exited_cleanly":true/; s/"exit_type":"[^"]\+"/"exit_type":"Normal"/'&lt;/span&gt; ~/.config/chromium/Default/Preferences

xinit &lt;span class="nv"&gt;$FP_CHROMIUM&lt;/span&gt; &lt;span class="nv"&gt;$CHROMIUM_OPTS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;a href="https://smashing.github.io/"&gt;Smashing&lt;/a&gt; is a Sinatra based framework that lets you build beautiful dashboards. (from their docs)&lt;/p&gt;

&lt;p&gt;Log in as the user &lt;code&gt;dietpi&lt;/code&gt;(it's the default user) and run these steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install ruby&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ruby-dev
&lt;span class="c"&gt;# Install gems&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;smashing bundler
&lt;span class="c"&gt;# Generate sample project&lt;/span&gt;
smashing new sample_dashboard
&lt;span class="nb"&gt;cd &lt;/span&gt;sample_dashboard
&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
bundle &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="c"&gt;# Run&lt;/span&gt;
smashing start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should be able to connect to it on localhost, or using the LAN address of the Raspberry Pi on port 3030 and it should look something like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OL0H1h4x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://photos.collectednotes.com/photos/7144/b996b1c5-a5dd-4f89-a6d4-64b81b634972" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OL0H1h4x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://photos.collectednotes.com/photos/7144/b996b1c5-a5dd-4f89-a6d4-64b81b634972" alt="Smashing Dashboard" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we know it works we need to set up the service that autostarts the dashboard and tell chromium to load our link on boot.&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;smashing.service&lt;/code&gt; in path &lt;code&gt;/etc/systemd/system&lt;/code&gt; containing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Start Smashing Dashboard&lt;/span&gt;
&lt;span class="py"&gt;Before&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;graphical.target&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network.target remote-fs.target&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;exec&lt;/span&gt;
&lt;span class="py"&gt;Restart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;
&lt;span class="py"&gt;RestartSec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;60&lt;/span&gt;
&lt;span class="py"&gt;TimeoutSec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5min&lt;/span&gt;
&lt;span class="py"&gt;KillMode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;control-group&lt;/span&gt;
&lt;span class="py"&gt;GuessMainPID&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;span class="py"&gt;User&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dietpi&lt;/span&gt;
&lt;span class="py"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dietpi&lt;/span&gt;
&lt;span class="py"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/home/dietpi/sample_dashboard&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/smashing start&lt;/span&gt;
&lt;span class="c"&gt;#ExecStop=/usr/local/bin/smashing stop
&lt;/span&gt;&lt;span class="py"&gt;PrivateTmp&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;PrivateDevices&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;ProtectSystem&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;full&lt;/span&gt;
&lt;span class="py"&gt;MountFlags&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;private&lt;/span&gt;
&lt;span class="py"&gt;NoNewPrivileges&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to change the &lt;code&gt;WorkingDirectory&lt;/code&gt; to the path where your dashboard is at.&lt;br&gt;&lt;br&gt;
More info about the service options &lt;a href="https://www.freedesktop.org/software/systemd/man/systemd.service.html"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Reload the Daemon to see our changes&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="c"&gt;# Start smashing on boot&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;smashing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to modify the link that Chromium loads we can either modify from the TUI using the app &lt;code&gt;dietpi-config&lt;/code&gt; or modify the variable &lt;code&gt;SOFTWARE_CHROMIUM_AUTOSTART_URL&lt;/code&gt; in &lt;code&gt;/boot/dietpi.txt&lt;/code&gt; and set it to &lt;code&gt;http://localhost:3030&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now reboot and it should automagically load the dashboard full-screen on boot having this as a final result:&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4gqaI5w8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://photos.collectednotes.com/photos/7144/2ab51731-1811-466b-91a2-f8d22eb600f2" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4gqaI5w8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://photos.collectednotes.com/photos/7144/2ab51731-1811-466b-91a2-f8d22eb600f2" alt="alt" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More info on Smashing &lt;a href="https://github.com/Smashing/smashing/wiki"&gt;here&lt;/a&gt;&lt;br&gt;&lt;br&gt;
If you want to have more control over the performance of the smashing service you can use &lt;code&gt;dietpi-services&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
DietPi has a lot of tooling that makes your life with a RaspberryPi much much better and I recommend looking more into it.&lt;/p&gt;

</description>
      <category>dashboard</category>
      <category>raspberrypi</category>
      <category>ruby</category>
      <category>dietpi</category>
    </item>
  </channel>
</rss>
