<?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: Kyle Buzby</title>
    <description>The latest articles on DEV Community by Kyle Buzby (@kbuzby).</description>
    <link>https://dev.to/kbuzby</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%2F548362%2Fa6494ac2-a558-43e0-b41a-75143a4cb70f.jpg</url>
      <title>DEV Community: Kyle Buzby</title>
      <link>https://dev.to/kbuzby</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kbuzby"/>
    <language>en</language>
    <item>
      <title>2022 Year in Review</title>
      <dc:creator>Kyle Buzby</dc:creator>
      <pubDate>Sat, 24 Dec 2022 01:34:34 +0000</pubDate>
      <link>https://dev.to/kbuzby/2022-year-in-review-97g</link>
      <guid>https://dev.to/kbuzby/2022-year-in-review-97g</guid>
      <description>&lt;h2&gt;
  
  
  Reflecting
&lt;/h2&gt;

&lt;p&gt;The last time I wrote something looking at what I’ve done and what I plan to do as I go forward was in March of 2021. At that time I was 3 months into a new position, and more specifically just started as a new team lead. I was working with some peers and in a team of 5 including myself, and with such a small team I was still doing 50-75% coding and learning a lot about our products.&lt;/p&gt;

&lt;p&gt;I entered into this new company and position with the mentality that I was going to succeed by asking questions, whether that's to fully understand what I’m working on or a question to advocate for change in the company or even just for myself. In other words, don’t let things just be told to me or just happen to me. I am happy to look back and recognize that I continued to hold this mentality to the current day and that it has continued to benefit me. I also recognize that it requires a ton of psychological safety and a healthy environment to take those risks, and I’m super lucky to have that where I work now.&lt;/p&gt;

&lt;p&gt;Among the things I advocated for, one that I’m particularly proud of is when I pitched a new role in our development group to focus purely on internal tools and infrastructure so that we can help keep things running smoothly on the inside. Both my VP of Engineering (now CTO) and CTO at the time gave me their support to post the position, and we had a perfect candidate apply within just a few weeks. Since then he has proven countless times the amount of value this position provides to our development group by introducing new automated integration testing, troubleshooting and improving the reliability of our build servers, and even overhauling a lot of our onboarding documentation.&lt;/p&gt;

&lt;p&gt;A little before that my team had suddenly grown from 5 to 9 within the span of a few short weeks. At that point, I was no longer able to code not only due to the number of people, but the scope of my team was continuing to expand. I honestly didn’t have much time to even consider it, but reflecting on that time I was nervous about stepping away from daily coding. I still have this concern sometimes, but I’m also getting more confident in my skills as a leader and manager.&lt;/p&gt;

&lt;p&gt;As I’ve already said before, I’m thankful to be in a supportive company, but it has also shown in that I think all of the things I’ve recognized in myself over the last year and a half, have also been recognized by the folks that I work with. One thing I had identified early on was that we have tech stack-centered teams (e.g. an API team, a UI team, and basically an “everything else” team), and as we grow it was showing that it was not an efficient structure to deliver on real features. A little bit ago my CTO approached me and said he thought it was time to make that kind of change, and that he wanted me to lead the restructured team. He totally acknowledged that I don’t have the track record to prove that I have done that job already, but that he believed that I could do it. That confidence and chance taken on me is an incredible feeling, and I’m very excited to start the new year as a Director of Engineering leading a development group that is more than double the size of the team I led the last year and a half.&lt;/p&gt;

&lt;p&gt;This has been a very career-focused year for me, and I am ok with that, but I also recognize that I need to improve on making my life more balanced with personal enriching activities. Despite that, this year did have a lot of great things too. I found a new outdoor hobby in paddle boarding! Despite Wisconsin having basically 6 months of winter, the other 6 months are pretty great for outdoors and there are tons of lakes in the area. Finding a way to get on the water has been an enjoyable way to enjoy the outdoors in the midwest.&lt;/p&gt;

&lt;p&gt;By far, the best personal life event from the past year has been developing a new friendship that has given me a new best friend. Not only has it been great to have another person so close in my life, but our friendship has been able to develop into a (growing) chosen family.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking ahead
&lt;/h2&gt;

