<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on the crosseroads</title>
    <link>https://www.thecrosseroads.net/post/</link>
    <description>Recent content in Posts on the crosseroads</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 30 Jun 2022 00:00:00 +0000</lastBuildDate><atom:link href="https://www.thecrosseroads.net/post/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Creating a Two-Tier CA using Yubikeys</title>
      <link>https://www.thecrosseroads.net/2022/06/creating-a-two-tier-ca-using-yubikeys/</link>
      <pubDate>Thu, 30 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://www.thecrosseroads.net/2022/06/creating-a-two-tier-ca-using-yubikeys/</guid>
      <description>&lt;p&gt;So you have more Yubikeys than sense? Great, me too! Let&amp;rsquo;s make a multi-tier certificate authority!&lt;/p&gt;
&lt;p&gt;By the end of this article, we&amp;rsquo;ll have a fully-functioning two-tier CA where the private keys for
the CAs are stored on Yubikeys. In addition, we&amp;rsquo;ll make sure that we generate the private keys
directly on the Yubikeys for zero chance of key compromise. All keys will be elliptic-curve (ECC),
and&amp;ndash;barring mistakes on my part&amp;ndash;the CA should fully adhere to &lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc5759&#34;&gt;RFC 5759&lt;/a&gt;, NSA&amp;rsquo;s &lt;em&gt;Suite B
Certificate and Certificate Revocation List (CRL) Profile&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&#34;butwhygif&#34;&gt;ButWhy.gif&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;For small- or low-&amp;ldquo;traffic&amp;rdquo; CAs, two &lt;a href=&#34;https://www.yubico.com/product/yubikey-5-nfc/&#34;&gt;Yubikeys&lt;/a&gt; at a cost of $45 each could be much more
feasible than two &lt;a href=&#34;https://www.yubico.com/product/yubihsm-2/&#34;&gt;YubiHSM 2&lt;/a&gt; devices at $650 each, or two &lt;a href=&#34;https://shop.nitrokey.com/shop/product/nkhs2-nitrokey-hsm-2-7&#34;&gt;Nitrokey HSM&lt;/a&gt; for
€99 each.&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;ve read other articles about using a single Yubikey as a root CA, but all of them seem to want
to generate the private key using OpenSSL and then import it to the Yubikey. Because of this, they
usually come with dire warnings about ensuring you generate the keys using a LiveCD distribution
of Linux, etc., etc. By generating the key directly on the Yubikey, you can do all this in an OS
environment you&amp;rsquo;re comfortable with and eschew all the LiveCD contortions, plus have confidence
that they private keys cannot accidentally leak at any time.&lt;/li&gt;
&lt;li&gt;I wanted the challenge!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: I am not a security engineer. If someone who &lt;em&gt;is&lt;/em&gt; a security engineer says this is not a smart
idea for your use case, then please listen to them, not me. ;-) My ultimate goal with this was to
use it to secure a handful of home-lab servers and have fun doing it.&lt;/p&gt;
&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;I probably shouldn&amp;rsquo;t have to say this, but following these instructions will wipe out whatever you
might have in the PIV slot(s) of your Yubikey(s). Please only follow these instructions on devices
you are okay with overwriting.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m using macOS, but as long as you have the various packages and commands installed, you should be
able to do this on most any platform. (Be aware that I haven&amp;rsquo;t actually tested that statement, but I
believe it to be true!)&lt;/p&gt;
&lt;p&gt;Things you&amp;rsquo;ll need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Two Yubikeys&lt;/li&gt;
&lt;li&gt;OpenSSL&lt;/li&gt;
&lt;li&gt;libp11 (for the pkcs11 OpenSSL engine)&lt;/li&gt;
&lt;li&gt;opensc (for the &lt;code&gt;pkcs11-tool1&lt;/code&gt;  command)&lt;/li&gt;
&lt;li&gt;gnutls (for the &lt;code&gt;p11tool&lt;/code&gt; command)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developers.yubico.com/yubico-piv-tool/&#34;&gt;yubico-piv-tool&lt;/a&gt; and &lt;a href=&#34;https://developers.yubico.com/yubico-piv-tool/YKCS11/&#34;&gt;libykcs11&lt;/a&gt;, which comes with it&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developers.yubico.com/yubikey-manager/&#34;&gt;ykman&lt;/a&gt; (optional)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You&amp;rsquo;ll want to know the location where your package manager installed the &lt;code&gt;libykcs11.{so,dylib,dll}&lt;/code&gt;
shared library. On my macOS laptop, I&amp;rsquo;ve installed the prebuilt package from Yubico and it
installed the file at &lt;code&gt;/usr/local/lib/libykcs11.dylib&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Unless you&amp;rsquo;re using a quite old version of OpenSSL, you should not need the path to the OpenSSL
pkcs11 engine from libp11. You can test to see if you do need it with the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ openssl engine -t pkcs11
(pkcs11) pkcs11 engine
     [ available ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If this command fails, you&amp;rsquo;ll need to tell OpenSSL where the engine is with the &lt;code&gt;dynamic_path&lt;/code&gt;
statement in the OpenSSL config files below.&lt;/p&gt;
&lt;h3 id=&#34;find-your-yubikeys&#34;&gt;Find your Yubikeys&lt;/h3&gt;
&lt;p&gt;All of the commands we use will want to know which &amp;ldquo;slot&amp;rdquo; your Yubikey is in. After plugging one or
more in, find them like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pkcs11-tool --module /usr/local/lib/libykcs11.dylib -T
Available slots:
Slot 0 (0x0): Yubico Yubikey NEO OTP+U2F+CCID
  token label        : YubiKey PIV #0
  token manufacturer : Yubico (www.yubico.com)
  token model        : YubiKey NEO
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 1.0
  firmware version   : 0.13
  serial num         : 0
  pin min/max        : 6/64
Slot 1 (0x1): Yubico YubiKey CCID
  token label        : YubiKey PIV #5212376
  token manufacturer : Yubico (www.yubico.com)
  token model        : YubiKey YK4
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 1.0
  firmware version   : 4.33
  serial num         : 5212376
  pin min/max        : 6/64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For illustration purposes I&amp;rsquo;ve plugged both cards into my machine. I do not recommend keeping both
plugged in when you start on the instructions below&amp;ndash;you &lt;em&gt;will&lt;/em&gt; get mixed up and do something silly
like overwrite the root CA&amp;rsquo;s key with a new key because you thought you specified the intermediate
CA card. (Ask me how I know.)&lt;/p&gt;
&lt;p&gt;For this run-through, we&amp;rsquo;ll use the card shown here in slot 1&amp;ndash;a Yubikey 4&amp;ndash;for the root, and the
card in slot 0&amp;ndash;a Yubikey NEO&amp;ndash;for the intermediate. I chose these particular cards out of my fleet
because I wanted the root CA to have a 384-bit ECC key (secp384r1), which the Yubikey 4 supports.
The intermediate will use a 256-bit key (secp256r1), for no other reason than it is the largest ECC
key the NEO supports.&lt;/p&gt;
&lt;p&gt;To make things easier, I suggest exporting a few environment variables with some relevant
information. I&amp;rsquo;ll use these in the instructions below so that they&amp;rsquo;re easier to read.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ export KEY_SLOT=0
$ export PIN=123456
$ export MGMT_KEY=010203040506070801020304050607080102030405060708
$ export LIBYKCS11=/usr/local/lib/libykcs11.dylib
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(You may be thinking, &amp;ldquo;why are the PIN and management keys the defaults?!?&amp;rdquo; Well, for one it makes
writing these instructions easier; secondly, it means that your super-secret PIN and management keys
are not hanging about in memory. You can either change the PIN, PUK, and management key before
following these instructions and update the environment variables above, or you can use the defaults
and immediately change the values once you&amp;rsquo;re done with everything. Either way, I definitely
recommend changing the values from the defaults as soon as you&amp;rsquo;re able.)&lt;/p&gt;
&lt;p&gt;Okay, so let&amp;rsquo;s test one of the keys:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pkcs11-tool --module &amp;quot;$LIBYKCS11&amp;quot; \
    --login --login-type so         \
    --pin $PIN --so-pin $MGMT_KEY   \
    --slot $KEY_SLOT --id 2         \
    --key-type EC:secp256r1         \
    --test-ec
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This should run a bunch of stuff and report back that everything looks good. If it does, let&amp;rsquo;s move
on! If not, fix those errors before continuing.&lt;/p&gt;
&lt;h3 id=&#34;reset-the-yubikeys&#34;&gt;Reset the Yubikeys&lt;/h3&gt;
&lt;p&gt;This step is optional, but highly encouraged so that you start from a clean slate. You can use the
&lt;code&gt;ykman&lt;/code&gt; command line utility or the Yubikey Manager GUI app to reset the PIV application on both
Yubikeys. With &lt;code&gt;ykman&lt;/code&gt; that will look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ykman piv reset
WARNING! This will delete all stored PIV data and restore factory settings. Proceed? [y/N]: y
Resetting PIV data...
Success! All PIV data have been cleared from the YubiKey.
Your YubiKey now has the default PIN, PUK and Management Key:
        PIN:    123456
        PUK:    12345678
        Management Key: 010203040506070801020304050607080102030405060708
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Note that it will complain and error out if you have more than one Yubikey connected.)&lt;/p&gt;
&lt;h2 id=&#34;create-the-ca-structure-and-the-root-ca&#34;&gt;Create the CA Structure and the Root CA&lt;/h2&gt;
&lt;p&gt;For the OpenSSL part of this guide, I will rely heavily on a series of articles on building an
OpenSSL CA that is compliant with &lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc5759&#34;&gt;RFC 5759&lt;/a&gt;, the NSA&amp;rsquo;s Suite B Certificate and Certificate
Revocation List (CRL) Profile. Those articles, in order, are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://community.f5.com/t5/technical-articles/building-an-openssl-certificate-authority-introduction-and/ta-p/279500&#34;&gt;Building an OpenSSL Certificate Authority - Introduction and Design Considerations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.f5.com/t5/technical-articles/building-an-openssl-certificate-authority-creating-your-root/ta-p/279520&#34;&gt;Building an OpenSSL Certificate Authority - Creating Your Root Certificate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.f5.com/t5/technical-articles/building-an-openssl-certificate-authority-creating-your/ta-p/279497&#34;&gt;Building an OpenSSL Certificate Authority - Creating Your Intermediary Certificate
Authority&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.f5.com/t5/technical-articles/building-an-openssl-certificate-authority-configuring-crl-and/ta-p/279492&#34;&gt;Building an OpenSSL Certificate Authority - Configuring CRL and OCSP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.f5.com/t5/technical-articles/building-an-openssl-certificate-authority-creating-ecc/ta-p/279468&#34;&gt;Building an OpenSSL Certificate Authority - Creating ECC Certificates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I won&amp;rsquo;t be focusing much on the OpenSSL &amp;ldquo;infrastructure&amp;rdquo; side of things&amp;ndash;this guide is about how to
bring the Yubikeys into that process&amp;ndash;so if you have questions or want to know why I make a certain
decision regarding the CA itself, have a look at those articles.&lt;/p&gt;
&lt;p&gt;Since we&amp;rsquo;re creating an OpenSSL CA, we need to create a directory structure for it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cd /somewhere/important
$ mkdir -p ca/{private,certs,crl}
$ cd ca/
$ touch index.txt
$ echo 1000 &amp;gt; serial
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We also need to create some configuration files for OpenSSL. First, create &lt;code&gt;pkcs11.cnf&lt;/code&gt;, which we&amp;rsquo;ll
use to tell OpenSSL where the &lt;code&gt;libykcs11&lt;/code&gt; library is. We will import this into the subsequent config
files so that we don&amp;rsquo;t have to repeat ourselves too much.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;na&#34;&gt;openssl_conf&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;openssl_def&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[openssl_def]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;engines&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;engine_section&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[engine_section]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;pkcs11&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;pkcs11_section&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[pkcs11_section]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;engine_id&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;pkcs11&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;MODULE_PATH&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;/usr/local/lib/libykcs11.dylib&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Second, create &lt;code&gt;openssl_root.cnf&lt;/code&gt;, which will be the config used when creating the root CA:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;na&#34;&gt;.include pkcs11.cnf&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ ca ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_ca&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;CA_default&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ CA_default ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;dir&lt;/span&gt;               &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;certs&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crl_dir&lt;/span&gt;           &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/crl&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;new_certs_dir&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;database&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/index.txt&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;serial&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/serial&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;rand_serial&lt;/span&gt;	  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;RANDFILE&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/private/.rand&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Our private key will reside on a Yubikey.&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#private_key       =&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;certificate&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs/ca.example.crt.pem&lt;/span&gt;

&lt;span class=&#34;na&#34;&gt;crlnumber&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/crlnumber&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crl&lt;/span&gt;               &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/crl/ca.example.crl.pem&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crl_extensions&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;crl_ext&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_crl_days&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;3650&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Set this to match the root CA&amp;#39;s key length.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_md&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;sha384&lt;/span&gt;

&lt;span class=&#34;na&#34;&gt;name_opt&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;ca_default&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;cert_opt&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;ca_default&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_days&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;3650&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;preserve&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;policy&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;policy_strict&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;email_in_dn&lt;/span&gt;	  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ policy_strict ]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# See the &amp;#34;Building a CA&amp;#34; articles above about the implications of these lines.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;countryName&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;match&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;stateOrProvinceName&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;match&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationName&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;match&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationalUnitName&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;optional&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;commonName&lt;/span&gt;              &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;supplied&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;emailAddress&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;optional&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ req ]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# This doesn&amp;#39;t matter to us; we&amp;#39;re using ECC, not RSA.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_bits&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;4096&lt;/span&gt;

