nixos-anywhere/quickstart.html
2023-09-17 18:03:11 +00:00

432 lines
22 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Quickstart - nixos-anywhere - install NixOS everywhere</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body>
<div id="body-container">
<!-- Provide site root to javascript -->
<script>
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script>
var html = document.querySelector('html');
var sidebar = null;
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded affix "><a href="requirements.html">System Requirements</a></li><li class="chapter-item expanded affix "><a href="quickstart.html" class="active">Quickstart</a></li><li class="chapter-item expanded affix "><a href="howtos/INDEX.html">How to Guide</a></li><li class="chapter-item expanded "><a href="howtos/no-os.html"><strong aria-hidden="true">1.</strong> Installing on a machine with no operating system</a></li><li class="chapter-item expanded "><a href="howtos/custom-kexec.html"><strong aria-hidden="true">2.</strong> Using your own kexec image</a></li><li class="chapter-item expanded "><a href="howtos/secrets.html"><strong aria-hidden="true">3.</strong> Secrets and full disk encryption</a></li><li class="chapter-item expanded "><a href="howtos/use-without-flakes.html"><strong aria-hidden="true">4.</strong> Use without flakes</a></li><li class="chapter-item expanded "><a href="howtos/terraform.html"><strong aria-hidden="true">5.</strong> Terraform</a></li><li class="chapter-item expanded affix "><a href="reference.html">Reference</a></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<!-- Track and set sidebar scroll position -->
<script>
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
sidebarScrollbox.addEventListener('click', function(e) {
if (e.target.tagName === 'A') {
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
}
}, { passive: true });
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
sessionStorage.removeItem('sidebar-scroll');
if (sidebarScrollTop) {
// preserve sidebar scroll position when navigating via links within sidebar
sidebarScrollbox.scrollTop = sidebarScrollTop;
} else {
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
var activeSection = document.querySelector('#sidebar .active');
if (activeSection) {
activeSection.scrollIntoView({ block: 'center' });
}
}
</script>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">nixos-anywhere - install NixOS everywhere</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="quickstart-guide-nixos-anywhere"><a class="header" href="#quickstart-guide-nixos-anywhere">Quickstart Guide: nixos-anywhere</a></h1>
<p><strong><em>Install NixOS everywhere via ssh</em></strong></p>
<img src="https://raw.githubusercontent.com/numtide/nixos-anywhere/main/docs/logo.png" width="150" height="150">
<p><a href="./INDEX.html">Documentation Index</a></p>
<h2 id="introduction"><a class="header" href="#introduction">Introduction</a></h2>
<p>This guide documents a simple installation of NixOS using <strong>nixos-anywhere</strong> on
a target machine running x86_64 Linux with
<a href="https://man7.org/linux/man-pages/man8/kexec.8.html">kexec</a> support. The example
used in this guide installs NixOS on a Hetzner cloud machine. The configuration
may be different for some other instances. We will be including further examples
in the <a href="./howtos/INDEX.html">How To Guide</a> as and when they are available.</p>
<p>You will need:</p>
<ul>
<li>A <a href="https://nixos.wiki/wiki/Flakes">flake</a> that controls the actions to be
performed</li>
<li>A disk configuration containing details of the file system that will be
created on the new server.</li>
</ul>
<p><strong>nixos-anywhere</strong> doesnt need to be installed. You can run it directly from
<a href="https://github.com/numtide/nixos-anywhere">Numtide's repository on Github.</a></p>
<p>Details of the flake, the disk configuration and the CLI command are discussed
below.</p>
<h2 id="steps-required-to-run-nixos-anywhere"><a class="header" href="#steps-required-to-run-nixos-anywhere">Steps required to run nixos-anywhere</a></h2>
<ol>
<li>
<p><strong>Enable Flakes and Create a Directory</strong>:</p>
<ul>
<li>Ensure that flakes are enabled on your system. To enable flakes, refer to
the <a href="https://nixos.wiki/wiki/Flakes#enable-flakes">NixOS Wiki</a>.</li>
<li>Create a directory to store the flake and configuration files.</li>
</ul>
</li>
<li>
<p><strong>Initialize a Flake</strong>: Within the newly-created directory, execute the
command:</p>
<pre><code class="language-bash">nix flake init
</code></pre>
<p>This command will generate a <code>flake.nix</code> file. Modify this file according to
your requirements.</p>
<ul>
<li>
<p><strong>For a Minimal Setup</strong>:<br />
You can copy and paste the example flake contents available
<a href="https://github.com/numtide/nixos-anywhere-examples/blob/main/flake.nix">here</a>.
This example is tailored for a virtual machine setup similar to one on
<a href="https://www.hetzner.com/cloud">Hetzner Cloud</a>.</p>
<p><strong>Hardware-Specific Configuration</strong>: If you're not using a virtual machine,
you'll need to generate a custom hardware configuration with
<code>nixos-generate-config</code>.</p>
</li>
</ul>
</li>
</ol>
<ul>
<li>
<p><strong>Getting <code>nixos-generate-config</code> on Target Machine</strong>:</p>
<ol>
<li><strong>Option 1</strong>: If NixOS is not installed, boot into an installer without
first installing NixOS.</li>
<li><strong>Option 2</strong>: Use the kexec tarball method, as described
<a href="https://github.com/nix-community/nixos-images#kexec-tarballs">here</a>.</li>
</ol>
</li>
<li>
<p><strong>Generate Configuration</strong>: Run the following command on the target machine:</p>
<pre><code class="language-bash">nixos-generate-config --no-filesystems --root /mnt
</code></pre>
<p>This creates the necessary configuration files under <code>/mnt/etc/nixos/</code>, which
you can then customize as needed.</p>
</li>
</ul>
<ol start="3">
<li>
<p><strong>Find SSH Key Line</strong>:<br />
if you cloned
<a href="https://github.com/numtide/nixos-anywhere-examples/blob/main/flake.nix">our nixos-anywhere-example</a>
you will also replace the SSH key like this: In your configuration, locate
the line that reads:</p>
<pre><code class="language-bash"># change this to your ssh key
&quot;CHANGE&quot;
</code></pre>
<p>Replace the text <code>CHANGE</code> with your own SSH key. This is crucial, as you will
not be able to log into the target machine post-installation without it.</p>
</li>
<li>
<p>In the same directory, create a file named <code>disk-config.nix</code>. This will be
used to specify the disk layout to the <strong>disko</strong> tool, which nixos-anywhere
uses to partition, format and mount the disks. Again, for a simple
installation you can paste the contents from the example
<a href="https://github.com/numtide/nixos-anywhere-examples/blob/main/disk-config.nix">here</a>.
This configures a standard GPT (GUID Partition Table) partition compatible
with both EFI and BIOS systems, and mounts the disk as <code>/dev/sda</code>. If this
doesnt meet your requirements, choose an example that suits your disk layout
from the
<a href="https://github.com/nix-community/disko/tree/master/example">disko examples</a>.
For more information about this configuration, refer to the
<a href="https://github.com/nix-community/disko">disko documentation.</a></p>
</li>
<li>
<p>Run the following command to create the <code>flake.lock</code> file:</p>
</li>
</ol>
<pre><code>nix flake lock
</code></pre>
<p>Optionally, you can commit these files to a repo such as Github, or you can
simply reference your local directory when you run <strong>nixos-anywhere</strong>. This
example uses a local directory on the source machine.</p>
<ol start="6">
<li>
<p>On the target machine, make sure you have access as root via ssh by adding
your SSH key to the file <code>authorized_keys</code> in the directory <code>/root/.ssh</code></p>
</li>
<li>
<p>(Optional) Test your nixos and disko configuration:</p>
</li>
</ol>
<p>The following command will automatically test your nixos configuration and run
disko inside a virtual machine, where</p>
<ul>
<li>
<p><code>&lt;path to configuration&gt;</code> is the path to the directory or repository
containing <code>flake.nix</code> and <code>disk-config.nix</code></p>
</li>
<li>
<p><code>&lt;configuration name&gt;</code> must match the name that immediately follows the text
<code>nixosConfigurations.</code> in the flake, as indicated by the comment in the
<a href="https://github.com/numtide/nixos-anywhere-examples/blob/main/flake.nix">example</a>).</p>
</li>
</ul>
<pre><code>nix run github:numtide/nixos-anywhere -- --flake &lt;path to configuration&gt;#&lt;configuration name&gt; --vm-test
</code></pre>
<ol start="8">
<li>
<p>You can now run <strong>nixos-anywhere</strong> from the command line as shown below,
where:</p>
<ul>
<li>
<p><code>&lt;path to configuration&gt;</code> is the path to the directory or repository
containing <code>flake.nix</code> and <code>disk-config.nix</code></p>
</li>
<li>
<p><code>&lt;configuration name&gt;</code> must match the name that immediately follows the
text <code>nixosConfigurations.</code> in the flake, as indicated by the comment in
the
<a href="https://github.com/numtide/nixos-anywhere-examples/blob/main/flake.nix">example</a>).</p>
</li>
<li>
<p><code>&lt;ip address&gt;</code> is the IP address of the target machine.</p>
</li>
</ul>
</li>
</ol>
<pre><code>nix run github:numtide/nixos-anywhere -- --flake &lt;path to configuration&gt;#&lt;configuration name&gt; root@&lt;ip address&gt;
</code></pre>
<p>The command would look  like this if you had created your files in a directory
named <code>/home/mydir/test</code> and the IP address of your target machine is
<code>37.27.18.135</code>:</p>
<pre><code>nix run github:numtide/nixos-anywhere -- --flake /home/mydir/test#hetzner-cloud root@37.27.18.135
</code></pre>
<p><strong>nixos-anywhere</strong> will then run, showing various output messages at each stage.
It may take some time to complete, depending on Internet speeds. It should
finish by showing the messages below before returning to the command prompt.</p>
<pre><code>Installation finished. No error reported.
Warning: Permanently added '&lt;ip-address&gt;' (ED25519) to the list of known hosts
</code></pre>
<p>When this happens, the target server will have been overwritten with a new
installation of NixOS. Note that the server's public SSH key will have changed.</p>
<p>If you have previously accessed this server using SSH, you may see the following
message the next time you try to log in to the target.</p>
<pre><code> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.
Please contact your system administrator.
Add correct host key in ~/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in ~/.ssh/known_hosts:6
remove with:
ssh-keygen -f ~/.ssh/known_hosts&quot; -R &quot;&lt;ip addrress&gt;&quot;
Host key for &lt;ip_address&gt; has changed and you have requested strict checking.
Host key verification failed.
</code></pre>
<p>This is because the <code>known_hosts</code> file in the <code>.ssh</code> directory now contains a
mismatch, since the server has been overwritten. To solve this, use a text
editor to remove the old entry from the <code>known_hosts</code> file. The next connection
attempt will then treat this as a new server.</p>
<p>The error message line <code>Offending ECDSA key in ~/.ssh/known_hosts:</code> gives the
line number that needs to be removed from the <code>known_hosts</code> file.</p>
<p>The new server's configurations are defined in the flake. <code>nixos-anywhere</code> does
not create <code>etc/nixos/configuration.nix</code>, since it expects the server to be
administered remotely. Any future changes to the configuration should be made to
the flake, and you would reference this flake when doing the nixos-rebuild
command or a deployment tool of your choice i.e.
<a href="https://github.com/zhaofengli/colmena">colmena</a>,
<a href="https://github.com/MatthewCroughan/nixinate">nixinate</a>.</p>
<p>This example can be run from the machine itself for updating (replace
<code>&lt;URL to your flake&gt;</code> with your flake i.e. <code>.#</code> if your flake is in the current
directory):</p>
<pre><code>nixos-rebuild switch --flake &lt;URL to your flake&gt;
</code></pre>
<p>You can also run <code>nixos-rebuild</code> to update a machine remotly, if you have set up
an openssh server and your ssh key for the root user:</p>
<pre><code>nixos-rebuild switch --flake &lt;URL to your flake&gt; --target-host &quot;root@&lt;ip address&gt;&quot;
</code></pre>
<p>For more information on different use cases of <strong>nixos-anywhere</strong> please refer
to the <a href="./howtos/INDEX.html">How to Guide</a>, and for more technical information and
explanation of known error messages, refer to the
<a href="./reference.html">Reference Manual</a>.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="requirements.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="howtos/INDEX.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="requirements.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="howtos/INDEX.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script>
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js"></script>
<script src="mark.min.js"></script>
<script src="searcher.js"></script>
<script src="clipboard.min.js"></script>
<script src="highlight.js"></script>
<script src="book.js"></script>
<!-- Custom JS scripts -->
</div>
</body>
</html>