<?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: Gabriel Guzman</title>
    <description>The latest articles on DEV Community by Gabriel Guzman (@gabeguz).</description>
    <link>https://dev.to/gabeguz</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%2F11285%2F132174.jpeg</url>
      <title>DEV Community: Gabriel Guzman</title>
      <link>https://dev.to/gabeguz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gabeguz"/>
    <language>en</language>
    <item>
      <title>Ansible</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Tue, 13 Apr 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/gabeguz/ansible-4gk6</link>
      <guid>https://dev.to/gabeguz/ansible-4gk6</guid>
      <description>&lt;p&gt;I’ve been playing with ansible off and on for several years now, usually in fits and starts. Ansible is a tool for managing computers. It lets you do things like setup a new web server in &lt;em&gt;exactly&lt;/em&gt; the same way you setup your old web server, or make sure that your new laptop has all the software you routinely use installed, or configure a cluster of computers identically regardless of their underlying operating system, package manager, or authentication system.&lt;/p&gt;

&lt;p&gt;In short, it’s a super powerful tool for automating everything about all your computers.&lt;/p&gt;

&lt;p&gt;Every time I manually provision a new server I tell myself, “this time I’m going to use ansible”, and every time I start I end up getting frustrated that it’s so hard to get started using ansible and I just provision the sever manually, again. Finally, I found a course on pluralsight (thanks $EMPLOYER) that walks you through setting up ansible to manage just your local machine. This was the guide I needed. It gave simple instructions that clearly told you how to get ansible working for just this one machine, from there it was pretty easy to apply the same learnings to several machines and I’m now happy to say that I’m using ansible to manage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;my work laptop&lt;/li&gt;
&lt;li&gt;my personal laptop&lt;/li&gt;
&lt;li&gt;my home router/firewall&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that if I ever need to replace my router, I can just run the router playbook that I’ve created on the new machine and my router will be provisioned exactly the same way as my current router. It also means that if one of my laptops kicks the bucket, I can be up and running again on a new machine quickly. I won’t need to remember all the stuff I usually have to install, I won’t need to remember the special way I have to configure my local smtp server to relay outgoing mail to my real smtp server. I won’t have to spend time trying to get my firewall rules just right. As long as I keep only using ansible to manage these machines, I’ll have no snowflakes!&lt;/p&gt;

&lt;p&gt;It also means that I can reuse the work I’ve done to get these machines setup to get my other machines setup as well. The ones that are left to do are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;smtpd server&lt;/li&gt;
&lt;li&gt;httpd server&lt;/li&gt;
&lt;li&gt;minecraft server&lt;/li&gt;
&lt;li&gt;vpn server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of those has their own unique tweaks that I’ll have to port to ansible before I can fully use it to provision them, but there will also be a fair amount of overlap from the work I’ve already done.&lt;/p&gt;

&lt;p&gt;If you have a pluralsight license, I can happily recommend this course: &lt;a href="https://www.pluralsight.com/courses/getting-started-ansible"&gt;Getting started with ansible&lt;/a&gt; and if you don’t &lt;a href="https://blog.laurentcharignon.com/post/laptop-setup-with-ansible/"&gt;here’s a blog post&lt;/a&gt; that takes a similar approach (i.e. managing your personal laptop with ansible). Finally, &lt;a href="https://docs.ansible.com/ansible-core/2.10/user_guide/index.html"&gt;the ansible docs&lt;/a&gt; are a useful if daunting resource.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I am an open source developer</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Tue, 27 Oct 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/gabeguz/i-am-an-open-source-developer-36mp</link>
      <guid>https://dev.to/gabeguz/i-am-an-open-source-developer-36mp</guid>
      <description>&lt;p&gt;I’m an open source developer. What does that mean to me?&lt;/p&gt;

&lt;h2&gt;
  
  
  Prefer open source software
&lt;/h2&gt;

&lt;p&gt;I always prefer open source software. If no open source software exists to do what I’m trying to do, see the next point.&lt;/p&gt;

&lt;h2&gt;
  
  
  If the software doesn’t exist, create it
&lt;/h2&gt;

&lt;p&gt;If there’s no software available to do what I’m trying to do, it’s my job to create it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contribute to open source software
&lt;/h2&gt;

&lt;p&gt;If I use open source software and find a way to improve that software, or fix a bug, it’s my job to improve it.&lt;/p&gt;

