<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Bastien Bourdon</title>
    <description>Trying to give back to the community - I write about tech, web development, data science, and leassons learned from the startup life</description>
    <link>https://bastien-brd.github.io/</link>
    <atom:link href="https://bastien-brd.github.io/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Thu, 18 Jun 2020 09:56:40 +0000</pubDate>
    <lastBuildDate>Thu, 18 Jun 2020 09:56:40 +0000</lastBuildDate>
    <generator>Jekyll v3.8.7</generator>
    
      <item>
        <title>Application-level encryption and Personally Identifiable Information (PII)</title>
        <description>&lt;p&gt;More privacy regulations and laws such as GDPR in Europe (with worldwide implications) require businesses to be very careful and responsible in the way they process, store and communicate user data.&lt;/p&gt;

&lt;p&gt;Extra care must be taken when processing what is often called Personally Identifiable Data, also referred to as PII. In most web application, &lt;strong&gt;PII means a user’s email address, phone number, full name, etc.&lt;/strong&gt; Basically it is any piece of information that, taken individually, can identify a person.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bastien-brd.github.io/images/illustrations/undraw_unlock_24mb.png&quot; alt=&quot;Data privacy - Illustration&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As a side note, IP addresses are sometimes considered personally identifiable, although it is a debated topic. The website https://eugdprcompliant.com/personal-data/ mentions: &lt;em&gt;“A much discussed topic is the IP address. The GDPR states that IP addresses should be considered personal data as it enters the scope of ‘online identifiers’.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a web application developer, you should take every reasonable step to protect your user PII data from leakage. There are many steps to this, at various levels of your stack. &lt;strong&gt;One of the ways to protect this data is to use application-level encryption.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;application-level-encryption-and-its-limitations&quot;&gt;Application Level Encryption and its limitations&lt;/h2&gt;

&lt;h3 id=&quot;premise&quot;&gt;Premise&lt;/h3&gt;

&lt;p&gt;Web applications usually store data in a database on a database server, either managed by a cloud provider (Microsoft Azure SQL Database, AWS RDS, etc.) or on a self-managed VM, or even on the same machine as the application.&lt;/p&gt;

&lt;p&gt;At the end of day, the database data is saved on disk somewhere. Most likely, the machine uses disk encryption so the data is encrypted at rest: if someone walks into your cloud provider’s datacenter (good luck) and pulls out the drive storing your database, they would only find gibberish. Also your application (hopefully) connects to your database server over SSL/TLS so the data is encrypted in transit.&lt;/p&gt;

&lt;p&gt;However &lt;strong&gt;consider if an attacker gains access to the database server (via SSH or any other way) or gets their hand on a database dump: the data is accessible in clear and the user PII is leaked.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;solution&quot;&gt;Solution&lt;/h3&gt;

&lt;p&gt;Application Level Encryption remedies this by having &lt;strong&gt;the application encrypt the data before sending it and saving it in the database&lt;/strong&gt;. When reading the data, the application decrypts it on the fly before serving it or using it.&lt;/p&gt;

&lt;p&gt;This means &lt;strong&gt;the data is never stored in clear anywhere&lt;/strong&gt;, and the clear version only lives shortly in memory when it is used.&lt;/p&gt;

&lt;h3 id=&quot;drawbacks-and-limitations&quot;&gt;Drawbacks and Limitations&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Application Level Encryption comes with a lot of overhead&lt;/strong&gt;. Encryption and decryption are expensive operations (slow and requires a lot of resource relatively to your application). Implementing it requires additional depencies to manage and maintain carefully and periodically, and developers are usually not very familiar with cryptography at this level. And finally it requires the usage of strong encryption keys which you need to handle very securely: if someone gets their hand on the key, they can access all the encrypted data.&lt;/p&gt;

&lt;p&gt;So &lt;strong&gt;application level encryption requires a good and careful key management process&lt;/strong&gt;. Using a Key Management System is strongly advised. I found that &lt;a href=&quot;https://azure.microsoft.com/en-gb/services/key-vault/&quot;&gt;Azure Key Vault&lt;/a&gt; is a great solution, but there are other good ones such as &lt;a href=&quot;https://www.vaultproject.io/&quot;&gt;Hashicorp Vault&lt;/a&gt;. A KMS will allow you to safely store your keys, and manage access to the keys granularly to each application or developer, giving them the minimum required privileges using role-based access control (RBAC). It will also facilitate key rotation: meaning changing the keys periodically (typically every year).&lt;/p&gt;

