nixos - cloud-init

But there’s no image?!#

When starting a new instance up on scaleway there is no option to select NixOS, but using the cloud init hook you are able to boot up an instance.

After a few moments you can login using your predefined SSH keys which have been initialised, along with the hostname and SSH serrvice, in /etc/nixos/configuration.nix:

{ ... }: {
  imports = [

  boot.cleanTmpDir = true;
  networking.hostName = "almond";
  networking.firewall.allowPing = true;
  services.openssh.enable = true;
  users.users.root.openssh.authorizedKeys.keys = [
    "# WARNING: Automatically generated file" 
    "# This file will be erased at every boot" 
    "# This file was generated with '/usr/local/sbin/scw-fetch-ssh-keys'" 
    "# And recreate your 'authorized_keys' file with the new keys:" 
    "ssh-keys --upgrade'" 
    "ssh-ed25519 ABCDEFG..." 
    "# Below your custom ssh keys from '/root/.ssh/instance_keys'" 

Configuring our install#

The main selling point of NixOS is its declarative configuration; you create a file describing your system and from it you can create a system which is reproducible.

For learning I was iterating by modifying /etc/nixos/host.nix (the file that we define in our cloud-init script). After each modification I ran nixos-rebuild test, which attempts to build the new system and “activate” it, but does not update the bootloader so on a reboot, your current stable system would be booted.

After a few iterations I ended up with the following cloud-init file which sets up the system ready for me to rsync the blog to the server. At a later stage I plan on using GitHub hooks to automate this stage and have it so everything is contained in a repo.

- path: /etc/nixos/host.nix
  permissions: '0644'
  content: |
    {pkgs, ...}:
        # create the /var/www directory so we
        # can rsync to it later
        systemd.tmpfiles.rules = [
                "d /var/www/ 755 root root"
        # list of packages we want to install
        environment.systemPackages = with pkgs;
        # allow http/https
        networking.firewall.allowedTCPPorts = [ 80 443 ];
        # setup nginx  
        services.nginx = {
                enable = true;
                virtualHosts."" = {
                        enableACME = true;
                        forceSSL = true;
                        root = "/var/www/blog";
        # setup the acme
        security.acme = {
                acceptTerms = true;
                email = "";

  - curl |  NIXOS_IMPORT=./host.nix NIX_CHANNEL=nixos-20.09 bash 2>&1 | tee /tmp/infect.log