diff options
Diffstat (limited to 'nixos/doc/manual/from_md/configuration')
-rw-r--r-- | nixos/doc/manual/from_md/configuration/abstractions.section.xml | 101 | ||||
-rw-r--r-- | nixos/doc/manual/from_md/configuration/sshfs-file-systems.section.xml | 139 |
2 files changed, 240 insertions, 0 deletions
diff --git a/nixos/doc/manual/from_md/configuration/abstractions.section.xml b/nixos/doc/manual/from_md/configuration/abstractions.section.xml new file mode 100644 index 00000000000..c71e23e34ad --- /dev/null +++ b/nixos/doc/manual/from_md/configuration/abstractions.section.xml @@ -0,0 +1,101 @@ +<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-module-abstractions"> + <title>Abstractions</title> + <para> + If you find yourself repeating yourself over and over, it’s time to + abstract. Take, for instance, this Apache HTTP Server configuration: + </para> + <programlisting language="bash"> +{ + services.httpd.virtualHosts = + { "blog.example.org" = { + documentRoot = "/webroot/blog.example.org"; + adminAddr = "alice@example.org"; + forceSSL = true; + enableACME = true; + enablePHP = true; + }; + "wiki.example.org" = { + documentRoot = "/webroot/wiki.example.org"; + adminAddr = "alice@example.org"; + forceSSL = true; + enableACME = true; + enablePHP = true; + }; + }; +} +</programlisting> + <para> + It defines two virtual hosts with nearly identical configuration; + the only difference is the document root directories. To prevent + this duplication, we can use a <literal>let</literal>: + </para> + <programlisting language="bash"> +let + commonConfig = + { adminAddr = "alice@example.org"; + forceSSL = true; + enableACME = true; + }; +in +{ + services.httpd.virtualHosts = + { "blog.example.org" = (commonConfig // { documentRoot = "/webroot/blog.example.org"; }); + "wiki.example.org" = (commonConfig // { documentRoot = "/webroot/wiki.example.com"; }); + }; +} +</programlisting> + <para> + The <literal>let commonConfig = ...</literal> defines a variable + named <literal>commonConfig</literal>. The <literal>//</literal> + operator merges two attribute sets, so the configuration of the + second virtual host is the set <literal>commonConfig</literal> + extended with the document root option. + </para> + <para> + You can write a <literal>let</literal> wherever an expression is + allowed. Thus, you also could have written: + </para> + <programlisting language="bash"> +{ + services.httpd.virtualHosts = + let commonConfig = ...; in + { "blog.example.org" = (commonConfig // { ... }) + "wiki.example.org" = (commonConfig // { ... }) + }; +} +</programlisting> + <para> + but not <literal>{ let commonConfig = ...; in ...; }</literal> since + attributes (as opposed to attribute values) are not expressions. + </para> + <para> + <emphasis role="strong">Functions</emphasis> provide another method + of abstraction. For instance, suppose that we want to generate lots + of different virtual hosts, all with identical configuration except + for the document root. This can be done as follows: + </para> + <programlisting language="bash"> +{ + services.httpd.virtualHosts = + let + makeVirtualHost = webroot: + { documentRoot = webroot; + adminAddr = "alice@example.org"; + forceSSL = true; + enableACME = true; + }; + in + { "example.org" = (makeVirtualHost "/webroot/example.org"); + "example.com" = (makeVirtualHost "/webroot/example.com"); + "example.gov" = (makeVirtualHost "/webroot/example.gov"); + "example.nl" = (makeVirtualHost "/webroot/example.nl"); + }; +} +</programlisting> + <para> + Here, <literal>makeVirtualHost</literal> is a function that takes a + single argument <literal>webroot</literal> and returns the + configuration for a virtual host. That function is then called for + several names to produce the list of virtual host configurations. + </para> +</section> diff --git a/nixos/doc/manual/from_md/configuration/sshfs-file-systems.section.xml b/nixos/doc/manual/from_md/configuration/sshfs-file-systems.section.xml new file mode 100644 index 00000000000..6b317aa63e9 --- /dev/null +++ b/nixos/doc/manual/from_md/configuration/sshfs-file-systems.section.xml @@ -0,0 +1,139 @@ +<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-sshfs-file-systems"> + <title>SSHFS File Systems</title> + <para> + <link xlink:href="https://github.com/libfuse/sshfs">SSHFS</link> is + a + <link xlink:href="https://en.wikipedia.org/wiki/Filesystem_in_Userspace">FUSE</link> + filesystem that allows easy access to directories on a remote + machine using the SSH File Transfer Protocol (SFTP). It means that + if you have SSH access to a machine, no additional setup is needed + to mount a directory. + </para> + <section xml:id="sec-sshfs-interactive"> + <title>Interactive mounting</title> + <para> + In NixOS, SSHFS is packaged as <package>sshfs</package>. Once + installed, mounting a directory interactively is simple as + running: + </para> + <programlisting> +$ sshfs my-user@example.com:/my-dir /mnt/my-dir +</programlisting> + <para> + Like any other FUSE file system, the directory is unmounted using: + </para> + <programlisting> +$ fusermount -u /mnt/my-dir +</programlisting> + </section> + <section xml:id="sec-sshfs-non-interactive"> + <title>Non-interactive mounting</title> + <para> + Mounting non-interactively requires some precautions because + <literal>sshfs</literal> will run at boot and under a different + user (root). For obvious reason, you can’t input a password, so + public key authentication using an unencrypted key is needed. To + create a new key without a passphrase you can do: + </para> + <programlisting> +$ ssh-keygen -t ed25519 -P '' -f example-key +Generating public/private ed25519 key pair. +Your identification has been saved in test-key +Your public key has been saved in test-key.pub +The key fingerprint is: +SHA256:yjxl3UbTn31fLWeyLYTAKYJPRmzknjQZoyG8gSNEoIE my-user@workstation +</programlisting> + <para> + To keep the key safe, change the ownership to + <literal>root:root</literal> and make sure the permissions are + <literal>600</literal>: OpenSSH normally refuses to use the key if + it’s not well-protected. + </para> + <para> + The file system can be configured in NixOS via the usual + <link xlink:href="options.html#opt-fileSystems">fileSystems</link> + option. Here’s a typical setup: + </para> + <programlisting language="bash"> +{ + system.fsPackages = [ pkgs.sshfs ]; + + fileSystems."/mnt/my-dir" = { + device = "my-user@example.com:/my-dir/"; + fsType = "sshfs"; + options = + [ # Filesystem options + "allow_other" # for non-root access + "_netdev" # this is a network fs + "x-systemd.automount" # mount on demand + + # SSH options + "reconnect" # handle connection drops + "ServerAliveInterval=15" # keep connections alive + "IdentityFile=/var/secrets/example-key" + ]; + }; +} +</programlisting> + <para> + More options from <literal>ssh_config(5)</literal> can be given as + well, for example you can change the default SSH port or specify a + jump proxy: + </para> + <programlisting language="bash"> +{ + options = + [ "ProxyJump=bastion@example.com" + "Port=22" + ]; +} +</programlisting> + <para> + It’s also possible to change the <literal>ssh</literal> command + used by SSHFS to connect to the server. For example: + </para> + <programlisting language="bash"> +{ + options = + [ (builtins.replaceStrings [" "] ["\\040"] + "ssh_command=${pkgs.openssh}/bin/ssh -v -L 8080:localhost:80") + ]; + +} +</programlisting> + <note> + <para> + The escaping of spaces is needed because every option is written + to the <literal>/etc/fstab</literal> file, which is a + space-separated table. + </para> + </note> + <section xml:id="sec-sshfs-troubleshooting"> + <title>Troubleshooting</title> + <para> + If you’re having a hard time figuring out why mounting is + failing, you can add the option + <literal>"debug"</literal>. This enables a verbose log + in SSHFS that you can access via: + </para> + <programlisting> +$ journalctl -u $(systemd-escape -p /mnt/my-dir/).mount +Jun 22 11:41:18 workstation mount[87790]: SSHFS version 3.7.1 +Jun 22 11:41:18 workstation mount[87793]: executing <ssh> <-x> <-a> <-oClearAllForwardings=yes> <-oServerAliveInterval=15> <-oIdentityFile=/var/secrets/wrong-key> <-2> <my-user@example.com> <-s> <sftp> +Jun 22 11:41:19 workstation mount[87793]: my-user@example.com: Permission denied (publickey). +Jun 22 11:41:19 workstation mount[87790]: read: Connection reset by peer +Jun 22 11:41:19 workstation systemd[1]: mnt-my\x2ddir.mount: Mount process exited, code=exited, status=1/FAILURE +Jun 22 11:41:19 workstation systemd[1]: mnt-my\x2ddir.mount: Failed with result 'exit-code'. +Jun 22 11:41:19 workstation systemd[1]: Failed to mount /mnt/my-dir. +Jun 22 11:41:19 workstation systemd[1]: mnt-my\x2ddir.mount: Consumed 54ms CPU time, received 2.3K IP traffic, sent 2.7K IP traffic. +</programlisting> + <note> + <para> + If the mount point contains special characters it needs to be + escaped using <literal>systemd-escape</literal>. This is due + to the way systemd converts paths into unit names. + </para> + </note> + </section> + </section> +</section> |