&lt;p&gt;I’m really excited to see what comes this year, both at work and personally. Obviously, at work, I have a huge amount of growth ahead of me as I learn how to lead managers instead of a direct team and lead a larger scope. But even within that, I have a couple of major goals and a few more general ones.&lt;br&gt;
The biggest thing I want to see with this new team is that it gives the developers on the team more ownership and accountability for the actual product that we ship as a company. I plan to make sure that they are involved in refining requirements, which will require a greater product understanding and expertise. We’ll also be able to have more ownership and focus on getting feedback from our stakeholders throughout the project. I’ve loved doing this as a developer in the past (even if not in the moment), and I hope that it helps bring the developers on our teams closer to the people that they are solving problems for. In addition to the individual developers, I hope that I can work with the leads, several of which are leading a small team for the first time, in order to help them feel comfortable leading and able to feel an even greater sense of ownership for the areas their teams cover.&lt;/p&gt;

&lt;p&gt;Among all the things required for me to learn how to manage with a layer of indirection, I’m nervous but also excited to learn how to lead a team where I no longer know how the majority of the code works at a low level. I’ve preached since day one of being a team lead that leads should not be expected to know everything about the code in their area, and it's often a mistake to try and do so, but I still found myself trying to do this in the past year and a half - however, with 200% or more code that falls into my scope, it is unreasonable for me to think I can do this at all at this point.&lt;/p&gt;

&lt;p&gt;There are tons of little goals that I have for work this coming year, but most importantly in the coming year, I want to really focus on continuing to make time for non-work related interests. Reflecting and remembering the interest I developed in paddle boarding this past year has me excited to continue that activity as soon as the weather allows. Until that happens, I hope to get into a routine with yoga again in the coming year - since the pandemic started I’ve had routines continue to get messed up as we would go in and out of quarantine, but now that things are more “stable” I want to get back into it. That being said I’m nervous about trying to establish a new routine right at the start of the year when I know I’m also going to be getting major surgery right away in March that will inevitably reset that routine all over again.&lt;/p&gt;

&lt;p&gt;I’ll close this out with a cliché that I hope to continue writing more. In the past, I wanted to write because I thought it was just a good idea, and potentially wanted some attention, but now I would like to get more practice writing to improve my effectiveness as a communicator so that I can harness my influence as a leader in my new role.&lt;/p&gt;

</description>
      <category>yearinreview</category>
      <category>goals</category>
    </item>
    <item>
      <title>Setting up a wildcard SSL with Let's Encrypt and Nginx</title>
      <dc:creator>Kyle Buzby</dc:creator>
      <pubDate>Sat, 29 May 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/kbuzby/setting-up-a-wildcard-ssl-with-let-s-encrypt-and-nginx-383c</link>
      <guid>https://dev.to/kbuzby/setting-up-a-wildcard-ssl-with-let-s-encrypt-and-nginx-383c</guid>
      <description>&lt;p&gt;Let's Encrypt has been a fantastic resource for any independent developer trying to stand up&lt;br&gt;
a website on their own with the smallest amount of hassle. Some years ago SSL wasn't the default&lt;br&gt;
choice and the process was expensive, tricky, and generally reserved for the companies who could&lt;br&gt;
devote time and resources to actually figuring it out. Let's Encrypt along with its CLI tool,&lt;br&gt;
&lt;code&gt;certbot&lt;/code&gt; allow for the simple method of obtaining and retrieving a SSL site for your website.&lt;/p&gt;

&lt;p&gt;The default instructions are aimed at setting up SSL for specific sites that you manage. However,&lt;br&gt;
if you have multiple sites all under the same domain, and running on or proxied through the same &lt;br&gt;
server, it can save a lot of time to have a wildcard certificate. This means that the SSL cert will&lt;br&gt;
apply to any subdomain of your overall domain without having to update the certificate. &lt;/p&gt;

&lt;p&gt;Unfortunately, &lt;code&gt;certbot&lt;/code&gt; is unable to handle automagically configuring your webserver to apply &lt;br&gt;
the certificates because you have to prove you have ownership of the domain through some DNS &lt;br&gt;
challenge entries. Since domains are managed in a number of ways and require an additional layer&lt;br&gt;
of authentication it's a manual process to update these certificates, which has to be done every &lt;br&gt;
90 days.&lt;/p&gt;
&lt;h2&gt;
  
  
  Generating Certificates
&lt;/h2&gt;

&lt;p&gt;The first step to setting up wildcard certs is installing &lt;code&gt;certbot&lt;/code&gt;.&lt;br&gt;
This can be done be following the instructions on &lt;a href="https://certbot.eff.org/lets-encrypt/"&gt;&lt;code&gt;certbot&lt;/code&gt;'s site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The software choice does not really matter because we'll be using a manual challenge method as opposed to&lt;br&gt;
the automatic methods that can be used with those specific web server options.&lt;/p&gt;

