Getting Started: AWS Edition

Prerequisites

Your setup machine needs the following:

  • Nix on your Setup Machine (unless you're using NixOS)

  • An id_ed25519 keypair on your Setup Machine. (Link coming soon.)

  • Git (Optional). Clan uses Git internally, but you can optionally install it to make your own use of it. See the Git installation instructions.

1. Create a Server on AWS

Danger

The steps in this document will erase all data on your Hetzner server's hard drive.

From inside the AWS Console, head to the EC2 service, and click on Instances on the left. Then click Launch Instances.

Provide a name, such as Clan Test Machine.

Under Application and OS Images, choose Quick Start, and under that click on Ubuntu.

Under Instance type you have some flexibility, but we recommend choosing at least t3-small; however t3-large works best.

Note

Do not use t2 instances. In general, use Nitro instance types: t3, m5, c5, r5, m6i, c6i, etc. Avoid Xen instance types: t2, m4, c4, r4, etc. as the newer kexec tool (used internally by Clan) doesn't work well with infrastructure changes Amazon recently put in place with the Xen technology.

Under Key pair, select one of your existing key pairs, or create a new one. (If you create a new one, choose ED25519 for the type. It will download automatically. Be sure to move it in your ~/.ssh directory.)

Under Network Settings you can either create a security group or use an existing one; in either case it needs to allow SSH traffic from at least your own IP address.

Under Configure Storage enter 16 for the GB.

Click Launch instance.

After the server is running, make sure you can log into it:

ssh -i <KEY-PAIR-FILE> ubuntu@<IP-ADDRESS>

substituting:

  • <KEY-PAIR-FILE> for the path and name of your key pair file
  • <IP-ADDRESS> for your new server's public IP address. You can find this by clicking on the instance ID in the console; it will be in the middle near the top.
Tip

The main username for Ubuntu on EC2 is ubuntu.

Then exit:

exit

Add your id_ed25519 key pair

Next we need to configure your server by adding your key pair.

Add the key pair from your local server:

ssh -i ~/.ssh/<KEY-PAIR-FILE>.pem ubuntu@<IP-ADDRESS> \
"cat >> /home/ubuntu/.ssh/authorized_keys" < ~/.ssh/id_ed25519.pub

replacing <KEY-PAIR-FILE> with the name of the file you used when you provisioned the server.

Now you should be able to connect without specifying a key:

ssh ubuntu@<IP-ADDRESS>

Then exit:

exit
Important

This step is not optional; Clan uses an existing id_ed25519 key to connect.

2. Run the Clan setup

Start by creating a new clan:

nix run "https://git.clan.lol/clan/clan-core/archive/main.tar.gz#clan-cli" --refresh -- init

and enter a name for it, e.g. MY-CLAN-1, followed by a domain, e.g. myclan1.lol. (This does not have to be an actual registered domain.)

Important

The first time you run this, Clan will automatically create an age key at ~/.config/sops/age/keys.txt. This key encrypts your secrets - back it up somewhere safe, and then type "y".

Important

If you've run this before, you'll also be asked to select admin keys; you'll most likely want to type "1" and press enter.

Change to the new folder:

cd MY-CLAN-1

You will see a message about direnv needing approval to run. Type:

direnv allow

3. Create a Machine Configuration

Next, create a machine configuration, which adds a description of a machine to your inventory. For this example, call it test-machine, by typing:

clan machines create test-machine

Open clan.nix, and find the inventory.machines line; add the following immediately after it; replace the IP address with your Hetzner server's IP address:

inventory.machines = { # FIND THIS LINE, ADD THE FOLLOWING
    test-machine = {
        deploy.targetHost = "root@<IP-ADDRESS>"; # REPLACE WITH YOUR MACHINE'S IP ADDRESS; keep "root@"
        tags = [ ];
    };
Note

Although you normally log in to AWS Ubuntu servers with username ubuntu, when Clan boots to NixOS, it will be using root, hence the root@ in this code snippet.

Test it out:

clan machines list

4. Add your allowed keys

Next, add your public key to the allowed keys. You can find it by running:

cat ~/.ssh/id_ed25519.pub

Open clan.nix, and replace PASTE_YOUR_KEY_HERE with the contents of the id_ed25519.pub file:

"admin-machine-1" = "PASTE_YOUR_KEY_HERE";

Verify that your configuration is valid:

clan show

5. Gather Hardware Configuration

Now gather the hardware configuration from the target machine; note that for this step we specify the ubuntu username:

clan machines init-hardware-config test-machine --target-host ubuntu@<IP-ADDRESS>

You will be asked to enter "y" to proceed.

Note

At some point, you will likely see "Connection timed out" occur multiple times. Please be patient, as the server is rebooting during this time, and it will eventually connect.

6. Add a Disk Configuration.

Next, configure a disk for the target machine. You'll run this command in two steps; first, type it like so:

clan templates apply disk ext4-single-disk test-machine --set mainDisk ""

This will generate an error; note the disk ID it prints out (typically starting with /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_), and add it inside the quotes, e.g.:

clan templates apply disk ext4-single-disk test-machine --set mainDisk "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_113572628"

7. Install NixOS

Install NixOS on the target machine by typing:

clan machines install test-machine

You will be asked whether you want to install — type y. You will also be prompted for a password; you can accept the defaults and press Enter.

You will then be asked for a password to assign to the root login for the machine. You can either create one, or let Clan assign a random one.

If you get an error about Sandboxing

If you get an error regarding sandboxing not being available, type the following to disable sandboxing, and then run the above command again:

clan vars generate test-machine --no-sandbox

8. Test the Connection

Now you can try connecting to the remote machine:

clan ssh test-machine

You'll quite likely get an error at first regarding the host identification. It should include a line to type to remove the old ID; paste the line you're shown, which will look similar to this:

  ssh-keygen -f '/home/user/.ssh/known_hosts' -R '<IP-ADDRESS>'

Then try again:

clan ssh test-machine

You should connect and see the prompt:

[root@test-machine:~]#

Practice: Install Some Packages

Now let's look at how you can use Clan to install and remove packages on a target machine.

For this demonstration we'll add three command-line packages: bat, btop, and tldr. In clan.nix, under inventory.instances, add the following lines:

  inventory.instances = {
    packages = {
      roles.default.machines."test-machine".settings = {
        packages = [ "bat" "btop" "tldr" ];
      };
    };
    # ... existing wifi service ...
  };

This declares that the three packages will be present on the machine. To install them, type:

clan machines update test-machine

Now ssh into the machine, and they should be present:

which bat
which btop
which tldr

Each will show a path to the binary file:

/run/current-system/sw/bin/bat
/run/current-system/sw/bin/btop
/run/current-system/sw/bin/tldr

Next, let's remove one of the three packages. The packages portion of clan.nix declares what additional packages should exist; by removing one, Nix will remove that package. Remove the "tldr" from the list:

        packages = [ "bat" "btop" ];

and run the update again:

clan machines update test-machine

Now when you check which tldr, it should show that it's not in the path:

which tldr
which: no tldr in (/run/wrappers/bin:/root/.nix-profile/bin:/nix/profile/bin:/root/.local/state/nix/profile/bin:/etc/profiles/per-user/root/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin)

Practice: Add a User

When you need to add a new user, you can do so right from within the clan.nix file, and then update the system.

Add a New User (no sudo access)

Let's add a user called Alice. Open clan.nix, and under inventory.instances, add the following:

  inventory.instances = { # Add the following under this line
    user-alice = {
      module.name = "users";
      roles.default.machines."test-machine" = {};
      roles.default.tags.all = {};
      roles.default.settings = {
        user = "alice";
      };
    };

Save the file. Now type the following to add a password for alice (include the no-sandbox if you needed no sandbox earlier):

clan vars generate test-machine --no-sandbox

You will be prompted for a password. Or you can press Enter to automatically generate one.

If you automatically generated one, to retrieve it type:

clan vars get test-machine user-password-alice/user-password
Note

On cloud machines, this password will be used for sudo access if you grant it. Typically password login is disabled on a cloud machine.

Next, let's add a key file so Alice can log in remotely. For this we'll use your own key file as before. Type:

cat ~/.ssh/id_ed25519.pub

Then open machines/test-machine/configuration.nix. Add the following, before the closing brace:

{
  imports = [

  ];

  # New machine!

  users.users.alice.openssh.authorizedKeys.keys = [
    "PASTE_YOUR_KEY_HERE"
  ];
}

and replace PASTE_YOUR_KEY_HERE with the contents of the file.

Now update the machine by typing:

clan machines update test-machine

Once complete, you can log in as alice:

ssh alice@<IP-ADDRESS>

replacing <IP-ADDRESS> with the Hetzner server's IP address.

Give that user sudo access

After you trust Alice, you can grant her sudo access. To do so, update the clan.nix file by adding her to the wheel group:

    user-alice = {
      module.name = "users";
      roles.default.machines."test-machine" = {};
      roles.default.tags.all = {};
      roles.default.settings = {
        user = "alice";
        groups = [ "wheel" ];  # Add this to allow sudo
      };
    };

Again type:

clan machines update test-machine

If you were already logged in as alice before running the update, you will need to log out and back in for the change to take.

Then after logged in as alice, try using sudo:

sudo echo "hello"

You will be prompted for the password and should see "hello" printed.

Revoke the sudo access

To revoke alice's sudo access, simply remove the line you added:

        groups = [ "wheel" ];

And once again run:

clan machines update test-machine

Log out, and log alice back in. Now try the same sudo command; you'll be prompted for password, but then shown:

alice is not in the sudoers file.