&lt;p&gt;All of this is &lt;strong&gt;additional maintenance, cost, and complexity&lt;/strong&gt;, and application level encryption can often be dismissed as overkill.&lt;/p&gt;

&lt;p&gt;Another drawback: &lt;strong&gt;your application cannot lookup a database row by an encrypted field&lt;/strong&gt;. In the case of PII, this means you cannot lookup a user by email for example, if the email field is stored encrypted (see last section of this article for a practical problem with this and a solution). This is because modern encryption algorithms use some smart random padding before encrypting a message: as a result, encrypting the same message several times does not produce the same encrypted value (but all these encrypted values decrypt to the same message: some serious mathematical black magic happening here). This also makes it impossible to sort by or filter by encrypted fields (you could select a subset of rows and sort/filter the whole set in code in your application, but that requires memory and is much less efficient than database-side). You can pretty much just read/decrypt these fields from rows you’ve already selected.&lt;/p&gt;

&lt;p&gt;Personally, the main drawback is that I don’t find application level encryption much more secure than just using encryption in transit and at rest on disk. &lt;strong&gt;Most likely, if an attacker manages to gain access to the database, it would be through a phishing attack on one of your users, a vulnerability in your application&lt;/strong&gt;, or gaining access to your application server. In this case, the attacker would also likely use your application to just decrypt the database data before dumping it…&lt;/p&gt;

&lt;h2 id=&quot;why-you-might-still-need-to-use-application-level-encryption&quot;&gt;Why you might still need to use Application Level Encryption&lt;/h2&gt;

&lt;p&gt;You might have noticed that the “drawbacks” section above is much larger than the “Premise” and “Solutions sections”. So in what cases might you still need to use it?&lt;/p&gt;

&lt;p&gt;I have found myself being forced to implement application level encryption for some large enterprise clients, whose Security Architecture teams would make that a mandatory requirement. In this case, we just priced that extra overhead in the commercial agreement and implemented it.&lt;/p&gt;

&lt;p&gt;In general, application level encryption is useful when you cannot completely trust the database server or provider, or if this is a mandatory requirement from a third party regulator or compliance team.&lt;/p&gt;

&lt;h2 id=&quot;one-last-problem-encrypting-application-usernames&quot;&gt;One last problem: encrypting application usernames&lt;/h2&gt;

&lt;p&gt;Many web applications use email address as the username for its users. Unfortunately the email address is  personally identifiable information, and you might be required to store it only encrypted.&lt;/p&gt;

&lt;p&gt;As we saw earlier, it is impossible to lookup a database row by an encrypted field. So how do you go about querying your database for a particular user by email address when they attempt to login for example?&lt;/p&gt;

&lt;p&gt;I’ll describe a solution to this problem in my next article.&lt;/p&gt;

&lt;hr /&gt;
</description>
        <pubDate>Tue, 12 Nov 2019 00:00:00 +0000</pubDate>
        <link>https://bastien-brd.github.io/2019/application-level-encryption-and-pii/</link>
        <guid isPermaLink="true">https://bastien-brd.github.io/2019/application-level-encryption-and-pii/</guid>
        
        <category>development</category>
        
        <category>security</category>
        
        
        <category>development</category>
        
        <category>security</category>
        
      </item>
    
      <item>
        <title>Setting up a data backup system at home</title>
        <description>&lt;p&gt;Data is more and more important, and grouping and backing up your personal data such as important documents and photos can be daunting and time consuming.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It is the most important task you most likely don’t do.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I find it easy to backup my data online on the fly: for example most of my documents (paperwork type) are in a Google Drive folder automaticcaly synced from my laptop(s) to my Drive account (using the Google Backup and Sync software), and my photos are all automatically backed up on Google Photos, as I take them from my phone. The first thing I do after coming back from travelling is to upload my non-connected camera’s (DLSR and GoPro) photos to my Google Photos account.&lt;/p&gt;