&lt;p&gt;Once &lt;code&gt;certbot&lt;/code&gt; is installed the method of generating certs is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo certbot certonly --manual --preferred-challenges=dns --server https://acme-v02.api.letsencrypt.org/directory -d \*.buzby.dev -d buzby.dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For your own server, you'll want to replace the &lt;code&gt;*.buzby.dev&lt;/code&gt; and &lt;code&gt;buzby.dev&lt;/code&gt; with your own domain.&lt;/p&gt;

&lt;p&gt;During this process &lt;code&gt;certbot&lt;/code&gt; will pause to allow you to add TXT records to your domain with a specified key.&lt;br&gt;
There will be two - one for each of the domain options specified. One thing to note is that the name of the &lt;br&gt;
TXT records will be your domain in both cases. This is ok because DNS allows you to configure multiple records &lt;br&gt;
with the same name by design.&lt;/p&gt;

&lt;p&gt;Ensuring these have a short TTL (time-to-live) will help to make sure they get created / updated quickly&lt;br&gt;
for the &lt;code&gt;certbot&lt;/code&gt; authorization process.&lt;/p&gt;

&lt;p&gt;Once this process is complete there will be new certificate files located in&lt;br&gt;
&lt;code&gt;/etc/letsencrypt/live/&amp;lt;your domain&amp;gt;/&lt;/code&gt; ready to use!&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuring Web Server
&lt;/h2&gt;

&lt;p&gt;Now, since we had to run &lt;code&gt;certbot&lt;/code&gt; in a manual process we have to configure the web server.&lt;br&gt;
Nginx is one of the most popular, and one that I've been using for the last few years.&lt;/p&gt;