&lt;span class=&#34;na&#34;&gt;distinguished_name&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;req_distinguished_name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;string_mask&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;utf8only&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# Set this to match the root CA&amp;#39;s key length.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_md&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;sha384&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Extension to add when the -x509 option is used.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;x509_extensions&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;v3_ca&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ req_distinguished_name ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;countryName&lt;/span&gt;                     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Country Name (2 letter code)&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;stateOrProvinceName&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;State or Province Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;localityName&lt;/span&gt;                    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Locality Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;0.organizationName&lt;/span&gt;              &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Organization Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationalUnitName&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Organizational Unit Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;commonName&lt;/span&gt;                      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Common Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;emailAddress&lt;/span&gt;                    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Email Address&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Update these to suit your environment&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;countryName_default&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;US&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;stateOrProvinceName_default&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;WA&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;localityName_default&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Seattle&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;0.organizationName_default&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Example Enterprises&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationalUnitName_default&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Example Enterprises Root CA&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ v3_ca ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;subjectKeyIdentifier&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;hash&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;authorityKeyIdentifier&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;keyid:always,issuer&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;basicConstraints&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;critical, CA:true, pathlen:1&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;keyUsage&lt;/span&gt;                &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;critical, digitalSignature, cRLSign, keyCertSign&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&#34;create-the-root-ca-key&#34;&gt;Create the Root CA Key&lt;/h3&gt;
&lt;p&gt;Create the Root CA&amp;rsquo;s private key on the Yubikey. This will overwrite any already-existing key in
slot 9c&amp;ndash;that&amp;rsquo;s the &lt;code&gt;--id 2&lt;/code&gt; part of the command&amp;ndash;on the card. (Slot 9c holds certificates used for
digital signatures. Read more about Yubikey certificate slots &lt;a href=&#34;https://developers.yubico.com/PIV/Introduction/Certificate_slots.html&#34;&gt;here&lt;/a&gt;.)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pkcs11-tool --module &amp;quot;$LIBYKCS11&amp;quot; \
    --login --login-type so         \
    --pin $PIN --so-pin $MGMT_KEY   \
    --slot $KEY_SLOT --id 2         \
    --key-type EC:secp384r1         \
    --keypairgen

Key pair generated:
Private Key Object; EC
  label:      Private key for Digital Signature
  ID:         02
  Usage:      decrypt, sign
  Access:     always authenticate, sensitive, always sensitive, never extractable, local
Public Key Object; EC  EC_POINT 384 bits
  EC_POINT:   046104295c28f6bca2b544cb2b858ad4c408562d2cf1b801464e3864107df1361a4d05e96c9e4cf8290ba6bd837862094f448c1caa7185068d01c691eab42a1142747ae43cfb04f1aab687efdac1a8d0b4cb0ab9851e03d91b91c0c71a7d2ecdec2f43
  EC_PARAMS:  06052b81040022
  label:      Public key for Digital Signature
  ID:         02
  Usage:      encrypt, verify
  Access:     local
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After creating the private key, we need to discover its &amp;ldquo;URI&amp;rdquo;&amp;ndash;yes, even private keys on a hardware
authentication device have URIs&amp;ndash;and add it as the &lt;code&gt;private_key&lt;/code&gt; in &lt;code&gt;openssl_root.cnf&lt;/code&gt; (the &lt;code&gt;openssl ca&lt;/code&gt; command will require this later on when we&amp;rsquo;re signing the intermediate certificate). For this
we&amp;rsquo;ll lean on the &lt;code&gt;p11tool&lt;/code&gt; command. What we need to do is tell it to list all private key objects
on the card. We then get to sort through the output until we find the object that corresponds with
the private key we just created. Ready? Me, neither. Let&amp;rsquo;s go!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ p11tool --provider=$LIBYKCS11 --list-keys --login
Token &#39;YubiKey PIV #5212376&#39; with URL &#39;pkcs11:model=YubiKey%20YK4;manufacturer=Yubico%20%28www.yubico.com%29;serial=5212376;token=YubiKey%20PIV%20%235212376&#39; requires user PIN
Enter PIN:
Object 0:
        URL: pkcs11:model=YubiKey%20YK4;manufacturer=Yubico%20%28www.yubico.com%29;serial=5212376;token=YubiKey%20PIV%20%235212376;id=%02;object=Private%20key%20for%20Digital%20Signature;type=private
        Type: Private key (EC/ECDSA)
        Label: Private key for Digital Signature
        Flags: CKA_PRIVATE; CKA_ALWAYS_AUTH; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE;
        ID: 02

Object 1:
        URL: pkcs11:model=YubiKey%20YK4;manufacturer=Yubico%20%28www.yubico.com%29;serial=5212376;token=YubiKey%20PIV%20%235212376;id=%19;object=Private%20key%20for%20PIV%20Attestation;type=private
        Type: Private key (RSA-2048)
        Label: Private key for PIV Attestation
        Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE;
        ID: 19
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Well those look&amp;hellip;exciting. (If you want more excitement, use &lt;code&gt;--list-all&lt;/code&gt; instead of &lt;code&gt;--list-keys&lt;/code&gt;
in the command.) You&amp;rsquo;ll notice the key with ID 02 is an ECDSA key, just like we created. (You may
also notice that &amp;ldquo;ID 02&amp;rdquo; aligns with how we identified the certificate slot in the &lt;code&gt;pkcs11-tool&lt;/code&gt;
command.) That&amp;rsquo;s our key, so copy the value of the &amp;ldquo;URL&amp;rdquo; field, then paste it into
&lt;code&gt;openssl_root.cnf&lt;/code&gt; as the value for the &lt;code&gt;private_key&lt;/code&gt; field. The relevant section should look
something like this now:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;k&#34;&gt;[ CA_default ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;dir&lt;/span&gt;               &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;certs&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crl_dir&lt;/span&gt;           &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/crl&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;new_certs_dir&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;database&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/index.txt&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;serial&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/serial&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;rand_serial&lt;/span&gt;	  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;RANDFILE&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/private/.rand&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Our private key will reside on a Yubikey.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;private_key&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;pkcs11:model=YubiKey%20YK4;manufacturer=Yubico%20%28www.yubico.com%29;serial=5212376;token=YubiKey%20PIV%20%235212376;id=%02;object=Private%20key%20for%20Digital%20Signature;type=private&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;certificate&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs/ca.example.crt.pem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;generate-the-csr-and-create-a-self-signed-certificate&#34;&gt;Generate the CSR and Create a Self-Signed Certificate&lt;/h3&gt;
&lt;p&gt;With the housekeeping out of the way, create a certificate-signing request (CSR). We will
immediately sign it using OpenSSL, creating a self-signed cert that will be the root certificate.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ OPENSSL_CONF=openssl_root.cnf openssl req \
    -new -x509 -sha384 -extensions v3_ca    \
    -days 3650                              \
    -engine pkcs11 -keyform engine          \
    -key slot_$KEY_SLOT-id_02               \
    -out certs/ca.example.crt.pem
engine &amp;quot;pkcs11&amp;quot; set.
Enter PKCS#11 token PIN for YubiKey PIV #5212376:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &#39;.&#39;, the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name [WA]:
Locality Name [Seattle]:
Organization Name [Example Enterprises]:
Organizational Unit Name [Example Enterprises Root CA]:
Common Name []:
Email Address []:
Enter PKCS#11 key PIN for Private key for Digital Signature: ******
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I like to have the text representation of the certificate alongside the public key, which we can
accomplish like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ openssl x509 -text             \
    -in certs/ca.example.crt.pem \
    -out certs/ca.example.crt.pem.new
$ mv certs/ca.example.crt.pem{.new,}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now you can see what the certificate &amp;ldquo;looks&amp;rdquo; like by peeking in &lt;code&gt;certs/ca.example.crt.pem&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            71:f3:9f:7e:6c:d5:50:b8:60:53:3b:ae:75:90:b5:b4:e5:14:c2:a5
        Signature Algorithm: ecdsa-with-SHA384
        Issuer: C = US, ST = WA, L = Seattle, O = Example Enterprises, OU = Example Enterprises Root CA
        Validity
            Not Before: Jun 29 20:39:58 2022 GMT
            Not After : Jun 26 20:39:58 2032 GMT
        Subject: C = US, ST = WA, L = Seattle, O = Example Enterprises, OU = Example Enterprises Root CA
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (384 bit)
                pub:
                    04:43:0e:41:cc:5f:3f:3a:36:53:e4:22:08:8b:11:
                    f2:8d:65:65:b3:5b:e0:3c:83:d1:38:f8:b8:80:b0:
                    0b:9c:c5:39:22:47:8b:b0:70:50:01:f2:a1:e3:96:
                    f5:a6:fd:87:d4:c6:08:18:3d:50:fc:29:35:51:71:
                    ec:33:4b:af:98:5f:e3:3a:b7:d9:c6:11:67:1f:2d:
                    ca:cb:b2:9f:e5:1c:54:80:0b:ba:40:f3:9b:41:34:
                    a4:af:87:83:1e:35:f4
                ASN1 OID: secp384r1
                NIST CURVE: P-384
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                CE:02:71:A8:84:7A:10:D5:C4:80:E5:23:5A:90:70:67:BC:97:B5:E0
            X509v3 Authority Key Identifier: 
                keyid:CE:02:71:A8:84:7A:10:D5:C4:80:E5:23:5A:90:70:67:BC:97:B5:E0

            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:1
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign, CRL Sign
    Signature Algorithm: ecdsa-with-SHA384
         30:65:02:30:0a:a6:a4:dd:84:1b:b4:3b:70:a7:82:32:c5:ba:
         f5:e6:69:93:2e:f8:3e:2a:9b:f0:ac:74:75:77:95:6a:42:24:
         27:ec:63:97:1e:8c:79:7f:88:c2:f8:dd:e3:3c:54:43:02:31:
         00:9d:f2:aa:de:37:93:67:81:e9:75:66:40:59:a2:75:5b:7a:
         2d:67:2e:6c:e9:24:99:9d:6d:ca:66:8c:f3:97:80:1a:93:d7:
         42:a9:f4:08:96:e1:5f:44:0f:c9:02:4f:0d
-----BEGIN CERTIFICATE-----
MIIChTCCAgugAwIBAgIUcfOffmzVULhgUzuudZC1tOUUwqUwCgYIKoZIzj0EAwMw
cDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMRww
GgYDVQQKDBNFeGFtcGxlIEVudGVycHJpc2VzMSQwIgYDVQQLDBtFeGFtcGxlIEVu
dGVycHJpc2VzIFJvb3QgQ0EwHhcNMjIwNjI5MjAzOTU4WhcNMzIwNjI2MjAzOTU4
WjBwMQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUx
HDAaBgNVBAoME0V4YW1wbGUgRW50ZXJwcmlzZXMxJDAiBgNVBAsMG0V4YW1wbGUg
RW50ZXJwcmlzZXMgUm9vdCBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABEMOQcxf
Pzo2U+QiCIsR8o1lZbNb4DyD0Tj4uICwC5zFOSJHi7BwUAHyoeOW9ab9h9TGCBg9
UPwpNVFx7DNLr5hf4zq32cYRZx8tysuyn+UcVIALukDzm0E0pK+Hgx419KNmMGQw
HQYDVR0OBBYEFM4CcaiEehDVxIDlI1qQcGe8l7XgMB8GA1UdIwQYMBaAFM4CcaiE
ehDVxIDlI1qQcGe8l7XgMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQD
AgGGMAoGCCqGSM49BAMDA2gAMGUCMAqmpN2EG7Q7cKeCMsW69eZpky74Piqb8Kx0
dXeVakIkJ+xjlx6MeX+Iwvjd4zxUQwIxAJ3yqt43k2eB6XVmQFmidVt6LWcubOkk
mZ1tymaM85eAGpPXQqn0CJbhX0QPyQJPDQ==
-----END CERTIFICATE-----
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&amp;rsquo;ll want to import the completed certificate to the Yubikey. Do so with the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pkcs11-tool --module &amp;quot;$LIBYKCS11&amp;quot;         \
    --login --login-type so                 \
    --pin $PIN --so-pin $MGMT_KEY           \
    --slot $KEY_SLOT --id 2                 \
    --write-object certs/ca.example.crt.pem \
    --type cert
Created certificate:
Certificate Object; type = X.509 cert
  label:      X.509 Certificate for Digital Signature
  subject:    DN: C=US, ST=WA, L=Seattle, O=Example Enterprises, OU=Example Enterprises Root CA
  ID:         02
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, if you use Yubikey Manager or &lt;code&gt;ykman piv info&lt;/code&gt;, you should see the Subject and Issuer DNs
(which should be the same), etc. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ykman piv info
PIV version: 4.3.3
PIN tries remaining: 3
Management key algorithm: TDES
CHUID:  No data available.
CCC:    No data available.
Slot 9c:
        Algorithm:      ECCP384
        Subject DN:     OU=Example Enterprises Root CA,O=Example Enterprises,L=Seattle,ST=WA,C=US
        Issuer DN:      OU=Example Enterprises Root CA,O=Example Enterprises,L=Seattle,ST=WA,C=US
        Serial:         650548932060042409555401858257111553448854471333
        Fingerprint:    e65811081b499751c6b1a384cfb4d2c3e2b5f0bb07bfeda3155f45c63c362bba
        Not before:     2022-06-29 20:39:58
        Not after:      2032-06-26 20:39:58
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You now have a root CA on a Yubikey!&lt;/p&gt;
&lt;p&gt;Well, you have a self-signed cert on a Yubikey that we&amp;rsquo;ve endowed with certain properties. To make
it useful as a root CA, we&amp;rsquo;ll need to create an intermediate, or subordinate CA. Get your next
Yubikey ready to go!&lt;/p&gt;
&lt;h2 id=&#34;create-the-intermediate-ca&#34;&gt;Create the Intermediate CA&lt;/h2&gt;
&lt;p&gt;Just like for the root CA, we need to create a directory structure for the intermediate CA:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cd /somewhere/important/ca
$ mkdir -p intermediate/{certs,crl,csr,private}
$ cd intermediate/
$ touch index.txt
$ echo 1000 &amp;gt; serial
$ echo 1000 &amp;gt; crlnumber
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need another OpenSSL config file. This should look similar to the root&amp;rsquo;s config.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;na&#34;&gt;.include ../pkcs11.cnf&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ ca ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_ca&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;CA_default&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ CA_default ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;dir&lt;/span&gt;               &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;certs&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crl_dir&lt;/span&gt;           &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/crl&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;new_certs_dir&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;database&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/index.txt&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;serial&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/serial&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;RANDFILE&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/private/.rand&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Our private key will reside on a Yubikey.&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#private_key       =&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;certificate&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs/int.example.crt.pem&lt;/span&gt;

&lt;span class=&#34;na&#34;&gt;crlnumber&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/crlnumber&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crl&lt;/span&gt;               &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/crl/int.example.crl.pem&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crl_extensions&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;crl_ext&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_crl_days&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;3650&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Set this to match the intermediate CA&amp;#39;s key length.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_md&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;sha256&lt;/span&gt;

&lt;span class=&#34;na&#34;&gt;name_opt&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;ca_default&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;cert_opt&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;ca_default&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_days&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;3650&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;preserve&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;policy&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;policy_loose&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ policy_loose ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;countryName&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;optional&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;stateOrProvinceName&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;optional&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;localityName&lt;/span&gt;     	&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;optional&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationName&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;optional&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationalUnitName&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;optional&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;commonName&lt;/span&gt;              &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;supplied&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;emailAddress&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;optional&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ req ]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# This doesn&amp;#39;t matter to us; we&amp;#39;re using ECC, not RSA.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_bits&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;4096&lt;/span&gt;

&lt;span class=&#34;na&#34;&gt;distinguished_name&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;req_distinguished_name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;string_mask&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;utf8only&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# Set this to match the intermediate CA&amp;#39;s key length.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_md&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;sha256&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Extension to add when the -x509 option is used.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;x509_extensions&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;v3_intermediate_ca&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ req_distinguished_name ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;countryName&lt;/span&gt;                     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Country Name (2 letter code)&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;stateOrProvinceName&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;State or Province Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;localityName&lt;/span&gt;                    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Locality Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;0.organizationName&lt;/span&gt;              &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Organization Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationalUnitName&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Organizational Unit Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;commonName&lt;/span&gt;                      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Common Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;emailAddress&lt;/span&gt;                    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Email Address&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Update these to suit your environment&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;countryName_default&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;US&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;stateOrProvinceName_default&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;WA&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;localityName_default&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Seattle&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;0.organizationName_default&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Example Enterprises&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationalUnitName_default&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Example Enterprises Intermediate CA&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;commonName_default&lt;/span&gt; 		&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Example Enterprises Intermediate Certificate Authority&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ v3_intermediate_ca ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;subjectKeyIdentifier&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;hash&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;authorityKeyIdentifier&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;keyid:always,issuer&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;basicConstraints&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;critical, CA:true, pathlen:0&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;keyUsage&lt;/span&gt;                &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;critical, digitalSignature, cRLSign, keyCertSign&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crlDistributionPoints&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;@crl_info&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;authorityInfoAccess&lt;/span&gt; 	&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;@ocsp_info&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ crl_ext ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;authorityKeyIdentifier&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;keyid:always&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ ocsp ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;basicConstraints&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;CA:FALSE&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;subjectKeyIdentifier&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;hash&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;authorityKeyIdentifier&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;keyid:always,issuer&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;keyUsage&lt;/span&gt;		 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;critical, digitalSignature&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;extendedKeyUsage&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;critical, OCSPSigning&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ crl_info ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;URI.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http://crl.example.com/intermediate.crl.pem&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ ocsp_info ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;caIssuers;URI.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http://ocsp.example.com/example-root.crt&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;OCSP;URI.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http://ocsp.example.com/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&#34;create-the-private-key&#34;&gt;Create the Private Key&lt;/h3&gt;
&lt;p&gt;Now we can create a private key, just like for the root CA. (Note that I depart from the CA guide a
bit here and use a 256-bit key; there is no reason for this other than I don&amp;rsquo;t have another Yubikey
that does P-384 that I want to sacrifice for this example! As you read the rest of the document,
keep in mind that NSA Suite B requires signatures to match the signing key&amp;rsquo;s length, so if you&amp;rsquo;re
using a 384-bit key for the intermediate, make sure you modify any commands accordingly to also use
384-bit signatures.)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pkcs11-tool --module &amp;quot;$LIBYKCS11&amp;quot; \
    --login --login-type so         \
    --pin $PIN --so-pin $MGMT_KEY   \
    --slot $KEY_SLOT --id 2         \
    --key-type EC:secp256r1         \
    --keypairgen
Key pair generated:
Private Key Object; EC
  label:      Private key for Digital Signature
  ID:         02
  Usage:      decrypt, sign
  Access:     always authenticate, sensitive, always sensitive, never extractable, local
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   0441042adfd3269920a167450663357b355a3a2e709279b062482a226ad7d4ecd412f22e6060e5ceb7febc20ea646ca3a498908e2082bec5211c883ef1d676fd092f14
  EC_PARAMS:  06082a8648ce3d030107
  label:      Public key for Digital Signature
  ID:         02
  Usage:      encrypt, verify
  Access:     local
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We should make note of this key&amp;rsquo;s URI, just like we had to do for the root key.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ p11tool --provider=$LIBYKCS11 --list-keys --login
Token &#39;YubiKey PIV #0&#39; with URL &#39;pkcs11:model=YubiKey%20NEO;manufacturer=Yubico%20%28www.yubico.com%29;serial=0;token=YubiKey%20PIV%20%230&#39; requires user PIN
Enter PIN:
Object 0:
        URL: pkcs11:model=YubiKey%20NEO;manufacturer=Yubico%20%28www.yubico.com%29;serial=0;token=YubiKey%20PIV%20%230;id=%02;object=Private%20key%20for%20Digital%20Signature;type=private
        Type: Private key (EC/ECDSA)
        Label: Private key for Digital Signature
        Flags: CKA_PRIVATE; CKA_ALWAYS_AUTH; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE;
        ID: 02
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Take that URI and add it as the private key value in &lt;code&gt;intermediate/openssl_intermediate.cnf&lt;/code&gt;. It
should now look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;k&#34;&gt;[ CA_default ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;dir&lt;/span&gt;               &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;certs&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crl_dir&lt;/span&gt;           &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/crl&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;new_certs_dir&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;database&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/index&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;serial&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/serial&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;RANDFILE&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/private/.rand&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Our private key will reside on a Yubikey.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;private_key&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;pkcs11:model=YubiKey%20NEO;manufacturer=Yubico%20%28www.yubico.com%29;serial=0;token=YubiKey%20PIV%20%230;id=%02;object=Private%20key%20for%20Digital%20Signature;type=private&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;certificate&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$dir/certs/int.example.crt.pem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;generate-a-csr&#34;&gt;Generate a CSR&lt;/h3&gt;
&lt;p&gt;Create a CSR for the root CA to sign. This is slightly different from what we did for the root CA
since we&amp;rsquo;re not trying to self-sign this one.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ OPENSSL_CONF=openssl_intermediate.cnf openssl req \
    -new -sha384 -engine pkcs11                     \
    -keyform engine -key slot_$KEY_SLOT-id_02       \
    -out csr/int.example.csr
engine &amp;quot;pkcs11&amp;quot; set.
Enter PKCS#11 token PIN for YubiKey PIV #5212376:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &#39;.&#39;, the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name [WA]:
Locality Name [Seattle]:
Organization Name [Example Enterprises]:
Organizational Unit Name [Example Enterprises Intermediate CA]:
Common Name [Example Enterprises Intermediate Certificate Authority]:
Email Address []:
Enter PKCS#11 key PIN for Private key for Digital Signature: ******
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can view the certificate signing request using OpenSSL, just like you can a certificate. Examine
the CSR in &lt;code&gt;csr/int.example.csr&lt;/code&gt; and make sure everything looks okay:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ openssl req -noout -text -in csr/int.example.csr
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = US, ST = WA, L = Seattle, O = Example Enterprises, OU = Example Enterprises Intermediate CA, CN = Example Enterprises Intermediate Certificate Authority
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:2a:df:d3:26:99:20:a1:67:45:06:63:35:7b:35:
                    5a:3a:2e:70:92:79:b0:62:48:2a:22:6a:d7:d4:ec:
                    d4:12:f2:2e:60:60:e5:ce:b7:fe:bc:20:ea:64:6c:
                    a3:a4:98:90:8e:20:82:be:c5:21:1c:88:3e:f1:d6:
                    76:fd:09:2f:14
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        Attributes:
            a0:00
    Signature Algorithm: ecdsa-with-SHA384
         30:45:02:20:5e:70:7e:ec:e0:65:5f:a6:3c:f5:d6:6b:89:d1:
         af:e9:d5:61:7e:b1:89:a0:a0:80:f1:25:87:fc:c6:67:41:de:
         02:21:00:e9:fd:8a:cb:d5:df:f9:86:73:78:8d:55:f4:80:c9:
         95:fe:de:8a:b9:59:c6:ad:65:17:e2:70:07:26:73:d1:40
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;complete-the-csr-and-sign-the-certificate&#34;&gt;Complete the CSR and Sign the Certificate&lt;/h3&gt;
&lt;p&gt;We now need to complete (sign) this CSR using the root key. Remove the &amp;ldquo;intermediate&amp;rdquo; Yubikey and
plug in the &amp;ldquo;root&amp;rdquo; Yubikey for the next step.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# do this in the root CA&#39;s directory, not the intermediate.
$ cd ..
$ OPENSSL_CONF=openssl_root.cnf openssl ca         \
    -extensions v3_intermediate_ca                 \
    -extfile intermediate/openssl_intermediate.cnf \
    -days 3600                                     \
    -engine pkcs11 -keyform engine                 \
    -in intermediate/csr/int.example.csr           \
    -out intermediate/certs/int.example.crt.pem
Using configuration from openssl_root.cnf
Enter PKCS#11 token PIN for YubiKey PIV #5212376:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            6d:d2:2d:17:5e:b1:43:56:1e:23:f2:82:0a:ab:25:68:59:26:51:dc
        Validity
            Not Before: Jun 30 17:37:23 2022 GMT
            Not After : May  8 17:37:23 2032 GMT
        Subject:
            countryName               = US
            stateOrProvinceName       = WA
            organizationName          = Example Enterprises
            organizationalUnitName    = Example Enterprises Intermediate CA
            commonName                = Example Enterprises Intermediate Certificate Authority
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                AF:60:EF:FF:07:1E:4B:CD:08:EB:78:E9:73:C1:CB:5E:9F:C9:7E:11
            X509v3 Authority Key Identifier:
                keyid:CE:02:71:A8:84:7A:10:D5:C4:80:E5:23:5A:90:70:67:BC:97:B5:E0

            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign, CRL Sign
            X509v3 CRL Distribution Points:

                Full Name:
                  URI:http://crl.example.com/intermediate.crl.pem

            Authority Information Access:
                CA Issuers - URI:http://ocsp.example.com/example-root.crt
                OCSP - URI:http://ocsp.example.com/

Certificate is to be certified until May  8 17:37:23 2032 GMT (3600 days)
Sign the certificate? [y/n]:y
Enter PKCS#11 key PIN for Private key for Digital Signature: ******


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If all looks good, remove the root CA Yubikey from the computer, &lt;strong&gt;store it somewhere safe&lt;/strong&gt;, and
only bring it out when you need to sign another intermediate CA&amp;rsquo;s certificate.&lt;/p&gt;
&lt;p&gt;If you wish, you can inspect the new certificate (&lt;code&gt;intermediate/certs/int.example.crt.pem&lt;/code&gt;) one more time:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            6d:d2:2d:17:5e:b1:43:56:1e:23:f2:82:0a:ab:25:68:59:26:51:dc
        Signature Algorithm: ecdsa-with-SHA384
        Issuer: C=US, ST=WA, L=Seattle, O=Example Enterprises, OU=Example Enterprises Root CA
        Validity
            Not Before: Jun 30 17:37:23 2022 GMT
            Not After : May  8 17:37:23 2032 GMT
        Subject: C=US, ST=WA, O=Example Enterprises, OU=Example Enterprises Intermediate CA, CN=Example Enterprises Intermediate Certificate Authority
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:2a:df:d3:26:99:20:a1:67:45:06:63:35:7b:35:
                    5a:3a:2e:70:92:79:b0:62:48:2a:22:6a:d7:d4:ec:
                    d4:12:f2:2e:60:60:e5:ce:b7:fe:bc:20:ea:64:6c:
                    a3:a4:98:90:8e:20:82:be:c5:21:1c:88:3e:f1:d6:
                    76:fd:09:2f:14
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                AF:60:EF:FF:07:1E:4B:CD:08:EB:78:E9:73:C1:CB:5E:9F:C9:7E:11
            X509v3 Authority Key Identifier: 
                keyid:CE:02:71:A8:84:7A:10:D5:C4:80:E5:23:5A:90:70:67:BC:97:B5:E0

            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign, CRL Sign
            X509v3 CRL Distribution Points: 

                Full Name:
                  URI:http://crl.example.com/intermediate.crl.pem

            Authority Information Access: 
                CA Issuers - URI:http://ocsp.example.com/example-root.crt
                OCSP - URI:http://ocsp.example.com/

    Signature Algorithm: ecdsa-with-SHA384
         30:65:02:31:00:82:d2:25:f3:f5:df:c8:09:f4:59:cf:d5:52:
         c9:67:5d:d3:d1:73:6d:90:69:4d:c5:43:1a:9b:d9:78:42:30:
         22:1c:39:ce:60:8a:9a:a7:a0:d6:d5:6c:4e:6c:61:51:1d:02:
         30:63:40:dd:c5:03:c5:d3:f9:6e:34:fb:f1:ba:8a:91:f9:69:
         24:56:a3:ee:10:4e:85:cb:4b:43:b0:1c:4d:0b:3a:13:59:86:
         71:42:9e:f8:50:fa:f5:e0:7a:fb:19:78:85
-----BEGIN CERTIFICATE-----
MIIDTjCCAtSgAwIBAgIUbdItF16xQ1YeI/KCCqslaFkmUdwwCgYIKoZIzj0EAwMw
cDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMRww
GgYDVQQKDBNFeGFtcGxlIEVudGVycHJpc2VzMSQwIgYDVQQLDBtFeGFtcGxlIEVu
dGVycHJpc2VzIFJvb3QgQ0EwHhcNMjIwNjMwMTczNzIzWhcNMzIwNTA4MTczNzIz
WjCBpzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRwwGgYDVQQKDBNFeGFtcGxl
IEVudGVycHJpc2VzMSwwKgYDVQQLDCNFeGFtcGxlIEVudGVycHJpc2VzIEludGVy
bWVkaWF0ZSBDQTE/MD0GA1UEAww2RXhhbXBsZSBFbnRlcnByaXNlcyBJbnRlcm1l
ZGlhdGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEKt/TJpkgoWdFBmM1ezVaOi5wknmwYkgqImrX1OzUEvIuYGDlzrf+vCDq
ZGyjpJiQjiCCvsUhHIg+8dZ2/QkvFKOCARIwggEOMB0GA1UdDgQWBBSvYO//Bx5L
zQjreOlzwcten8l+ETAfBgNVHSMEGDAWgBTOAnGohHoQ1cSA5SNakHBnvJe14DAS
BgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjA8BgNVHR8ENTAzMDGg
L6AthitodHRwOi8vY3JsLmV4YW1wbGUuY29tL2ludGVybWVkaWF0ZS5jcmwucGVt
MGoGCCsGAQUFBwEBBF4wXDA0BggrBgEFBQcwAoYoaHR0cDovL29jc3AuZXhhbXBs
ZS5jb20vZXhhbXBsZS1yb290LmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au
ZXhhbXBsZS5jb20vMAoGCCqGSM49BAMDA2gAMGUCMQCC0iXz9d/ICfRZz9VSyWdd
09FzbZBpTcVDGpvZeEIwIhw5zmCKmqeg1tVsTmxhUR0CMGNA3cUDxdP5bjT78bqK
kflpJFaj7hBOhctLQ7AcTQs6E1mGcUKe+FD69eB6+xl4hQ==
-----END CERTIFICATE-----
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now to finish the signing process, plug the intermediate CA Yubikey back into your computer. Even
though the intermediate Yubikey has some of the values for the certificate correctly filled out, you
should write the new certificate data to the card just like we did with the root card.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pkcs11-tool --module &amp;quot;$LIBYKCS11&amp;quot;        \
    --login --login-type so                \
    --pin $PIN --so-pin $MGMT_KEY          \
    --slot $KEY_SLOT --id 2                \
    --write-object                         \
    intermediate/certs/int.example.crt.pem \
    --type cert
Created certificate:
Certificate Object; type = X.509 cert
  label:      X.509 Certificate for Digital Signature
  subject:    DN: C=US, ST=WA, O=Example Enterprises, OU=Example Enterprises Intermediate CA, CN=Example Enterprises Intermediate Certificate Authority
  ID:         02
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want, check that things look okay using &lt;code&gt;ykman&lt;/code&gt; or the Yubikey Manager:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ykman piv info
PIV version: 0.1.3
PIN tries remaining: 3
Management key algorithm: TDES
CHUID:	No data available.
CCC: 	No data available.
Slot 9c:
	Algorithm:	ECCP256
	Subject DN:	CN=Example Enterprises Intermediate Certificate Authority,OU=Example Enterprises Intermediate CA,O=Example Enterprises,ST=WA,C=US
	Issuer DN:	OU=Example Enterprises Root CA,O=Example Enterprises,L=Seattle,ST=WA,C=US
	Serial:		626967078516719141285955126592050016717579375068
	Fingerprint:	9d3c1806eed095b4a561e8ee9521650ea1b4ff9b0a2d1439d2da3c14ab1de4c8
	Not before:	2022-06-30 17:37:23
	Not after:	2032-05-08 17:37:23
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;create-the-crl-and-ocsp-certificate&#34;&gt;Create the CRL and OCSP Certificate&lt;/h2&gt;
&lt;p&gt;Following the CA guide, next we&amp;rsquo;ll create a CRL and sign it with the intermediate CA:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Do basically everything from here out in the intermediate directory
$ cd intermediate/
$ OPENSSL_CONF=openssl_intermediate.cnf openssl ca \
    -engine pkcs11 -keyform engine                 \
    -gencrl -out crl/intermediate.crl.pem
engine &amp;quot;pkcs11&amp;quot; set.
Using configuration from openssl_intermediate.cnf
Enter PKCS#11 token PIN for YubiKey PIV #0:
Enter PKCS#11 key PIN for Private key for Digital Signature: ******
Enter PKCS#11 key PIN for Private key for Digital Signature: ******
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can verify the CRL using OpenSSL:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ openssl crl -in crl/intermediate.crl.pem -noout -text
Certificate Revocation List (CRL):
        Version 2 (0x1)
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: C = US, ST = WA, O = Example Enterprises, OU = Example Enterprises Intermediate CA, CN = Example Enterprises Intermediate Certificate Authority
        Last Update: Jun 30 18:18:54 2022 GMT
        Next Update: Jun 27 18:18:54 2032 GMT
        CRL extensions:
            X509v3 Authority Key Identifier:
                keyid:AF:60:EF:FF:07:1E:4B:CD:08:EB:78:E9:73:C1:CB:5E:9F:C9:7E:11

            X509v3 CRL Number:
                4097
No Revoked Certificates.
    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:21:00:e7:2f:5e:17:a6:1c:9d:d7:c0:b2:48:23:9a:
         2e:32:9e:85:d6:47:b7:25:c6:db:b5:bc:85:4b:c4:67:9e:78:
         69:02:20:5b:bb:29:1e:86:d1:52:25:2c:b6:8e:20:f0:12:e7:
         a3:0c:d4:34:e5:d4:df:c2:8a:ba:38:99:f3:e4:2a:53:6d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&amp;rsquo;s also create an OCSP certificate. For this, we &lt;em&gt;will&lt;/em&gt; generate a private key using OpenSSL
instead of it being on a Yubikey, since it is going to be like a server certificate.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ OPENSSL_CONF=openssl_server.cnf openssl req           \
    -new -newkey ec:&amp;lt;(openssl ecparam -name prime256v1) \
    -keyout private/ocsp.example.key.pem                \
    -out csr/ocsp.example.csr.pem                       \
    -extensions server_cert
Generating an EC private key
writing new private key to &#39;private/ocsp.example.key.pem&#39;
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &#39;.&#39;, the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name [WA]:
Locality Name [Seattle]:
Organization Name [Example Enterprises]:
Organizational Unit Name [Information Technology]:
Common Name []:ocsp.example.com
Email Address []:ocsp@example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That command created the CSR; now we need to sign it using the intermediate CA key.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ OPENSSL_CONF=openssl_intermediate.cnf openssl ca \
    -engine pkcs11 -keyform engine                 \
    -extensions ocsp -days 365                     \
    -in csr/ocsp.example.csr.pem                   \
    -out certs/ocsp.example.crt.pem
engine &amp;quot;pkcs11&amp;quot; set.
Using configuration from openssl_intermediate.cnf
Enter PKCS#11 token PIN for YubiKey PIV #0:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 4097 (0x1001)
        Validity
            Not Before: Jun 30 18:58:51 2022 GMT
            Not After : Jun 30 18:58:51 2023 GMT
        Subject:
            countryName               = US
            stateOrProvinceName       = WA
            localityName              = Seattle
            organizationName          = Example Enterprises
            organizationalUnitName    = Information Technology
            commonName                = ocsp.example.com
            emailAddress              = ocsp@example.com
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Subject Key Identifier:
                C1:C1:7D:A3:02:DE:B7:B2:F6:85:BE:24:7A:C9:BE:B2:39:E0:F1:A0
            X509v3 Authority Key Identifier:
                keyid:AF:60:EF:FF:07:1E:4B:CD:08:EB:78:E9:73:C1:CB:5E:9F:C9:7E:11

            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Extended Key Usage: critical
                OCSP Signing
Certificate is to be certified until Jun 30 18:58:51 2023 GMT (365 days)
Sign the certificate? [y/n]:y
Enter PKCS#11 key PIN for Private key for Digital Signature: ******


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cool, now you have a certificate you can use to set up an OCSP responder.&lt;/p&gt;
&lt;h2 id=&#34;create-and-sign-a-web-server-certificate&#34;&gt;Create and Sign a Web Server Certificate&lt;/h2&gt;
&lt;p&gt;Alright, let&amp;rsquo;s create some end-entity certificates. Let&amp;rsquo;s say you have a web server that requires a
certificate; your new Yubikey PKI should do nicely!&lt;/p&gt;
&lt;p&gt;What follows will be a simplified version of a generic create-request-sign process for getting a
signed certificate for a web server. If you&amp;rsquo;re reading this, most probably you already have a
process that does everything up to sending the CSR somewhere to get it signed. It&amp;rsquo;s at that point
where we&amp;rsquo;ll pick up in more detail.&lt;/p&gt;
&lt;p&gt;For this example, we&amp;rsquo;ll create a generic &lt;code&gt;openssl_server.cnf&lt;/code&gt; file to hold defaults that apply to
all server certificates. Then, we&amp;rsquo;ll create a config file for a mythical server named
&amp;ldquo;web01.example.com&amp;rdquo; that includes the generic server config. (If you&amp;rsquo;re wondering why we need a
config file per entity at all instead of specifying everything on the command line, it&amp;rsquo;s because we
want to assign some subject alternative names to the certificate. Currently the only way to set
subject alternative names is via a config file.)&lt;/p&gt;
&lt;p&gt;First create &lt;code&gt;intermediate/openssl_server.cnf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;k&#34;&gt;[ req ]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# This doesn&amp;#39;t matter to us; we&amp;#39;re using ECC, not RSA.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_bits&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;4096&lt;/span&gt;

&lt;span class=&#34;na&#34;&gt;distinguished_name&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;req_distinguished_name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;string_mask&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;utf8only&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_md&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;sha256&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ req_distinguished_name ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;countryName&lt;/span&gt;                     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Country Name (2 letter code)&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;stateOrProvinceName&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;State or Province Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;localityName&lt;/span&gt;                    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Locality Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;0.organizationName&lt;/span&gt;              &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Organization Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationalUnitName&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Organizational Unit Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;commonName&lt;/span&gt;                      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Common Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;emailAddress&lt;/span&gt;                    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Email Address&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Update these to suit your environment&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;countryName_default&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;US&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;stateOrProvinceName_default&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;WA&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;localityName_default&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Seattle&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;0.organizationName_default&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Example Enterprises&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationalUnitName_default&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Information Technology&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;commonName_default&lt;/span&gt; 		&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ server_cert ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;basicConstraints&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;CA:FALSE&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;nsCertType&lt;/span&gt;		 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;server&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;nsComment&lt;/span&gt;		 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;OpenSSL Generated Server Certificate&amp;#34;&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;subjectKeyIdentifier&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;hash&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;authorityKeyIdentifier&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;keyid,issuer:always&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;keyUsage&lt;/span&gt;		 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;critical, digitalSignature, keyEncipherment&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;extendedKeyUsage&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;serverAuth&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crlDistributionPoints&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;@crl_info&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;authorityInfoAccess&lt;/span&gt; 	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;@ocsp_info&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ crl_info ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;URI.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http://crl.example.com/intermediate.crl.pem&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ ocsp_info ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;caIssuers;URI.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http://ocsp.example.com/example-root.crt&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;OCSP;URI.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http://ocsp.example.com/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;hellip;and then create &lt;code&gt;intermediate/openssl_web01.cnf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;na&#34;&gt;.include openssl_server.cnf&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ req_distinguished_name ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;commonName_default&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;web01.example.com&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ server_cert ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;subjectAltName&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;@alt_names&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ alt_names ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;DNS.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;web01.example.com&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;DNS.1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;web.example.com&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Okay, now we can get to creating the certificate itself.&lt;/p&gt;
&lt;h3 id=&#34;create-the-csr&#34;&gt;Create the CSR&lt;/h3&gt;
&lt;p&gt;In the real world, you&amp;rsquo;d probably generate the private key and CSR on the server and send the CSR
elsewhere to get it signed. For this example we&amp;rsquo;ll pretend that these steps happen in the CA. How
this step happens isn&amp;rsquo;t that important for this article.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ OPENSSL_CONF=openssl_web01.cnf openssl req            \
    -new -newkey ec:&amp;lt;(openssl ecparam -name prime256v1) \
    -keyout private/web01.example.key.pem               \
    -out csr/web01.example.csr
Generating an EC private key
writing new private key to &#39;private/web01.example.key.pem&#39;
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &#39;.&#39;, the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name [WA]:
Locality Name [Seattle]:
Organization Name [Example Enterprises]:
Organizational Unit Name [Information Technology]:
Common Name [web01.example.com]:
Email Address []:
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;sign-the-certificate&#34;&gt;Sign the Certificate&lt;/h3&gt;
&lt;p&gt;Maybe you generated the CSR in the previous step, or maybe a CSR magically fell into your lap for
you to sign. Let&amp;rsquo;s do that. Notice that the certificate has the common name and subject alternative
names we set in the config:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ OPENSSL_CONF=openssl_intermediate.cnf openssl ca \
    -engine pkcs11 -keyform engine                 \
    -extfile openssl_web01.cnf                     \
    -extensions server_cert -days 730              \
    -in csr/web01.example.csr                      \
    -out certs/web01.example.crt.pem
engine &amp;quot;pkcs11&amp;quot; set.
Using configuration from openssl_intermediate.cnf
Enter PKCS#11 token PIN for YubiKey PIV #0:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 4097 (0x1001)
        Validity
            Not Before: Jun 30 19:20:08 2022 GMT
            Not After : Jun 29 19:20:08 2024 GMT
        Subject:
            countryName               = US
            stateOrProvinceName       = WA
            localityName              = Seattle
            organizationName          = Example Enterprises
            organizationalUnitName    = Information Technology
            commonName                = web01.example.com
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Cert Type:
                SSL Server
            Netscape Comment:
                OpenSSL Generated Server Certificate
            X509v3 Subject Key Identifier:
                8F:BE:E6:5B:41:4F:D5:A3:36:09:BE:58:A7:DD:AE:FD:B5:09:31:A9
            X509v3 Authority Key Identifier:
                keyid:AF:60:EF:FF:07:1E:4B:CD:08:EB:78:E9:73:C1:CB:5E:9F:C9:7E:11
                DirName:/C=US/ST=WA/L=Seattle/O=Example Enterprises/OU=Example Enterprises Root CA
                serial:6D:D2:2D:17:5E:B1:43:56:1E:23:F2:82:0A:AB:25:68:59:26:51:DC

            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 CRL Distribution Points:

                Full Name:
                  URI:http://crl.example.com/intermediate.crl.pem

            Authority Information Access:
                CA Issuers - URI:http://ocsp.example.com/example-root.crt
                OCSP - URI:http://ocsp.example.com/

            X509v3 Subject Alternative Name:
                DNS:web01.example.com, DNS:web.example.com
Certificate is to be certified until Jun 29 19:20:08 2024 GMT (730 days)
Sign the certificate? [y/n]:y
Enter PKCS#11 key PIN for Private key for Digital Signature: ******


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Review the actual certificate and ensure the common name and subject alternative names are correct:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ openssl x509 -noout -text -in certs/web01.example.crt.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 4097 (0x1001)
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: C = US, ST = WA, O = Example Enterprises, OU = Example Enterprises Intermediate CA, CN = Example Enterprises Intermediate Certificate Authority
        Validity
            Not Before: Jun 30 19:20:08 2022 GMT
            Not After : Jun 29 19:20:08 2024 GMT
        Subject: C = US, ST = WA, L = Seattle, O = Example Enterprises, OU = Information Technology, CN = web01.example.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:66:8e:38:8a:e4:0b:c0:69:df:9e:e3:76:91:f3:
                    2f:38:73:67:2d:a5:85:0a:06:d5:83:7c:34:e9:3c:
                    90:a4:3b:2d:a3:5d:ce:c3:e9:9e:b4:5e:84:f8:9a:
                    8b:a1:f4:0a:79:e7:a0:6a:9f:bd:b1:f2:4e:65:a2:
                    1b:03:79:7d:ba
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Cert Type:
                SSL Server
            Netscape Comment:
                OpenSSL Generated Server Certificate
            X509v3 Subject Key Identifier:
                8F:BE:E6:5B:41:4F:D5:A3:36:09:BE:58:A7:DD:AE:FD:B5:09:31:A9
            X509v3 Authority Key Identifier:
                keyid:AF:60:EF:FF:07:1E:4B:CD:08:EB:78:E9:73:C1:CB:5E:9F:C9:7E:11
                DirName:/C=US/ST=WA/L=Seattle/O=Example Enterprises/OU=Example Enterprises Root CA
                serial:6D:D2:2D:17:5E:B1:43:56:1E:23:F2:82:0A:AB:25:68:59:26:51:DC

            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 CRL Distribution Points:

                Full Name:
                  URI:http://crl.example.com/intermediate.crl.pem

            Authority Information Access:
                CA Issuers - URI:http://ocsp.example.com/example-root.crt
                OCSP - URI:http://ocsp.example.com/

            X509v3 Subject Alternative Name:
                DNS:web01.example.com, DNS:web.example.com
    Signature Algorithm: ecdsa-with-SHA256
         30:46:02:21:00:92:22:ab:ec:2d:c8:ab:89:11:81:ac:7a:33:
         46:63:7d:29:b1:c6:93:37:13:57:ad:ec:78:43:f1:f5:fb:1a:
         30:02:21:00:ba:63:f5:2a:fa:9c:99:51:d1:5a:f8:79:20:c0:
         87:3f:7d:64:89:e6:55:fb:f5:b2:03:f2:17:ab:5d:86:e8:d4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If everything looks good, you can send that certificate back to the requester and let them install
it on &lt;code&gt;web01.example.com&lt;/code&gt;!&lt;/p&gt;
&lt;h2 id=&#34;sign-a-yubikey-user-certificate&#34;&gt;Sign a Yubikey User Certificate&lt;/h2&gt;
&lt;p&gt;What&amp;rsquo;s that? You have yet another Yubikey just sitting around, gathering dust? (Or is that just me?)
Let&amp;rsquo;s see what it would look like to go through this process using a physical key, shall we?&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve probably figured it out, but we&amp;rsquo;ll need another config file just for user certs. It&amp;rsquo;s called
&lt;code&gt;intermediate/openssl_user.cnf&lt;/code&gt;, and it looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;na&#34;&gt;.include ../pkcs11.cnf&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ req ]&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# This doesn&amp;#39;t matter to us; we&amp;#39;re using ECC, not RSA.&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_bits&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;4096&lt;/span&gt;

&lt;span class=&#34;na&#34;&gt;distinguished_name&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;req_distinguished_name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;string_mask&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;utf8only&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;default_md&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;sha256&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ req_distinguished_name ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;countryName&lt;/span&gt;                     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Country Name (2 letter code)&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;stateOrProvinceName&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;State or Province Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;localityName&lt;/span&gt;                    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Locality Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;0.organizationName&lt;/span&gt;              &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Organization Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationalUnitName&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Organizational Unit Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;commonName&lt;/span&gt;                      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Common Name&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;emailAddress&lt;/span&gt;                    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Email Address&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Update these to suit your environment&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;countryName_default&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;US&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;stateOrProvinceName_default&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;WA&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;localityName_default&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Seattle&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;0.organizationName_default&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Example Enterprises&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;organizationalUnitName_default&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Information Technology&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;commonName_default&lt;/span&gt; 		&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ usr_cert ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;basicConstraints&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;CA:FALSE&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;nsCertType&lt;/span&gt;		 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;client, email&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;nsComment&lt;/span&gt;		 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;OpenSSL Generated Client Certificate&amp;#34;&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;subjectKeyIdentifier&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;hash&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;authorityKeyIdentifier&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;keyid,issuer&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;keyUsage&lt;/span&gt;		 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;critical, nonRepudiation, digitalSignature, keyEncipherment&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;extendedKeyUsage&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;clientAuth, emailProtection&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;crlDistributionPoints&lt;/span&gt;	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;@crl_info&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;authorityInfoAccess&lt;/span&gt; 	 &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;@ocsp_info&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ crl_info ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;URI.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http://crl.example.com/intermediate.crl.pem&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;[ ocsp_info ]&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;caIssuers;URI.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http://ocsp.example.com/example-root.crt&lt;/span&gt;
&lt;span class=&#34;na&#34;&gt;OCSP;URI.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http://ocsp.example.com/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note specifically that, since we&amp;rsquo;re dealing with a Yubikey, we need to include the &lt;code&gt;pkcs11.cnf&lt;/code&gt; file
so OpenSSL can figure out how to interact with it.&lt;/p&gt;
&lt;h3 id=&#34;generate-the-private-key-on-the-yubikey&#34;&gt;Generate the Private Key on the Yubikey&lt;/h3&gt;
&lt;p&gt;As we have done for both CA certs, we&amp;rsquo;ll need to generate the private key on the end-user&amp;rsquo;s Yubikey,
but this time we&amp;rsquo;ll use slot 9a (&amp;quot;&lt;code&gt;--id 1&lt;/code&gt;&amp;quot;) instead of 9c. &lt;em&gt;Make sure this is the only Yubikey
plugged in, or else you may risk overwriting the intermediate CA&amp;rsquo;s private key.&lt;/em&gt; Or, you know, just
do this on a machine far away from the intermediate Yubikey.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pkcs11-tool --module &amp;quot;$LIBYKCS11&amp;quot; \
    --login --login-type so         \
    --pin $PIN --so-pin $MGMT_KEY   \
    --slot $KEY_SLOT --id 1         \
    --key-type EC:secp256r1 --keypairgen
Key pair generated:
Private Key Object; EC
  label:      Private key for PIV Authentication
  ID:         01
  Usage:      decrypt, sign
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   0441040296db53c7dca7f6019624da1419923b32603672652e64643d34d23f40d6f4dc946a753d93860707032db7c64002e6300086f44725591707dc06c141bf5a7904
  EC_PARAMS:  06082a8648ce3d030107
  label:      Public key for PIV Authentication
  ID:         01
  Usage:      encrypt, verify
  Access:     local
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;generate-the-csr&#34;&gt;Generate the CSR&lt;/h3&gt;
&lt;p&gt;This should look a lot like generating every other CSR we&amp;rsquo;ve generated; not a lot of new ground
here.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ OPENSSL_CONF=openssl_user.cnf openssl req   \
    -new -engine pkcs11                       \
    -keyform engine -key slot_$KEY_SLOT-id_01 \
    -out csr/user.seth.csr
engine &amp;quot;pkcs11&amp;quot; set.
Enter PKCS#11 token PIN for YubiKey PIV #19171898:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &#39;.&#39;, the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name [WA]:
Locality Name [Seattle]:
Organization Name [Example Enterprises]:
Organizational Unit Name [Information Technology]:
Common Name []:Seth
Email Address []:seth@example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Walk the CSR over to the computer with the CA, ensure that the intermediate CA Yubikey is plugged
in, and proceed to signing the CSR.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ OPENSSL_CONF=openssl_intermediate.cnf openssl ca \
    -engine pkcs11 -keyform engine                 \
    -extfile openssl_user.cnf                      \
    -extensions usr_cert -days 365                 \
    -in csr/user.seth.csr                          \
    -out certs/user.seth.crt.pem
engine &amp;quot;pkcs11&amp;quot; set.
Using configuration from openssl_intermediate.cnf
Enter PKCS#11 token PIN for YubiKey PIV #0:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 4098 (0x1002)
        Validity
            Not Before: Jun 30 19:51:07 2022 GMT
            Not After : Jun 30 19:51:07 2023 GMT
        Subject:
            countryName               = US
            stateOrProvinceName       = WA
            localityName              = Seattle
            organizationName          = Example Enterprises
            organizationalUnitName    = Information Technology
            commonName                = Seth
            emailAddress              = seth@example.com
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Cert Type:
                SSL Client, S/MIME
            Netscape Comment:
                OpenSSL Generated Client Certificate
            X509v3 Subject Key Identifier:
                4A:3F:C1:54:2F:A3:4C:6B:E7:7A:DC:6E:3A:D1:1B:A7:35:AA:A0:C0
            X509v3 Authority Key Identifier:
                keyid:AF:60:EF:FF:07:1E:4B:CD:08:EB:78:E9:73:C1:CB:5E:9F:C9:7E:11

            X509v3 Key Usage: critical
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Client Authentication, E-mail Protection
            X509v3 CRL Distribution Points:

                Full Name:
                  URI:http://crl.example.com/intermediate.crl.pem

            Authority Information Access:
                CA Issuers - URI:http://ocsp.example.com/example-root.crt
                OCSP - URI:http://ocsp.example.com/

Certificate is to be certified until Jun 30 19:51:07 2023 GMT (365 days)
Sign the certificate? [y/n]:y
Enter PKCS#11 key PIN for Private key for Digital Signature: ******


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Take the &lt;code&gt;intermediate/certs/user.seth.crt.pem&lt;/code&gt; (or, uh, whatever name you gave it) file over to the
computer where the user&amp;rsquo;s Yubikey is plugged in, and import the signed certificate:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pkcs11-tool --module &amp;quot;$LIBYKCS11&amp;quot; \
    --login --login-type so         \
    --pin $PIN --so-pin $MGMT_KEY   \
    --slot $KEY_SLOT --id 1         \
    --write-object                  \
    certs/user.seth.crt.pem         \
    --type cert
Created certificate:
Certificate Object; type = X.509 cert
  label:      X.509 Certificate for PIV Authentication
  subject:    DN: C=US, ST=WA, L=Seattle, O=Example Enterprises, OU=Information Technology, CN=Seth/emailAddress=seth@example.com
  ID:         01
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verify it if you wish, using &lt;code&gt;ykman&lt;/code&gt; or the Yubikey Manager app:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ykman piv info
PIV version: 5.4.3
WARNING: Using default PIN!
PIN tries remaining: 3/3
WARNING: Using default Management key!
Management key algorithm: TDES
CHUID:	No data available.
CCC: 	No data available.
Slot 9a:
	Algorithm:	ECCP256
	Subject DN:	1.2.840.113549.1.9.1=seth@example.com,CN=Seth,OU=Information Technology,O=Example Enterprises,L=Seattle,ST=WA,C=US
	Issuer DN:	CN=Example Enterprises Intermediate Certificate Authority,OU=Example Enterprises Intermediate CA,O=Example Enterprises,ST=WA,C=US
	Serial:		4098
	Fingerprint:	50ed7684a902c9cebb35ced0693c1b5d347a77f4cf54141fe254354e5fce06c3
	Not before:	2022-06-30 19:51:07
	Not after:	2023-06-30 19:51:07
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;final-details&#34;&gt;Final Details&lt;/h2&gt;
&lt;p&gt;In order for any entity to be able to validate literally any of this, you&amp;rsquo;ll have to give each
client the root and intermediate CAs&#39; public keys (&lt;code&gt;ca/certs/ca.example.crt.pem&lt;/code&gt; and
&lt;code&gt;ca/intermediate/int.example.crt.pem&lt;/code&gt;). I won&amp;rsquo;t go into detail on how to do this for every platform
and browser, but generally you&amp;rsquo;ll need to either create a PFX certificate bundle or PEM bundle
containing both certificates. Generally speaking:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat intermediate/certs/int.example.crt.pem certs/ca.example.crt.pem &amp;gt; cert-bundle.pem
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;should get you working for macOS&amp;rsquo;s Keychain.app and *NIX-y things, but not Windows or Firefox. These
last two require PKCS#12 PFX files. Create one something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ openssl pkcs12 -export -nokeys \
    -passout pass:password       \
    -in cert-bundle.pem          \
    -out cert-bundle.pfx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(The password doesn&amp;rsquo;t really do anything here since the only things in the file are public
certificates.)&lt;/p&gt;
&lt;p&gt;In addition, any server that uses certificates signed by your new CA must have the intermediate
certificate available to send to clients along with its own certificate. It&amp;rsquo;s up to you to figure
out what exactly your software&amp;rsquo;s needs are. :-)&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;And there you have it. If you followed the steps in this article, you should now have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One Yubikey&amp;ndash;in a safe place&amp;ndash;that contains the private key for the root CA.&lt;/li&gt;
&lt;li&gt;One Yubikey that contains the private key for the intermediate CA.&lt;/li&gt;
&lt;li&gt;A full-blown OpenSSL CA, complete with config files for creating CAs, server certificates, and
user certificates&lt;/li&gt;
&lt;li&gt;One web server private key and certificate, signed by the intermediate CA, that you can load on
some web server somewhere&lt;/li&gt;
&lt;li&gt;One Yubikey that contains a user certificate, signed by the intermediate CA&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not bad for &lt;em&gt;*checks notes*&lt;/em&gt; 6900 words/33 minutes!&lt;/p&gt;
&lt;h2 id=&#34;sources&#34;&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc5759&#34;&gt;RFC 5759&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developers.yubico.com/PIV/Introduction/Certificate_slots.html&#34;&gt;PIV certificate slots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developers.yubico.com/yubico-piv-tool/YKCS11/Supported_applications/pkcs11tool.html&#34;&gt;OpenSC&amp;rsquo;s
pkcs11-tool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://colinpaice.blog/2021/03/08/using-openssl-with-an-hsm-keystore-and-opensc-pkcs11-engines/&#34;&gt;Using openssl with an HSM keystore, and opensc pkcs11
engines.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developers.yubico.com/PIV/Guides/Certificate_authority.html&#34;&gt;Certificate Authority with a
Yubikey&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.f5.com/t5/technical-articles/building-an-openssl-certificate-authority-introduction-and/ta-p/279500&#34;&gt;Building an OpenSSL Certificate Authority - Introduction and Design Considerations for Elliptical
Curves&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.f5.com/t5/technical-articles/building-an-openssl-certificate-authority-creating-your-root/ta-p/279520&#34;&gt;Building an OpenSSL Certificate Authority - Creating Your Root Certificate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.f5.com/t5/technical-articles/building-an-openssl-certificate-authority-creating-your/ta-p/279497&#34;&gt;Building an OpenSSL Certificate Authority - Creating Your Intermediary Certificate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.f5.com/t5/technical-articles/building-an-openssl-certificate-authority-configuring-crl-and/ta-p/279492&#34;&gt;Building an OpenSSL Certificate Authority - Configuring CRL and OCSP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://community.f5.com/t5/technical-articles/building-an-openssl-certificate-authority-creating-ecc/ta-p/279468&#34;&gt;Building an OpenSSL Certificate Authority - Creating ECC Certificates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Install Missing Docs on Alpine Linux</title>
      <link>https://www.thecrosseroads.net/2022/06/install-missing-docs-on-alpine-linux/</link>
      <pubDate>Thu, 09 Jun 2022 15:31:11 -0400</pubDate>
      
      <guid>https://www.thecrosseroads.net/2022/06/install-missing-docs-on-alpine-linux/</guid>
      <description>&lt;p&gt;So maybe you&amp;rsquo;re not using Alpine Linux &lt;em&gt;solely&lt;/em&gt; as a Docker container, and you want to have a useful
