{"data":{"allMarkdownRemark":{"edges":[{"node":{"id":"92132641-afb7-53d7-8663-09c7b3dec866","frontmatter":{"category":"DevOps","title":"Monitoring screens on Raspberry Pi","date":"2019-05-02","summary":"How to setup monitoring tools on TV screens using Raspberry Pi","thumbnail":{"relativePath":"pages/monitoring-screens/screens.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAQX/xAAXAQADAQAAAAAAAAAAAAAAAAABAgME/9oADAMBAAIQAxAAAAGuV+ZqLOeBv//EABoQAQADAAMAAAAAAAAAAAAAAAEAAhEDEjP/2gAIAQEAAQUCyyd2NwZhOb0//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAIRUf/aAAgBAwEBPwGNpT//xAAYEQADAQEAAAAAAAAAAAAAAAAAAhEBMf/aAAgBAgEBPwGpOGKf/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAEQITER/9oACAEBAAY/Au0aW4wZ/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAERMSH/2gAIAQEAAT8hUE0UuHcTUWQVsCF//9oADAMBAAIAAwAAABBMD//EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQMBAT8Q7axV/8QAGBEBAQADAAAAAAAAAAAAAAAAAQARIaH/2gAIAQIBAT8QC07hTN//xAAaEAEBAQEAAwAAAAAAAAAAAAABEQBRMUGx/9oACAEBAAE/EOs8EuY6EsQM8KHpwGjZyuCJ5OYFE583/9k=","width":578,"height":325,"src":"/static/adf3f762bfd697b8fdc141491acaadb2/a2998/screens.jpg","srcSet":"/static/adf3f762bfd697b8fdc141491acaadb2/a2998/screens.jpg 1x,\n/static/adf3f762bfd697b8fdc141491acaadb2/99cce/screens.jpg 1.5x,\n/static/adf3f762bfd697b8fdc141491acaadb2/6e995/screens.jpg 2x,\n/static/adf3f762bfd697b8fdc141491acaadb2/968b1/screens.jpg 3x"}}},"authorName":"Konstantin Shcherban","authorDescription":"Konstantin is DevOps Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/monitoring-screens/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACyElEQVQ4y4VUO2gUURR9mZmN8YcItoKVjeXuzsxu9jOzm92NkBBTqDEmjZAEgtqIpSgI1gp+uhS6kEI7wc7GQsFCLERiISGCaGHhF02yu+M5s/cujyC4cJY379573r3n3XdNvV51xsYiJ4rKbqlUyBj8wjAYyWazp4BVYB3YAraBDeAhMBcE/l76lkrFTLVachuNyCGXEbJMrVbx6ADnaWAtn88nvu8nWBMdQcJ9Auv3wCxjWq2aC9IMSF3DzCyyG1YAs9pSYkL2melmLpfT71tKGkUlz2iZJAuCgA5dEjGAwPoV0AbuAy+tfR7YkZjb5CiXR1OutEw5jWQdCfgCnEiSxNg/7LWAj+KTSiHSzBvrAtascrriPCmnDkP4AYQ0Em3TGPHf8P38ARpP/4PsHQ7aU69Hqdi4OJeI47JXLg9IX1tVbUuWCzSsygcJO+L0goGNRpySoB1colarerhEvcCn4tuxCB/TsC5ZdS3Ct2Ho75uZmRoigWbIbgCxt7Q0O8TLsgg17o2R2+JHzzJcV/1IoBlybel42SLsCcc3I6UqoaZ+lUHFYjjCzJSQa+4J4UVLKiX8ScOGVXJXDN+xd7SfZXFYS65U+n2Wz+cOw+ezHadSkfCRdVJiZdlmMG9ZtHMpgWR3Z0eMSvWExjmrbXoCbZ951dIim7Yk6u1IYtlwavChW51Pp01tXOwf01eC9RHs/Rbbnx2Hf4IUh/Q5zdol8H3KG22Pj9edOK54LF1876pd37TELhqdZ+J4MwxDHUvXgDOFQrB7YqLpjI4WdhG8GLYNbCeBK/1+TWNWRG+Pfy5Hj5Dek3IXzX9+8DkL/AIeLC/PDU1NHXdSQk5altNsDkjPAT+ArzKyFnK5bB2IxbYik4hanmfM5GTL6Q/Y2DUc25y0HLToubR8TI39cL4APJOxr/35AXgOXEJnHKQvepP6eiQj119kDrZjqLo8HAAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png","srcSet":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png 1x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/eb85b/avatar.png 1.5x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/4f71c/avatar.png 2x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/9ec3e/avatar.png 3x"}}},"headerImage":null},"html":"<p>To have visual alerting we watch dashboards powered by <a href=\"https://grafana.com/\">Grafana</a>, <a href=\"https://www.elastic.co/products/kibana\">Kibana</a> and <a href=\"https://www.opsgenie.com/\">OpsGenie</a> on big TV screens hanging on the walls where we sit. For OpsGenie we use <a href=\"https://www.opsgenie.com/blog/2015/10/real-time-alert-dashboard\">this dashboard</a> with custom modifications.</p>\n<p>First version of screens were powered by Linux laptops connected over HDMI cables.\nThat was not scalable, was expensive and required manual support to update Linux,\nrestart laptops, etc.</p>\n<p>Later DevOps team's boss Jönas Fleer found a nice project <a href=\"https://www.balena.io/blog/resin-io-changes-name-to-balena-releases-open-source-edition/\">ResinOS</a>. This project (<a href=\"https://www.balena.io/blog/resin-io-changes-name-to-balena-releases-open-source-edition/\">was renamed to balena</a>) allows to attach <a href=\"https://www.raspberrypi.org/\">Raspberry Pi</a> devices to a nice dashboard, automatically upload and run Docker image on them and manage all of that in an easy and pretty way.</p>\n<p><a href=\"https://www.balena.io/\">Balena</a> provides customized <a href=\"https://github.com/balena-os\">operating system</a> that runs supervisor\nwhose task is to get updates of your Docker images pushed to balena cloud,\npull them locally and restart container with new changes.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/4357891f724320749544f6c61ac0a35d/91dc6/balena-architecture.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 52.849999999999994%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsSAAALEgHS3X78AAACrklEQVQoz11Tb0hTURS/29AFiRlRSIVCpET1oag+FIJBQRpBCfWlfwgGQfTnS4SYFUrRB4NslhRZQv5Bp2KWxpxbJrrMMptzc8+59/b29rb33vbe23Q6czBP21vPXD843HPP/d3D+Z1zLwIoR3YcUAIAIFkCYd6oSKzVfZDxeArWx+PKyGJELZ/39ZtQa4de8lu0/as+EmzxRGzcYsPoLxQt1XnKhBMM+/aGJkoMwkhpL8/DaYCljSLRrgzgTQqZrO3SoRTMB0ERYqclAsvDOcK3UjnJQmZiT84O3YNwHUSIWhgb/Xh/7T2buVtV9yZZRFuXQaoyBT4TUgvcB98yPwGM+V1FXNr2APP1tNNpuYzNjFyatmrOJ3gR951tQaxqS039YG57ly4nKVn3T/KC60Lpok2ZLYSwrTx5xR6dugi0SXMjnlCF/oPoflvmJzsdLKmfpbHmk1LL3K3K0V8RhJUhNIXR0iBgLmDRihHY7WccB+3jTcVygmvW5vxH5vp88GqyhBhkMPR0EevWf/G6hho4V0uuzOPoSgWFP0O0M96VpSg8CM6v9LgpaodMWAFIi/mrbhuMx/ix8RIyFv5RI86HDwN8Uqyt2D7zfZPNQe5MkcEY3+dYqHZpqkAhNUygdDIIhdEFO4CrCIC7Dh6KEAk6vB+WUZooCg0B7+fhkA3l+DhhM8N6ThBE39ngglblI5+okabX2ignJyjTAdFR8nxuAOVNeqCAYue+4fTvzh4jc0jm8AL/iuM5cDm7mxL7WOBIpg0b2uW2PzzqcdwtRYUFFTdlshWHUwzLQNj98kwyApLE+he1WbpBi1p+p4bh2X2Yk9wDXqTCJ4ul4dHYrQ24+Wo6InCOAfBL4wdmXTorwnEhCtnJn1Met6cpLWrr1Ge8buzIXhsb+Amrvf0DieCZh3FpfDUAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"balena architecture\"\n        title=\"\"\n        src=\"/static/4357891f724320749544f6c61ac0a35d/40fad/balena-architecture.png\"\n        srcset=\"/static/4357891f724320749544f6c61ac0a35d/707e9/balena-architecture.png 148w,\n/static/4357891f724320749544f6c61ac0a35d/649e0/balena-architecture.png 295w,\n/static/4357891f724320749544f6c61ac0a35d/40fad/balena-architecture.png 590w,\n/static/4357891f724320749544f6c61ac0a35d/b3fef/balena-architecture.png 885w,\n/static/4357891f724320749544f6c61ac0a35d/301c0/balena-architecture.png 1180w,\n/static/4357891f724320749544f6c61ac0a35d/b5a53/balena-architecture.png 1770w,\n/static/4357891f724320749544f6c61ac0a35d/91dc6/balena-architecture.png 2000w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>So to prepare a new monitoring screen you need to:</p>\n<ol>\n<li>Purchase Raspberry Pi device and SD card for it. Balena also provides <a href=\"https://www.balena.io/fin/\">special devices</a> that they build on Raspberry Pi platform.</li>\n<li>Write <a href=\"https://www.balena.io/docs/learn/getting-started/raspberrypi3/nodejs/\">Balena OS</a> to SD card.</li>\n<li><a href=\"https://www.balena.io/docs/learn/getting-started/raspberrypi3/nodejs/#deploy-code\">Create and setup repository</a> with app that you would like to be executed on your Raspberry Pi.</li>\n<li><code class=\"language-text\">git push</code> and watch the magic.</li>\n</ol>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/107bc0d489efdc0c676b911849127bae/f36d5/success_unicorn_simple_nodejs.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 96.7065868263473%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAACpUlEQVQ4y52UzUsbQRTAA4V+/AHuvfSidwWroP9D6aEeeuul2kNLj21PRU091Ar9E4SCIl56MLaKQSMhUD/QmEKTbCJkk2zcTWZ3J1+7M69v1t1t4heNDx5vktn5zfuY90IhlMT7r3d/fBiXPn6f7tuN7vRFolHp3beIFJ6ekT7NzUnh2bD0ZWFBCofD0vzneWlmdlZaWlqSlpeXhe1bXV0V63shX/a2Ys+yqV12mDu2suksTWeyNPFbpuk/aVxnaAY1f3pK5ZxM8/k8lWWZlkolX81KpQL7+/vPA+DPnY1JBQgUSRnkbA4ymSyc5vJQLJaholagUFCAMQ43SSKReB0AI5ubU6rjgFGnTrlUYrquc7yZK0qR4+1cKRa5qqq83W4LKhcirKe2AMZisTcBcA2Bis1BJwarlFVuEAOUQgHKpTJoZxqo6CXCodVqud4InqdCnEvAja2tqTr+aVqUGYTwarUGhmGAQUzQtSpYlgWargN6GADBd/Uq4M729pSXCuaF4R0AaLe6c+fDbgRudwC9j85DwkLUdAfq9PyeDs96BwoR3pGqA9RiLrw7f7cACmtjYanJgmfTufffQHeBAAtBzSZzDzOHX8pjT0AHAdUzG5oNBg4+KZHHlgfv2UP/kA8Q1iSOa+12D0Dc7Kqy3wwiXMtwXK8vVPta4KTnodPxFgNtNjgq4/8YXXK59aLR6CuOGNEZlNbdFhOdUq83wDRNLA7FUG0MuXXtcIjH428D4MrKyotk8qSx92uvdnR0THBskYODQ5JMpoj4fXKSIjjCSCqVIjgsCA4Pommab6u1Ws1eX19/GQD7+/sfjo2PPRkZeTwhdGhoCO3IxPDwcGAHBwddFXsX16Ojo08HBgYenY+uyJowd1DFxH1wS70vGIuLi6G/LHZxYIcIluUAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"success unicorn simple nodejs\"\n        title=\"\"\n        src=\"/static/107bc0d489efdc0c676b911849127bae/40fad/success_unicorn_simple_nodejs.png\"\n        srcset=\"/static/107bc0d489efdc0c676b911849127bae/707e9/success_unicorn_simple_nodejs.png 148w,\n/static/107bc0d489efdc0c676b911849127bae/649e0/success_unicorn_simple_nodejs.png 295w,\n/static/107bc0d489efdc0c676b911849127bae/40fad/success_unicorn_simple_nodejs.png 590w,\n/static/107bc0d489efdc0c676b911849127bae/f36d5/success_unicorn_simple_nodejs.png 668w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Our app is a simple Docker image with X server, Firefox browser and command line tools to resize graphical windows. By the time of this project writing Alpine Linux for ARM didn't support latest Firefox because of <a href=\"https://lists.alpinelinux.org/alpine-devel/6295.html\">porting Rust issues</a>.</p>\n<p>You may ask, why Firefox and not Chromium? Unfortunately Chromium is too heavy for poor Raspberry Pi device, even for 3 B+ model that we use.</p>\n<p>Here's a Dockerfile that balena builds and deploys on devices:</p>\n<div class=\"gatsby-highlight\" data-language=\"dockerfile\"><pre class=\"language-dockerfile\"><code class=\"language-dockerfile\">FROM resin/%%BALENA_MACHINE_NAME%%-alpine:3.7\n\nRUN apk add --update --no-cache \\\n  xf86-video-fbdev \\\n  xf86-input-libinput \\\n  mesa \\\n  mesa-dri-swrast \\\n  xorg-server \\\n  mesa-egl \\\n  xf86-input-evdev \\\n  xdotool \\\n  bash \\\n  firefox-esr\n\nADD profiles.ini /root/.mozilla/firefox/profiles.ini\nADD run /bin/run\n\n# set timezone\nARG TIMEZONE=Europe/Berlin\nRUN apk add --update --no-cache tzdata &amp;&amp; \\\n  cp /usr/share/zoneinfo/$TIMEZONE /etc/localtime &amp;&amp; \\\n  echo $TIMEZONE &gt; /etc/timezone &amp;&amp; \\\n  apk del tzdata\n\n## comment out if you don&#39;t want systemd\nENV INITSYSTEM on\nENV DBUS_SYSTEM_BUS_ADDRESS unix:path=/host/run/dbus/system_bus_socket\n\nENTRYPOINT [ &quot;/bin/run&quot; ]</code></pre></div>\n<p>Of course when you have many screens it would be inefficient to duplicate app just to open different web URLs in a browser. For that purpose we installed <a href=\"https://dashkiosk.readthedocs.io/en/latest/\">DashKiosk</a> and configured all devices to open the same web link that was a DashKiosk URL. In DashKiosk you manage connected devices to open proper dashboards URLs.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/0e1808198db036704aaf648256569813/6fc9c/dashkiosk.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 54.69238790406674%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACVElEQVQoz2WR708ScRzHedwpJyj8Az4B1tYcR8IDmdaa2nqaK/MPMPvxqLbMisbccsrakmzN3DQsY3TNrewH0/FDhKtzHoirOXUqKJwHd8dxkMBxYt8EV5vvfR5+35/Xa5+vZGrq7YTNNjk29s5sRvv7Hc9H7A7H++OgKPoBRR3HsdvtNtvr8YnxsdHRN5OTktraWrlMfgqCTjc0ON1ur9/v8/kCgQCGYfO+eec359zs7HcMA4PjuNvl1mg0EARJpdL6+nqJQqFQKpVVVVXnWlpMJlNra/vVzq6OjittbRet1pGBwaHLndf4bPbwKBzH6XQ6GIYBUqVSSerq6splvcHwyeW3f56b8QRmPBj61eXCg1+mP04PPiUXMHaRiFGp1d09RKuVwrBMJlOr1RUyWIYgCMOmwPq8IIARiiKTSiUpqsDzuXQ6Q9PR6M7q2poOQcBjuVwO/P+WQQDZaDRah4d7rnezDFMSxWKhUDoQLRbLjZu3+h4+GrJYwN4Uy2i1WviIXCmXtZuamiwvXnXfuR9JcmxeJLksuy8MPHvZc/fB7d7HveYnTK64RVJAEFzrXxmkrL1Hs6XDw9/5Asdn9mhml6QomskJxVKplC8ICYbdikSRk9rV1dUGvd7j9c44nZ4FfwDHD0Qxy6c3d2IkzSY5nuYyfE6IxOIVck3Nf9oQZGxuNt3raz/TcEl7tuv8BUE4YLL7wV/r4Y3IeozaiCc2KebnxvZJshKWSpHGxvVQmPb58qFlIbxCxpPbCXaZWAoRxHKQCBFL4VBwEf8B/hmQy+U/rI9coYc3jnEAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"dashkiosk\"\n        title=\"\"\n        src=\"/static/0e1808198db036704aaf648256569813/40fad/dashkiosk.png\"\n        srcset=\"/static/0e1808198db036704aaf648256569813/707e9/dashkiosk.png 148w,\n/static/0e1808198db036704aaf648256569813/649e0/dashkiosk.png 295w,\n/static/0e1808198db036704aaf648256569813/40fad/dashkiosk.png 590w,\n/static/0e1808198db036704aaf648256569813/b3fef/dashkiosk.png 885w,\n/static/0e1808198db036704aaf648256569813/301c0/dashkiosk.png 1180w,\n/static/0e1808198db036704aaf648256569813/b5a53/dashkiosk.png 1770w,\n/static/0e1808198db036704aaf648256569813/6fc9c/dashkiosk.png 1918w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>When device is restarted it needs to reconnect to the same URL it was configured before. Because DashKiosk determines device id by browser profile, we need to save it. For that Firefox profile is saved on <a href=\"https://www.balena.io/docs/learn/develop/runtime/#storage\">Raspberry Pi's SDcard</a> which is persistent storage and data written there survives application and device's restarts.</p>\n<p>Here's profiles.ini added in Dockerfile above:</p>\n<div class=\"gatsby-highlight\" data-language=\"ini\"><pre class=\"language-ini\"><code class=\"language-ini\"><span class=\"token header\"><span class=\"token punctuation\">[</span><span class=\"token section-name selector\">General</span><span class=\"token punctuation\">]</span></span>\n<span class=\"token key attr-name\">StartWithLastProfile</span><span class=\"token punctuation\">=</span><span class=\"token value attr-value\">1</span>\n\n<span class=\"token header\"><span class=\"token punctuation\">[</span><span class=\"token section-name selector\">Profile0</span><span class=\"token punctuation\">]</span></span>\n<span class=\"token key attr-name\">Name</span><span class=\"token punctuation\">=</span><span class=\"token value attr-value\">default</span>\n<span class=\"token key attr-name\">IsRelative</span><span class=\"token punctuation\">=</span><span class=\"token value attr-value\">0</span>\n<span class=\"token key attr-name\">Path</span><span class=\"token punctuation\">=</span><span class=\"token value attr-value\">/data/firefox-profile</span>\n<span class=\"token key attr-name\">Default</span><span class=\"token punctuation\">=</span><span class=\"token value attr-value\">1</span></code></pre></div>\n<p>And here's docker entrypoint script. It's purpose is to </p>\n<ol>\n<li>Get bigger <a href=\"https://www.kernel.org/doc/gorman/html/understand/understand015.html\">shm device</a>.</li>\n<li>Start Firefox.</li>\n<li>Resize Firefox window, enter full screen mode.</li>\n<li>Sleep forever.</li>\n</ol>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token shebang important\">#!/bin/bash</span>\n<span class=\"token comment\"># URL is set in balena device settings</span>\n<span class=\"token comment\"># it should point to dashkiosk</span>\n<span class=\"token assign-left variable\">URL</span><span class=\"token operator\">=</span><span class=\"token variable\">${URL<span class=\"token operator\">:-</span>http<span class=\"token operator\">:</span><span class=\"token operator\">/</span><span class=\"token operator\">/</span>jodel-app.com}</span>\n\n<span class=\"token comment\"># By default docker gives us 64MB of shared memory size but to display heavy</span>\n<span class=\"token comment\"># pages we need more.</span>\n<span class=\"token function\">umount</span> /dev/shm <span class=\"token operator\">&amp;&amp;</span> <span class=\"token function\">mount</span> -t tmpfs shm /dev/shm\n\n<span class=\"token function\">rm</span> /tmp/.X0-lock <span class=\"token operator\">&amp;></span>/dev/null <span class=\"token operator\">||</span> <span class=\"token boolean\">true</span>\n\n<span class=\"token function\">mkdir</span> -p /data/firefox-profile\nstartx /usr/bin/firefox <span class=\"token string\">\"<span class=\"token variable\">$URL</span>\"</span> -- -dpms -s off -s noblank -nocursor<span class=\"token operator\">&amp;</span>\n<span class=\"token comment\"># wait until Xserver and Firefox start</span>\n<span class=\"token function\">sleep</span> <span class=\"token number\">40</span>\n<span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\"><span class=\"token environment constant\">DISPLAY</span></span><span class=\"token operator\">=</span>:0\nxdotool search --name <span class=\"token string\">\".*Mozilla Firefox\"</span> windowsize <span class=\"token number\">100</span>% <span class=\"token number\">100</span>%\nxdotool search --name <span class=\"token string\">\".*Mozilla Firefox\"</span> key <span class=\"token string\">\"F11\"</span>\n<span class=\"token comment\"># sleep forever</span>\n<span class=\"token function\">tail</span> -f /dev/null</code></pre></div>\n<p>Once application is ready it's not the end of configuration. Because latest web tools such as Grafana or Kibana require quite some hardware resources we need to tune balena OS settings to give container more GPU memory and include additional video drivers.</p>\n<p>For that <a href=\"https://www.balena.io/docs/learn/manage/configuration/#managing-device-configuration-variables\">update device configuration</a> or entire fleet with following <a href=\"https://www.balena.io/docs/learn/manage/configuration/#variable-list\">variables</a>:</p>\n<p><code class=\"language-text\">RESIN_HOST_CONFIG_gpu_mem=128</code> sets 128MB of GPU memory, by default it's only 16MB.</p>\n<p><code class=\"language-text\">RESIN_HOST_CONFIG_dtoverlay=\"vc4-fkms-v3d\"</code> enables <a href=\"https://www.raspberrypi.org/forums/viewtopic.php?t=159853\">new 3d driver</a>.</p>\n<p>That's it, took me a lot of time to make it work on Alpine Linux.</p>\n<p>Result looks like this:\n<a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/adf3f762bfd697b8fdc141491acaadb2/0e6dd/screens.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 56.2535158447403%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAQX/xAAXAQADAQAAAAAAAAAAAAAAAAABAgME/9oADAMBAAIQAxAAAAGuV+ZqLOeBv//EABoQAQADAAMAAAAAAAAAAAAAAAEAAhEDEjP/2gAIAQEAAQUCyyd2NwZhOb0//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAIRUf/aAAgBAwEBPwGNpT//xAAYEQADAQEAAAAAAAAAAAAAAAAAAhEBMf/aAAgBAgEBPwGpOGKf/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAEQITER/9oACAEBAAY/Au0aW4wZ/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAERMSH/2gAIAQEAAT8hUE0UuHcTUWQVsCF//9oADAMBAAIAAwAAABBMD//EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQMBAT8Q7axV/8QAGBEBAQADAAAAAAAAAAAAAAAAAQARIaH/2gAIAQIBAT8QC07hTN//xAAaEAEBAQEAAwAAAAAAAAAAAAABEQBRMUGx/9oACAEBAAE/EOs8EuY6EsQM8KHpwGjZyuCJ5OYFE583/9k='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"screens\"\n        title=\"\"\n        src=\"/static/adf3f762bfd697b8fdc141491acaadb2/f8fb9/screens.jpg\"\n        srcset=\"/static/adf3f762bfd697b8fdc141491acaadb2/e8976/screens.jpg 148w,\n/static/adf3f762bfd697b8fdc141491acaadb2/63df2/screens.jpg 295w,\n/static/adf3f762bfd697b8fdc141491acaadb2/f8fb9/screens.jpg 590w,\n/static/adf3f762bfd697b8fdc141491acaadb2/85e3d/screens.jpg 885w,\n/static/adf3f762bfd697b8fdc141491acaadb2/d1924/screens.jpg 1180w,\n/static/adf3f762bfd697b8fdc141491acaadb2/9452e/screens.jpg 1770w,\n/static/adf3f762bfd697b8fdc141491acaadb2/0e6dd/screens.jpg 5333w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Because of the relatively small result docker image size (280MB vs 450MB with Debian based image) new deployments to balena are quite fast. Hope you will find this article useful and it will save you some time on solving monitoring challenge.</p>\n<p>What's left to do is to configure scheduled turn off and on of screens during working hours.</p>","fields":{"slug":"/monitoring-screens/","tags":["auto1","engineering","monitoring","alerting","iot","RaspberryPi"]}}}]}},"pageContext":{"slug":"/tags/RaspberryPi","tag":"RaspberryPi","categories":["Architecture","Coding","DevOps","Engineering","ProjectManagement","QA","Social","TechRadar"]}}