&lt;p&gt;These statements are aspirational, not absolute. There are always exceptions and I’m not going to spend my life worrying about what piece of not free software I used today.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>development</category>
      <category>philosophy</category>
    </item>
    <item>
      <title>Goodbye Google</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Fri, 23 Oct 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/gabeguz/goodbye-google-4m4p</link>
      <guid>https://dev.to/gabeguz/goodbye-google-4m4p</guid>
      <description>&lt;p&gt;I’ve been a gmail user since it first came out, and I used to be a fan of google, but now I find myself more and more concerned with their data gathering practices. I’ve decided to move all of my personal services off of google onto open source self hosted alternatives. This page will act as a checklist for each of the services I’m able to get off of. Each of the links below will talk about what I’m using now and how I set it up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Services To Replace
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[x] search
&lt;/li&gt;
&lt;li&gt;[x] browser
&lt;/li&gt;
&lt;li&gt;[x] email
&lt;/li&gt;
&lt;li&gt;[x] calendar
&lt;/li&gt;
&lt;li&gt;[ ] photos
&lt;/li&gt;
&lt;li&gt;[ ] contacts
&lt;/li&gt;
&lt;li&gt;[ ] maps
&lt;/li&gt;
&lt;li&gt;[ ] android

&lt;ul&gt;
&lt;li&gt;[x] authenticator
&lt;/li&gt;
&lt;li&gt;[x] play store
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Search
&lt;/h3&gt;

&lt;p&gt;This one was the easiest of the bunch. Instead of using google.com as a search engine, I now use duckduckgo.com. I’ve made duckduckgo.com my default search engine for &lt;em&gt;everything.&lt;/em&gt; There’s even a command line tool that lets you search from the cli: &lt;a href="https://github.com/jarun/ddgr"&gt;https://github.com/jarun/ddgr&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Browser
&lt;/h3&gt;

&lt;p&gt;Instead of using chrome, I’m now exclusively using &lt;a href="https://getfirefox.com"&gt;Firefox&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Email
&lt;/h3&gt;

&lt;p&gt;Email was complicated since there are so many moving parts. Instead of gmail, I’m now using a combination of &lt;a href="https://man.openbsd.org/smtpd"&gt;OpenBSD’s smtpd&lt;/a&gt;, the &lt;a href="https://www.dovecot.org/"&gt;dovecot imap server&lt;/a&gt;, and &lt;a href="https://man.openbsd.org/spamd"&gt;OpenBSD’s spamd&lt;/a&gt; hosted on a &lt;a href="https://www.vultr.com/"&gt;Vultr VPS&lt;/a&gt; running &lt;a href="https://www.openbsd.org"&gt;OpenBSD&lt;/a&gt;. To read and send mail I’m now using &lt;a href="https://git.sr.ht/~sircmpwn/aerc"&gt;aerc&lt;/a&gt; as well as &lt;a href="https://www.thunderbird.net/en-US/"&gt;Thunderbird&lt;/a&gt; as my local clients. I don’t do webmail anymore.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calendar
&lt;/h3&gt;

&lt;p&gt;For my calendar, I’m now using &lt;a href="https://www.simplemobiletools.com/calendar/"&gt;simple calendar&lt;/a&gt; synching to a self hosted instance of &lt;a href="https://kristaps.bsd.lv/kcaldav/"&gt;kcaldav&lt;/a&gt;. I pretty much only use my calendar on my phone so I don’t currently have a web version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Photos
&lt;/h3&gt;

&lt;p&gt;No good solution for photos yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contacts
&lt;/h3&gt;

&lt;p&gt;Haven’t tried to figure out contact syncing yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maps
&lt;/h3&gt;

&lt;p&gt;While I’ve used &lt;a href="https://openstreetmap.org"&gt;openstreetmap&lt;/a&gt; it’s not very effective where I live. I’ve been contributing to it when I can, but it can’t yet replace google maps for me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Android
&lt;/h3&gt;

&lt;p&gt;I know there are some open source forks of Android out there and I’ve tried &lt;a href="https://en.wikipedia.org/wiki/CyanogenMod"&gt;CyanogenMod&lt;/a&gt; previously (which I guess is now called &lt;a href="https://lineageos.org/"&gt;LineageOS&lt;/a&gt;), but I think ideally I’d like something like the &lt;a href="https://www.pine64.org/"&gt;PinePhone&lt;/a&gt; to fully opt out of the Android ecosystem.&lt;/p&gt;

&lt;h4&gt;
  
  
  Authenticator
&lt;/h4&gt;

&lt;p&gt;Instead of Google Authenticator I’m using &lt;a href="https://f-droid.org/en/packages/org.shadowice.flocke.andotp/"&gt;andOTP&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Play Store
&lt;/h4&gt;

&lt;p&gt;Instead of the play store, I’m using &lt;a href="https://f-droid.org/en/"&gt;F-Droid&lt;/a&gt; a catalog of open source software for Android.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>openbsd</category>
      <category>selfhosting</category>
    </item>
    <item>
      <title>exercism.io looking for mentors</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Wed, 08 Aug 2018 12:59:23 +0000</pubDate>
      <link>https://dev.to/gabeguz/exercismio-looking-for-mentors-496n</link>
      <guid>https://dev.to/gabeguz/exercismio-looking-for-mentors-496n</guid>
      <description>&lt;p&gt;Hello, dev.to'ers.  exercism.io -- "an online platform designed to help you improve your coding skills through practice and mentorship" is looking for mentors!  If you're looking to learn by teaching or just want to pay-it-forward by volunteering to an awesome effort to get others up and running in the language of their choice, this is a great place to start.  I've been using their site since their launch to practice programming problems in different languages, and have recently started mentoring others in those same exercises.  If you're interested in mentoring, check out: &lt;a href="https://exercism.io/mentoring-faqs" rel="noopener noreferrer"&gt;https://exercism.io/mentoring-faqs&lt;/a&gt; or if you just want to practice coding, and get feedback on your work: &lt;a href="https://exercism.io" rel="noopener noreferrer"&gt;https://exercism.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently, the PHP track needs some mentors (and I know there are a few of you out there who enjoy PHP, as I do) but there are lots of different language tracks to choose from!  &lt;/p&gt;