set of documentation installed. First things first: when you install packages, make sure you grab
the &lt;code&gt;-doc&lt;/code&gt; package as well (duh). So for instance, if you want to install &lt;code&gt;rsync&lt;/code&gt;, make sure you run
&lt;code&gt;apk add rsync rsync-doc&lt;/code&gt;. (Alternately, using shell expansion: &lt;code&gt;apk add rsync{,-doc}&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;But how to install any missing documentation packages for packages that have already been installed?
When trying to figure this out for myself, I found &lt;a href=&#34;https://georgegarside.com/blog/technology/alpine-linux-install-all-man-pages/&#34;&gt;this article&lt;/a&gt;, and it did a good
job of doing what I wanted, but&amp;ndash;as mentioned in the article&amp;ndash;it can be slow. Even the solution at
the end of the article took 55 seconds to enumerate 45 packages. (I think this is due to running
&lt;code&gt;apk info&lt;/code&gt; on each and every package to see whether it has a &lt;code&gt;-doc&lt;/code&gt; package or not, which takes just
takes time.)&lt;/p&gt;
&lt;p&gt;I worked on it a bit and came up with a quicker solution, which uses a single invocation of &lt;code&gt;apk search&lt;/code&gt; with the full list of potential &lt;code&gt;-doc&lt;/code&gt; packages:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ apk list -I |    # get all installed packages...
    # for all non-doc packages, strip off the version and append -doc...
    awk &#39;!/(-doc)/ { print gensub(/^(.*)-[[:digit:]].*/, &amp;quot;\\1-doc&amp;quot;, &amp;quot;g&amp;quot;, $1); }&#39; |
    # ...get apk to tell us what is real and what isn&#39;t...
    xargs apk search |
    # ...strip off the version yet again (apk add doesn&#39;t like it)...
    awk &#39;{ print gensub(/^(.*)-[[:digit:]].*/, &amp;quot;\\1&amp;quot;, &amp;quot;g&amp;quot;, $1); }&#39; |
    # ...and then actually install them.
    xargs -rt sudo apk add -i

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Doing it this way took only four seconds (down from 55!) and actually caught eleven more packages
that had docs than the other method. Not bad!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Minecraft on Apple Silicon</title>
      <link>https://www.thecrosseroads.net/2021/12/minecraft-on-apple-silicon/</link>
      <pubDate>Sun, 26 Dec 2021 15:29:23 -0500</pubDate>
      
      <guid>https://www.thecrosseroads.net/2021/12/minecraft-on-apple-silicon/</guid>
      <description>&lt;h2 id=&#34;can-i-run-minecraft-on-my-new-m1apple-silicon-mac&#34;&gt;Can I run Minecraft on my new M1/Apple Silicon Mac?&lt;/h2&gt;
&lt;p&gt;Sure! Let&amp;rsquo;s start with the simplest scenario and go get the &lt;a href=&#34;https://www.minecraft.net/en-us/store/minecraft-java-edition&#34;&gt;official Minecraft: Java Edition
client&lt;/a&gt; for macOS. Open the DMG and drag the Minecraft app to the Applications shortcut:&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/01-install-minecraft-client.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/01-install-minecraft-client_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/01-install-minecraft-client.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/01-install-minecraft-client_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/01-install-minecraft-client.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/01-install-minecraft-client.png&#34;
                alt=&#34;Minecraft installation&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;(Note that this requires you to &lt;a href=&#34;https://support.apple.com/en-us/HT211861&#34;&gt;install Rosetta 2&lt;/a&gt;, which is foreshadowing for
the rest of this post.)&lt;/p&gt;
&lt;p&gt;Log in with your Microsoft or Mojang account. Unless you have already played Minecraft through the
official launcher, the launcher should default to giving you a new 1.18.1 instance. Click &amp;ldquo;Play&amp;rdquo; and
let the launcher download all the assets it needs. Once it launches you&amp;rsquo;ll be greeted by the usual
Minecraft title screen:&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/02-minecraft-title-screen.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/02-minecraft-title-screen_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/02-minecraft-title-screen_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/02-minecraft-title-screen_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/02-minecraft-title-screen.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/02-minecraft-title-screen_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/02-minecraft-title-screen_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/02-minecraft-title-screen_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/02-minecraft-title-screen.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/02-minecraft-title-screen.png&#34;
                alt=&#34;Minecraft title screen&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;Minecraft title screen&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Create a new world just to make sure everything works, and hit F3 to take a look at your frame rate
