Skip to content

Instantly share code, notes, and snippets.

@ibizaman
Created December 5, 2023 19:10
Show Gist options
  • Save ibizaman/5a87a024a0810eabecfeffc52863bc87 to your computer and use it in GitHub Desktop.
Save ibizaman/5a87a024a0810eabecfeffc52863bc87 to your computer and use it in GitHub Desktop.
nixos-render-doc TOCs with multiple headings
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Home Assistant Demo</title>
<link rel="stylesheet" type="text/css" href="static/style.css" />
<link rel="stylesheet" type="text/css" href="static/tomorrow-night.min.css" />
<script src="static/highlight.min.js" type="text/javascript"></script>
<script src="static/highlight.load.js" type="text/javascript"></script>
<meta name="generator" content="nixos-render-docs" />
<link rel="home" href="index.html" title="Self Host Blocks Manual" />
<link rel="up" href="index.html" title="Self Host Blocks Manual" />
<link rel="prev" href="blocks-monitoring.html" title="Monitoring Block" />
<link rel="next" href="options.html" title="Appendix A. Self Host Blocks Options" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Home Assistant Demo</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="blocks-monitoring.html">Prev</a>&nbsp;</td>
<th width="60%" align="center">&nbsp;</th>
<td width="20%" align="right">&nbsp;<a accesskey="n" href="options.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="part">
<div class="titlepage">
<div>
<div>
<h1 class="title"><a id="demo-homeassistant"></a>Home Assistant Demo</h1>
</div>
</div>
</div>
<div class="partintro">
<p>
<span class="strong">
<strong>This whole demo is highly insecure as all the private keys are available publicly. This is only done for convenience as it is just a demo. Do not expose the VM to the internet.</strong>
</span>
</p>
<p>
The <a class="link" href="./flake.nix" target="_top"><code class="literal">flake.nix</code></a> file sets up Home Assistant server that uses a LDAP server to setup users in only about
<a class="link" href="./flake.nix#L29-L45" target="_top">15 lines</a> of related code.
</p>
<p>This guide will show how to deploy this setup to a Virtual Machine, like showed <a class="link" href="https://nixos.wiki/wiki/NixOS_modules#Developing_modules" target="_top">here</a>, in 5 commands.</p>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a id="deploy-to-the-vm"></a>Deploy to the VM</h2>
</div>
</div>
</div>
<p>Build VM with:</p>
<pre class="programlisting">
nixos-rebuild build-vm-with-bootloader --fast -I nixos-config=./configuration.nix -I nixpkgs=.
</pre>
<p>Start VM with (this call is blocking):</p>
<pre class="programlisting">
QEMU_NET_OPTS=&quot;hostfwd=tcp::2222-:2222,hostfwd=tcp::8080-:80&quot; ./result/bin/run-nixos-vm
</pre>
<p>With the VM started, print the VM’s public age key with the following command. The value you need is the one staring with <code class="literal">age</code>.</p>
<pre class="programlisting">
$ nix shell nixpkgs#ssh-to-age --command sh -c &#x27;ssh-keyscan -p 2222 -4 localhost | ssh-to-age&#x27;
# localshost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
# localhost:2222 SSH-2.0-OpenSSH_9.1
skipped key: got ssh-rsa key type, but only ed25519 keys are supported
age1l9dyy02qhlfcn5u9s4y2vhsvjtxj2c9avrpat6nvjd6rjar3tflq66jtz0
</pre>
<p>Now, make the <code class="literal">secrets.yaml</code> file decryptable in the VM.</p>
<pre class="programlisting">
SOPS_AGE_KEY_FILE=keys.txt nix run --impure nixpkgs#sops -- \
--config sops.yaml -r -i \
--add-age age1l9dyy02qhlfcn5u9s4y2vhsvjtxj2c9avrpat6nvjd6rjar3tflq66jtz0 \
secrets.yaml
</pre>
<p>Finally, deploy with:</p>
<pre class="programlisting">
SSH_CONFIG_FILE=ssh_config nix run nixpkgs#colmena --impure -- apply
</pre>
<p>This step will require you to accept the host’s fingerprint. The deploy will take a few minutes the first time and subsequent deploys will take around 15 seconds.</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a id="access-home-assistant-through-your-browser"></a>Access Home Assistant Through Your Browser</h2>
</div>
</div>
</div>
<p>Add the following entry to your <code class="literal">/etc/hosts</code> file:</p>
<pre class="programlisting">
networking.hosts = {
&quot;127.0.0.1&quot; = [ &quot;ha.example.com&quot; &quot;ldap.example.com&quot; ];
};
</pre>
<p>Which produces:</p>
<pre class="programlisting">
$ cat /etc/hosts
127.0.0.1 ha.example.com ldap.example.com
</pre>
<p>Go to <a class="link" href="http://ldap.example.com:8080" target="_top">http://ldap.example.com:8080</a> and login with:</p>
<div class="itemizedlist">
<ul class="itemizedlist compact" style="list-style-type: disc;">
<li class="listitem">
<p>username: <code class="literal">admin</code></p>
</li>
<li class="listitem">
<p>
password: the value of the field <code class="literal">lldap.user_password</code> in the <code class="literal">secrets.yaml</code> file which is
<code class="literal">fccb94f0f64bddfe299c81410096499a</code>.
</p>
</li>
</ul>
</div>
<p>Create the group <code class="literal">homeassistant_user</code> and a user assigned to that group.</p>
<p>Go to <a class="link" href="http://ha.example.com:8080" target="_top">http://ha.example.com:8080</a> and login with the user and password you just created above.</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a id="in-more-details"></a>In More Details</h2>
</div>
</div>
</div>
<div class="toc">
<dl class="toc">
<dt>
<span class="section"> <a href="demo-homeassistant.html#files">Files</a> </span>
</dt>
<dt>
<span class="section"> <a href="demo-homeassistant.html#virtual-machine">Virtual Machine</a> </span>
</dt>
<dt>
<span class="section"> <a href="demo-homeassistant.html#secrets">Secrets</a> </span>
</dt>
<dt>
<span class="section"> <a href="demo-homeassistant.html#ssh">SSH</a> </span>
</dt>
<dt>
<span class="section"> <a href="demo-homeassistant.html#deploy">Deploy</a> </span>
</dt>
</dl>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="files"></a>Files</h3>
</div>
</div>
</div>
<div class="itemizedlist">
<ul class="itemizedlist compact" style="list-style-type: disc;">
<li class="listitem">
<p>
<a class="link" href="./flake.nix" target="_top"><code class="literal">flake.nix</code></a>: nix entry point, defines one target host for
<a class="link" href="https://colmena.cli.rs" target="_top">colmena</a> to deploy to as well as the selfhostblock’s config for setting up the home assistant server paired with the LDAP server.
</p>
</li>
<li class="listitem">
<p>
<a class="link" href="./configuration.nix" target="_top"><code class="literal">configuration.nix</code></a>: defines all configuration required for colmena to deploy to the VM. The file has comments
if you’re interested.
</p>
</li>
<li class="listitem">
<p>
<a class="link" href="./hardware-configuration.nix" target="_top"><code class="literal">hardware-configuration.nix</code></a>: defines VM specific layout. This was generated with nixos-generate-config
on the VM.
</p>
</li>
<li class="listitem">
<p>Secrets related files:</p>
<div class="itemizedlist">
<ul class="itemizedlist compact" style="list-style-type: circle;">
<li class="listitem">
<p>
<a class="link" href="./keys.txt" target="_top"><code class="literal">keys.txt</code></a>: your private key for sops-nix, allows you to edit the
<code class="literal">secrets.yaml</code> file. This file should never be published but here I did it for convenience, to be able to deploy to the VM in less steps.
</p>
</li>
<li class="listitem">
<p>
<a class="link" href="./secrets.yaml" target="_top"><code class="literal">secrets.yaml</code></a>: encrypted file containing required secrets for Home Assistant and the LDAP server. This
file can be publicly accessible.
</p>
</li>
<li class="listitem">
<p>
<a class="link" href="./sops.yaml" target="_top"><code class="literal">sops.yaml</code></a>: describes how to create the <code class="literal">secrets.yaml</code> file. Can be publicly
accessible.
</p>
</li>
</ul>
</div>
</li>
<li class="listitem">
<p>SSH related files:</p>
<div class="itemizedlist">
<ul class="itemizedlist compact" style="list-style-type: circle;">
<li class="listitem">
<p>
<a class="link" href="./sshkey" target="_top"><code class="literal">sshkey(.pub)</code></a>: your private and public ssh keys. Again, the private key should usually not be published as it
is here but this makes it possible to deploy to the VM in less steps.
</p>
</li>
<li class="listitem">
<p>
<a class="link" href="./ssh_config" target="_top"><code class="literal">ssh_config</code></a>: the ssh config allowing you to ssh into the VM by just using the hostname
<code class="literal">example</code>. Usually you would store this info in your <code class="literal">~/.ssh/config</code> file but it’s provided here to avoid making you do that.
</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="virtual-machine"></a>Virtual Machine</h3>
</div>
</div>
</div>
<p>
<span class="emphasis"><em>More info about the VM.</em></span>
</p>
<p>We use <code class="literal">build-vm-with-bootloader</code> instead of just <code class="literal">build-vm</code> as that’s the only way to deploy to the VM.</p>
<p>
The VM’s User and password are both <code class="literal">nixos</code>, as setup in the <a class="link" href="./configuration.nix" target="_top"><code class="literal">configuration.nix</code></a> file under
<code class="literal">user.users.nixos.initialPassword</code>.
</p>
<p>You can login with <code class="literal">ssh -F ssh_config example</code>. You just need to accept the fingerprint.</p>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="secrets"></a>Secrets</h3>
</div>
</div>
</div>
<p>
<span class="emphasis"><em>More info about the secrets.</em></span>
</p>
<p>The private key in the <code class="literal">keys.txt</code> file is created with:</p>
<pre class="programlisting">
$ nix shell nixpkgs#age --command age-keygen -o keys.txt
Public key: age1algdv9xwjre3tm7969eyremfw2ftx4h8qehmmjzksrv7f2qve9dqg8pug7
</pre>
<p>We use the printed public key in the <code class="literal">admin</code> field in <code class="literal">sops.yaml</code> file.</p>
<p>The <code class="literal">secrets.yaml</code> file must follow the format:</p>
<pre class="programlisting">
home-assistant: |
name: &quot;My Instance&quot;
country: &quot;US&quot;
latitude_home: &quot;0.100&quot;
longitude_home: &quot;-0.100&quot;
time_zone: &quot;America/Los_Angeles&quot;
unit_system: &quot;metric&quot;
lldap:
user_password: XXX...
jwt_secret: YYY...
</pre>
<p>You can generate random secrets with:</p>
<pre class="programlisting">
$ nix run nixpkgs#openssl -- rand -hex 64
</pre>
<div class="section">
<div class="titlepage">
<div>
<div>
<h4 class="title"><a id="public-key-necessity"></a>Why do we need the VM’s public key</h4>
</div>
</div>
</div>
<p>
The <a class="link" href="./sops.yaml" target="_top"><code class="literal">sops.yaml</code></a> file describes what private keys can decrypt and encrypt the
<a class="link" href="./secrets.yaml" target="_top"><code class="literal">secrets.yaml</code></a> file containing the application secrets. Usually, you will create and add secrets to that file and when
deploying, it will be decrypted and the secrets will be copied in the <code class="literal">/run/secrets</code> folder on the VM. We thus need one private key for you to edit the
<a class="link" href="./secrets.yaml" target="_top"><code class="literal">secrets.yaml</code></a> file and one in the VM for it to decrypt the secrets.
</p>
<p>
Your private key is already pre-generated in this repo, it’s the <a class="link" href="./sshkey" target="_top"><code class="literal">sshkey</code></a> file. But when creating the VM in the step above, a new
private key and its accompanying public key were automatically generated under <code class="literal">/etc/ssh/ssh_host_ed25519_key</code> in the VM. We just need to get the public key and add it to the
<code class="literal">secrets.yaml</code> which we did in the Deploy section.
</p>
<p>To open the <code class="literal">secrets.yaml</code> file and optionnally edit it, run:</p>
<pre class="programlisting">
SOPS_AGE_KEY_FILE=keys.txt nix run --impure nixpkgs#sops -- \
--config sops.yaml \
secrets.yaml
</pre>
</div>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="ssh"></a>SSH</h3>
</div>
</div>
</div>
<p>The private and public ssh keys were created with:</p>
<pre class="programlisting">
ssh-keygen -t ed25519 -f sshkey
</pre>
<p>
You don’t need to copy over the ssh public key over to the VM as we set the <code class="literal">keyFiles</code> option which copies the public key when the VM gets created. This allows us also to disable ssh
password authentication.
</p>
<p>For reference, here is what you would need to do if you didn’t use the option:</p>
<pre class="programlisting">
$ nix shell nixpkgs#openssh --command ssh-copy-id -i sshkey -F ssh_config example
</pre>
</div>
<div class="section">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="deploy"></a>Deploy</h3>
</div>
</div>
</div>
<p>If you get a NAR hash mismatch error like herunder, you need to run <code class="literal">nix flake lock --update-input selfhostblocks</code>.</p>
<pre class="programlisting">
error: NAR hash mismatch in input ...
</pre>
</div>
</div>
<div class="toc">
<p><strong>Table of Contents</strong></p>
<dl class="toc">
<dt>
<span class="section"> <a href="demo-homeassistant.html#deploy-to-the-vm">Deploy to the VM</a> </span>
</dt>
<dt>
<span class="section"> <a href="demo-homeassistant.html#access-home-assistant-through-your-browser">Access Home Assistant Through Your Browser</a> </span>
</dt>
<dt>
<span class="section"> <a href="demo-homeassistant.html#in-more-details">In More Details</a> </span>
</dt>
</dl>
</div>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="blocks-monitoring.html">Prev</a>&nbsp;</td>
<td width="20%" align="center">&nbsp;</td>
<td width="40%" align="right">&nbsp;<a accesskey="n" href="options.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Monitoring Block&nbsp;</td>
<td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td>
<td width="40%" align="right" valign="top">&nbsp;Appendix A. Self Host Blocks Options</td>
</tr>
</table>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment