aboutsummaryrefslogtreecommitdiff
path: root/posts/git-to-deploy.njk
blob: 9676602a5fc825f122884ecb222e7d8cca88f8f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
---
layout: post.njk
title: Using Git to Deploy NixOS Configurations
tags: post 
date: 2024-01-20
---

<p>Lately I have been learning Nix+NixOS, which is configured using a
declarative programming language. What is nice about that is that allows
us to reproduce a system very easily. However, I googled around and
tried to figure out how to easily deploy my config from a local machine
to a Nix machine. I started off SSHing into the machine and making edits
using nano in the config, but it’s tedious and I’d rather use my local
machine to change the configurations. There is also little advantage to
having a declarative config if I can’t reuse it elsewhere.</p>
<p>There are tools out there like <a
href="https://github.com/serokell/deploy-rs/tree/master">deploy-rs</a>
and <a href="https://github.com/NixOS/nixops">Nixops</a>, however I
found them a bit overkill for my need. There also seems to be a way to
use nixos-rebuild to build a change on your local machine and deploy,
which is intriguing but I don’t run nixos on my machine so it felt like
a no-go. So in the end, I came up with a script to make the setup easy.
It makes use of git, so it allows me to make my changes using a git flow
similar to Heroku. Here is what the installation script looks like:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Start of by adding git to our configuration.nix, we will levarage this to</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="co"># be able to easily make changes to our machine without SSH.</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="fu">sed</span> <span class="at">-i</span> <span class="st">&#39;s/}/  programs.git.enable = true;\n}/g&#39;</span> /etc/nixos/configuration.nix</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="co"># Rebuild nix so we have git available</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="ex">nixos-rebuild</span> switch</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="co"># Set up a git repository where our nixos configuration lives</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> /etc/nixos</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> init</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="co"># Change branch name to main instead of master</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> branch <span class="at">-m</span> main</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="co"># Add existing config and commit</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> add .</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> commit <span class="at">-m</span> <span class="st">&quot;Initial commit&quot;</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="co"># Allow us to push changes to our machine and have those changes immediately reflected in the files</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> config receive.denyCurrentBranch updateInstead</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="co"># Store a push-to-checkout script to variable $validate_script</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a><span class="bu">read</span> <span class="at">-r</span> <span class="at">-d</span> <span class="st">&#39;&#39;</span> <span class="va">validate_script</span> <span class="op">&lt;&lt;-EOF</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="st">#!/bin/sh</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a><span class="st">echo &quot;Running push-to-checkout hook&quot;</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a><span class="st"># Get the changes made</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a><span class="st">git read-tree -u -m HEAD &quot;</span><span class="va">$1</span><span class="st">&quot;</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a><span class="st"># Run a dry-build to see that it works</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a><span class="st">nixos-rebuild dry-build</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a><span class="st">result=</span><span class="va">$?</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a><span class="st">if [ </span><span class="va">$result</span><span class="st"> -eq 1 ] ; then</span></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a><span class="st">  # In case of failure, we&#39;ll undo the changes applied from read-tree</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a><span class="st">  git stash --all --quiet</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a><span class="st">  exit 1</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a><span class="st">fi</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a><span class="st">exit 0</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a><span class="op">EOF</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a><span class="bu">echo</span> <span class="st">&quot;</span><span class="va">$validate_script</span><span class="st">&quot;</span> <span class="op">&gt;</span> /etc/nixos/.git/hooks/push-to-checkout</span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a><span class="co"># Make the hook executable</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a><span class="fu">chmod</span> +x /etc/nixos/.git/hooks/push-to-checkout</span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true" tabindex="-1"></a><span class="co"># Add a git hook to apply the changes afterward</span></span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true" tabindex="-1"></a><span class="bu">echo</span> <span class="at">-e</span> <span class="st">&#39;#!/bin/sh \nnixos-rebuild switch&#39;</span> <span class="op">&gt;</span> /etc/nixos/.git/hooks/post-receive</span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true" tabindex="-1"></a><span class="co"># Make the hook executable</span></span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true" tabindex="-1"></a><span class="fu">chmod</span> +x /etc/nixos/.git/hooks/post-receive</span></code></pre></div>
<p>Once set up, you can clone the repo on your local computer</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> clone root@your-machine:/etc/nixos</span></code></pre></div>
<p>And if you’d like to set up a backup on <a
href="https://sourcehut.org/">Sourcehut</a>, you can do so easily:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> remote add backup git@git.sr.ht:~username/reponame</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> push backup main</span></code></pre></div>
<p>This script can be ran on a new machine. I used <a
href="https://github.com/elitak/nixos-infect/tree/master">Nixos-infect</a>
to setup NixOS on a VPC that I rent on Hetzner Cloud.</p>
<p>Edit: Thanks to Valentin Gagarin for pointing out the distinction between Nix and NixOS. I have updated the article to correctly call it NixOS instead of Nix.</p>