(upper left-hand corner). It will probably be pretty low right when you start the world simply
because Minecraft is still generating chunks and whatnot, but after a few seconds it should
stabilize. On my M1 Max, I saw 21 frames per second as soon as I entered the world, but it quickly
ramped up to about 60-70 fps, with dips into the 40s and spikes into the low 100s.&lt;/p&gt;
&lt;p&gt;Just after starting the new world:&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/03-new-world-who-dis.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/03-new-world-who-dis_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/03-new-world-who-dis_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/03-new-world-who-dis_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/03-new-world-who-dis.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/03-new-world-who-dis_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/03-new-world-who-dis_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/03-new-world-who-dis_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/03-new-world-who-dis.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/03-new-world-who-dis.png&#34;
                alt=&#34;26fps: not great&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;26fps: not great&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&amp;hellip;and after a few minutes:&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/04-60fps.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/04-60fps_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/04-60fps_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/04-60fps_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/04-60fps.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/04-60fps_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/04-60fps_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/04-60fps_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/04-60fps.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/04-60fps.png&#34;
                alt=&#34;60fps after chunk generation settled&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;60fps after chunk generation settled&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Not bad. Let&amp;rsquo;s quit the game and see if we can do better.&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/05-crashed.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/05-crashed_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/05-crashed_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/05-crashed_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/05-crashed.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/05-crashed_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/05-crashed_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/05-crashed_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/05-crashed.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/05-crashed.png&#34;
                alt=&#34;Minecraft crashes on quit&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;This did not go according to plan&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&amp;hellip;Uh, wait a minute. The game crashed! I don&amp;rsquo;t remember that happening on my Intel-based MacBook
Pro. We should probably investigate that.&lt;/p&gt;
&lt;p&gt;(Note: maybe don&amp;rsquo;t immediately start doing all the things I do in this article, as you read it. I
wrote it in a stream-of-consciousness style, walking through various reasonable steps a reasonably
technical person might do, so you can better understand the &lt;em&gt;why&lt;/em&gt; of the solution I present
here. When doing my own research to get Minecraft working as well as I could on my M1 Max, I found a
number of GitHub gists and blog posts that essentially boiled down to, &amp;ldquo;just go download these
random binaries someone built and run this wrapper script and everything will be alright!&amp;rdquo; There&amp;rsquo;s
nothing inherently &lt;em&gt;wrong&lt;/em&gt; with that, and if you&amp;rsquo;d rather just get things working and don&amp;rsquo;t care
about seeing me blather on, I encourage you to seek those resources out. But I needed to understand
why those steps are necessary and wanted to use binaries &lt;em&gt;I&lt;/em&gt; built instead of trusting someone
else&amp;rsquo;s year-old builds, and wanted to pass on that knowledge to others who might find it useful.)&lt;/p&gt;
&lt;h2 id=&#34;intel-arm-and-universal-binaries-oh-my&#34;&gt;Intel, Arm, and Universal Binaries, Oh My!&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;ve had your Apple Silicon-based Mac for a bit, you may have come across software that is not
optimized for the M1 processor. Instead, the software is built for Intel-based Macs (which have been
around since 2006), and this software will not run on an M1-based Mac without Rosetta 2
installed. &lt;a href=&#34;https://en.wikipedia.org/wiki/Rosetta_(software)#Rosetta_2&#34;&gt;Rosetta 2&lt;/a&gt; is a layer that interprets the Intel machine instructions and translates
them to the native Arm instruction set that the M1 processor can understand. As you can imagine,
this translation does not come for free, and running Intel-only apps on an M1 Mac can be much slower
than if it was natively built for the M1.&lt;/p&gt;
&lt;p&gt;You may have never (or very rarely) had to actively decide whether to download and install an Intel
(also called &amp;ldquo;amd64&amp;rdquo; or &amp;ldquo;x86-64&amp;rdquo;) versus an Apple Silicon (&amp;ldquo;M1&amp;rdquo;, &amp;ldquo;arm64&amp;rdquo;, or &amp;ldquo;aarch64&amp;rdquo;) app. This is
because Apple has what they call &amp;ldquo;Universal Binaries&amp;rdquo;, which just means that one executable file can
contain a version of the code compiled for Intel as well as another version compiled for the
M1. This is what most developers target nowadays, so that their app will run natively regardless of
whether it runs on an Intel or Apple Silicon processor.&lt;/p&gt;
&lt;p&gt;With the technicalities dispensed with, we can easily see whether an app was compiled for the M1 or
whether it&amp;rsquo;s running under Rosetta 2. Open Activity Monitor (check in the &lt;em&gt;Utilities&lt;/em&gt; folder under
&lt;em&gt;Applications&lt;/em&gt;, or use Spotlight to find it) and check the &amp;ldquo;Kind&amp;rdquo; column. If it says &amp;ldquo;Apple&amp;rdquo;, then
that software has been compiled for the M1. If it says &amp;ldquo;Intel&amp;rdquo;, though, then you can be sure that
macOS is using Rosetta 2 to run the app, and performance may not be on-par with what you might
expect from your fancy (and expensive) new machine. Let&amp;rsquo;s take a look at the &lt;code&gt;java&lt;/code&gt; process when
Minecraft starts up:&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/06-intel-jvm.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/06-intel-jvm.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/06-intel-jvm.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/06-intel-jvm.png&#34;
                alt=&#34;Activity Monitor showing java running as an Intel process&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Hm, Intel.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;But wait,&amp;rdquo; you say, &amp;ldquo;I don&amp;rsquo;t remember installing Java!&amp;rdquo; True: Minecraft bundles its own JRE (&amp;ldquo;Java
Runtime Environment&amp;rdquo;) so that you don&amp;rsquo;t have to bring one to the party. It also lets them update it
so you don&amp;rsquo;t have to remember to do so.&lt;/p&gt;
&lt;p&gt;So what we&amp;rsquo;ve discovered here is that the Java runtime that comes with Minecraft is not optimized
for the M1 processor, so Rosetta 2 has to translate the entire Minecraft experience from Intel
instructions to M1&amp;rsquo;s &amp;ldquo;Arm&amp;rdquo; instructions. That can&amp;rsquo;t be good for performance. Can we fix that, maybe?&lt;/p&gt;
&lt;h2 id=&#34;byo-jre&#34;&gt;BYO JRE&lt;/h2&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/07-java-executable.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/07-java-executable_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/07-java-executable_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/07-java-executable_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/07-java-executable.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/07-java-executable_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/07-java-executable_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/07-java-executable_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/07-java-executable.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/07-java-executable.png&#34;
                alt=&#34;You can set a different Java executable if you need to&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;You can set a different Java executable if you need to&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;It turns out, maybe we can! The Minecraft launcher lets you bring your own JRE to the party if you