&lt;p&gt;Come help us out! &lt;/p&gt;

</description>
      <category>programming</category>
      <category>mentorship</category>
      <category>craft</category>
    </item>
    <item>
      <title>git bundle</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Wed, 30 May 2018 19:53:37 +0000</pubDate>
      <link>https://dev.to/gabeguz/git-bundle-2l5o</link>
      <guid>https://dev.to/gabeguz/git-bundle-2l5o</guid>
      <description>&lt;p&gt;I had an interesting problem at work the other day.  We'd hired some external contractors to build an android app for us, and now we needed to get the code from them and into our private GitHub.  The problem was, I couldn't quickly get them access to the repo since there's a fair amount of process involved in getting those approvals.  They also didn't have enough seats to add me as a contributor to their GitHub account, and so we were stuck with me asking them to send a .zip file with the code.   Instead, they came back to me with a git bundle file, which I'd never heard of (though I've been using git for a long time now).   A git bundle file is essentially a full repository in a single file.  You can have branches, history, tags, basically everything you expect in a repository, but it's all contained in a single file.   This makes sharing the repository or moving the full repository pretty straightforward.  Assume I have a git project called myproj, and I want to send that to someone else.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;host1$ cd myproj
host1$ git bundle create repo.bundle master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That will make a bundle file (repo.bundle) that contains all the history of the master branch.  You can then send this file to a friend, and they can clone it just like if it were a remote git origin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;host2$ git clone -b master ./repo.bundle myproj
host2$ cd myproj
host2$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another pretty neat thing about git bundles is, if you need to update one, you can send an incremental file update with only the latest changes.  The recipient just puts that in place of their existing bundle, and runs &lt;code&gt;git pull&lt;/code&gt; w/in their repo.  &lt;/p&gt;

&lt;p&gt;This isn't something you'd use every day, but in certain situations (like getting a git repo from one place to another w/out being able to share a remote origin) it works great!&lt;/p&gt;

&lt;p&gt;More info on git bundle: &lt;a href="https://git-scm.com/docs/git-bundle" rel="noopener noreferrer"&gt;https://git-scm.com/docs/git-bundle&lt;/a&gt;&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>git</category>
      <category>development</category>
    </item>
    <item>
      <title>DHCP</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Wed, 23 May 2018 11:48:15 +0000</pubDate>
      <link>https://dev.to/gabeguz/dhcp-3jl3</link>
      <guid>https://dev.to/gabeguz/dhcp-3jl3</guid>
      <description>&lt;p&gt;Once upon a time, if you wanted to connect to the internet (or even to your local network) you needed to edit a bunch of files, ask your system or network administrator for an IP address, and hope you didn't mess up your computer too badly since you didn't know what you were doing.  Today, you just plug in your Ethernet cord, or login to your wifi network and you're good to go.  How does that work?&lt;/p&gt;

&lt;h1&gt;
  
  
  Assumptions
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;The network cable is good&lt;/li&gt;
&lt;li&gt;The port is active (plugged into a switch or hub at the other end)&lt;/li&gt;
&lt;li&gt;There is a DHCP server &lt;em&gt;somewhere&lt;/em&gt; on the network&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Preliminaries
&lt;/h1&gt;

&lt;p&gt;Ok, so you've got your cable plugged in, and you see some blinking lights, that's a good sign.  It means that the physical interface (the network card) is receiving information over the network, and possibly sending information over the network. &lt;br&gt;
You won't be able to reach hosts on the internet at this point as your computer doesn't have an IP address.  Your TCP/IP network information currently looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|---------------|
|  My Computer  |
|---------------|
|IP: 0.0.0.0    |
|Router: 0.0.0.0|
|DNS: 0.0.0.0   |
|---------------|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No IP (Internet Protocol) address - The IP address is the address of your computer on the Internet.  It's how other hosts on the interenet know where to reach you.  When you browse to &lt;a href="https://duckduckgo.com" rel="noopener noreferrer"&gt;https://duckduckgo.com&lt;/a&gt;, you send your IP address as the "return address" so that the duckduckgo server knows where to send a reply.  &lt;/p&gt;