&lt;p&gt;This is a good solution, as long a you trust the online storage providers involved. But who knows how it will be in a few years, in a decade, in a few decades… And what if you lose your access to your account somehow (a hack or simply by forgetting)?&lt;/p&gt;

&lt;p&gt;In this article I describe how to have a small cheap machine (Raspberry Pi) constantly running at home, backing up the content of your different online storage accounts such as Google Photos and Google Drive, Dropbox, etc. into a single hard drive, safely stored at home.&lt;/p&gt;

&lt;p&gt;It is cheap both because of the Raspberry Pi is inexpensive (you can even use an older model), and you won’t even notice its electricity consumption on your home bill.&lt;/p&gt;

&lt;p&gt;The process involves installing an open source software called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone&lt;/code&gt; on your Raspberry Pi, in charge of periodically copying your data from your various accounts online, into an external hard drive.&lt;/p&gt;

&lt;h2 id=&quot;install-rclone-on-the-raspberry-pi&quot;&gt;Install rclone on the Raspberry Pi&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone&lt;/code&gt; is an open source software that replicates the infamous &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt; unix command, but allows you to easily use online storage accounts such as Dropbox and Google Drive as remote servers.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone&lt;/code&gt; has a quite a few binary distributions available, including a Linux 32bit ARM compatible with the Raspberry Pi 3.&lt;/p&gt;

&lt;p&gt;Install it by SSHing into your Pi and executing the following commands from :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -O https://downloads.rclone.org/rclone-v1.38-linux-arm.zip
unzip rclone-v1.38-linux-arm.zip 
rm rclone-v1.38-linux-arm.zip 
cd rclone-v1.38-linux-arm/
sudo cp rclone /usr/bin/
sudo chown root:root /usr/bin/rclone 
sudo chmod 755 /usr/bin/rclone 
sudo mkdir -p /usr/local/share/man/man1
sudo cp rclone.1 /usr/local/share/man/man1/
sudo mandb 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note: These steps can be made into a Docker image for easily running rclone on any other Raspberry Pi.&lt;/p&gt;

&lt;h2 id=&quot;create-a-ssh-tunnel-during-rclone-config&quot;&gt;Create a SSH tunnel during rclone config&lt;/h2&gt;

&lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone config&lt;/code&gt; and pick &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; to register a new remote storage account and choose a name for it. In my example, I register my Google Drive account calling it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drive_bastien&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When registering a remote storage into rclone, you will need to authenticate to that storage account most likely.
This is the case for Google Drive for example, with which you need to authenticate to your Google account in order 
to authorize your rclone setup to access and modify your drive.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone config&lt;/code&gt; makes this authentication super easy, by temporarily creating a local webserver, 
asking you to open your browser at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://127.0.0.1:53682/auth&lt;/code&gt; and authenticate to your Google account there.
However most likely you will be setting up rclone on a headless server where you cannot do that.
My solution is to create a SSH tunnel from your local machine to your headless server, forwarding the server’s port 53682
to a port on your machine.&lt;/p&gt;

&lt;p&gt;In order to open the temporary browser window for authenticating with Google Drive account on your Raspberry Pi:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh -nNT -L 9001:127.0.0.1:53682 pi@raspberrypi.local
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nNT&lt;/code&gt; flags makes the command not create a tty session and open any shell)&lt;/p&gt;

&lt;p&gt;On your machine (not the Raspberry Pi), open your browser at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:9001/auth&lt;/code&gt;, and sign in to your Google Account.
Once the authentication succeeded, you will have to manually change the domain in the URL in your browser back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:9001&lt;/code&gt; to complete the setup.&lt;/p&gt;

&lt;p&gt;Kill the tunnel once the config is completed.&lt;/p&gt;

&lt;h2 id=&quot;try-to-sync-a-folder-from-remote-into-a-local-folder&quot;&gt;Try to sync a folder from remote into a local folder&lt;/h2&gt;

&lt;p&gt;That’s it, you can now easily copy and synchronise any folders and files. 
Try running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rclone lsd drive_bastien:&lt;/code&gt; and see the list of top level folders listed.
For my setup, I test backing up one particular folder called “Papers” from my Google Drive into a folder called “backup” on the Raspberry Pi:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rclone copy drive_bastien:Papers/ ./backup/Papers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and notice that all the folders and files under Papers have copied locally, preserving the file timestamps and meta-data etc.&lt;/p&gt;

