---
title: Simple nixos config for vps static site
date: 2023-01-29 
tags:
  - nixos
draft: false
---

Setting up a little static site is something I've done a few different times on a few different operating systems. It's a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let's encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.

I'm going to go through a bit of the nixos config I've got for my vps.

### SSH

Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.

```nix
services.openssh = {
  enable = true;
  ports = [ 69 ];
  settings = {
    passwordAuthentication = false;
    permitRootLogin = "no";
  };
};
```

### ADDING A USER

Generally, it's nice to have a user so you're not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.

```nix
users.users = {
  ronald = {
    isNormalUser = true;
    shell = pkgs.fish;
    extraGroups = [ "wheel" "nginx" ];
	openssh.authorizedKeys.keyFiles = [ "/path/to/public/key/file" ]
  };
};
```

### NGINX

I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of `/var/www/example-site` at `example-site.here`. It also opens the ports for http and https in the firewall. 

```nix
services.nginx = {
 enable = true;
 virtualHosts."example-site.here" = {
   enableACME = true;
   forceSSL = true;
   root = "/var/www/example-site/";
 };
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
```

### HTTPS

You can also make nix deal with all the let's encrypt certbot stuff. It looks like this:

```nix
security.acme = {
  acceptTerms = true;
  defaults.email = "ronald@email.yes";
};
```

This will set up certificates for any sites you set the `enableAMCE` to true option for.

### CRON

This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn't want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour. 

```nix
services.cron = {
  enable = true;
  systemCronJobs = [
    "@hourly      root    cp -r /home/ronald/example-site /var/www/"
  ];
};
```

This means I can just rsync the updated site from my laptop to the server and it'll be updated within the hour. Good enough for me.