&lt;p&gt;No Router address - A router is just a computer that is configured to transfer packets from one network to another.  All the machines on your local network can talk to each other without a router, as long as you know their IP address, you can send packets to them directly.  If you want to get to another network, you need to send your packets through a router that knows about both of the networks.  Usually a router is physically plugged into at least two networks via two ethernet cards, and can pass packets from one card to the other.&lt;/p&gt;

&lt;p&gt;No DNS server address - We've talked about &lt;a href="https://dev.to/gabeguz/whats-dns-13c3"&gt;DNS&lt;/a&gt; in a previous post, but basically DNS is your address book.  You ask for &lt;a href="https://duckduckgo.com/" rel="noopener noreferrer"&gt;https://duckduckgo.com/&lt;/a&gt; and the DNS server is in charge of looking that name (duckduckgo.com) up in its address book and telling you the IP address for that name is: 107.20.240.232 (promise, look it up).&lt;/p&gt;

&lt;h1&gt;
  
  
  No IP, now what?
&lt;/h1&gt;

&lt;p&gt;What can you do w/out an IP address?   We can't reach other hosts on the internet yet, but we &lt;em&gt;can&lt;/em&gt; talk to other hosts on our own network.  Not having an IP address means we can't tell others where to reach us, but we can YELL into the darkness and hope someone is listening. That's basically what your computer does when it's first plugged into a network (assuming you have a DHCP client running).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;you&amp;gt; HELLO?
you&amp;gt; HELLOOOOOOOOOOOOOOO!
dhcpserver&amp;gt; HEY!
dhcpserver&amp;gt; STOP YELLING.  Use the phone, call me here: 192.168.1.2
dhcpserver&amp;gt; And, here's a number you can use: 192.168.1.115
dhcpserver&amp;gt; Also, this is the number for the router, in case you need to get on another network: 192.168.1.1
dhcpserver&amp;gt; make sure you let me know you're going to use this.
you&amp;gt; oh, hey, thanks!  I'll remember that my number is 192.168.1.115 and yours is 192.168.1.2.  
dhcpserver&amp;gt; Great, oops, almost forgot, here is the DNS server you can use to lookup other computers: 192.168.1.3.  See you around!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your computer (via it's dhclient program) sends a message called &lt;code&gt;DHCPDISCOVER&lt;/code&gt; to the network broadcast address (a special address that anyone on the network can recieve messages to) this address is known by your computer ahead of time, and on TCP/IP networks is 255.255.255.255. Sending packets to this address will send them to all hosts on the local network.  Routers will &lt;em&gt;not&lt;/em&gt; forward broadcast messages on to other networks.  If there's a DHCP server listening, it will reply with a &lt;code&gt;DHCPOFFER&lt;/code&gt; message that contains all the information you need to configure yourself as part of the local TCP/IP network.  Since you don't yet have an IP address configured, the DHCP server will also use a broadcast message to send you the &lt;code&gt;DHCPOFFER&lt;/code&gt;.  Then your computer will send back a &lt;code&gt;DHCPREQUEST&lt;/code&gt; message asking the DHCP server to reserve the number it just told you about for you.  If everything goes well, the DHCP server will respond with a &lt;code&gt;DHCPACK&lt;/code&gt; with any additional information (such as DNS server addresses) it has.  This message lets you know it's ok to start using that IP address officially on the network.&lt;/p&gt;

&lt;p&gt;Now, assuming all that went well,  your network configuration should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|--------------------|
|     My Computer    |
|--------------------|
|IP: 192.168.1.115   |
|Router: 192.168.1.1 |
|DNS: 192.168.1.3    |
|--------------------|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can confirm your current ip address using the &lt;code&gt;ifconfig&lt;/code&gt; command on most unix like systems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ifconfig iwm0
iwm0: flags=8943&amp;lt;UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST&amp;gt; mtu 1500
        lladdr e8:2a:ea:ab:49:24
        index 1 priority 4 llprio 3
        groups: wlan egress
        media: IEEE802.11 autoselect (HT-MCS14 mode 11n)
        status: active
        ieee80211: nwid Odessa chan 11 bssid ac:f1:df:62:d6:9a 70% wpakey wpaprotos wpa2 wpaakms psk wpaciphers ccmp wpagroupcipher ccmp
        inet 192.168.0.115 netmask 0xffffff00 broadcast 192.168.1.255
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can confirm your router address using the &lt;code&gt;route&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ route show
Routing tables

Internet:
Destination        Gateway            Flags   Refs      Use   Mtu  Prio Iface
default            192.168.1.1        UGS        9      860     -    12 iwm0 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you can confirm your DNS server by looking at the contents of /etc/resolv.conf&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat /etc/resolv.conf
nameserver 192.168.1.3
lookup file bind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Questions
&lt;/h1&gt;

&lt;p&gt;Congratulations, you're on the internet!  A few questions to think about: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What would happen if you decided to run a DHCP server on your laptop and start passing out IP addresses on your network? &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What more can you do before you have an IP address? &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What allows you to have connections to other computers on the network before you have your TCP/IP networking configured? &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>networking</category>
      <category>beginners</category>
      <category>development</category>
    </item>
    <item>
      <title>Good Practices - Code Review Comments</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Mon, 07 May 2018 21:24:23 +0000</pubDate>
      <link>https://dev.to/gabeguz/good-practices---code-review-comments-455</link>
      <guid>https://dev.to/gabeguz/good-practices---code-review-comments-455</guid>
      <description>&lt;p&gt;If you do code review, you likely come across the same issues over and over again.  People who are contributing to your code base for the first time may not know your team's internal standards, they may come from a different language and do things slightly differently.  A new hire may need to get up to speed quickly on submitting changes to your repository.  How can you make sure these cases are handled while minimizing the impact on your code reviewers?  One helpful tool is the "Code Review Comments" document.     &lt;/p&gt;

&lt;p&gt;A "Code Review Comments" document is a collection of comments that come up again and again in code review sessions.  For example, if you're always having to tell people "Make sure you're using prepared statements when sending input to an SQL server", you could just add that to this document, and then when you see unescaped SQL, just point the submitter to your doc.&lt;/p&gt;

&lt;h1&gt;
  
  
  Onboarding New Developers
&lt;/h1&gt;

&lt;p&gt;When a new developer joins your team, you can point them to this document so they can get a quick overview of your standard practices.  This is a good place to put things like: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All code must be linted, and conform to our internal code style standards before being submitted for review (you &lt;em&gt;do&lt;/em&gt; have code standards right?) &lt;/li&gt;
&lt;li&gt;Code submitted as a PR should be tested by another developer before it's merged&lt;/li&gt;
&lt;li&gt;We prefer using "guard clauses" rather than deeply nested if / else blocks see: &lt;a href="https://www.thechrisoshow.com/2009/02/16/using-guard-clauses-in-your-ruby-code/" rel="noopener noreferrer"&gt;https://www.thechrisoshow.com/2009/02/16/using-guard-clauses-in-your-ruby-code/&lt;/a&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Anything that's not covered by your linter/code formatter can live in this document.&lt;/p&gt;

&lt;h1&gt;
  
  
  Decreasing Cognitive Load
&lt;/h1&gt;

&lt;p&gt;Reading code is generally considered harder than writing code so anything that places less cognitive load on the reviewer is good.  If all the simple stuff is covered in your Code Review Comments document, then the reviewer can focus on the meat of the change request without having to worry about stuff that they shouldn't have to worry about.   This will also help with personal style differences that may come up in a review.  If it's clearly stated that your team prefers shorter variable names, then it's harder for someone to argue that in this case, they really think that &lt;code&gt;loopIndexVariable&lt;/code&gt; is a better name than &lt;code&gt;i&lt;/code&gt; for a loop index because it's more descriptive.&lt;/p&gt;

&lt;h1&gt;
  
  
  Limiting Bike Shedding
&lt;/h1&gt;

&lt;p&gt;If you find yourself constantly getting into arguments over stuff that's really not that important, you can throw it in the doc (once the team comes to consensus on the best colour to paint the bike shed) and then any time someone thinks another colour would be better, just link them to the doc and be done with it.  For more on &lt;a href="https://en.wikipedia.org/wiki/Law_of_triviality" rel="noopener noreferrer"&gt;Bike Shedding&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Formalizing Team Standards
&lt;/h1&gt;

&lt;p&gt;Often, the longer a team works together, the more unwritten rules they will develop for how they like their code.   This works great until you try to bring a new person into the group.  The new person needs to discover these standards by trial and error, which can be frustrating and take time.  Maintaining a Code Review Comments document can help formalize these unspoken standards and reduce friction when a new member joins the team.  Instead of having to have several code reviews rejected because of internal standards that everyone else is aware of, the new developer can just read the document.&lt;/p&gt;

&lt;h1&gt;
  
  
  Don't Over Do It
&lt;/h1&gt;

&lt;p&gt;One thing you definitely &lt;em&gt;don't&lt;/em&gt; want to do with this type of document is to fill it with so much minutia that it itself becomes a source of cognitive load for the developer.  It should be fairly succinct, and easy to read.  A good example of this is the go teams &lt;a href="https://github.com/golang/go/wiki/CodeReviewComments" rel="noopener noreferrer"&gt;Code Review Comments&lt;/a&gt; document.  It's filled with things that have come up over and over again in code reviews, and have been added to the document to improve the development and code review experience for both the submitter and the reviewer.  &lt;/p&gt;

&lt;h1&gt;
  
  
  Starting Your Own
&lt;/h1&gt;

&lt;p&gt;It's really easy to start a document like this.  Any time you're doing a code review and have to comment on the same thing more than once, add it to the document.  Get your team to do the same, then you can review the doc together from time to time and decide what to keep and what to discard.  When new contributors join the team, send them the doc before they submit their first PR so they can make sure their code is ready for code review.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Maintaining a Code Review Comments document can be a good way to onboard new developers, decrease the cognitive load on your reviewers, and formalize unwritten team standards.  Instead of having to discover these things via trial and error, a new contributor can scan the document and get up to speed with the internal standards of a new team quickly.  This can reduce friction for the new developer and improve the code review experience for all parties.   &lt;/p&gt;

&lt;p&gt;Do you use a document like this with your team?  Feedback, thoughts?  Leave a comment.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>development</category>
      <category>codereview</category>
    </item>
    <item>
      <title>What are the constraints for uploading an image?</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Thu, 03 May 2018 11:16:47 +0000</pubDate>
      <link>https://dev.to/gabeguz/what-are-the-constraints-for-uploading-an-image-3odo</link>
      <guid>https://dev.to/gabeguz/what-are-the-constraints-for-uploading-an-image-3odo</guid>
      <description>&lt;p&gt;Tried uploading a header image and I got an error message that just said "invalid file" but didn't give me any reasons why the file was invalid.  I assume it's because it's over the file-size limit, but I'm not sure what that is.  Any way we could improve this error message, or barring that be more descriptive about what the requirements are for the image near the "upload image" dialog? &lt;/p&gt;

</description>
      <category>discuss</category>
      <category>meta</category>
      <category>images</category>
    </item>
    <item>
      <title>What's DNS?</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Wed, 25 Apr 2018 21:53:19 +0000</pubDate>
      <link>https://dev.to/gabeguz/whats-dns-13c3</link>
      <guid>https://dev.to/gabeguz/whats-dns-13c3</guid>
      <description>&lt;p&gt;DNS is basically the address book of the internet.  When you type &lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt; into your browser, the computer needs to figure out how to get your request to the right server.  Routing over the internet works via IP addresses, so to get to &lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt;, you first need to figure out what its IP address is.  &lt;/p&gt;

&lt;p&gt;This is where DNS, the Domain Name System comes in.  At a high level, when you hit enter in your browsers location bar, the browser does a DNS lookup to try and find the IP address of the server name you entered. A DNS lookup consists of calling an Operating System function (a syscall) called &lt;code&gt;gethostbyname()&lt;/code&gt;.  This function takes a string such as "&lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt;" and returns a structure that includes the IP address of the host, among other information.  On my system, that struct looks like this&lt;sup id="fnref1"&gt;1&lt;/sup&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct  hostent { 
    char    *h_name;    /* official name of host */ 
    char    **h_aliases;    /* alias list */ 
    int h_addrtype; /* host address type */ 
    int h_length;   /* length of address */ 
    char    **h_addr_list;  /* list of returned addresses */ 
}; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How does &lt;code&gt;gethostbyname()&lt;/code&gt; know what the IP address of &lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt; is?  Unix like computers (including Macs) have a file called &lt;code&gt;/etc/resolv.conf&lt;/code&gt; that tells the Operating System where it should look for name to address lookups, you can check yours by typing &lt;code&gt;cat /etc/resolv.conf&lt;/code&gt; in your terminal program.  &lt;/p&gt;

&lt;p&gt;Mine looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat /etc/resolv.conf
# Generated by iwm0 dhclient
nameserver 192.168.0.1
lookup file bind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tells me a few things: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;#Generated by iwm0 dhclient&lt;/code&gt; This tells me the file itself was generated by the &lt;code&gt;dhclient&lt;/code&gt; program. &lt;code&gt;dhclient&lt;/code&gt; is the program that hands out IP addresses to computers that request them via DHCP (Dynamic Host Configuration Protocol)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nameserver 192.168.0.1.&lt;/code&gt; This tells me the IP address of a server I can use to lookup names I don't already know about.  This will be important soon.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lookup file bind&lt;/code&gt; This tells the computer what database it should use to 'lookup' IP addresses, 'file' tells the computer to first check the &lt;code&gt;/etc/hosts&lt;/code&gt; file, and 'bind' tells the computer to ask DNS for the IP address.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're a web developer, you've likely used the &lt;code&gt;/etc/hosts&lt;/code&gt; file to have a web address point to your computer temporarily for testing.  If not, that's ok we'll talk about it now.  &lt;/p&gt;

&lt;p&gt;If you look in &lt;code&gt;/etc/hosts&lt;/code&gt; you'll see something that looks a bit like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat /etc/hosts
127.0.0.1       localhost
::1             localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a mapping of IP address, hostname, and aliases.  In the above example, there are no aliases defined.  If I wanted to prank myself, I could do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat /etc/hosts
127.0.0.1       localhost
::1             localhost
127.0.0.1       www.duckduckgo.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when I try to browse to &lt;a href="https://www.duckduckgo.com/" rel="noopener noreferrer"&gt;https://www.duckduckgo.com/&lt;/a&gt; I get an error, because &lt;code&gt;gethostbyname("www.duckduckgo.com")&lt;/code&gt; is returning 127.0.0.1, which is the IP address of my local computer, and not the address of &lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt;.  If I knew the IP address of &lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt;, I could put it here and everything would work, at least until the IP of &lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt; changed.  &lt;/p&gt;

&lt;p&gt;A long, long, time ago, there was no DNS, just a bunch of computers and a bunch of people adding entries to &lt;code&gt;/etc/hosts&lt;/code&gt; files by hand, or maybe copy pasting from a file that was distributed by Stanford&lt;sup id="fnref2"&gt;2&lt;/sup&gt;.  Eventually this became too cumbersome and someone decided to write some code, thus DNS was born.&lt;/p&gt;

&lt;p&gt;Now we come to the second option in our &lt;code&gt;resolv.conf&lt;/code&gt; example, &lt;code&gt;bind.&lt;/code&gt; If &lt;code&gt;gethostbyname()&lt;/code&gt; can't find an entry in &lt;code&gt;/etc/hosts&lt;/code&gt; it then queries the DNS server specified in the &lt;code&gt;nameserver&lt;/code&gt; section of &lt;code&gt;/etc/resolv.conf&lt;/code&gt; this is your DNS server. &lt;/p&gt;

&lt;p&gt;So, the Operating System sends a query to 192.168.0.1 asking for the IP address for the "&lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt;" server.  If 192.168.0.1 knows the IP address, it will return it to you, if not... it will then ask its DNS server (also defined in the &lt;code&gt;/etc/resolv.conf&lt;/code&gt; file but now on your DNS server) what the address is for "&lt;a href="http://www.duckduckgo.com." rel="noopener noreferrer"&gt;www.duckduckgo.com.&lt;/a&gt;" If &lt;em&gt;that&lt;/em&gt; server knows the IP address, it will return it, and if not, it will again ask its DNS server if &lt;em&gt;that&lt;/em&gt; server knows the IP address to "&lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt;" and so on... until one of two things happens: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; No one knows the IP address of &lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt; - In this case you will get an error and someone will have to go fix the DNS records for that website. &lt;/li&gt;
&lt;li&gt; Eventually someone will say "Oh, yeah... I know that guy, here's his address" - In this case you will then open a TCP request to the IP address that you just found (there's at least one other full blog post there) and ask the server for a web page.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's basically how DNS works, in a nutshell.  But, but but, I hear you ask... how does the DNS server that finally responds know what the IP address is for "&lt;a href="http://www.duckduckgo.com?" rel="noopener noreferrer"&gt;www.duckduckgo.com?&lt;/a&gt;"  Excellent question.  Basically, the administrator or the devops team, or the developer (now that things are all orchestrated and defined in code) will tell the "authoritative" name server for the domain "Hey, I just setup this server, it's going to host web pages, its name is '&lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt;' and its IP address is '184.72.104.138'."&lt;/p&gt;

&lt;p&gt;You do this in what's called a &lt;a href="https://en.wikipedia.org/wiki/Zone_file" rel="noopener noreferrer"&gt;Zone file&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can play with DNS queries yourself using the &lt;code&gt;dig&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ dig www.duckduckgo.com


; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.4.2-P2 &amp;lt;&amp;lt;&amp;gt;&amp;gt; www.duckduckgo.com
;; global options:  printcmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 57389
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.duckduckgo.com.            IN      A

;; ANSWER SECTION:23.21.193.169
www.duckduckgo.com.     123     IN      CNAME   duckduckgo.com.
duckduckgo.com.         59      IN      A       23.21.193.169
duckduckgo.com.         59      IN      A       107.20.240.232
duckduckgo.com.         59      IN      A       184.72.104.138

;; Query time: 51 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Wed Apr 25 17:41:15 2018
;; MSG SIZE  rcvd: 98
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of that stuff you can ignore for now, the interesting thing is the &lt;code&gt;QUESTION SECTION&lt;/code&gt; which basically just repeats your query back for you, and the &lt;code&gt;ANSWER SECTION&lt;/code&gt; which in this case tells us that "&lt;a href="http://www.duckduckgo.com" rel="noopener noreferrer"&gt;www.duckduckgo.com&lt;/a&gt;" is a &lt;a href="https://en.wikipedia.org/wiki/CNAME_record" rel="noopener noreferrer"&gt;CNAME&lt;/a&gt;(Canonical Name)&lt;br&gt;
 which is kind of like an alias, to "duckduckgo.com" which has 3 IP addresses: 23.21.193.169, 107.20.240.232, and 184.72.104.138.   You should be able to confirm that any of those go to the duckduckgo.com website, by copy-pasting them into your browser (this won't always work because you can have multiple websites running on the same server at the same IP address).  &lt;/p&gt;

&lt;p&gt;That's all I've got to say about that.&lt;br&gt;
Questions, feedback?  Leave a comment! &lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://man.openbsd.org/gethostbyname#DESCRIPTION" rel="noopener noreferrer"&gt;https://man.openbsd.org/gethostbyname#DESCRIPTION&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Hosts_(file)" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Hosts_(file)&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>networking</category>
      <category>beginners</category>
      <category>ops</category>
      <category>dns</category>
    </item>
    <item>
      <title>Scaling your engineering teams</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Tue, 24 Apr 2018 12:23:50 +0000</pubDate>
      <link>https://dev.to/gabeguz/scaling-your-engineering-teams-2b9e</link>
      <guid>https://dev.to/gabeguz/scaling-your-engineering-teams-2b9e</guid>
      <description>

&lt;p&gt;I had the pleasure to work with &lt;a href="https://www.linkedin.com/in/cathy-axais-a955b958/back"&gt;Cathy Axais&lt;/a&gt; when I was a team-lead at Seedbox.  She had the unenviable task of being the sole Quality Assurance resource at the company for a team of 30 developers.  There was no way she would have been able to keep up with the QA load placed on her if she tried to perform the traditional Dev -&amp;gt; QA -&amp;gt; Production cycle; she needed a way to scale.&lt;/p&gt;

&lt;p&gt;What did she do?  She embedded herself with each of the development teams in turn and taught us how to test.   What were her requirements?  Fairly simple -- &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;PRs need to be tested before they go to production&lt;/li&gt;
&lt;li&gt;The developer who wrote the code can't be the developer who tests it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;She spent about 3 weeks with my team, showing us what she looked for when testing a system, how to spot things that were likely to break, and how to get into the "testing mindset."  This wasn't the easiest thing to do, sometimes we (developers) can be grumpy when presented with change, but from my point of view it paid off in spades.  After she finished with us, she went to the next team, and so on until she'd gotten all the developers on board.   I don't have the numbers, but I know the defect rate dropped substantially once we stopped testing our own code, an optimization that I take for granted now, but hadn't really considered before.  &lt;/p&gt;

&lt;p&gt;I haven't found a better way to scale a supporting function to the development process.  Need your application to be secure?  Don't pass it over to a security team, instead get the security team to teach the developers what to look for to spot insecure code, and show them how to fix it.  Want performance?  Don't call in a bunch of performance experts to fix all your performance problems, call in one, and get her to instil the "performance mindset" in your developers.&lt;/p&gt;

&lt;p&gt;This is what full-stack means to me.  You get subject matter experts who can help your teams improve the functions they might not be optimized for.  Every hand off of the code before it reaches production increases the time it takes to get features out the door, especially if there is a path that returns that code to the developer where the process has to start again.  How many of us have worked in environments where getting code to production requires QA sign-off, security review, architecture review, a release manager, a release date, a roll-back plan, and 4 hours of your day (if everything goes well)?  &lt;/p&gt;

&lt;p&gt;Each of those steps presents the possibility that your code might go all the way back to the starting line, possibly days after you last touched it.  &lt;/p&gt;

&lt;p&gt;If you want to move fast, it's important to keep your feedback cycles as short as possible.  Often that means getting developers to do &lt;em&gt;everything&lt;/em&gt;.  Ops, security, performance, QA, deployment, site reliability. None of these things should be outside of the ability of the team.&lt;/p&gt;

&lt;p&gt;I'm not saying you should get rid or your QA team, or your security team, or your SREs, just that you should think of them as subject-matter experts who can educate your developers on best-practices for their area of expertise.   Think of them more as mentors, and tool builders.  For example, Ops can build out infrastructure as code so that the development teams can define their own infrastructure needs independent of the ops team.  We'll always need the ops team for when we hit the limits of our understanding, or for architecture planning assistance, but we should be able to come to them with 80% of the work already done.  &lt;/p&gt;

&lt;p&gt;Passing your code off to another group leads to bottlenecks, and there will always be defects that get through.  I think it's better to find the defects quickly and push fixes just as quickly.  Get the feedback cycle as short as possible and educate your developers in areas where they are weak.&lt;/p&gt;

&lt;p&gt;How do you scale your teams?&lt;/p&gt;


</description>
      <category>workplace</category>
      <category>scaling</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Any plans to create a publish api for dev.to?</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Wed, 11 Apr 2018 22:00:16 +0000</pubDate>
      <link>https://dev.to/gabeguz/any-plans-to-create-a-publish-api-for-devto-3cnk</link>
      <guid>https://dev.to/gabeguz/any-plans-to-create-a-publish-api-for-devto-3cnk</guid>
      <description>&lt;p&gt;Anyone else think it would be very useful to be able to push content to dev.to via an API?  Does one already exist, I couldn't find one.  &lt;/p&gt;

</description>
      <category>discuss</category>
      <category>meta</category>
    </item>
    <item>
      <title>What's your favorite way to version an API?</title>
      <dc:creator>Gabriel Guzman</dc:creator>
      <pubDate>Mon, 12 Mar 2018 17:58:42 +0000</pubDate>
      <link>https://dev.to/gabeguz/whats-your-favorite-way-to-version-an-api--4591</link>
      <guid>https://dev.to/gabeguz/whats-your-favorite-way-to-version-an-api--4591</guid>
      <description></description>
      <category>discuss</category>
    </item>
  </channel>
</rss>