&lt;h2 id=&quot;create-a-cron-job-to-run-every-day-to-backup-the-data-you-want-from-your-google-drive&quot;&gt;Create a CRON job to run every day to backup the data you want from your Google Drive&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;crontab -e
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I recommend explicitely adding one line per folder you want, with appropriate schedule:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0 0 * * * rclone copy drive_bastien:Google\ Photos /backup/Photos
0 0 * * * rclone copy drive_bastien:Papers /backup/Papers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;
</description>
        <pubDate>Sat, 07 Oct 2017 00:00:00 +0000</pubDate>
        <link>https://bastien-brd.github.io/2017/home-backup/</link>
        <guid isPermaLink="true">https://bastien-brd.github.io/2017/home-backup/</guid>
        
        <category>raspberry-pi</category>
        
        
        <category>raspberry-pi</category>
        
      </item>
    
      <item>
        <title>Quickly setup a USB sound card on a Raspberry Pi 3</title>
        <description>&lt;p&gt;The raspberry-pi is a marvellous little device! So versatile, so powerful (relative to its price and size), it allows an infinite number of applications.&lt;/p&gt;

&lt;p&gt;As a music fan and guitar playing aficionado, the first ideas that came to my mind were mostly about combining my interests in computers and music. In my personal pipeline of potential projects: a guitar tuner, a whole plethora of guitar effects (all-in-one effect pedal), a loop station, training a Recurrent Neural Network to correct my mistakes as I play, etc…&lt;/p&gt;

&lt;p&gt;Unfortunately, the raspberry-pi does not come with a built in microphone or any audio input. And setting one up is not straight forward: to my surprise, there is a high number of posts online asking about how to setup audio input on the pi, and very little satisfying answers.&lt;/p&gt;

&lt;p&gt;My investigation led me to using a USB sound card instead of trying to use the GPIO pins (way too manual and raw). Yes it sounds a little bit less maker-y, but hey, I want to get stuff done. As far as I know, there is only one GPIO sound card availbale on the market, but there is close to no documentation and support for it.&lt;/p&gt;

&lt;p&gt;I settled for a &lt;a href=&quot;https://www.amazon.co.uk/Creative-Blaster-Portable-Headphone-Amplifier/dp/B00JFRHLQK&quot;&gt;Sound Blaster E1&lt;/a&gt; (30 GBP as I write this article): it was within my price range and I trusted Sound Blaster would take care of writing proper drivers compatible with most OS including linux (I run &lt;a href=&quot;https://www.raspberrypi.org/downloads/raspbian/&quot;&gt;Debian Jessie&lt;/a&gt;). I am sure many other and possibly cheaper options are available out there. However the trouble with USB cards is that you have to trust the maker provide sane drivers, ideally plug-and-play for any linux machines. This is the case with the Sound Blaster E1. Also: it looks pretty cool.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bastien-brd.github.io/images/2016-09-16-raspberrypi-usb-sound/raspberry-pi-sound-card.jpg&quot; alt=&quot;My sound card plugged to my Raspberry Pi 3&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;enough-talk-lets-get-that-bad-boy-working&quot;&gt;Enough talk, let’s get that bad boy working.&lt;/h3&gt;

&lt;p&gt;Start by plugging the USB sound card into any of your raspberry-pi’s USB ports, and ssh onto its command line.
If your card has sane drivers, you can make sure the sound card is available as sound output device by typing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;aplay &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;which should return at least 2 cards’ descriptions (one for the built in audio output and one for your sound card)&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;****&lt;/span&gt; List of PLAYBACK Hardware Devices &lt;span class=&quot;k&quot;&gt;****&lt;/span&gt;
card 0: ALSA &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;bcm2835 ALSA], device 0: bcm2835 ALSA &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;bcm2835 ALSA]
  Subdevices: 8/8
  Subdevice &lt;span class=&quot;c&quot;&gt;#0: subdevice #0&lt;/span&gt;
  Subdevice &lt;span class=&quot;c&quot;&gt;#1: subdevice #1&lt;/span&gt;
  Subdevice &lt;span class=&quot;c&quot;&gt;#2: subdevice #2&lt;/span&gt;
  Subdevice &lt;span class=&quot;c&quot;&gt;#3: subdevice #3&lt;/span&gt;
  Subdevice &lt;span class=&quot;c&quot;&gt;#4: subdevice #4&lt;/span&gt;
  Subdevice &lt;span class=&quot;c&quot;&gt;#5: subdevice #5&lt;/span&gt;
  Subdevice &lt;span class=&quot;c&quot;&gt;#6: subdevice #6&lt;/span&gt;
  Subdevice &lt;span class=&quot;c&quot;&gt;#7: subdevice #7&lt;/span&gt;
