6.4 KiB
title | description | date | image | categories | tags | draft | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Remote deployments on NixOs | A quick and dirty guide to get started with building systems to remote instances | 2024-05-04 00:00:00+0000 | taylor-vick-M5tzZtFCOfs-unsplash.jpg |
|
|
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
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
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.
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.
# configuration.nix
services.openssh = {
enable = true;
allowSFTP = true;
settings = {
PasswordAuthentication = true;
PermitRootLogin = "yes";
};
};
networking.hostName = "server1";
networking.domain = "localhost";
Rebuild the system
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
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
.
scp root@server:/etc/nixos/configuration.nix configuration.nix
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.
nix flake init .
Paste the following in the file.
# 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.
# 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.
# nginx.nix
services.nginx = {
enable = true;
virtualHosts = {
"example.com" = {
locations."/" = {
# ...
};
};
};
}
Insert it in the configuration.nix imports
section.
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.
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
journalctl -u nginx.service -n 200
Displays the status of the service
systemctl status nginx.service
Afterthoughts
The first-boot section could be skipped if you create a custom nixos installation media 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