really want to. What if we got a native M1 &amp;ldquo;arm64&amp;rdquo; version of Java 17 and told Minecraft to use that?&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll need to get yourself a Java runtime built for Arm instead of Intel. The easiest way to do
this is to head to &lt;a href=&#34;https://adoptium.net&#34;&gt;Adoptium&lt;/a&gt; or &lt;a href=&#34;https://www.azul.com/downloads/?version=java-17-lts&amp;amp;os=macos&amp;amp;architecture=arm-64-bit&amp;amp;package=jre&#34;&gt;Azul&lt;/a&gt;, both of which offer OpenJDK builds for a number of
different platforms. (I used the Azul JVMs for this post.) I suggest getting the JDK (Java
Development Kit) over the JRE because it comes with niceties like the Java compiler.&lt;/p&gt;
&lt;p&gt;What was that? Why do you need a Java compiler if we&amp;rsquo;re not compiling anything? &lt;em&gt;*looks at the rest
of this post*&lt;/em&gt; Uh, no reason&amp;hellip;&lt;/p&gt;
&lt;p&gt;Go to the Azul link above and click the &amp;ldquo;.dmg&amp;rdquo; link. Once downloaded, open the DMG and follow the
instructions to install Java 17 where macOS likes them to be
(&lt;code&gt;/Library/Java/JavaVirtualMachines/&lt;/code&gt;). The next thing you need to do is tell Minecraft to use this
instead of its bundled version. In the Minecraft launcher, click the &amp;ldquo;Installations&amp;rdquo; tab at the top
of the window, then click on your 1.18 instance. In the Edit screen that comes up, choose &amp;ldquo;More
Options&amp;rdquo;; on the &amp;ldquo;Java Executable&amp;rdquo; line, either click Browse to find the &lt;code&gt;java&lt;/code&gt; command you want to
use or, if you&amp;rsquo;re following along with me, just right-click and paste
&lt;code&gt;/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/bin/java&lt;/code&gt; into the box.&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/08-arm-jvm.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/08-arm-jvm_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/08-arm-jvm_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/08-arm-jvm_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/08-arm-jvm.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/08-arm-jvm_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/08-arm-jvm_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/08-arm-jvm_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/08-arm-jvm.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/08-arm-jvm.png&#34;
                alt=&#34;Java executable has been set to our newly-downloaded JVM&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;Java executable has been set to our newly-downloaded JVM&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Click Save, and then click Play! Congratulations, you&amp;rsquo;re done!&amp;ndash;uh, wait a minute.&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/09-arm64-crash.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/09-arm64-crash_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/09-arm64-crash_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/09-arm64-crash_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/09-arm64-crash.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/09-arm64-crash_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/09-arm64-crash_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/09-arm64-crash_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/09-arm64-crash.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/09-arm64-crash.png&#34;
                alt=&#34;Minecraft launcher crashes on startup with an arm64 Java build&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;Well this was un^H^Hexpected&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;(This is the part where I hope you weren&amp;rsquo;t actually following along with me, because at this point
