4o1x5.dev/content/post/guides/nix/remote-development/index.md

249 lines
6.4 KiB
Markdown
Raw Normal View History

---
#title: Getting started with remote deployment on NixOs
title: Remote deployments on NixOs
description: A quick and dirty guide to get started with building systems to remote instances
date: 2024-05-04 00:00:00+0000
image: taylor-vick-M5tzZtFCOfs-unsplash.jpg
categories:
- Nix
- Guide
- Sysadmin
tags:
- Nix
- NixOs
- Server Management
draft: false
---
With the capabilities of Nix & Nixos, we can tailor-make services on our local computer,
build the system, and then transmit it to a remote server using the `--target-host` argument for `nixos-rebuild`
command. This is an efficient method of deploying services to distant servers because you
don't have to connect to the machine via SSH and set up the files locally before building
them there.
## How remote deployments work
![](diagram1.svg)
NixOS allows for a seamless build process, where you can create the system on your local computer and then use
SSH to transfer the configuration files to a remote machine where the services are deployed.
This process is easy to manage and streamline. Ez to learn!
## Getting started
First you will need a machine running NixOs. Duh. But also you will need to have root access to it in some way.
If you have the root user and its password then you are set to go and can skip to the section where [I explain how to get ready for remote deployment](#first-boot)
### Setting up NixOs on a server.
#### Installing
I assume if you are reading this article you know how to install an operating system.
You will need to flash an usb drive with NixOs, for the sake of an easy install I will use `latest-nixos-plasma5-x86_64-linux.iso` since It comes with a fearly easy to use Calamares installer.
![Installer](nixosinstaller.png)
You can go ahead and click through it and it will install.
## First boot
For remote deployment to work you will need to enable ssh and configure some parameters for it to work.
We are enabling root login and also sftp for file transfer.
```nix
# configuration.nix
services.openssh = {
enable = true;
allowSFTP = true;
settings = {
PasswordAuthentication = true;
PermitRootLogin = "yes";
};
};
networking.hostName = "server1";
networking.domain = "localhost";
```
**Rebuild the system**
```zsh
sudo nixos-rebuild switch
```
## Setting up key auth
To facilitate easy deployments, you can transfer your public SSH key to the remote machine, allowing you to log
in without having to enter the password for each rebuild. This method is both more convenient and safe
```bash
ssh-copy-id root@server
```
## Create a directory for the remote
On your local machine, it's important to organize your files into a directory, particularly when working with
multiple servers. This is demonstrated below, where I showcase my personal file
organization method.
{{< filetree/container >}}
{{< filetree/folder name="servers" >}}
{{< filetree/folder name="server1" state="closed" >}}
{{< filetree/file name="configuration.nix" >}}
{{< filetree/file name="flake.nix" >}}
{{< filetree/file name="flake.lock" >}}
{{< /filetree/folder >}}
{{< filetree/folder name="server2" state="closed" >}}
{{< filetree/file name="configuration.nix" >}}
{{< filetree/folder name="services" state="closed" >}}
{{< filetree/file name="matrix.nix" >}}
{{< filetree/file name="webserver.nix" >}}
{{< /filetree/folder >}}
{{< filetree/file name="flake.nix" >}}
{{< filetree/file name="flake.lock" >}}
{{< /filetree/folder >}}
{{< /filetree/folder >}}
{{< /filetree/container >}}
## Copying essential files from remote
NixOS does not support partial builds, so you will need to transfer all the necessary files from `/etc/nixos` to
your local machine. This includes files such as `hardware-configuration.nix` and `configuration.nix`.
```bash
2024-05-10 15:51:31 +02:00
scp root@server:/etc/nixos/configuration.nix configuration.nix
```
```bash
2024-05-10 15:51:31 +02:00
scp root@server:/etc/nixos/hardware-configuration.nix hardware-configuration.nix
```
## Create flakes
You can create a file called `flake.nix` or use `nix` to do so.
```bash
nix flake init .
```
Paste the following in the file.
```nix
# flake.nix
{
description = "Server1 deployments";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
};
outputs =
{ self
, nixpkgs
, ...
}:
let
system = "x86_64-linux";
in
{
nixosConfigurations.server1 = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
./configuration.nix
];
};
};
}
```
Here is an example of how your `configuration.nix` should look like.
```nix
# configuration.nix
{ config, pkgs, ... }:
{
imports =
[
./hardware-configuration.nix
];
networking.hostName = "server1";
networking.domain = "example.com";
services.openssh = {
enable = true;
allowSFTP = true;
settings = {
PasswordAuthentication = true;
PermitRootLogin = "yes";
};
};
}
```
## Set up a service
This little example shows a dummy nginx service.
```nix
# nginx.nix
services.nginx = {
enable = true;
virtualHosts = {
"example.com" = {
locations."/" = {
# ...
};
};
};
}
```
Insert it in the configuration.nix `imports` section.
```nix
imports = [
./hardware-configuration.nix
./nginx.nix
];
```
## Deploy!
After all this we can just go ahead and execute a rebuild like we would do on our local machine. Except in this case we have to add the `--flake` to the rebuild command and also add the hostname we are building for.
```bash
nixos-rebuild switch --flake .#server1 --target-host root@server --show-trace
```
## Service management
Since NixOs uses systemd we can utilize its tools such as `journalctl` or `systemcl` to check up on how our services are doing.
Here are a few commands I recommend using
Prints the last 100 logs of nginx
```bash
journalctl -u nginx.service -n 200
```
Displays the status of the service
```bash
systemctl status nginx.service
```
## Afterthoughts
The first-boot section could be skipped if you [create a custom nixos installation media](https://wiki.nixos.org/wiki/Creating_a_NixOS_live_CD) then flash that to the server. With a custom media you can define ssh to already have these options enabled and also can add your public key.
This is how I've been doing my deployments for the past 1 month for the 4 of my servers. It's much easier than my old-school method of ssh-ing into my alpine machines and manage my deployments with `docker-compose`