card 0: ALSA &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;bcm2835 ALSA], device 1: bcm2835 ALSA &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;bcm2835 IEC958/HDMI]
  Subdevices: 1/1
  Subdevice &lt;span class=&quot;c&quot;&gt;#0: subdevice #0&lt;/span&gt;
card 1: E1 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Sound Blaster E1], device 0: USB Audio &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;USB Audio]
  Subdevices: 1/1
  Subdevice &lt;span class=&quot;c&quot;&gt;#0: subdevice #0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And similarily check the audio input devices:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;arecord &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check the order in which your cards have been loaded:&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/asound/modules
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In my case and I think in the case of most USB sound cards, we get the following, meaning the USB card comes second:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0 snd_bcm2835
1 snd_usb_audio
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first thing to do is to make everything a lot easier by switching this default order, so that your USB sound card always gets defined as the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;card 0&lt;/code&gt;.
You do this by editing or creating the following file:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/modprobe.d/alsa-base.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and giving it the following content&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# This sets the index value of the cards but doesn't reorder.
options snd_usb_audio index=0
options snd_bcm2835 index=1

# Does the reordering.
options snd slots=snd_usb_audio,snd_bcm2835
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then we need to make sure the audio configuration shipped with the USB card is used: this is done by editing the alsa configuration file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/alsa/alsa.conf&lt;/code&gt; by only uncommenting one line (remove the # sign):&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;load card-specific configuration files &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;on request&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then simply reboot your raspberry-pi. You can now check again &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aplay -l&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arecord -l&lt;/code&gt; for the order in which devices come. A quick way to test the default setup is to run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;speaker-test&lt;/code&gt; commandin the shell. You should hear some white noise coming out of the speaker/headphone plugged to your USB sound card.&lt;/p&gt;

&lt;p&gt;You can record a few seconds of audio using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arecord test.wav&lt;/code&gt; command, and CTRL+C to stop recording. Listen to your test with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aplay test.wav&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You should now be setup to use your Raspberry Pi with a USB soundcard and get cracking on some cool project involving audio input and output. Personally, my first project is making a &lt;a href=&quot;https://github.com/Bastien-Brd/pi-tuner/&quot;&gt;guitar tuner using different pitch detection technics&lt;/a&gt;. To get started withthis project, I published a post in which I explain one way to &lt;a href=&quot;/2016/dsp-on-raspberrypi/&quot;&gt;get started with Digital Signal Processing on the Raspberry Pi 3&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;
</description>
        <pubDate>Fri, 16 Sep 2016 00:00:00 +0000</pubDate>
        <link>https://bastien-brd.github.io/2016/raspberrypi-usb-sound/</link>
        <guid isPermaLink="true">https://bastien-brd.github.io/2016/raspberrypi-usb-sound/</guid>
        
        <category>raspberry-pi</category>
        
        <category>music</category>
        
        
        <category>raspberry-pi</category>
        
        <category>music</category>
        
      </item>
    
      <item>
        <title>Work in progress: Experimenting with DSP on Raspberry Pi</title>
        <description>&lt;p&gt;In this article I describe how I got started experimenting with &lt;em&gt;Digital Sound Processing (DSP)&lt;/em&gt; on Raspberry Pi.&lt;/p&gt;

&lt;p&gt;My first objective was to configure the Pi the play and record audio to and from my USB sound card. You can read how to set this up &lt;a href=&quot;/2016/raspberrypi-usb-sound/&quot;&gt;in my previous article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The initial project I want to achieve is creating a guitar tuner; it would consist of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the Raspberry Pi listening to audio input as stream (coming from the USB sound card)&lt;/li&gt;
  &lt;li&gt;taking samples of 1 or 2 seconds&lt;/li&gt;
  &lt;li&gt;approximating the pitch of the string played (implementing my own pitch detection algorithm)&lt;/li&gt;
  &lt;li&gt;determining what is the closest expected note and how far from that note the current pitch is&lt;/li&gt;
  &lt;li&gt;and using two 8-segments led displays (wired to the Pi’s GPIOs) to give a visual indication of the target note (A, B, C#, etc.) and of how to get there (up or down)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I start with experimenting with &lt;a href=&quot;http://python-sounddevice.readthedocs.io/&quot;&gt;Python Sounddevice library&lt;/a&gt; which allows to play and record audio represented as Numpy arrays. This library binds with the PortAudio library. I choose python-sounddevice because I am comfortable dealing with Numpy and the scipy stack in general. Moreover, I know whatever pitch detection algorithm I implement, it will have to be fast, and pure python would likely be too slow.&lt;/p&gt;

&lt;p&gt;First let’s install PortAudio on the Pi. It requires Alsa (which of course is already installed on Debian Jessie) but also its developer library:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;libasound-dev libportaudio2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also CFFI (C Foreign Function Interface for Python) needs to be installed, you can get it via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt; nut you need to install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libffi&lt;/code&gt; first:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;libffi-dev
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;cffi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can finally install sounddevice:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;sounddevice
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can test recording and playing some audio in our python3 interpreter:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query_devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Sound&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Blaster&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;E1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;USB&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Audio&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bcm2835&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bcm2835&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IEC958&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HDMI&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sysdefault&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;front&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;surround40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iec958&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spdif&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dmix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ALSA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# we use my USB sound card device
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# seconds
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44100&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# samples by second
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myrecording&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myrecording&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;220500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We have recorded 5 seconds of audio from the default input device (my sound blaster card, listed as device 0) at a sample rate of 44100 Hz, on 2 channels. To simplify things in the future, I will always use one single channel, since I don’t care about stereo input for pitch detection.&lt;/p&gt;

&lt;hr /&gt;
</description>
        <pubDate>Mon, 12 Sep 2016 00:00:00 +0000</pubDate>
        <link>https://bastien-brd.github.io/2016/dsp-on-raspberrypi/</link>
        <guid isPermaLink="true">https://bastien-brd.github.io/2016/dsp-on-raspberrypi/</guid>
        
        <category>general</category>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Hello world!</title>
        <description>&lt;p&gt;Hello and welcome!&lt;/p&gt;

&lt;p&gt;My name is Bastien Bourdon and this is the first post on my personal website. Its main purpose will be mostly to write for myself: I find writing an article about a subject one is working on helps a lot with completing a specific goal or milestone within that project, and forces good structure and communication.&lt;/p&gt;

&lt;p&gt;I will write mostly about tech (web development, dev ops, data science), my experience as a startup co-founder and entrepreneur in general, and possibly any other subject or idea that piques my interest.&lt;/p&gt;

&lt;p&gt;Web technologies are just a tiny subset of my original background, but as I spent time building online solutions, I have been astonished by the openness of its amazing community of developers and everything they are willing to share. Giving back and contributing is the primary motivation for this website.&lt;/p&gt;

&lt;p&gt;Throughout my posts you will encounter some code examples presented in some beautiful highlighting such as:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;say_hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;greetings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Bonjour!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;greetings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;User has been greeted.&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While you wait for more progress on my writing, check out my startup’s website: &lt;a href=&quot;https://edgefolio.com&quot;&gt;edgefolio.com&lt;/a&gt;. Do not hesitate contacting me if you think any of it is interesting to you.&lt;/p&gt;

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

&lt;hr /&gt;
</description>
        <pubDate>Mon, 12 Sep 2016 00:00:00 +0000</pubDate>
        <link>https://bastien-brd.github.io/2016/hello-world/</link>
        <guid isPermaLink="true">https://bastien-brd.github.io/2016/hello-world/</guid>
        
        <category>general</category>
        
        
        <category>general</category>
        
      </item>
    
  </channel>
</rss>