you&amp;rsquo;re probably not terribly happy with me.)&lt;/p&gt;
&lt;h2 id=&#34;well-that-didnt-work&#34;&gt;Well That Didn&amp;rsquo;t Work&lt;/h2&gt;
&lt;p&gt;What do we do now? We didn&amp;rsquo;t even get a crash report like our last crash to figure out what might
have happened. Fortunately there are still log files we can look at. The logs are in
&lt;code&gt;~/Library/ApplicationSupport/minecraft&lt;/code&gt;, and the summary is that one of the libraries that
Minecraft uses for graphics (LWJGL) failed to load. I guess we&amp;rsquo;ll need to investigate that, now.&lt;/p&gt;
&lt;p&gt;At this point, though, we&amp;rsquo;ve gone about as far as we can (should?) with the official Minecraft
launcher. What we need is something that will make it easier to tweak our Minecraft instance&amp;rsquo;s
various Java settings.&lt;/p&gt;
&lt;h2 id=&#34;enter-multimc&#34;&gt;Enter MultiMC&lt;/h2&gt;
&lt;p&gt;From their website, &amp;ldquo;&lt;a href=&#34;https://multimc.org&#34;&gt;MultiMC&lt;/a&gt; is an alternative launcher for Minecraft. It allows you to have
multiple, cleanly separated instances of Minecraft (each with their own mods, resource packs, saves,
etc) and helps you manage them and their associated options with a simple and powerful interface.&amp;rdquo;
On the left-hand side of the MultiMC main page, find the &amp;ldquo;Download &amp;amp; Install&amp;rdquo; link, then choose to
download the &amp;ldquo;Mac OS X&amp;rdquo; version (&lt;a href=&#34;https://files.multimc.org/downloads/mmc-stable-osx64.tar.gz&#34;&gt;direct link&lt;/a&gt;). Double-click the file and it will
unpack the MultiMC app. You can drag that into your Applications folder (or wherever else you want
to put it). Once you have it installed, open the app and create a new Minecraft instance by clicking
the &amp;ldquo;Add instance&amp;rdquo; button. Choose &amp;ldquo;1.18.1&amp;rdquo; as the version, give it a name if you like and click OK.&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/10-multimc-add-instance.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/10-multimc-add-instance_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/10-multimc-add-instance_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/10-multimc-add-instance.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/10-multimc-add-instance_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/10-multimc-add-instance_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/10-multimc-add-instance.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/10-multimc-add-instance.png&#34;
                alt=&#34;MultiMC new installation window&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Now we can start customizing our new install. First we need to ensure the instance runs with the
proper Java version&amp;ndash;which, in the case of 1.18, is Java 17. (Other Minecraft versions require
different versions of Java, which is beyond the scope of this post.) Since we downloaded one for our
previous (failed) attempt using the Minecraft launcher, we&amp;rsquo;ll use that one.&lt;/p&gt;
&lt;p&gt;If you only have a single JVM installed, MultiMC will probably do the right thing and automatically
use it. If you have multiple JVMs installed&amp;ndash;say, you want to play vanilla Minecraft 1.18 as well as
an older 1.16 or 1.12 world&amp;ndash;then you&amp;rsquo;ll need to tell MultiMC which JVM to use for each instance.&lt;/p&gt;
&lt;p&gt;Select the instance icon in the middle pane and click &amp;ldquo;Edit instance&amp;rdquo; in the menu on the right-hand
side. In the window that appears, click Settings on the left.&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/11-instance-settings.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/11-instance-settings_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/11-instance-settings_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/11-instance-settings_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/11-instance-settings.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/11-instance-settings_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/11-instance-settings_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/11-instance-settings_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/11-instance-settings.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/11-instance-settings.png&#34;
                alt=&#34;MultiMC instance settings window&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Select the checkbox next to &amp;ldquo;Java installation&amp;rdquo;. If the path that appears isn&amp;rsquo;t correct, you can
click &amp;ldquo;Auto-detect&amp;rdquo; and choose the correct one. (Remember: for 1.18 we&amp;rsquo;re looking for Java 17.)&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/12-choose-your-own-jvm.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/12-choose-your-own-jvm_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/12-choose-your-own-jvm_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/12-choose-your-own-jvm_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/12-choose-your-own-jvm.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/12-choose-your-own-jvm_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/12-choose-your-own-jvm_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/12-choose-your-own-jvm_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/12-choose-your-own-jvm.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/12-choose-your-own-jvm.png&#34;
                alt=&#34;MultiMC instance Java installation selection&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;At this point, we&amp;rsquo;ve set up MultiMC the same way as our failed official Minecraft launcher
experiment&amp;hellip;which means that if you started your new instance now, it would most likely result in
the same failure we saw earlier. We now have to tackle that LWJGL error.&lt;/p&gt;
&lt;h2 id=&#34;that-lwjgl-error&#34;&gt;That LWJGL Error&lt;/h2&gt;
&lt;p&gt;To make a long story, uh, less long, the &lt;a href=&#34;https://www.lwjgl.org/&#34;&gt;LWJGL&lt;/a&gt; Java library also includes &amp;ldquo;native&amp;rdquo; code (i.e.,
not Java bytecode) that needs to match the architecture of the JVM that loads it. In other words, if
you want to load the LWJGL library into a JVM compiled for Intel Macs, you will not only need the
(processor-agnostic) Java components of the library, but also some library files compiled for Intel
processors; similarly, if you run the Arm-compiled JVM, you&amp;rsquo;ll need LWJGL libraries compiled for the
M1 (Arm-based) processor.&lt;/p&gt;
&lt;p&gt;Can you guess where our crash is coming from? If you guessed &amp;ldquo;Minecraft bundles Intel-only versions
of the LWJGL natives and we&amp;rsquo;re trying to run an Arm JVM to avoid the Rosetta 2 tax,&amp;rdquo; you guessed
right!&lt;/p&gt;
&lt;p&gt;So, where do we get these native libraries? From the official LWJGL website, of course. They provide
a neat way to download a &lt;a href=&#34;https://www.lwjgl.org/customize&#34;&gt;customized version&lt;/a&gt; of the LWJGL library files. To make
it easy, you can load &lt;a href=&#34;../downloads/code/lwjgl-release-all-zip.json&#34;&gt;this config&lt;/a&gt; and then click &amp;ldquo;Download&amp;rdquo;. After a bit, you&amp;rsquo;ll get
a ZIP file of all the resources you requested. Find this file in Finder and double-click it to unzip
it into a folder named &amp;ldquo;lwjgl-release-3.3.0-custom&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;At this point, you&amp;rsquo;ll need to open Terminal.app (or your favorite terminal app) so you can run some
things on the command line. What we&amp;rsquo;re going to do is take all of the JAR files in that ZIP file we
downloaded, extract them all into a single base directory, and repack them into a single JAR
file. (Why do this? To make it easier for us, as we only have to specify a single JAR file to add to
the Java classpath.)&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ pwd
/Users/seth/Downloads/lwjgl-release-3.3.0-custom
$ mkdir -p extracted
$ cd extracted/
$ for f in ../*.jar; do jar -xf &amp;quot;$f&amp;quot;; done
$ jar cf ../../lwjgl-release-3.3.0.jar .
$ ls -lah ../../lwjgl-release-3.3.0.jar
-rw-r--r--  1 seth  staff    18M Dec 26 19:19 ../../lwjgl-release-3.3.0.jar
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At the end of this you will have a file called &lt;code&gt;lwjgl-release-3.3.0.jar&lt;/code&gt; in the same directory where
the downloaded ZIP file exists. The last step of this process is to move that file into a directory
where MultiMC can find it, and then tell MultiMC to use it.&lt;/p&gt;
&lt;p&gt;Back in MultiMC, select your 1.18 instance again and click &amp;ldquo;Edit instance&amp;rdquo; just as before. This time
click the &amp;ldquo;Version&amp;rdquo; tab on the left.&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/13-multimc-versions.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/13-multimc-versions_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/13-multimc-versions_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/13-multimc-versions_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/13-multimc-versions.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/13-multimc-versions_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/13-multimc-versions_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/13-multimc-versions_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/13-multimc-versions.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/13-multimc-versions.png&#34;
                alt=&#34;MultiMC Versions window&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;See that line for LWJGL 3? We need to edit that. Click the &amp;ldquo;Customize&amp;rdquo; button on the right side,
then click &amp;ldquo;Edit&amp;rdquo;. This should bring up a TextEdit window with some default JSON stuff in it. Select
everything, delete it, and then paste the following into the window instead:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;formatVersion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;libraries&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;lwjgl:lwjgl-release-3.3.0:1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;#34;MMC-hint&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;local&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;#34;MMC-filename&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;lwjgl-release-3.3.0.jar&amp;#34;&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;LWJGL 3&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;releaseTime&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2019-06-24T12:52:52+00:00&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;release&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;org.lwjgl3&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;3.3.0&amp;#34;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That tells MultiMC to use the JAR file we created instead of its defaults. With that done, we now
need to move our new JAR file into the right place. Close the TextEdit window and, back in MultiMC,
click the &amp;ldquo;Open libraries&amp;rdquo; button on the right. It will open a Finder window. Move (or copy and
paste) the &lt;code&gt;lwjgl-release-3.3.0.jar&lt;/code&gt; we created earlier into this directory. Close the Finder
window.&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/14-jar-copied.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/14-jar-copied_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/14-jar-copied_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/14-jar-copied_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/14-jar-copied.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/14-jar-copied_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/14-jar-copied_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/14-jar-copied_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/14-jar-copied.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/14-jar-copied.png&#34;
                alt=&#34;Finder window showing that we&amp;#39;ve copied the LWJGL jar file into the correct location&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Let&amp;rsquo;s go ahead and click the &amp;ldquo;Launch&amp;rdquo; button in the lower right and see what happens. Cross our
fingers, and&amp;hellip;&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/15-fps-with-arm64-jvm.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/15-fps-with-arm64-jvm_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/15-fps-with-arm64-jvm_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/15-fps-with-arm64-jvm_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/15-fps-with-arm64-jvm.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/15-fps-with-arm64-jvm_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/15-fps-with-arm64-jvm_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/15-fps-with-arm64-jvm_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/15-fps-with-arm64-jvm.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/15-fps-with-arm64-jvm.png&#34;
                alt=&#34;100fps with no other changes!&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;100fps with no other changes!&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Whoa, success! And we&amp;rsquo;ve gained about 40 frames per second after all this for an average of around
100fps. Not bad! Let&amp;rsquo;s go into our Minecraft video settings and make this window full-screen so we
can see it in all its glory&amp;ndash;&lt;/p&gt;
&lt;p&gt;Uh, wait a minute.&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/16-fullscreen-crash.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/16-fullscreen-crash_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/16-fullscreen-crash_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/16-fullscreen-crash_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/16-fullscreen-crash.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/16-fullscreen-crash_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/16-fullscreen-crash_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/16-fullscreen-crash_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/16-fullscreen-crash.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/16-fullscreen-crash.png&#34;
                alt=&#34;Crash report due to trying to full-screen the Minecraft window&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;pls to stahp with all the crashing&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/vadernoo.jpg&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/vadernoo.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/vadernoo.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/vadernoo.jpg&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;*&lt;em&gt;ahem*&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Okay. So at least we&amp;rsquo;ve made progress, right? That&amp;rsquo;s a thing that&amp;rsquo;s happened.&lt;/p&gt;
&lt;h2 id=&#34;break-out-your-compiler&#34;&gt;Break Out Your Compiler&lt;/h2&gt;
&lt;p&gt;In for a penny, in for a pound, right?&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve stumbled on another Java library that requires native code; one that unfortunately is not
shipped as a Universal binary, but containing only Intel-specific instructions. This time it&amp;rsquo;s the
&lt;a href=&#34;https://github.com/shannah/Java-Objective-C-Bridge/&#34;&gt;Java Objective-C Bridge&lt;/a&gt;. Thankfully, this library added support for M1 Macs about a month prior
to when I wrote this post (but hasn&amp;rsquo;t yet pushed a new version to Maven Central, I guess), so we
&amp;ldquo;just&amp;rdquo; have to compile it on our own.&lt;/p&gt;
&lt;p&gt;This is the part where you&amp;rsquo;ll be glad you listened to me earlier and downloaded a JDK (Java
Development Kit) instead of just the JRE.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll also need &lt;a href=&#34;https://maven.apache.org&#34;&gt;Apache Maven&lt;/a&gt;, a tool used to build Java projects. I&amp;rsquo;m not going to go into how
to download and install it (although it&amp;rsquo;s really as simple as &amp;ldquo;download and make sure the &lt;code&gt;bin/&lt;/code&gt;
directory is in your &lt;code&gt;$PATH&lt;/code&gt;&amp;quot;); you can find those resources elsewhere.&lt;/p&gt;
&lt;p&gt;And, uh, not to bury the lede here, but you will also need Xcode&amp;ndash;or at least the command-line
tools, which I think (&lt;em&gt;think&lt;/em&gt;) you can install by running &lt;code&gt;xcode-select --install&lt;/code&gt; in your
terminal. (Unfortunately I did not realize this was a requirement until after I wrote the whole post
and was proofreading it&amp;ndash;I already had Xcode installed&amp;ndash;or I would have better guidance here.) Since
Xcode is such a large download, this is really a bit out of the way just to play Minecraft if you
don&amp;rsquo;t already have it installed.&lt;/p&gt;
&lt;p&gt;But if you&amp;rsquo;re all-in on this little experiment and you have all the tools, you can follow the README
and run &lt;code&gt;mvn clean install&lt;/code&gt; and watch it go. At the end you&amp;rsquo;ll have a JAR in the &lt;code&gt;target/&lt;/code&gt;
directory:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ls -lah target/java-objc-bridge-1.1-SNAPSHOT.jar
-rw-r--r--  1 seth  staff    91K Dec 27 00:20 target/java-objc-bridge-1.1-SNAPSHOT.jar
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Just like we did before, we need to copy this JAR into a place that MultiMC can find it. This time,
though, we need to create our own &amp;ldquo;custom package&amp;rdquo;. Start by navigating to the same &amp;ldquo;Version&amp;rdquo;
configuration window where we edited the LWJGL config and click &amp;ldquo;Add Empty&amp;rdquo;. You can make the name
&amp;ldquo;java-objc-bridge&amp;rdquo; and the uid &amp;ldquo;ca.weblite.java-objc-bridge&amp;rdquo;, then click Edit and paste the
following JSON into the editor window:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;formatVersion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;libraries&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;#34;MMC-filename&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;java-objc-bridge-1.1-SNAPSHOT.jar&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;#34;MMC-hint&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;local&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;java-objc-bridge:java-objc-bridge-1.1-SNAPSHOT:1&amp;#34;&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;java-objc-bridge&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;snapshot&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ca.weblite.java-objc-bridge&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;1.1&amp;#34;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Close the window, then click the &amp;ldquo;Move up&amp;rdquo; button until our new custom package is at the top of the
list. Now click &amp;ldquo;Open libraries&amp;rdquo; and copy the &lt;code&gt;java-objc-bridge-1.1-SNAPSHOT.jar&lt;/code&gt; file you just
built into the libraries folder, right next to the LWJGL one we added earlier.&lt;/p&gt;
&lt;p&gt;Phew! Let&amp;rsquo;s try this again!&lt;/p&gt;


&lt;figure&gt;
    &lt;a href=&#34;../2021/12/minecraft-on-apple-silicon/img/17-fullscreen-works.png&#34; target=&#34;_blank&#34;&gt;
        &lt;picture&gt;
            &lt;source type=&#34;image/avif&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/17-fullscreen-works_640w.avif 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/17-fullscreen-works_1280w.avif 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/17-fullscreen-works_1920w.avif 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/17-fullscreen-works.avif&#39;&gt;
            &lt;source type=&#34;image/webp&#34; sizes=&#34;90vw&#34;
                srcset=&#39;
                    /2021/12/minecraft-on-apple-silicon/img/17-fullscreen-works_640w.webp 640w, 
                    /2021/12/minecraft-on-apple-silicon/img/17-fullscreen-works_1280w.webp 1280w, 
                    /2021/12/minecraft-on-apple-silicon/img/17-fullscreen-works_1920w.webp 1920w, 
                    /2021/12/minecraft-on-apple-silicon/img/17-fullscreen-works.webp&#39;&gt;
            &lt;img src=&#34;../2021/12/minecraft-on-apple-silicon/img/17-fullscreen-works.png&#34;
                alt=&#34;Minecraft video settings showing Fullscreen: ON&#34;&gt;
        &lt;/picture&gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;This has been a long post coming&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;FINALLY.&lt;/p&gt;
&lt;h2 id=&#34;lets-wrap-this-up&#34;&gt;Let&amp;rsquo;s Wrap This Up&lt;/h2&gt;
&lt;p&gt;Well that was a lot of fun, wasn&amp;rsquo;t it? (You can stop laughing now.)&lt;/p&gt;
&lt;p&gt;This will get you working for Minecraft 1.18. Other (older) versions of Minecraft use a different
Java version and rely on different libraries (or different versions of the same libraries we&amp;rsquo;ve
already seen), and so each may pose their own unique challenges to getting a fully-native Minecraft
experience set up. Hopefully Mojang will support the M1 natively in the near future, at which point
none of this post will be relevant any longer.&lt;/p&gt;
&lt;p&gt;At the time of this writing, a fork of MultiMC (called &amp;ldquo;&lt;a href=&#34;https://github.com/MinecraftMachina/ManyMC&#34;&gt;ManyMC&lt;/a&gt;&amp;quot;) exists that supposedly solves
all of these problems for you, for many versions of Minecraft and Minecraft Forge. Right now it has
a large disclaimer on the top of the README, cautioning that it is an unofficial project, so its
state of support may change at any time. I like how that project handles transparently serving
corrected natives. One drawback for me is that in my limited poking at it and its various supporting
repos, all I found were compiled JARs and not the patches required&amp;ndash;if any&amp;ndash;to get them working on
the M1. I would approach it with the same hesitancy as I do the other &amp;ldquo;Minecraft on M1&amp;rdquo; hacks that
ask you to download precompiled JARs that come without source code. No, the authors are not required
to provide the sources (unless the code&amp;rsquo;s license requires it), especially if all they&amp;rsquo;re doing is
recompiling the library to get arm64 natives. And I&amp;rsquo;m sure that many people who just want Minecraft
to work well on their new Apple Silicon won&amp;rsquo;t care about this aspect of it, and that&amp;rsquo;s perfectly
okay. Heck, I&amp;rsquo;ve been known to pipe &lt;code&gt;curl&lt;/code&gt; to &lt;code&gt;sh&lt;/code&gt; a few times, myself, so maybe I&amp;rsquo;m being
hypocritical here. I guess in this instance it would just be nice if I could both trust &lt;em&gt;and&lt;/em&gt;
verify.&lt;/p&gt;
&lt;p&gt;So, almost 3,000 words later: do what you want, play Minecraft the way you want, and have some fun!&lt;/p&gt;
&lt;p&gt;Maybe in a part 2 we can see what it will take to get a Minecraft Forge-based client up and running.
(Spoiler alert: more of the same, really!)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Pocket, Please Let Me Rename Things.</title>
      <link>https://www.thecrosseroads.net/2020/12/pocket-please-let-me-rename-things./</link>
      <pubDate>Tue, 29 Dec 2020 15:26:19 -0500</pubDate>
      
      <guid>https://www.thecrosseroads.net/2020/12/pocket-please-let-me-rename-things./</guid>
      <description>&lt;p&gt;Sometimes I just want to name things the way I deem fit. &lt;a href=&#34;https://www.getpocket.com&#34;&gt;Pocket&lt;/a&gt;, back when they were
called &amp;ldquo;Read It Later&amp;rdquo;, used to include this functionality. Somewhere along the way, Pocket decided
to remove that feature in preference to augmenting their product to do a &lt;em&gt;really good job&lt;/em&gt; of
figuring out what an article&amp;rsquo;s title should be. However, there are still many times that it would be
helpful to have the ability to manually rename an article. I&amp;rsquo;ll detail some problematic articles
below, with screenshots.&lt;/p&gt;
&lt;h2 id=&#34;but-first-history&#34;&gt;But First, History&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been using Pocket since it was named &lt;em&gt;Read It Later&lt;/em&gt;; &lt;a href=&#34;https://en.wikipedia.org/wiki/Pocket_(service)&#34;&gt;Wikipedia tells me&lt;/a&gt; (in a
roundabout fashion) that that means I&amp;rsquo;ve most likely used the service for over a decade. I&amp;rsquo;ve used
it on Android phones, iOS devices, even Windows phones. I&amp;rsquo;ve used the actual website. I keep
&amp;ldquo;Recommended by Pocket&amp;rdquo; as the only thing on my new tab/window page in Firefox.&lt;/p&gt;
&lt;p&gt;Wikipedia also tells me that &lt;a href=&#34;https://getpocket.com/premium&#34;&gt;Pocket Premium&lt;/a&gt; has been A Thing™ since May
2014; I&amp;rsquo;ve been a subscriber since June of the same year. Needless to say, &lt;em&gt;I like this product&lt;/em&gt;,
and I will continue to use it for quite some time, I&amp;rsquo;m sure.&lt;/p&gt;
&lt;p&gt;I can&amp;rsquo;t find it any longer, but there used to be a support forum for Pocket, with a number of
threads asking for rename (or &lt;em&gt;title editing&lt;/em&gt;) support. I marked a few as helpful (or upvoted, or
whatever you were supposed to do to them to register relevance without &amp;ldquo;me too&amp;rdquo;&amp;lsquo;ing the post), and
even (if I recall correctly) wrote some comments expressing my desire for the feature. The feature
requests were denied back then for the same reason the feature request &lt;a href=&#34;https://help.getpocket.com/article/1063-pockets-top-feature-requests#coreimprovements&#34;&gt;isn&amp;rsquo;t considered
today&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While we don’t currently offer title editing functionality, we encourage you to report any
incorrect titles so we can try to get them fixed!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(But I &lt;em&gt;will&lt;/em&gt; note that that feature seems to be under consideration now, so perhaps this post is
timely!)&lt;/p&gt;
&lt;h2 id=&#34;why-allow-title-editing&#34;&gt;Why Allow Title Editing?&lt;/h2&gt;
&lt;p&gt;So, if Pocket does a &lt;em&gt;really good job&lt;/em&gt; of extracting titles from articles most of the time, why do I
even need the ability to rename articles myself? Well, as with everything in life, nothing is
perfect. Pocket recognizes this, and does give you a way to &lt;a href=&#34;https://getpocket.com/contact_support?subject=Reporting%20an%20issue%20with%20Article%20View&amp;amp;&amp;amp;message=Article%20URL:%0DDescription%20of%20Issue:&#34;&gt;report items with incorrect
titles&lt;/a&gt;. While that&amp;rsquo;s a great option to have, &lt;em&gt;it doesn&amp;rsquo;t help me in the
moment&lt;/em&gt;. Another option that the &lt;a href=&#34;https://help.getpocket.com/article/1063-pockets-top-feature-requests#coreimprovements&#34;&gt;help article&lt;/a&gt; suggests is that users use Tags
&amp;ldquo;&amp;hellip;as a way to help identify and organize items that might not have a title that helps you identify
them easily.&amp;rdquo; That sounds okay on the surface, but I humbly suggest that the best tag to help me
identify an article easily &lt;em&gt;is the title of the article&lt;/em&gt;. I use Tags as just that: tags, or
categories, to help me &amp;ldquo;group&amp;rdquo; articles together. I have tags for computer-related articles,
science, programming, health, etc. If I had to guess, this is probably how most people use
tags. Using a tag to help identify a badly-named article seems antithetical to what I see as the
main use of tags.&lt;/p&gt;
&lt;h2 id=&#34;but-how-bad-is-it-really&#34;&gt;But How Bad is it, Really?&lt;/h2&gt;
&lt;p&gt;Not that bad. Really! As I&amp;rsquo;ve said, most of the time Pocket gets it right. But I think that there
will always be some web pages that Pocket can &lt;em&gt;never&lt;/em&gt; name properly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://homepages.inf.ed.ac.uk/wadler/papers/papers-we-love/landin-next-700.pdf&#34;&gt;Technical PDFs&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/SimpleMadeEasy.md&#34;&gt;Github pages&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://len.falken.ink/misc/writing-for-the-internet-across-a-human-lifetime.txt&#34;&gt;Some random person&amp;rsquo;s non-marked-up personal web page&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are only three examples, but I&amp;rsquo;m sure you can think of a thousand more, given the size of the
Internet.&lt;/p&gt;
&lt;h2 id=&#34;yes-but-citation-needed&#34;&gt;Yes, But [Citation Needed]&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;re right, so here you go. There&amp;rsquo;s no way this list will look good, because it&amp;rsquo;s just a bunch of
screenshots and I&amp;rsquo;m not a designer. Clicking on the screenshots will show you how the article looks
in Pocket.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.executeprogram.com/blog/teaching-the-unfortunate-parts&#34;&gt;Teaching the Unfortunate Parts&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/A561FD10-B97E-46F2-A37A-3343A5292B73_1_201_a.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/A561FD10-B97E-46F2-A37A-3343A5292B73_1_201_a_huf973257bcf871ef13ffb308ffa474937_71215_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/A561FD10-B97E-46F2-A37A-3343A5292B73_1_201_a_huf973257bcf871ef13ffb308ffa474937_71215_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/A561FD10-B97E-46F2-A37A-3343A5292B73_1_201_a.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.jonstodle.com/youre-allowed-to-write-slow-rust-code/&#34;&gt;You&amp;rsquo;re Allowed to Write Slow Rust Code&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/10805C63-AF25-4842-BE39-C7EE71689244_1_105_c.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/10805C63-AF25-4842-BE39-C7EE71689244_1_105_c_hu8db5f6879d58d1062f7a82b646ad6318_19247_480x0_resize_q75_box.jpeg 500w
                    
                    
                    &#39;
            
            src=&#34;../img/pocket/10805C63-AF25-4842-BE39-C7EE71689244_1_105_c.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://pgjones.dev/blog/rest-api-evolution-2020/&#34;&gt;My evolution writing JSON-REST APIs&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/CFAAEFBB-4FE9-4719-929D-32977B60D569_1_105_c.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/CFAAEFBB-4FE9-4719-929D-32977B60D569_1_105_c_huf6ebf742326fa91ec4dde12690859ac3_66697_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/CFAAEFBB-4FE9-4719-929D-32977B60D569_1_105_c_huf6ebf742326fa91ec4dde12690859ac3_66697_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/CFAAEFBB-4FE9-4719-929D-32977B60D569_1_105_c.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;del&gt;&lt;a href=&#34;https://samcurry.net/hacking-apple/&#34;&gt;We Hacked Apple for 3 Months: Here’s What We Found&lt;/a&gt;&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;(This one &lt;em&gt;was&lt;/em&gt; wrong, but sometime between when I saved the article and when I wrote this post,
they corrected it! Sadly, the only way I knew about the update was because the web view showed the
title correctly, leading me to refresh the reading list on my iPhone and get the updated title
there. I&amp;rsquo;m not sure how I would have discovered this otherwise, which is a different issue,
really; probably dealing with the Permanent Library feature of Pocket Premium&amp;hellip;maybe?)&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/92FA2C5F-E929-40F2-ACF4-BAEBBCF99CDD_1_105_c.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/92FA2C5F-E929-40F2-ACF4-BAEBBCF99CDD_1_105_c_hu32dd1231780a41662fad10cafe7b3d4b_69388_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/92FA2C5F-E929-40F2-ACF4-BAEBBCF99CDD_1_105_c_hu32dd1231780a41662fad10cafe7b3d4b_69388_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/92FA2C5F-E929-40F2-ACF4-BAEBBCF99CDD_1_105_c.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://spectrum.ieee.org/computing/it/inside-hidden-world-legacy-it-systems&#34;&gt;Inside the Hidden World of Legacy IT Systems&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/BCA8C747-4791-400F-9B42-0E0C5B42122D_1_201_a.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/BCA8C747-4791-400F-9B42-0E0C5B42122D_1_201_a_huf973257bcf871ef13ffb308ffa474937_64584_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/BCA8C747-4791-400F-9B42-0E0C5B42122D_1_201_a_huf973257bcf871ef13ffb308ffa474937_64584_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/BCA8C747-4791-400F-9B42-0E0C5B42122D_1_201_a.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.walknsqualk.com/post/014-tiny-fpga-bx/&#34;&gt;FPGA Design for Software Engineers&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/5967C678-2EA3-49B0-B759-1ACB54DFA77C_1_201_a.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/5967C678-2EA3-49B0-B759-1ACB54DFA77C_1_201_a_huf973257bcf871ef13ffb308ffa474937_110878_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/5967C678-2EA3-49B0-B759-1ACB54DFA77C_1_201_a_huf973257bcf871ef13ffb308ffa474937_110878_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/5967C678-2EA3-49B0-B759-1ACB54DFA77C_1_201_a.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Those random PDFs I mentioned earlier (mmm, bacon; sadly, that paper is titled, &amp;ldquo;&lt;a href=&#34;https://researcher.watson.ibm.com/researcher/files/us-bacon/Bacon04Unified.pdf&#34;&gt;A Unified Theory
of Garbage Collection&lt;/a&gt;&amp;rdquo;, and&amp;mdash;probably&amp;mdash;has nothing to do with &lt;em&gt;actual&lt;/em&gt; bacon.)&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/44BAC224-75B1-43C5-8F17-DD721D08FDC7_1_105_c.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/44BAC224-75B1-43C5-8F17-DD721D08FDC7_1_105_c_hu36f4a95839ccea206f453fa0c5e035d2_108645_480x0_resize_q75_box.jpeg 500w
                    
                    
                    &#39;
            
            src=&#34;../img/pocket/44BAC224-75B1-43C5-8F17-DD721D08FDC7_1_105_c.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/SimpleMadeEasy.md&#34;&gt;Simple Made Easy - Talk Transcript&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/8772BAB7-9080-42E3-A487-FEC91C6E6642_1_105_c.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/8772BAB7-9080-42E3-A487-FEC91C6E6642_1_105_c_hu32dd1231780a41662fad10cafe7b3d4b_89216_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/8772BAB7-9080-42E3-A487-FEC91C6E6642_1_105_c_hu32dd1231780a41662fad10cafe7b3d4b_89216_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/8772BAB7-9080-42E3-A487-FEC91C6E6642_1_105_c.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://exple.tive.org/blarg/2020/11/26/punching-holes/&#34;&gt;Punching Holes&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/E39D3C64-10F6-45CA-8751-B687E68FA185_1_201_a.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/E39D3C64-10F6-45CA-8751-B687E68FA185_1_201_a_huf973257bcf871ef13ffb308ffa474937_110719_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/E39D3C64-10F6-45CA-8751-B687E68FA185_1_201_a_huf973257bcf871ef13ffb308ffa474937_110719_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/E39D3C64-10F6-45CA-8751-B687E68FA185_1_201_a.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://len.falken.ink/misc/writing-for-the-internet-across-a-human-lifetime.txt&#34;&gt;WRITING FOR THE INTERNET ACROSS A HUMAN LIFETIME&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/88638842-7FB0-41BE-AEBD-3BB35A33257F_1_201_a.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/88638842-7FB0-41BE-AEBD-3BB35A33257F_1_201_a_huf973257bcf871ef13ffb308ffa474937_76375_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/88638842-7FB0-41BE-AEBD-3BB35A33257F_1_201_a_huf973257bcf871ef13ffb308ffa474937_76375_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/88638842-7FB0-41BE-AEBD-3BB35A33257F_1_201_a.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.cmpxchg8b.com/2020/07/you-dont-need-reproducible-builds.html&#34;&gt;You Don&amp;rsquo;t Need Reproducible Builds&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/1A7F186D-8917-41D9-A05A-67D69A03C5F9_1_201_a.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/1A7F186D-8917-41D9-A05A-67D69A03C5F9_1_201_a_huf973257bcf871ef13ffb308ffa474937_129218_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/1A7F186D-8917-41D9-A05A-67D69A03C5F9_1_201_a_huf973257bcf871ef13ffb308ffa474937_129218_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/1A7F186D-8917-41D9-A05A-67D69A03C5F9_1_201_a.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://thenewstack.io/c-creator-bjarne-stroustrup-weighs-in-on-distributed-systems-type-safety-and-rust/&#34;&gt;C++ Creator Bjarne Stroustrup Weighs in on Distributed Systems, Type Safety and
Rust&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(This one is interesting, because the article view seems to have figured out the title, but the title
shown in the list view is incorrect.)&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/FDE37DC2-6184-4CFC-858A-51D6AC313616_1_105_c.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/FDE37DC2-6184-4CFC-858A-51D6AC313616_1_105_c_hu047700260c371f8a717451e37a897475_105759_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/FDE37DC2-6184-4CFC-858A-51D6AC313616_1_105_c_hu047700260c371f8a717451e37a897475_105759_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/FDE37DC2-6184-4CFC-858A-51D6AC313616_1_105_c.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://neugierig.org/software/blog/2020/05/ninja.html&#34;&gt;The Success and Failure of Ninja&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/55901A75-2CDC-447E-90F9-8735203D520F_1_201_a.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/55901A75-2CDC-447E-90F9-8735203D520F_1_201_a_huf973257bcf871ef13ffb308ffa474937_103015_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/55901A75-2CDC-447E-90F9-8735203D520F_1_201_a_huf973257bcf871ef13ffb308ffa474937_103015_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/55901A75-2CDC-447E-90F9-8735203D520F_1_201_a.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://martinheinz.dev/blog/13&#34;&gt;Making Python Programs Blazingly Fast&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/90D6F2D3-8FC5-40FE-99EC-FD517A3533BE_1_201_a.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/90D6F2D3-8FC5-40FE-99EC-FD517A3533BE_1_201_a_huf973257bcf871ef13ffb308ffa474937_103521_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/90D6F2D3-8FC5-40FE-99EC-FD517A3533BE_1_201_a_huf973257bcf871ef13ffb308ffa474937_103521_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/90D6F2D3-8FC5-40FE-99EC-FD517A3533BE_1_201_a.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://interconnected.org/home/2020/04/16/rss_for_books&#34;&gt;Re: Tom Critchlow’s proposal for a decentralised Goodreads-like system, how about using RSS?&lt;/a&gt;&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/58CC2797-C7E7-44D0-9905-F3A54C74056F_1_201_a.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/58CC2797-C7E7-44D0-9905-F3A54C74056F_1_201_a_huf973257bcf871ef13ffb308ffa474937_76700_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/58CC2797-C7E7-44D0-9905-F3A54C74056F_1_201_a_huf973257bcf871ef13ffb308ffa474937_76700_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/58CC2797-C7E7-44D0-9905-F3A54C74056F_1_201_a.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And here&amp;rsquo;s an example of something that &lt;em&gt;has&lt;/em&gt; a well-extracted title, but I still wish I could
rename:&lt;/p&gt;

























&lt;figure&gt;
    &lt;a href=&#34;../img/pocket/A4CCA48A-4294-4E12-9E01-F209779CF2FE_1_105_c.jpeg&#34; target=&#34;_blank&#34;&gt;
        &lt;img
            
            sizes=&#34;(max-width: 600px) 480px,
                   (max-width: 1000px) 800px&#34;
            
            srcset=&#39;
                    
                    /img/pocket/A4CCA48A-4294-4E12-9E01-F209779CF2FE_1_105_c_hu32dd1231780a41662fad10cafe7b3d4b_85440_480x0_resize_q75_box.jpeg 500w
                    
                    
                    , /img/pocket/A4CCA48A-4294-4E12-9E01-F209779CF2FE_1_105_c_hu32dd1231780a41662fad10cafe7b3d4b_85440_800x0_resize_q75_box.jpeg 800w
                    
                    &#39;
            
            src=&#34;../img/pocket/A4CCA48A-4294-4E12-9E01-F209779CF2FE_1_105_c.jpeg&#34;
            

            
            
            &gt;
    &lt;/a&gt;
    &lt;figcaption&gt;&lt;center&gt;&lt;em&gt;&lt;small&gt;&lt;/small&gt;&lt;/em&gt;&lt;/center&gt;&lt;/figcaption&gt;
&lt;/figure&gt;



&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So there you have it. This is my plea to &lt;a href=&#34;https://twitter.com/pocket&#34;&gt;Pocket&lt;/a&gt; to please consider adding support
for editing article titles. The sixteen examples above took me back in my archive until about April,
2020; I could have kept going, but I got bored of taking screenshots. I really love that, 95% of the
time, I don&amp;rsquo;t have to think about (re-)naming an article. At the same time, I think that the list
above shows a diverse-enough sampling that we can all agree that attempting to get the titles right
on all of them is simply infeasible. And even when a title &lt;em&gt;can&lt;/em&gt; be extracted properly, there are
still times when the user may want or need to edit the title to make it shorter, simpler, more
exact, etc. Finally, using Tags to get around this limitation is, in my opinion, simply using a
different feature to get around a limitation in an adjacent feature.&lt;/p&gt;
&lt;p&gt;I want to finish this by reiterating that I love the Pocket service, and it has only gotten better
over the years. Thanks, Pocket, for keeping my &amp;ldquo;read it later&amp;rdquo; list organized for over a decade!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Booting a ZFS Root via UEFI on Debian</title>
      <link>https://www.thecrosseroads.net/2016/02/booting-a-zfs-root-via-uefi-on-debian/</link>
      <pubDate>Tue, 09 Feb 2016 12:56:39 -0500</pubDate>
      
      <guid>https://www.thecrosseroads.net/2016/02/booting-a-zfs-root-via-uefi-on-debian/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m playing with ZFS on Linux using Debian jessie (and eventually
stretch). I decided I really wanted to use ZFS for everything, including
&lt;code&gt;/boot/grub&lt;/code&gt; and swap space. In addition, I wanted to boot using UEFI.
This is how I did it.&lt;/p&gt;
&lt;p&gt;The official &lt;a href=&#34;https://github.com/zfsonlinux/pkg-zfs/wiki/HOWTO-install-Debian-GNU-Linux-to-a-Native-ZFS-Root-Filesystem&#34;&gt;ZFS Root on Debian&lt;/a&gt; HOWTO is much more cautious
and wants you to create an &lt;code&gt;ext4&lt;/code&gt; partition for &lt;code&gt;/boot/grub&lt;/code&gt; and a
separate partition for swap. Being the idiot^Wdaredevil I am, I decided
to flout that advice and go all-in on ZFS. The rest of this article
details the steps involved in making this happen. (You really want to
read the &lt;a href=&#34;https://github.com/zfsonlinux/pkg-zfs/wiki/HOWTO-install-Debian-GNU-Linux-to-a-Native-ZFS-Root-Filesystem&#34;&gt;ZFS Root on Debian&lt;/a&gt; guide first, and then come back
here to see where I deviated. Also, standard disclaimers apply: &lt;em&gt;I&amp;rsquo;m
doing this on a laptop I don&amp;rsquo;t care about and won&amp;rsquo;t use for any
production purpose. If following this guide creates a monster that eats
your disk and calls your mother names, I take no responsibility. It
worked for me, but might not work for you.&lt;/em&gt; Phew.)&lt;/p&gt;
&lt;h2 id=&#34;get-your-install-environment-ready&#34;&gt;Get Your Install Environment Ready&lt;/h2&gt;
&lt;p&gt;This part is going to smell a lot like the &lt;a href=&#34;https://github.com/zfsonlinux/pkg-zfs/wiki/HOWTO-install-Debian-GNU-Linux-to-a-Native-ZFS-Root-Filesystem&#34;&gt;official guide&lt;/a&gt;.
I&amp;rsquo;ll make a note of where I deviate from it, though.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Download the &lt;a href=&#34;http://www.rodsbooks.com/refind/getting.html&#34;&gt;rEFInd Boot Manager&lt;/a&gt;. You&amp;rsquo;ll use it to reboot
into your new Debian install the first time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download and boot a Live CD, such as
&lt;a href=&#34;http://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-8.3.0-amd64-standard.iso&#34;&gt;debian-live-8.3.0-amd64-standard.iso&lt;/a&gt;. The official guide
specifically requires using a Live CD and not just an installer CD,
so I used the &amp;ldquo;standard&amp;rdquo; non-graphical Live CD. Use whatever Live CD
you are comfortable with, as long as it&amp;rsquo;s Debian 8. (Of course, I&amp;rsquo;m
doing all this with an &amp;ldquo;iso-hybrid&amp;rdquo; image that I&amp;rsquo;ve &lt;code&gt;dd&lt;/code&gt;&amp;lsquo;ed to a USB
stick.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once booted, download and install the &lt;a href=&#34;http://archive.zfsonlinux.org/debian/pool/main/z/zfsonlinux/zfsonlinux_6_all.deb&#34;&gt;zfsonlinux&lt;/a&gt;
package. This simply adds the ZoL package repository to your APT
sources.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;$ &lt;/span&gt;sudo -i
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;wget -q http://archive.zfsonlinux.org/debian/pool/main/z/zfsonlinux/zfsonlinux_6_all.deb
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;dpkg -i zfsonlinux_6_all.deb
&lt;span class=&#34;go&#34;&gt;Selecting previously unselected package zfsonlinux.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;(Reading database ... 44337 files and directories currently installed.)
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Preparing to unpack zfsonlinux_6_all.deb ...
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Unpacking zfsonlinux (6) ...
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Setting up zfsonlinux (6) ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install the ZFS packages in the Live CD environment. This will
compile the SPL and ZFS dynamic kernel modules, which will take some
time.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-get update
&lt;span class=&#34;go&#34;&gt;Hit http://archive.zfsonlinux.org jessie InRelease
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Hit http://archive.zfsonlinux.org jessie/main amd64 Packages
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Hit http://security.debian.org jessie/updates InRelease
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Ign http://archive.zfsonlinux.org jessie/main Translation-en_US
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Ign http://archive.zfsonlinux.org jessie/main Translation-en
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Hit http://security.debian.org jessie/updates/main Sources
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Hit http://security.debian.org jessie/updates/main amd64 Packages
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Ign http://http.debian.net jessie InRelease
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Hit http://security.debian.org jessie/updates/main Translation-en
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Hit http://http.debian.net jessie Release.gpg
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Hit http://http.debian.net jessie Release
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Hit http://http.debian.net jessie/main Sources
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Hit http://http.debian.net jessie/main amd64 Packages
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Hit http://http.debian.net jessie/main Translation-en
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Reading package lists... Done
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-get install linux-image-amd64 debian-zfs
&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Loading new spl-0.6.5 DKMS files...
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;First Installation: checking all kernels...
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Building only for 3.16.0-4-amd64
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Building initial module for 3.16.0-4-amd64
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Done.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Loading new zfs-0.6.5.2 DKMS files..
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;First Installation: checking all kernels...
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Building only for 3.16.0-4-amd64
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Building initial module for 3.16.0-4-amd64
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Done.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Load the kernel module and verify that it loaded properly:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;modprobe zfs
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;dmesg &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep ZFS
&lt;span class=&#34;go&#34;&gt;[ 7446.660850] ZFS: Loaded module v0.6.5.2-2, ZFS pool version 5000, ZFS filesystem version 5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;partition-your-disks&#34;&gt;Partition Your Disks&lt;/h2&gt;
&lt;p&gt;I am performing these steps on a laptop with a single drive; as such my
setup will not uncover any issues that may arise from using multiple
drives in a mirror or RAIDZ configuration. (Just FYI.)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I want everything on ZFS, including &lt;code&gt;/boot/grub&lt;/code&gt; and my swap partition.
So I will create one large zpool using the entire disk:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zpool create -o &lt;span class=&#34;nv&#34;&gt;ashift&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;12&lt;/span&gt; -o &lt;span class=&#34;nv&#34;&gt;altroot&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/mnt -m none rpool /dev/disk/by-id/&amp;lt;disk_name&amp;gt;
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;atime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;off rpool
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;relatime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;on rpool
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;compression&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;lz4 rpool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;a href=&#34;https://illumos.org/man/1m/zpool&#34;&gt;&lt;code&gt;zpool create&lt;/code&gt;&lt;/a&gt; will label the disk using &lt;a href=&#34;https://en.wikipedia.org/wiki/GUID_Partition_Table&#34;&gt;GPT&lt;/a&gt; and
actually create two partitions; partition 1 is the ZFS pool, and
partition 9 is for the &lt;a href=&#34;https://en.wikipedia.org/wiki/EFI_system_partition&#34;&gt;EFI System Partition&lt;/a&gt; (ESP).  We&amp;rsquo;ll use
this later. I also go ahead and disable &lt;code&gt;atime&lt;/code&gt;, enable &lt;code&gt;relatime&lt;/code&gt;,
and enable lz4 compression on the root dataset so that these are
inherited all the way down. I can always override them in a child
dataset if necessary. &amp;ldquo;Wait, so handing &lt;code&gt;zpool(1m)&lt;/code&gt; a whole disk
still creates &lt;em&gt;two partitions&lt;/em&gt;?&amp;rdquo;, you ask? Yes. Yes it does. So then why
do I care so much about not creating a third or fourth partition for
&lt;code&gt;/boot/grub&lt;/code&gt; or swap?  Principles, my friend. And blatant disregard
for rules. Moving on&amp;hellip;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use &lt;a href=&#34;https://illumos.org/man/1m/zfs&#34;&gt;&lt;code&gt;zfs(1m)&lt;/code&gt;&lt;/a&gt; to create a zvol for swap space:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs create -o &lt;span class=&#34;nv&#34;&gt;compression&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;off -V 4G rpool/swap
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;mkswap -L swap /dev/zvol/rpool/swap
&lt;span class=&#34;go&#34;&gt;Setting up swapspace version 1, size = 4194300 KiB
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;LABEL=swap, UUID=354f7cba-fa33-45bb-97c7-7c6aa6109b22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
I&amp;rsquo;ll make sure to add an entry into &lt;code&gt;/etc/fstab&lt;/code&gt; later, after that file
gets created.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create the &lt;code&gt;ROOT&lt;/code&gt; filesystem. (This is &lt;em&gt;not&lt;/em&gt; the same as &lt;code&gt;/&lt;/code&gt;; this will
be the parent dataset for all future boot environments.)
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs create -o &lt;span class=&#34;nv&#34;&gt;mountpoint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;none rpool/ROOT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create the initial &amp;ldquo;boot environment&amp;rdquo; and mount &lt;code&gt;rpool&lt;/code&gt; at &lt;code&gt;/rpool&lt;/code&gt;:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs create -o &lt;span class=&#34;nv&#34;&gt;mountpoint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/ rpool/ROOT/debian-1
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mountpoint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/rpool rpool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
Setting the mountpoint for the &lt;code&gt;rpool&lt;/code&gt; filesystem deviates from
the ZFS on Debian guide, but seems in-line with what OpenIndiana does
by default. I do this now instead of when I created the pool, because
otherwise the &lt;code&gt;rpool/ROOT/debian-1&lt;/code&gt; filesystem cannot mount properly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set the &lt;code&gt;bootfs&lt;/code&gt; property on the pool to the boot environment you
just created:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zpool &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;bootfs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;rpool/ROOT/debian-1 rpool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create any other filesystems you want. If the filesystems should be
managed as a unit (i.e., all part of the same boot environment), then
make sure to create them under &lt;code&gt;rpool/ROOT/debian-1&lt;/code&gt;. (While there&amp;rsquo;s
not a &lt;a href=&#34;https://illumos.org/man/1m/beadm&#34;&gt;&lt;code&gt;beadm(1m)&lt;/code&gt;&lt;/a&gt;-type command for Linux yet, I still want to
set up the system up as if there were. That way if/when &lt;code&gt;beadm&lt;/code&gt; gets
ported, the system will be ready to handle it.)
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs create -o &lt;span class=&#34;nv&#34;&gt;mountpoint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home rpool/home
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs create -o &lt;span class=&#34;nv&#34;&gt;mountpoint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/usr rpool/ROOT/debian-1/usr
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs create -o &lt;span class=&#34;nv&#34;&gt;mountpoint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/var rpool/ROOT/debian-1/var
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs create -o &lt;span class=&#34;nv&#34;&gt;mountpoint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/var/tmp -o &lt;span class=&#34;nv&#34;&gt;setuid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;off rpool/ROOT/debian-1/var/tmp
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs create -o &lt;span class=&#34;nv&#34;&gt;mountpoint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/tmp -o &lt;span class=&#34;nv&#34;&gt;setuid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;off rpool/tmp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
The ZFS on Debian guide mentions setting &lt;code&gt;exec=off&lt;/code&gt; on the two &lt;code&gt;tmp&lt;/code&gt;
filesystems they create. When I followed those instructions, I got
errors during DKMS compilation, I believe, so I left it enabled.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, export the zpool.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zpool &lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; rpool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once all the above steps are done, you should now have the following
layout (you might want to check this before exporting the pool):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zpool get all rpool
&lt;span class=&#34;go&#34;&gt;NAME   PROPERTY                    VALUE                       SOURCE
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  size                        238G                        -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  capacity                    0%                          -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  altroot                     -                           default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  health                      ONLINE                      -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  guid                        14661786247243457179        default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  version                     -                           default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  bootfs                      rpool/ROOT/debian-1         local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  delegation                  on                          default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  autoreplace                 off                         default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  cachefile                   -                           default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  failmode                    wait                        default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  listsnapshots               off                         default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  autoexpand                  off                         default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  dedupditto                  0                           default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  dedupratio                  1.00x                       -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  free                        237G                        -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  allocated                   1.12G                       -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  readonly                    off                         -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  ashift                      12                          local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  comment                     -                           default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  expandsize                  -                           -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  freeing                     0                           default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  fragmentation               0%                          -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  leaked                      0                           default
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@async_destroy       enabled                     local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@empty_bpobj         active                      local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@lz4_compress        active                      local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@spacemap_histogram  active                      local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@enabled_txg         active                      local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@hole_birth          active                      local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@extensible_dataset  enabled                     local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@embedded_data       active                      local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@bookmarks           enabled                     local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@filesystem_limits   enabled                     local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool  feature@large_blocks        enabled                     local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs list -t all -o name,type,mountpoint,compress,exec,setuid,atime,relatime
&lt;span class=&#34;go&#34;&gt;NAME                         TYPE        MOUNTPOINT  COMPRESS  EXEC  SETUID  ATIME  RELATIME
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool                        filesystem  /rpool           lz4    on      on    off        on
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT                   filesystem  none             lz4    on      on    off        on
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1          filesystem  /                lz4    on      on    off        on
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1/usr      filesystem  /usr             lz4    on      on    off        on
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1/var      filesystem  /var             lz4    on      on    off        on
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1/var/tmp  filesystem  /var/tmp         lz4   off     off    off        on
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/home                   filesystem  /home            lz4    on      on    off        on
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/swap                   volume      -                off     -       -      -         -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/tmp                    filesystem  /tmp             lz4   off     off    off        on
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;install-debian&#34;&gt;Install Debian&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Reimport the pool and create the cache file:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zpool import -d /dev/disk/by-id -R /mnt rpool
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;mkdir -p /mnt/etc/zfs
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zpool &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;cachefile&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/mnt/etc/zfs/zpool.cache rpool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
In case you&amp;rsquo;re wondering about the options passed to &lt;code&gt;zpool import&lt;/code&gt;
(and don&amp;rsquo;t have a copy of the &lt;a href=&#34;https://illumos.org/man/1m/zpool&#34;&gt;&lt;code&gt;zpool(1m)&lt;/code&gt;&lt;/a&gt; man page), the
&lt;code&gt;-d&lt;/code&gt; option tells &lt;code&gt;zpool&lt;/code&gt; to search the &lt;code&gt;/dev/disk/by-id&lt;/code&gt; directory
for importable pools, and the &lt;code&gt;-R&lt;/code&gt; option tells it to use &lt;code&gt;/mnt&lt;/code&gt; as
the &lt;code&gt;altroot&lt;/code&gt; and set the &lt;code&gt;cachefile&lt;/code&gt; property to &lt;code&gt;none&lt;/code&gt;. The latter
gives us the chance to create the directory for the cache file first,
then set the option appropriately.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Since I didn&amp;rsquo;t create a separate partition for &lt;code&gt;/boot/grub&lt;/code&gt;, I can
skip some things in the official guide and move directly to using
&lt;a href=&#34;https://wiki.debian.org/Debootstrap&#34;&gt;&lt;code&gt;debootstrap(8)&lt;/code&gt;&lt;/a&gt; to install the base Debian system.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-get install debootstrap
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;debootstrap --arch&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;amd64 jessie /mnt http://httpredir.debian.org/debian/
&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;I: Base system installed successfully.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;configure-your-new-debian-system&#34;&gt;Configure Your New Debian System&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create &lt;code&gt;/etc/{hosts,hostname}&lt;/code&gt;. Substitute whatever you&amp;rsquo;re going to
name your machine for &amp;ldquo;debzfs&amp;rdquo; in the command below.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; debzfs &amp;gt; /mnt/etc/hostname
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;sed -i -Ee &lt;span class=&#34;s2&#34;&gt;&amp;#34;s#(127.+)#\1 debzfs#&amp;#34;&lt;/span&gt; /mnt/etc/hosts
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;cat /mnt/etc/hosts
&lt;span class=&#34;go&#34;&gt;127.0.0.1	localhost debzfs
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;::1		localhost ip6-localhost ip6-loopback
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;ff02::1		ip6-allnodes
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;ff02::2		ip6-allrouters
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create &lt;code&gt;/mnt/etc/fstab&lt;/code&gt;. It should be empty (except for a comment,
maybe), but a line needs to be added for the swap device. Here I use
&lt;a href=&#34;http://linux.die.net/man/1/printf&#34;&gt;&lt;code&gt;printf(1)&lt;/code&gt;&lt;/a&gt; for terseness, but you can use your favorite
editor to do this as well.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/dev/zvol/rpool/swap\tnone\t\tswap\tdefaults\t0 0\n&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; /mnt/etc/fstab
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;cat /mnt/etc/fstab
&lt;span class=&#34;go&#34;&gt;/dev/zvol/rpool/swap	none		swap	defaults	0 0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;If you created a dataset for &lt;code&gt;/tmp&lt;/code&gt; not under the boot
environment (like I did), you might notice at some point that
&lt;code&gt;systemd&lt;/code&gt; won&amp;rsquo;t mount &lt;code&gt;/tmp&lt;/code&gt; before things want to use it. If that
is the case, you can attempt to try the workaround documented
&lt;a href=&#34;http://wiki.complete.org/ConvertingToZFS#zfs_mounting_workaround_.28for_separate_.2Fusr.2C_.2Fvar.29&#34;&gt;here&lt;/a&gt;, or you can do what I did and just set the
mountpoint on &lt;code&gt;rpool/tmp&lt;/code&gt; to &lt;code&gt;legacy&lt;/code&gt; and add a line to &lt;code&gt;fstab&lt;/code&gt;,
like this:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mountpoint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;legacy rpool/tmp
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;rpool/tmp\t\t/tmp\t\tzfs\tdefaults\t0 0\n&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; /mnt/etc/fstab
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;cat /mnt/etc/fstab
&lt;span class=&#34;go&#34;&gt;/dev/zvol/rpool/swap	none		swap	defaults	0 0
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/tmp		/tmp		zfs	defaults	0 0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
I&amp;rsquo;d much rather figure out how to tell &lt;code&gt;systemd&lt;/code&gt; to mount &lt;code&gt;/tmp&lt;/code&gt;
earlier, but until then this method certainly works.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do some minor network configuration. The ZFS on Debian page just puts
all interface configuration into &lt;code&gt;/mnt/etc/network/interfaces&lt;/code&gt;, but
here I&amp;rsquo;ve chosen to create a separate file per-interface in
&lt;code&gt;/mnt/etc/network/interfaces.d/&lt;/code&gt;. It&amp;rsquo;s your choice.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;ls /mnt/etc/network/interfaces.d/
&lt;span class=&#34;go&#34;&gt;eth0  lo
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;cat /mnt/etc/network/interfaces.d/eth0
&lt;span class=&#34;go&#34;&gt;auto eth0
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;iface eth0 inet dhcp
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;cat /mnt/etc/network/interfaces.d/lo
&lt;span class=&#34;go&#34;&gt;auto lo
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;iface lo inet loopback
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Bind-mount some useful filesystems into the new system.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; f in dev dev/pts proc sys&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; mount -v --bind &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;,/mnt&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;/&lt;span class=&#34;nv&#34;&gt;$f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;span class=&#34;go&#34;&gt;mount: /dev bound on /mnt/dev.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;mount: /dev/pts bound on /mnt/dev/pts.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;mount: /dev/proc bound on /mnt/proc.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;mount: /dev/sys bound on /mnt/sys.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go ahead and copy the &lt;code&gt;zfsonlinux&lt;/code&gt; package you downloaded earlier
into &lt;code&gt;/mnt/root&lt;/code&gt; so you don&amp;rsquo;t have to download it again, then
&lt;a href=&#34;http://linux.die.net/man/1/chroot&#34;&gt;&lt;code&gt;chroot(1)&lt;/code&gt;&lt;/a&gt; into your new system.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;cp zfsonlinux_6_all.deb /mnt/root/
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;chroot /mnt /bin/bash --login
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now that you&amp;rsquo;re in the new environment, you have to setup ZoL all
over again&amp;hellip;. (It seems that there is a documentation error in the
official guide when running the &lt;code&gt;locale-gen&lt;/code&gt; command. Use what I&amp;rsquo;ve
got below instead.)
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-get install locales
&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;sed -i -Ee &lt;span class=&#34;s1&#34;&gt;&amp;#39;s/# (en_US.UTF+)/\1/&amp;#39;&lt;/span&gt; /etc/locale.gen
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;locale-gen
&lt;span class=&#34;go&#34;&gt;Generating locales (this might take a while)...
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;  en_US.UTF-8... done
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Generation complete.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-get install lsb-release
&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;dpkg -i /root/zfsonlinux_6_all.deb
&lt;span class=&#34;go&#34;&gt;Selecting previous unselected package zfsonlinux.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;(Reading database ... 11210 files and directories currently installed.)
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Preparing to unpack zfsonlinux_6_all.deb ...
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Unpacking zfsonlinux (6) ...
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Setting up zfsonlinux (6) ...
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-get update
&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Okay, hold on. I&amp;rsquo;m going to stop here and deviate once again from the
ZFS on Debian guide.&lt;/p&gt;
&lt;h3 id=&#34;apt-pin-zol-packages&#34;&gt;APT-Pin ZoL Packages&lt;/h3&gt;
&lt;p&gt;In the realm of &amp;ldquo;that thing that happened that one time&amp;rdquo;, the first time
I tried this setup I got into a situation after updating to Debian&amp;rsquo;s
testing channel (stretch) where the &lt;code&gt;spl&lt;/code&gt; package from Debian updated
before the &lt;code&gt;spl&lt;/code&gt; and &lt;code&gt;zfs&lt;/code&gt; packages from ZoL, which broke ZFS for a
while until I could uninstall the Debian version and reinstall the ZoL
version. Since then I&amp;rsquo;ve created an preferences file to pin ZoL packages
at a higher priority than the Debian ones. (I&amp;rsquo;m sure this will never
come back to bite me, ever.) If you want to do this, create the file
&lt;code&gt;/etc/apt/preferences.d/50-zol-packages&lt;/code&gt; with the following content. If
you&amp;rsquo;d rather not mess with the Natural Order of Things, then feel free
to skip this part.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/apt/preferences.d/50-zol-packages
&lt;span class=&#34;gp&#34;&gt;&amp;gt; &lt;/span&gt;Package: *
&lt;span class=&#34;gp&#34;&gt;&amp;gt; &lt;/span&gt;Pin: origin archive.zfsonlinux.org
&lt;span class=&#34;gp&#34;&gt;&amp;gt; &lt;/span&gt;Pin-Priority: &lt;span class=&#34;m&#34;&gt;900&lt;/span&gt;
&lt;span class=&#34;gp&#34;&gt;&amp;gt; &lt;/span&gt;EOF
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-cache policy spl
&lt;span class=&#34;go&#34;&gt;spl:
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;  Installed: 0.6.5-1
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;  Candidate: 0.6.5-1
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;  Version table:
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt; *** 0.6.5-1 0
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;        900 http://archive.zfsonlinux.org/debian/ jessie/main amd64 Packages
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;        100 /var/lib/dpkg/status
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-cache policy grub2-common
&lt;span class=&#34;go&#34;&gt;grub2-common:
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;  Installed: 2.02-beta2.9-ZOL11-7aa9f6
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;  Candidate: 2.02-beta2.9-ZOL11-7aa9f6
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;  Version table:
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt; *** 2.02-beta2.9-ZOL11-7aa9f6 0
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;        900 http://archive.zfsonlinux.org/debian/ jessie/main amd64 Packages
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;        100 /var/lib/dpkg/status
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;     2.02~beta2-22+deb8u1 0
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;        500 http://httpredir.debian.org/debian/ jessie/main amd64 Packages
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(Debian jessie doesn&amp;rsquo;t have an &lt;code&gt;spl&lt;/code&gt; package, but &lt;a href=&#34;https://packages.debian.org/stretch/spl&#34;&gt;stretch&lt;/a&gt;
(testing) does, so I&amp;rsquo;m showing the output for &lt;code&gt;grub2-common&lt;/code&gt; as well to
show you the difference.)&lt;/p&gt;
&lt;h2 id=&#34;install-zol-again-and-grub2-efi-support&#34;&gt;Install ZoL (Again) and GRUB2 EFI Support&lt;/h2&gt;
&lt;p&gt;And now we continue on. Installing the &lt;code&gt;debian-zfs&lt;/code&gt; metapackage will
install the &lt;code&gt;spl&lt;/code&gt;, &lt;code&gt;spl-dkms&lt;/code&gt;, &lt;code&gt;zfs-dkms&lt;/code&gt;, and &lt;code&gt;zfsutils&lt;/code&gt; packages. Note
that the DKMS modules will get compiled (again) at this time.&lt;/p&gt;
&lt;p&gt;Once more I&amp;rsquo;ve deviated from the ZFS on Debian instructions. Instead of
installing &lt;code&gt;grub-pc&lt;/code&gt;, I&amp;rsquo;m installing the &lt;code&gt;grub-efi&lt;/code&gt; package because I
want to boot via UEFI. Exciting times.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-get install linux-image-amd64 debian-zfs
&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-get install grub2-common grub-efi zfs-initramfs
&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-get dist-upgrade
&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;digression-get-ready-for-uefi-boot&#34;&gt;Digression: Get Ready for UEFI Boot&lt;/h2&gt;
&lt;p&gt;Keep in mind that the Debian live-installer you booted from didn&amp;rsquo;t boot
in (U)EFI mode, so configuring GRUB2 will only halfway work.  What we
need to do is reboot into UEFI mode so that &lt;code&gt;grub-install&lt;/code&gt; can access
and set EFI variables properly. However, before we do that we can finish
out the installation process and prepare partition 9 to be the &lt;a href=&#34;https://en.wikipedia.org/wiki/EFI_system_partition&#34;&gt;ESP&lt;/a&gt;.
We need to install the &lt;code&gt;dosfstools&lt;/code&gt; package to be able to format part9
as VFAT. Note that my disk is &lt;code&gt;/dev/sda&lt;/code&gt;; yours might be different. You
can also use the &lt;code&gt;/dev/disk/by-id/identifier-part9&lt;/code&gt; path instead if you
want to stay consistent with the rest of this process.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;apt-get install dosfstools
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;mkdir /boot/efi
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;mkfs.vfat /dev/sda9
&lt;span class=&#34;go&#34;&gt;mkfs.fat 3.0.27 (2014-11-12)
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;mount /dev/sda9 /boot/efi
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;grub-probe -d /dev/sda9
&lt;span class=&#34;go&#34;&gt;fat
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;update-grub
&lt;span class=&#34;go&#34;&gt;Generating grub configuration file ...
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Found linux image: /boot/vmlinuz-3.16.0-4-amd64
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Found initrd image: /boot/initrd.img-3.16.0-4-amd64
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;done
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;grub-install -d /usr/lib/grub/x86_64-efi /dev/sda &lt;span class=&#34;c1&#34;&gt;# Note: actually unsuccessful!&lt;/span&gt;
&lt;span class=&#34;go&#34;&gt;Installing for x86_64-efi platform.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;efibootmgr: EFI variables are not supported on this system.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;efibootmgr: EFI variables are not supported on this system.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Installation finished. No error reported
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;find /boot/efi -type f
&lt;span class=&#34;go&#34;&gt;/boot/efi/EFI/debian/grubx64.efi
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We&amp;rsquo;re going to want to mount the ESP to &lt;code&gt;/boot/efi&lt;/code&gt;, so add a line to
&lt;code&gt;/etc/fstab&lt;/code&gt; for it. (If you want, you can mount it read-only instead,
or not automatically mount it, etc.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/dev/sda9\t\t/boot/efi\tvfat\tdefaults\t0 1\n&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; /etc/fstab
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;cat /etc/fstab
&lt;span class=&#34;go&#34;&gt;/dev/zvol/rpool/swap	none		swap	defaults	0 0
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/tmp		/tmp		zfs	defaults	0 0
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;/dev/sda9		/boot/efi	vfat	defaults	0 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point, &lt;strong&gt;you will not be able to boot your install without using
rEFInd&lt;/strong&gt;.  We&amp;rsquo;ll fix that in a minute. Let&amp;rsquo;s go ahead and finish out the
instructions in the official guide.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;passwd root
&lt;span class=&#34;go&#34;&gt;Enter new UNIX password:
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Retype new UNIX password:
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;passwd: password updated successfully
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;umount /boot/efi
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt;
&lt;span class=&#34;go&#34;&gt;logout
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; f in dev/pts dev proc sys boot/efi&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; umount /mnt/&lt;span class=&#34;nv&#34;&gt;$f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs umount -a
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zpool &lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; rpool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If &lt;code&gt;umount(8)&lt;/code&gt; complains about not being able to unmount &lt;code&gt;/sys&lt;/code&gt;, find out
what other random things got mounted there while you weren&amp;rsquo;t looking
(&lt;code&gt;mount|grep /mnt/sys&lt;/code&gt;) and unmount those first, then try to unmount
&lt;code&gt;/sys&lt;/code&gt; again.&lt;/p&gt;
&lt;h2 id=&#34;reboot-into-refind&#34;&gt;Reboot into rEFInd&lt;/h2&gt;
&lt;p&gt;Download the &lt;a href=&#34;http://www.rodsbooks.com/refind/getting.html&#34;&gt;rEFInd Boot Manager&lt;/a&gt; USB image (if you haven&amp;rsquo;t
already) and &lt;a href=&#34;http://linux.die.net/man/1/dd&#34;&gt;&lt;code&gt;dd(1)&lt;/code&gt;&lt;/a&gt; it to a USB stick. (If you have a second
thumb drive, use that so that you still have the Debian Live environment
on the first stick in case you need it.) Once you&amp;rsquo;ve done that, reboot
your machine.  Now would be a good time to make sure your &amp;ldquo;BIOS&amp;rdquo; is set
to boot into UEFI mode. After verifying that, insert the rEFInd stick
and tell your system to boot to it.&lt;/p&gt;
&lt;p&gt;Even though &lt;code&gt;grub-install&lt;/code&gt; failed to write to the EFI variables, it
still put all of the boot files where they needed to go, so rEFInd
should be able to identify your Debian installation. Select it from the
boot manager screen (if it&amp;rsquo;s not already selected) and boot.&lt;/p&gt;
&lt;p&gt;Log in as root (because everything worked swimmingly and it &lt;em&gt;actually
booted&lt;/em&gt;, right? Right? Whew!) and use &lt;code&gt;grub-install&lt;/code&gt; to fix the UEFI variables
it couldn&amp;rsquo;t set last time.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;grub-install /dev/sda
&lt;span class=&#34;go&#34;&gt;Installing for x86_64-efi platform.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Installation finished. No error reported.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Before doing anything else, let&amp;rsquo;s reboot without rEFInd and make sure
that all the UEFI stuff is set properly and that your machine can boot
under its own power. If anything goes wrong, go back over this article
and make sure that you performed all the steps (and that none of them
failed, horribly or otherwise). You should also consult the &lt;a href=&#34;https://github.com/zfsonlinux/pkg-zfs/wiki/HOWTO-install-Debian-GNU-Linux-to-a-Native-ZFS-Root-Filesystem&#34;&gt;ZFS Root on
Debian&lt;/a&gt; documentation as well.&lt;/p&gt;
&lt;p&gt;If you rebooted and everything worked, you should be able to log back in
as root and start installing whatever other things you want! Before you
get too far down the road, though, it&amp;rsquo;d probably be a good idea to
snapshot your boot environment just in case.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs snapshot -r rpool/ROOT/debian-1@2016020401-pristine
&lt;span class=&#34;gp&#34;&gt;# &lt;/span&gt;zfs list -rt all -o name,type,used,refer,mountpoint rpool/ROOT
&lt;span class=&#34;go&#34;&gt;NAME                                             TYPE         USED  REFER  MOUNTPOINT
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT                                       filesystem  1.12G    96K  none
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1                              filesystem  1.12G   554M  /
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1@2016020401-pristine          snapshot        0   554M  -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1/usr                          filesystem   337M   337M  /usr
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1/usr@2016020401-pristine      snapshot        0   337M  -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1/var                          filesystem   252M   252M  /var
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1/var@2016020401-pristine      snapshot        0   252M  -
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1/var/tmp                      filesystem    96K    96K  /var/tmp
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;rpool/ROOT/debian-1/var/tmp@2016020401-pristine  snapshot        0    96K  -
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;And this is where I leave you, with Debian installed on a ZFS root and
booting from UEFI. Where you go from here is up to you. Install a
desktop environment or two, all the utilities you want, create yourself
a regular user, and enjoy the benefits of using ZFS.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Crashplan on SmartOS</title>
      <link>https://www.thecrosseroads.net/2015/12/crashplan-on-smartos/</link>
      <pubDate>Fri, 04 Dec 2015 13:03:25 -0500</pubDate>
      
      <guid>https://www.thecrosseroads.net/2015/12/crashplan-on-smartos/</guid>
      <description>&lt;p&gt;It&amp;rsquo;s taken quite a while, but I have replaced my home server&amp;rsquo;s OS with
&lt;a href=&#34;https://smartos.org/&#34;&gt;SmartOS&lt;/a&gt;. (It was previously running Windows with Hyper-V.
Look for a future blog post about the migration in general.)  With the
previous layout, I had a single Linux guest called &amp;ldquo;nas&amp;rdquo; that was my
file server, but did triple-duty running &lt;a href=&#34;http://plex.tv&#34;&gt;Plex&lt;/a&gt; and the
&lt;a href=&#34;https://crashplan.com/&#34;&gt;CrashPlan&lt;/a&gt; client as well.  After migrating most of my other
Hyper-V guests to OS zones where possible, it was time to tackle getting
a CrashPlan zone going.  Unfortunately, Code42 &lt;a href=&#34;http://support.code42.com/Terms_And_Conditions/Platform_Support_Policy/Solaris_Platform_Retirement&#34;&gt;retired Solaris as a
supported platform&lt;/a&gt; a while back.  However, since it&amp;rsquo;s &amp;ldquo;just
Java&amp;rdquo;, I figured the Linux package might work in an LX-brand zone.
Turns out, it works quite well&amp;ndash;with one minor caveat.&lt;/p&gt;
&lt;p&gt;(I won&amp;rsquo;t rehash what an LX zone is; instead I will point you towards
Bryan Cantrill&amp;rsquo;s excellent talk, &lt;em&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=TrfD3pC0VSs&#34;&gt;The Dream is Alive! Running Linux
containers on an illumos kernel&lt;/a&gt;&lt;/em&gt;.)&lt;/p&gt;
&lt;h2 id=&#34;why&#34;&gt;Why?&lt;/h2&gt;
&lt;p&gt;I use CrashPlan as a local backup target for various clients on my home
network.  Some of these clients (like my desktop and laptop) backup to
both this internal host and to the CrashPlan service, and some only
backup to the internal host, depending on how important I deem their
data.  For months I did not have this local backup target available, and
it was time to change that.&lt;/p&gt;
&lt;h2 id=&#34;zone-creation&#34;&gt;Zone Creation&lt;/h2&gt;
&lt;p&gt;So, first I needed an LX zone.  Using &lt;code&gt;imgadm avail&lt;/code&gt; I found a few
different images that I could potentially use.  I decided to go for an
Ubuntu zone:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;go&#34;&gt;root@vm ~ $ imgadm avail | grep lx-ubuntu
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;818cc79e-ceb3-11e4-99ee-7bc8c674e754  lx-ubuntu-14.04         20150320    other    2015-03-20T03:45:09Z
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;430da066-e3a7-11e4-9657-332a2dbdf565  lx-ubuntu-14.04         20150415    other    2015-04-15T19:40:25Z
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;a21a64a0-0809-11e5-a64f-ff80e8e8086f  lx-ubuntu-14.04         20150601    other    2015-06-01T02:55:17Z
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I simply chose the most recently-released lx-ubuntu image I could find
at the time and constructed the following zone configuration file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;alias&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;crashplan&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;hostname&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;crashplan&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;brand&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;lx&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;kernel_version&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;3.13.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;quota&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;max_physical_memory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2048&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;image_uuid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;a21a64a0-0809-11e5-a64f-ff80e8e8086f&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;resolvers&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;192.168.2.1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;nics&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;nic_tag&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;ip&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;192.168.2.20&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;netmask&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;255.255.255.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;gateway&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;192.168.2.1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;primary&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;filesystems&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;lofs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;zones/crashplan&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/opt/crashplan&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note the &lt;code&gt;filesystems&lt;/code&gt; section.  Here I am telling &lt;code&gt;vmadm(1M)&lt;/code&gt; that I want
to mount the &lt;code&gt;zones/crashplan&lt;/code&gt; dataset into the zone at
&lt;code&gt;/opt/crashplan&lt;/code&gt;.  This will become Crashplan&amp;rsquo;s default backup archive
location, where all backup data from other computers will be stored.
Before creating the zone, I had to create a new ZFS filesystem called
&amp;ldquo;zones/crashplan&amp;rdquo;, like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;go&#34;&gt;root@vm ~ $ zfs create zones/crashplan
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;root@vm ~ $ zfs set compression=off dedup=off zones/crashplan
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;root@vm ~ $ zfs get compression,dedup zones/crashplan
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;NAME    	PROPERTY	VALUE		SOURCE
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;zones/crashplan	compression	off		local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;zones/crashplan	dedup		off		local
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;root@vm ~ $ zfs list zones/crashplan
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;NAME		USED	AVAIL	REFER	MOUNTPOINT
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;zones/crashplan	19K	855G	19K	/zones/crashplan
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, I&amp;rsquo;ve created the ZFS dataset and turned off compression and
deduplication.  Since CrashPlan does its own compression (I think) and
deduplication (for sure), I didn&amp;rsquo;t see a need to make ZFS try to do the
same things over again.&lt;/p&gt;
&lt;p&gt;To make sure I have all syntax right (because that&amp;rsquo;s rarely a thing on
the first shot), I typically check the JSON file with &lt;code&gt;vmadm validate&lt;/code&gt;
and then create the zone if it is valid:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;go&#34;&gt;root@vm /opt/vmdefs $ vmadm validate create -f crashplan_lx.json 
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;VALID &amp;#39;create&amp;#39; payload for lx brand VMs.
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;root@vm /opt/vmdefs $ vmadm create -f crashplan_lx.json 
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;Successfully created VM f5b988e9-260b-4103-8bab-441c8e0df0fe
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;root@vm /opt/vmdefs $ vmadm list | grep crashplan
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;f5b988e9-260b-4103-8bab-441c8e0df0fe  LX    2048     running           crashplan
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;crashplan-installation&#34;&gt;CrashPlan Installation&lt;/h2&gt;
&lt;p&gt;At this point, I could log in to the zone and treat it just like a
normal Ubuntu host, meaning that everything from here on is the same as
when I installed CrashPlan on the previous, real Linux guest.  After
updating the zone, I downloaded the &lt;a href=&#34;https://www.code42.com/crashplan/thankyou/?os=linux&#34;&gt;Linux CrashPlan
client&lt;/a&gt; and copied it over, then installed the app as per
&lt;a href=&#34;https://support.code42.com/CrashPlan/4/Getting_Started/Installing_The_Code42_CrashPlan_App#Linux&#34;&gt;the documentation&lt;/a&gt; (starting at &amp;ldquo;Extract the
TGZ&amp;hellip;&amp;quot;).  Since this install was going to be headless, I then switched
over to the &lt;a href=&#34;https://support.code42.com/CrashPlan/4/Configuring/Using_CrashPlan_On_A_Headless_Computer&#34;&gt;headless usage guide&lt;/a&gt; and followed the
instructions there.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;go&#34;&gt;root@crashplan:~# tar xzf CrashPlan_4.4.1_Linux.tgz
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;root@crashplan:~# cd crashplan-install/
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;root@crashplan:~/crashplan-install# ./install.sh 
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;[...]
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;root@crashplan:~/crashplan-install# service crashplan status
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;CrashPlan Engine (pid 75632) is running.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I used my laptop&amp;rsquo;s CrashPlan client to configure the host (as per the
headless guide).  Once I was done configuring and had restored &amp;ldquo;normal
operation&amp;rdquo;, I enabled my new host as a backup target on my laptop and
watched it merrily start backing up!&lt;/p&gt;
&lt;h2 id=&#34;caveat&#34;&gt;Caveat&lt;/h2&gt;
&lt;p&gt;I was so happy about having CrashPlan working under an LX zone that I
tweeted about it&amp;hellip;and as sometimes happens, I was informed of a
potential issue:&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;&lt;a href=&#34;https://twitter.com/Crosse3?ref_src=twsrc%5Etfw&#34;&gt;@Crosse3&lt;/a&gt; &lt;a href=&#34;https://twitter.com/crashplan?ref_src=twsrc%5Etfw&#34;&gt;@crashplan&lt;/a&gt; &lt;a href=&#34;https://twitter.com/opensolaris?ref_src=twsrc%5Etfw&#34;&gt;@opensolaris&lt;/a&gt; however note this bug might affect you: &lt;a href=&#34;https://t.co/KiTdM1ssRf&#34;&gt;https://t.co/KiTdM1ssRf&lt;/a&gt;&lt;/p&gt;&amp;mdash; Chris Ridd (@chrisridd) &lt;a href=&#34;https://twitter.com/chrisridd/status/667391853164122112?ref_src=twsrc%5Etfw&#34;&gt;November 19, 2015&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;The &lt;a href=&#34;https://github.com/joyent/smartos-live/issues/490&#34;&gt;bug&lt;/a&gt; relates to &lt;a href=&#34;http://support.code42.com/CrashPlan/4/Troubleshooting/Linux_Real-Time_File_Watching_Errors&#34;&gt;this troubleshooting
guide&lt;/a&gt; and seems to be specific to using the
CrashPlan client to watch for changes on the local filesystem and sync
them in real-time to a remote backup target.  So far I have not been
bitten by this particular issue and, since I am not backing up my local
backup server to another backup server (wat) I don&amp;rsquo;t think I will run
into it any time soon.  But if this is something you want to do, you
might want to watch that Github issue.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Since standing up the zone I&amp;rsquo;ve pointed my desktop and laptop at it, and
they&amp;rsquo;ve been backing up perfectly fine ever since.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;go&#34;&gt;root@vm ~ $ zfs list zones/crashplan
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;NAME		USED	AVAIL	REFER	MOUNTPOINT
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;zones/crashplan	230G	763G	230G	/zones/crashplan
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And here&amp;rsquo;s one of my favorite parts:  instead of wasting an entire 2+GB
of memory had I built this as a KVM guest, the zone is using less than a
quarter of that!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell-session&#34; data-lang=&#34;shell-session&#34;&gt;&lt;span class=&#34;go&#34;&gt;root@vm ~ $ zonememstat -az f5b988e9-260b-4103-8bab-441c8e0df0fe
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt;                                 ZONE         ALIAS  RSS(MB)  CAP(MB)    NOVER  POUT(MB)
&lt;/span&gt;&lt;span class=&#34;go&#34;&gt; f5b988e9-260b-4103-8bab-441c8e0df0fe     crashplan      352     2048        0         0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;ve been very happy with SmartOS in general and the flexibility of OS
vs. LX vs. KVM zones in particular.  If you&amp;rsquo;re looking for a nice
hypervisor-type OS, SmartOS deserves some serious consideration.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Blog Cleanup</title>
      <link>https://www.thecrosseroads.net/2015/11/blog-cleanup/</link>
      <pubDate>Sun, 15 Nov 2015 09:26:19 -0500</pubDate>
      
      <guid>https://www.thecrosseroads.net/2015/11/blog-cleanup/</guid>
      <description>&lt;p&gt;Anything older than 2014 got moved to an &amp;ldquo;archive&amp;rdquo; section.  You
probably don&amp;rsquo;t want to go there, but if you do, the link is on the left.
I also migrated the site to &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;.  Had I done that
recently, it might have made a good blog post.  Alas, it is not to be.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Blog moved to Google App Engine</title>
      <link>https://www.thecrosseroads.net/2014/05/blog-moved-to-google-app-engine/</link>
      <pubDate>Sat, 31 May 2014 22:38:20 -0400</pubDate>
      
      <guid>https://www.thecrosseroads.net/2014/05/blog-moved-to-google-app-engine/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been playing with Google App Engine for a project lately, and I
decided to give it a shot for hosting this blog.  Since Octopress is
just a bunch of static files, there isn&amp;rsquo;t much fiddling to do at all to
make it work.  In fact, simply copying the app.yaml file from
&lt;a href=&#34;https://github.com/relarge/octopress-gae/&#34;&gt;this Github repository&lt;/a&gt; was all that was needed.&lt;/p&gt;
&lt;p&gt;Neat!&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
