simple nixos config for vps static site
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.
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.
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.
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:
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.
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.