From ba1be9573ef20d6424ae987257a1c727c47d4b53 Mon Sep 17 00:00:00 2001 From: Kyren223 Date: Tue, 6 Oct 2026 20:46:31 +0300 Subject: Initial setup for website rewrite --- ...-the-perfect-distro-for-a-production-server.mdx | 284 --------------------- 1 file changed, 284 deletions(-) delete mode 100644 src/content/blogs/nixos-the-perfect-distro-for-a-production-server.mdx (limited to 'src/content/blogs/nixos-the-perfect-distro-for-a-production-server.mdx') diff --git a/src/content/blogs/nixos-the-perfect-distro-for-a-production-server.mdx b/src/content/blogs/nixos-the-perfect-distro-for-a-production-server.mdx deleted file mode 100644 index 7b8c235..0000000 --- a/src/content/blogs/nixos-the-perfect-distro-for-a-production-server.mdx +++ /dev/null @@ -1,284 +0,0 @@ ---- -title: "NixOS: The perfect distro for a production server" -description: My experience using NixOS to manage my production VPS -date: 2025-01-01 ---- - -NixOS is a linux distribution praised for it's functional-style declarative -configuration that allows you to manage the entire system through the Nix -programming language, making your sytem reproducible and more reliable. - -This is in contrast to other linux distros that use a more imperative approach -of managing the system by running commands to install packages, create -users, etc. - -## NixOS as a daily-driver operating system - -About half a year ago I started using Windows subsystem for linux which enabled -me to run a linux distro in the terminal, 6 weeks ago I finally decided to make -the jump and switch from windows to a full linux desktop experience. - -I wanted a linux distro with a large set of latest-version packages but still -stable without risk of getting my system broken (sorry Arch). - -I was considering going with Tumbleweed, a rolling release distro -by openSUSE which I was already familiar with because I was using it in WSL. - -But then I remembered Nix, this weird thing that is an operating system, -programming language, and a package manager. - -Nixpkgs is the the package repository with the most fresh packages (even more than AUR), -and it has a really cool benefit of being able to install all my packages -through a config file, similar to NVIM with lazy.nvim or rust with cargo. - -Initially I was considering using something like Debian with nixpkgs as I heard -that was possible, but some people warned me that it's a bad idea to not use -the native package manager, so I ended up **going with NixOS as my first linux -distro on desktop**. - -I followed a [great video about installing NixOS](https://www.youtube.com/watch?v=a67Sv4Mbxmc) by Vimjoyer -and was able to get it up and running. -Although I experienced some issues in the first few days, that was expected -and I was able to solve all of them. - -One trap to be aware of is the nix community is sometimes too enthusiastic and -will try to convince you to do things "the nix way" like rewriting your -perfectly fine existing configs in nix or moving from stow to home manager. - -In my opinion, I don't want to waste so much time configuring everything, -I am OK with only configuring system settings and packages while having things -like other dotfiles or scripts be handled the "normal linux way". - -## NixOS as a production server distro - -A few days ago I got my first VPS, a RS 1000 from netcup (use code -`36nc17355743780` for a $5 discount), -my goal with it was to host my website along with some other self-hosted apps -including my own server for a terminal-based social media I am working on -(which I will make a blog post about in the future). - -Infrastructure as code (IaC) is the practice of managing servers through -configuration files rather than manual instructions (such as running commands), -this has several benefits such as being able to use version control and ensuring -a more reproducible server that can be easily deployed and updated using these -files. - -This is where NixOS comes in and really shines, all these "nix ways" of -configuring stuff as a desktop OS seems overkill and time consuming but for a -server that's exactly the point, to be able to reproduce the entire system -from only a bunch of nix files. - -## Configuring a server with NixOS - -After struggling to install NixOS, I discovered [NixOS Anywhere](https://github.com/nix-community/nixos-anywhere) -which made it very easy to install remotely through SSH. - -First thing was setting up proper SSH authentication and security. - -Nix makes it really simple to do, just add these 2 lines to enable ssh -but disable the insecure password authentication - -```nix -services.openssh.enable = true; -services.openssh.settings.PasswordAuthentication = false; -``` - -And to add a public key to connect with to the root user - -```nix -users.users.root.openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO7P9K9D5RkBk+JCRRS6AtHuTAc6cRpXfRfRMg/Kyren" -]; -``` - -If you would like to know how I generated a key that ends with `/Kyren` read -my first blog post - [The search for the perfect ssh key](http://localhost:4321/blogs/the-search-for-the-perfect-ssh-key) - -### Managing secrets with sops-nix - -Next, before we can get into configuring a webserver, we need a good way -to store secrets for things like SSL certifications, [sops-nix](https://github.com/Mic92/sops-nix) is a nix module -that integrates the [sops CLI tool](https://github.com/getsops/sops) into nix. - -Rather than having to set up 20 different secrets for each thing, it allows -us only setup 1 secret that is stored on the server and on the admin's -system, then, any additional secret can be defined in a file that gets -encrypted automatically by sops which can safely be committed into version control. - -At runtime sops will write all these files to a directory which can then be -accessed by anything that needs access to that secret, sops also makes it easy -to let specific users or groups access to a specific secret. - -### Setting up automatic updates - -We have added sops-nix, but how can we get it into the server? - -The simple approach would be to ssh as root into the server, git clone the -repository with the config and then run - -```sh -nixos-rebuild switch --flake .#default -``` - -_assuming you are inside the git directory where your `flake.nix` is and your -`nixosConfigurations` is called `default`_ - -While that certainly works, a better approach would be to listen for changes -to the git repository and automatically pull and rebuild the system. - -```nix -system.autoUpgrade = { - enable = true; - flake = "github:kyren223/server#default"; - dates = "minutely"; # Poll interval - flags = [ - "--no-write-lock-file" # Prevent flake.lock from upgrading - "--option" "tarball-ttl" "0" # Required for polling below 1h - ]; -}; -``` - -This will automatically run every minute to fetch the github repository -and rebuild the system. - -But wait, what if the repository is private? that's where sops-nix comes in! - -```nix -sops.secrets.github-access-token = { }; -nix.extraOptions = "!include /run/secrets/github-access-token"; -``` - -The first line defines a new `github-access-token` secret, and the second line -makes sure nix is aware of it so it can use it when trying to fetch the repo. - -Of course, make sure to define the secret in your `secrets.yml` file, -The key would be `gituhb-access-token` and the value would be a github PAT -token. -It's recommended to only give the token read-only access to the repo's contents. - -## Serving a static website - -Now that we have a way to manage our secrets, and continious deployment of our -nix configuration, we can finally start working on a website. - -The plan is to host multiple websites in the future so I'll be using [Nginx](https://nginx.org/en/) -as a reverse proxy. - -```nix -services.nginx.enable = true; -services.nginx.virtualHosts."kyren.codes" = { - useACMEHost = "kyren.codes"; - forceSSL = true; - locations."/" = { - index = "index.html"; - root = "/srv/website"; - }; -}; -``` - -This enables nginx, which installs it on our system then defines a new virtual -host with the domain `kyren.codes`, later if we were to host other sites, the -virtualHost can be something like `git.kyren.codes`. - -The `locations."/"` sets the base url of our website to `/srv/website` which is -where I have my website's static files, and nginx will serve `index.html` as -the default page when you go to that domain, later I will explain how to setup -continious deployment to automatically update this directory on push to master. - -The `useACMEHost` and `forceSSL` makes sure the server uses https, you'd need -to get a SSL certificate from [Let's Encrypt](https://letsencrypt.org/), once -again, Nix makes it really simple to do - -```nix -# Define the token using nix, make sure the "acme" user can access it -sops.secrets.cloudflare-dns-api-token = { mode = "0440"; owner = "acme"; }; - -security.acme.acceptTerms = true; -security.acme.defaults.email = "acme@kyren.codes"; # Your email - -security.acme.certs."kyren.codes" = { - domain = "kyren.codes"; - extraDomainNames = [ "*.kyren.codes" ]; - dnsProvider = "cloudflare"; - environmentFile = "${pkgs.writeText "cf-creds" '' - CF_DNS_API_TOKEN_FILE=${config.sops.secrets.cloudflare-dns-api-token.path} - ''}"; - webroot = null; -}; - -# Allow nginx to access acme certs -users.users.nginx.extraGroups = [ "acme" ]; -``` - -This defines a `kyren.codes` entry (which is what `useACMEHost` references) -I am using cloudflare as my DNS provider, but you can get a full list of -supported DNS providers at [this link](https://go-acme.github.io/lego/dns/), and -of course make sure to change the environment variables to match your provider. - -Now if we commit and push these changes and wait about a minute for the server -to pull the changes, we should have a working static site at `kyren.codes`. - -### Setting up continious deployment for the website - -The way we are going to do this on the server is create a new linux user and -add to it a public ssh key that will be used for deployments. - -It's recommended that the user is restricted as much as possible so in the case -of a hacker getting access to the key, they won't be able to get into other -services that are running on the server. - -We can create a user declaratively like this - -```nix -users.users.website = { - isNormalUser = true; - group = "users"; - openssh.authorizedKeys.keys = [ - # Allow an admin to manually SSH - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO7P9K9D5RkBk+JCRRS6AtHuTAc6cRpXfRfRMg/Kyren" - - # The deployment public key - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ1B/i/AQLYt6mrz0P/oUJItpvWXp7z0xHNzmcPdtwWd" - ]; -}; - -# Make sure the /srv/website always exists -# Give read and write permissions to the website user -# Give read permissions to the nginx group (so nginx can serve it) -systemd.tmpfiles.rules = [ - "d /srv/website 0750 website nginx" -]; -``` - -Now all you need to do is have a github action (or similar) that builds your -website then copies the build output into the server by SSH-ing into it. -You can take a look at [my github action](https://github.com/Kyren223/website/blob/master/.github/workflows/deploy.yml) -for my website to see an example of how you can do it. - -## Conclusions - -NixOS helps system admins and developers achieve infrastructure as code by -allowing them to declare the entire machine's configuration using the powerful -Nix programming language. - -This makes the state of production machines more consistent and reliable while -making it easy to reproduce across hundreds of machines. - -Compared with the traditional approach of a debian or ubuntu server, where -system admins would have to painfully manage the state of all machines ensuring -all the dependencies, firewalls, OS settings, etc are configured properly. - -Because of the difficulty, OCI containers such as docker became popular, but -they come with a cost, mainly performane due to virtualization. NixOS makes it -easy to configure programs to run on bare-metal making it a better, more -performant alternative to docker. - -**Thanks for reading! wishing you a year full of code, growth and new oppurtunities!** - -If you'd like to learn more about NixOS, here are some resources I found useful: - -- [NixOS in production](https://github.com/Gabriella439/nixos-in-production) -- [Vimjoyer's Youtube Channel](https://www.youtube.com/@vimjoyer/videos) - -Have questions or just want to chat? feel free to contact me on discord at -Kyren223 or email me at `contact at kyren.codes`. -- cgit v1.3.1