&lt;p&gt;For your &lt;code&gt;server&lt;/code&gt; blocks in Nginx sites you'll need four new fields to configure the site&lt;br&gt;
with SSL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {

        listen 443 ssl; # Make sure the 'ssl' is added here as well

        ssl_certificate /etc/letsencrypt/live/buzby.dev/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/buzby.dev/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        ...

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

&lt;/div&gt;



&lt;p&gt;(again replacing &lt;code&gt;buzby.dev&lt;/code&gt; with your own domain)&lt;/p&gt;

&lt;p&gt;If you additionally want to force redirect the server's HTTP port 80 traffic you can configure&lt;br&gt;
a second server to redirect to the HTTPS server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
        listen 80;

        server_name kyle.buzby.dev;

        if ($host = kyle.buzby.dev) {
                return 301 https://$host$request_uri;
        }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now all the configuration is set - restart the server and you'll have a wildcard SSL certificate&lt;br&gt;
active on your server!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo service nginx restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tutorial</category>
      <category>https</category>
      <category>webdev</category>
      <category>ssl</category>
    </item>
    <item>
      <title>Compiling Rust programs for Synology DS418j</title>
      <dc:creator>Kyle Buzby</dc:creator>
      <pubDate>Tue, 20 Apr 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/kbuzby/compiling-rust-programs-for-synology-ds418j-gb7</link>
      <guid>https://dev.to/kbuzby/compiling-rust-programs-for-synology-ds418j-gb7</guid>
      <description>&lt;p&gt;Rust is a great tool because it allows compiling native code.&lt;br&gt;
This means you do not need to have a runtime installed on a target machine,&lt;br&gt;
but it does mean that you need to compile the program targeted for the hardware&lt;br&gt;
you expect it to run on ahead of time.&lt;br&gt;
Given the strength of not needing a runtime, I wanted to use&lt;br&gt;
Rust to compile some small executables for my Synology DS418j.&lt;/p&gt;
&lt;h2&gt;
  
  
  Determining the Target
&lt;/h2&gt;

&lt;p&gt;Rust has a good set of tools already to cross compile programs for a number of platforms.&lt;br&gt;
Assuming that you use &lt;code&gt;rustup&lt;/code&gt; command (which is the recommended way), the default target&lt;br&gt;
installed when you install Rust is the one that matches your platform. You can see a list&lt;br&gt;
of already built targets by running &lt;code&gt;rustup target list&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first step towards figuring out what I needed to target was determining the architecture that my NAS is running. I have the DS418j, which I know&lt;br&gt;
is one that doesn't have one of the fancy Intel processors, and is likely a cheaper ARM processor.&lt;br&gt;
After ssh'ing into the machine I was able to get this info by running &lt;code&gt;uname -a&lt;/code&gt; on the NAS to get the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Linux potabo 4.4.59+ #25556 SMP Thu Mar 4 17:52:53 CST 2021 aarch64 GNU/Linux synology_rtd1296_ds418j
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The notable piece of information for me was the &lt;code&gt;aarch64&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Looking at the list of targets available from &lt;code&gt;rustup&lt;/code&gt;, the one&lt;br&gt;
that most closely matches is &lt;code&gt;aarch64-unknown-linux-gnu&lt;/code&gt;.&lt;br&gt;
The breakdown of these targets is &lt;code&gt;&amp;lt;architecture&amp;gt;-&amp;lt;vendor&amp;gt;-&amp;lt;system&amp;gt;-&amp;lt;abi&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Compiling a Project
&lt;/h2&gt;

&lt;p&gt;If you don't already have a project to compile then running &lt;code&gt;cargo new &amp;lt;executable name&amp;gt;&lt;/code&gt; will scaffold out the folder for you.&lt;/p&gt;
&lt;h3&gt;
  
  
  Installing toolchain dependencies
&lt;/h3&gt;

&lt;p&gt;We need to install some dependencies first in order to compile.&lt;/p&gt;

&lt;p&gt;First, we need to get the base rust crates to compile our project against. This is done with &lt;code&gt;rustup&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rustup target add aarch64-unknown-linux-gnu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This installs the crates into your dev environment allowing you to use this as a target across any project.&lt;/p&gt;

&lt;p&gt;Second, we'll need to install the &lt;code&gt;gcc&lt;/code&gt; tools to be able to have a linker that will link our binaries to the ones we expect to be on the target system. The real simple way to do this is installing all gcc-aarch64 tools with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt-get install gcc-aarch64*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the environment is all prepped.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring the project
&lt;/h3&gt;

&lt;p&gt;The Rust project still needs a bit more information in order to find the right linker to use for the given target.&lt;br&gt;
This is done through a cargo config file.&lt;br&gt;
From the root of the Rust project you can create a &lt;code&gt;.cargo&lt;/code&gt; folder, and a &lt;code&gt;config&lt;/code&gt; file within it.&lt;/p&gt;

&lt;p&gt;In the config file the following block needs to be added to tell cargo to use the specified linker when compiling for the given target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compiling!
&lt;/h3&gt;

&lt;p&gt;Finally, the project is ready to compile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cargo build --target=aarch64-unknown-linux-gnu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After building you can copy the created binary from the &lt;code&gt;target/aarch64-unknown-linux-gnu/debug&lt;/code&gt; folder to the target machine and run it to verify it works!&lt;/p&gt;

</description>
      <category>synology</category>
      <category>rust</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Reflecting and looking forward</title>
      <dc:creator>Kyle Buzby</dc:creator>
      <pubDate>Sat, 27 Mar 2021 18:59:29 +0000</pubDate>
      <link>https://dev.to/kbuzby/reflecting-and-looking-forward-21p7</link>
      <guid>https://dev.to/kbuzby/reflecting-and-looking-forward-21p7</guid>
      <description>&lt;p&gt;2020 was a year of significant growth for me - I had started with a set of goals, some quite lofty, and some that I could just not prioritize at this time. Ultimately, I feel like I ended in a place where I was more confident in myself and put myself into a place that has given me a chance to sky rocket my growth at the start of this year.&lt;/p&gt;

&lt;h2&gt;
  
  
  2020
&lt;/h2&gt;

&lt;p&gt;At the start of last year I was working at Epic Systems, 6 months into my official role as a "Software Developer". I worked incredibly hard while working to get the experience and qualifications necessary to reach that level, with the support of my partner and my team lead at the time.&lt;/p&gt;

&lt;p&gt;My work leading up to that transfer led me to be trusted with some deep technical projects on our team, and previous experience as a Software Test Engineer put me in a strong position to help out with performance. The projects were hard, but not just technically or in terms of functionally, but in terms of timelines imposed by project leads and expectations. This wasn't just my team but across the company - it also didn't feel like it was out of the norm.&lt;/p&gt;

&lt;p&gt;On top of this since I was new to the role I felt like I was constantly fighting to "prove" myself. I was told that I shouldn't, but my base personality just can't help but feel competitive and making sure that I'm doing "good enough". This was compounded by the fact that I was only paid at the starting salary of a new developer (who are commonly hired directly out of college). My team leads tried to assure me I had to "room to grow" and I had nothing to prove, as I was already a high performer - but why wasn't I paid like one?&lt;/p&gt;

&lt;p&gt;Ultimately, I did not feel this was right and found a new job by the end of the year. I was extremely down by no longer feeling supported where I previously was, and had wanted to give so much time back to.&lt;/p&gt;

&lt;p&gt;Despite ending on a bitter note I was extremely proud of where I was. I learned how to value myself, the value of my time, and am starting to value my knowledge beyond the level of a "new developer". I had experiences with team leads who were actually not as supportive as the ones I've had in the past, and taught me how to ask more for what I need for guidance in order to grow.&lt;/p&gt;

&lt;h2&gt;
  
  
  2021
&lt;/h2&gt;

&lt;p&gt;At the start of 2021, I begin the first workday at a new company, one much much smaller than I had spent the last 5 years in. It was refreshing. The proceses are flexible, the culture is more relaxed, people have more ownership. It took me no time to get up to speed on the technologies that I was not familiar with (largely Docker), and I was quickly able to contribute - the best part was that I felt like I was doing a &lt;em&gt;normal&lt;/em&gt; amount of work, but it was called out as pleasant surprise. I now &lt;em&gt;knew&lt;/em&gt; I was not as junior as I was made to feel at Epic.&lt;/p&gt;

&lt;p&gt;I asked a ton of questions in my first few weeks. I wanted to know the company, why things were the way they are, and to see what can change and be made better. Despite ending a bit bitter, I learned a lot at Epic, and I feel motivated to carry some of those ideals forward, or to learn and do the things I didn't like better. I believe this has helped me to stand out among my peers. I'm used to listening more than asking questions, but I feel like I have a stronger foundation to justify the questions I'm now asking... and it's &lt;em&gt;empowering&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Several weeks into the job, I asked about the potential move to being a team lead within a time frame and when everyone felt I was up to speed enough of the base workings. Our team was technically very large, too large for our current team lead to manage effectively. To my surprise this opportunity presented itself sooner than I ever expected, and now I'm currently acting as lead for my team, which is a truly exciting place to be in. I get to work on code frequently, but I now can help drive a product forward more actively, and work to give my team the best environment to grow how they need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking forward
&lt;/h2&gt;

&lt;p&gt;Having reached my goal from the previous year of being a team lead, but doing it a new company, I have a whole new set of things to work. This isn't the end of writing code for me - being on a small team I will still frequently get to excercise those bits of my job, and hope to continue to grow technically and to carry forward my previous experience to be a resource for my team and company as a technical leader. &lt;/p&gt;

&lt;p&gt;But now with my new responsibilities, I hope to learn how to guide and mentor younger developers, and support and help more senior developers still get what they need out of their work. I hope to grow my skills in project planning and estimation and help increase the output by my team, &lt;em&gt;without putting them through death marches&lt;/em&gt;. I truly want my team to be healthy, and strong, and enjoy what they do. I know I'm likely being a wide-eyed naive baby team lead, and I'm going to make mistakes, but that's ok. &lt;/p&gt;

&lt;p&gt;Most of all I don't want to lose the curiosity I've grown from being a devloper, in fact, I hope to continue become even more curious about what I can do next.&lt;/p&gt;

</description>
      <category>personal</category>
      <category>goals</category>
    </item>
    <item>
      <title>Setting up GitHub as Mirror</title>
      <dc:creator>Kyle Buzby</dc:creator>
      <pubDate>Mon, 28 Dec 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/kbuzby/setting-up-github-as-mirror-19i6</link>
      <guid>https://dev.to/kbuzby/setting-up-github-as-mirror-19i6</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;A common interest of mine is to own as much of my own data as possible, which largely means hosting a lot of the services that we all know and love. This one is about git, or simply put, source control for my personal projects.&lt;br&gt;
Source code is something I have less of any issue being in the public domain or on someone else's server (definitely not against open source), but over the years I've seen my GitHub profile become inundated with these small side project repos that are never touched after a few commits. So in order to keep that a little more groomed I've maintained my own git repo on my local Synology NAS device.&lt;/p&gt;

&lt;p&gt;All that being said there is only so much you can do with git on a local NAS, and if you want to do more like CI/CD you'll be rolling your own or setting up a bunch more services.&lt;br&gt;
One feature I wanted was automated deploys of &lt;a href="https://kyle.buzby.dev"&gt;my website&lt;/a&gt; - I had some simple bash scripts running for a while and even involved a second server, but it was more than I wanted to maintain and became clunky after I started letting the second server sleep. What I really wanted was something like GitHub actions&lt;/p&gt;

&lt;p&gt;Enter mirroring. &lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up GitHub to mirror
&lt;/h2&gt;

&lt;p&gt;The first step to setting up a GitHub mirror is to create your repo normally, but make sure to leave it empty / bare, otherwise you'll have to be a little &lt;code&gt;--force&lt;/code&gt;ful to make things work.&lt;/p&gt;

&lt;p&gt;A simple option would be to set a second remote in your working copy in order to commit there as well, but that would involve remembering to set it up each time you (or someone else) checks out the repo as well as intentionally add commits there. &lt;br&gt;
This is a sure-fire way to make sure the mirror gets out of sync.&lt;/p&gt;

&lt;p&gt;So, we'll want to have the private remote repo commit directly to the mirror. On the private remote repo add the GitHub repo as a remote using the same command as you would in a working copy where &lt;code&gt;github-mirror&lt;/code&gt; is the name I chose to represent that remote URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add remote github-mirror &amp;lt;github git URL&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Mirroring your commits
&lt;/h2&gt;

&lt;p&gt;Traditionally mirroring is a full clone of a repository - including all branches, tags, etc. This is done with the &lt;code&gt;--mirror&lt;/code&gt; option when performing a clone / push. This flag creates / updates a cloned repository to be a "mirror" of the remote as opposed to a standard "working copy". GitHub has &lt;a href="https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/finding-ways-to-contribute-to-open-source-on-github#open-source-projects-with-mirrors-on-github"&gt;some official mirrors&lt;/a&gt;, but there is no built in support to handle this for you.&lt;/p&gt;

&lt;p&gt;If you want GitHub to be a full mirror then you can simply use the &lt;code&gt;--mirror&lt;/code&gt; flag in a push command such as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;--mirror&lt;/span&gt; github-mirror
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will push &lt;em&gt;all&lt;/em&gt; branches from your remote repo to the mirror, so if you're like me and want to restrict this to only the main branch then you can push specific refs.&lt;/p&gt;

&lt;p&gt;The command to push commits from only one branch on a remote to another branch on a second remote is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push github-mirror main:refs/heads/main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dissecting this command we have the first two pieces, &lt;code&gt;git push&lt;/code&gt;, which is the standard command for pushing commits to a remote.&lt;/p&gt;

&lt;p&gt;The third piece is &lt;code&gt;github-mirror&lt;/code&gt; which is the name of the remote created above. This can also directly be a URL if you do not have a remote set up. &lt;/p&gt;

&lt;p&gt;The fourth piece, &lt;code&gt;main:refs/heads/main&lt;/code&gt;, is actually two in one, separated by the colon.&lt;br&gt;
The first half is the name of the local branch we are pushing commits from - or in git terms, the "source".&lt;br&gt;
The second piece is the destination, if it's omitted then git will try to use a branch of the same name. If one doesn't exist then it will be created. &lt;br&gt;
Specifying the &lt;code&gt;refs/*&lt;/code&gt; starting piece means that we are specifically trying to send a specific type of object to a specific location in the remote, expanding it to &lt;code&gt;refs/heads/*&lt;/code&gt; means that we want to only send commit objects, which is applicable here since this is simple a mirror to take advantage of GitHub actions.&lt;br&gt;
Finally the full &lt;code&gt;refs/heads/main&lt;/code&gt; is specifying the precise location to update from our local main.&lt;/p&gt;

&lt;p&gt;If you specify a destination, but not its namespace and git will try to to find the best location - most likely under &lt;code&gt;refs/heads&lt;/code&gt;, but specificity is probably good in this case since we're moving in an direction where we automatically mirror.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: this will only push commits from a single branch - if you want tags as well, then you should use the &lt;code&gt;--tags&lt;/code&gt; option to push all tags from your local tags to the remote.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;As with most git commands there are a number of other flags / options / flavors of arguments that you can pass to &lt;code&gt;git push&lt;/code&gt;. If this doesn't cover what you need exactly - then definitely check out &lt;a href="https://www.git-scm.com/docs/git-push"&gt;the documentation &lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Automating commits to mirror
&lt;/h2&gt;

&lt;p&gt;Now, that we have a command to run, we can automate updating the mirror when pushing to the private repo.&lt;/p&gt;

&lt;p&gt;The first step will be to make sure you have &lt;a href="https://docs.github.com/en/github-ae@latest/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account"&gt;SSH keys set up for GitHub repo&lt;/a&gt; from your remote server so you can push without interactive authentication.&lt;/p&gt;

&lt;p&gt;Second we'll make use of server-side &lt;a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks"&gt;git hooks&lt;/a&gt; in order to execute this when a new commit is received - specifically the &lt;code&gt;post-receive-hook&lt;/code&gt;, which will run once the commits have been successfully received.&lt;br&gt;
Without going into too much detail, a hook is essentially a named script that is placed in the &lt;code&gt;.git/hooks&lt;/code&gt; directory of your repo and executed at the defined time.&lt;br&gt;
There are examples of all these hooks in git repos - removing the &lt;code&gt;.example&lt;/code&gt; suffix will allow git to execute them.&lt;/p&gt;

&lt;p&gt;Now we're ready to create a shell script to run and execute our push to the &lt;code&gt;github-mirror&lt;/code&gt;. For my purposes, since I'm only pushing one branch - I only want to push to the mirror when commits on that same branch are received. This done with the arguments that are passed to the script when executed by git.&lt;br&gt;
In order these arguments are &lt;code&gt;oldRevision&lt;/code&gt;, &lt;code&gt;newRevision&lt;/code&gt;, and &lt;code&gt;ref&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, with that knowledge and the example script already provided we can make a post-receive script that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;oldrev newrev ref
&lt;span class="k"&gt;do
if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ .&lt;span class="k"&gt;*&lt;/span&gt;/main&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;# when committing to main branch&lt;/span&gt;
    &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Main ref received. Mirroring to GitHub"&lt;/span&gt;
        git push github-mirror main:refs/heads/main
    &lt;span class="k"&gt;else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Ref &lt;/span&gt;&lt;span class="nv"&gt;$ref&lt;/span&gt;&lt;span class="s2"&gt; successfully received. Doing nothing: only the main branch may be deployed on this server."&lt;/span&gt;
&lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: it's a good idea to echo a response - the output of this script and anything it runs will be output to your local terminal when pushing to the private repo and will let you know the hook is running.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Saving that file and making sure it's named &lt;code&gt;post-receive&lt;/code&gt; is then all you need to do to have this start running on every commit to your private repo!&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Synology CardDAV Setup</title>
      <dc:creator>Kyle Buzby</dc:creator>
      <pubDate>Sun, 20 Dec 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/kbuzby/synology-carddav-setup-2jio</link>
      <guid>https://dev.to/kbuzby/synology-carddav-setup-2jio</guid>
      <description>&lt;h2&gt;
  
  
  What is CardDAV
&lt;/h2&gt;

&lt;p&gt;CardDAV is a simple protocol that operates over HTTP/HTTPS - in fact, it's built on top of the generic WebDAV protocol that is itself built on HTTP/HTTPS.&lt;br&gt;&lt;br&gt;
It allows you to have a web server implementing the protocol to provide vCard contact info a standardized format. Having a centralized server of course means that you can sync that data elsewhere.&lt;br&gt;
The standard was first proposed and made popular by Apple with iOS7, from there it was adopted or supported by more services making it a fairly ubiquitous service.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why do this?
&lt;/h2&gt;

&lt;p&gt;I personally have a desire to own as much of my own data as possible, sometimes that's not easy (like running an email server), but this seemed relatively doable due to pre-built support and the network infrastructure I already have set up.&lt;/p&gt;

&lt;p&gt;If I wanted to avoid going through the trouble of running my own server I could make use of the fact that Apple's contact management is already built on CardDAV and could sync my contacts through that account.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up CardDAV on Synology Server
&lt;/h2&gt;

&lt;p&gt;Synology has a great package ecosystem for their devices, so this step was extremely simple - just open the package manager on the device and install the CardDAV Server package.&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding HTTPS by default
&lt;/h2&gt;

&lt;p&gt;I have a .dev domain so everything must use HTTPS since that is a requirement set by Google as owner of the TLD, so updating this was as simple as checking the box in the Synology config to redirect all HTTP traffic to the HTTPS port.&lt;/p&gt;
&lt;h2&gt;
  
  
  Updating proxy config
&lt;/h2&gt;

&lt;p&gt;My home network and all the services running on it are set up on my .dev domain. &lt;br&gt;
Now isn't the time for details, but the gist is that I have a nginx web server sitting in front of all my services in order to access things by a clean URI (no ports). This also allows me to keep my SSL setup on one machine.&lt;/p&gt;

&lt;p&gt;Since the CardDAV server is running on its own port on the Synology that will require setting it up as its own virtual host - paths are technically possible, but far too often services don't handle rewritten URL paths and won't function properly.&lt;/p&gt;

&lt;p&gt;Adding the following (and replacing things in angle brackets with real endpoints) as a new enabled host, and restarting the server does the trick:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Handle redirects to HTTPS coming through the web server
# Synology would also do this, but better to do it earlier in the stream
server {
        listen 80;
        listen [::]:80;

        server_name &amp;lt;new server name&amp;gt;;

        if ($host = &amp;lt;new server name&amp;gt;) {
                return 301 https://$host$request_uri;
        }
}

# Set up the proxy virtual host
server {
        listen 443 ssl;
        listen [::]:443 ssl;

        include &amp;lt;path to shared SSL config&amp;gt;;

        server_name &amp;lt;new server name&amp;gt;;

        location / {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_pass https://&amp;lt;IP address of synology&amp;gt;:&amp;lt;HTTPS port of CardDAV server&amp;gt;/;
                proxy_redirect https://&amp;lt;IP address of synology&amp;gt;:&amp;lt;HTTPS port of CardDAV server&amp;gt; https://&amp;lt;new server name&amp;gt;;
        }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last two steps to making this work are to make it accessible by the new host name on my internal network by adding a host record to my pihole (pointing it at the web server), and also a host record to the DNS config of my domain provider. I'm leaving this service open to the internet because the Synology has built in password security around accessing the service, and I want to make sure my contacts will sync up when I'm not on home wifi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syncing to other devices
&lt;/h2&gt;

&lt;p&gt;Now that the server is setup we'll want to make use of it to get the same contact list every where!&lt;/p&gt;

&lt;h3&gt;
  
  
  iPhone
&lt;/h3&gt;

&lt;p&gt;Since Apple's contact management is already built on top of vCards and CardDAV servers, it's a relatively simple process to point your phone to a personal server.&lt;/p&gt;

&lt;p&gt;First step is to add the CardDAV account by going to Settings &amp;gt; Contacts &amp;gt; Add Account. From there you can fill out your server, user name, and password - if not going through standard HTTP/HTTPS ports like configured on the Synology device by default you can configure that under the advanced settings. You don't want to fill out the account URL because that will be populated by querying the server.&lt;/p&gt;

&lt;p&gt;Second, since I've had my phone for a few years all of my contacts were stored locally, so I had to find a way to get them uploaded. To do this I made sure my contacts were synced to my iCloud account - then, once they were all uploaded exported the full list as a csv file. From there I was able to take the csv and upload it directly into the synology interface.&lt;/p&gt;

&lt;p&gt;Next I set the default contact account on my phone as the account added by step 1 - and now everything should be synced through the personal server!&lt;/p&gt;

&lt;h3&gt;
  
  
  Outlook
&lt;/h3&gt;

&lt;p&gt;Outlook was a bit trickier to set up because it does not have built in support for CardDAV (Exchange is the most popularly connected service to outlook which manages contacts through ActiveSync protocols).&lt;br&gt;
That being said, it's easy to get add ins that enabled syncing for CardDAV and CalDAV servers. I personally used &lt;a href="https://www.arpdev.com"&gt;Open Protocols Connector&lt;/a&gt; as that just happened to be what turned up when searching for add-ins. But there are certainly &lt;a href="https://caldavsynchronizer.org"&gt;more out there&lt;/a&gt;.&lt;br&gt;
The Open Protocols Connector allows free use, but the product still requires registration by getting a registration code from the site.&lt;/p&gt;

&lt;p&gt;The add in adds a Server ribbon tab to the workspace, which has the 'Connection' button to configure server info.&lt;/p&gt;

&lt;p&gt;I was unfortunately not able to directly set up the server as simply as the iPhone because it was not recognizing the root server as a CardDAV resource.&lt;br&gt;
It turns out it wasn't asking for the generic server as the iPhone does in order to query for the account URL - it needs the actual account URL directly.&lt;br&gt;
Since i had the iPhone setup already done, I was able to pull the account URL from those settings and copy that over the computer in order to get things synced up.&lt;/p&gt;

&lt;p&gt;After getting that last piece setup, I saw my contacts start to flow in, and then tested creating a new one to make sure it was working in both directions. Voila! Shared contacts between my two primary locations for sending / receiving email!&lt;/p&gt;

</description>
      <category>synology</category>
      <category>carddav</category>
    </item>
  </channel>
</rss>
