[rulkc] [PATCH v3] nix: introduce initial generic configuration

Maxim Moskalets maxmoskm at yandex.ru
Mon Jun 29 00:00:10 MSK 2026


From: Maxim Moskalets <Maxim.Moskalets at kaspersky.com>

Add a NixOS configuration for cgit server as initial.
Services added:
- cgit (over HTTP)
- sshd
- fail2ban
- firewall (iptables as default backend)

Nix and NixOS used for versionability and reproducibility of the
system. As bonus, it also provides a way to easily deploy the system
on different machines.

Signed-off-by: Maxim Moskalets <Maxim.Moskalets at kaspersky.com>
---
v2:
 - Add fail2ban service
 - Add beget hardware-configuration
 - Add build and deploy guide to README.md
 - Switch to nixos-unstable branch
v3:
 - Use SrvOS flake with common server config parts
 - Add ports forwarding in QEMU for local debug
 - Switch nixpkgs to latest release
---
 .gitignore                              |  3 ++
 README.md                               | 30 +++++++++++
 config/default.nix                      |  9 ++++
 config/disko.nix                        | 33 ++++++++++++
 config/nix.nix                          |  3 ++
 config/programs/default.nix             |  5 ++
 config/programs/neovim.nix              |  8 +++
 config/services/default.nix             |  6 +++
 config/services/fail2ban.nix            | 15 ++++++
 config/services/ssh.nix                 |  9 ++++
 config/virtualisation.nix               | 18 +++++++
 flake.lock                              | 69 +++++++++++++++++++++++++
 flake.nix                               | 45 ++++++++++++++++
 modules/admins.nix                      | 35 +++++++++++++
 modules/default.nix                     |  7 +++
 modules/hostings/beget.nix              | 34 ++++++++++++
 modules/hostings/default.nix            |  6 +++
 modules/hostings/selectel.nix           | 29 +++++++++++
 modules/services/default.nix            |  3 ++
 modules/services/landau-cgit.nix        | 44 ++++++++++++++++
 modules/services/landau-gitolite.nix    |  0
 servers/cgit-hardware-configuration.nix | 36 +++++++++++++
 servers/cgit.nix                        | 21 ++++++++
 23 files changed, 468 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 README.md
 create mode 100644 config/default.nix
 create mode 100644 config/disko.nix
 create mode 100644 config/nix.nix
 create mode 100644 config/programs/default.nix
 create mode 100644 config/programs/neovim.nix
 create mode 100644 config/services/default.nix
 create mode 100644 config/services/fail2ban.nix
 create mode 100644 config/services/ssh.nix
 create mode 100644 config/virtualisation.nix
 create mode 100644 flake.lock
 create mode 100644 flake.nix
 create mode 100644 modules/admins.nix
 create mode 100644 modules/default.nix
 create mode 100644 modules/hostings/beget.nix
 create mode 100644 modules/hostings/default.nix
 create mode 100644 modules/hostings/selectel.nix
 create mode 100644 modules/services/default.nix
 create mode 100644 modules/services/landau-cgit.nix
 create mode 100644 modules/services/landau-gitolite.nix
 create mode 100644 servers/cgit-hardware-configuration.nix
 create mode 100644 servers/cgit.nix

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c27297c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.patch
+*.qcow2
+/result
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1b71883
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+# LANDAU servers configurations
+
+## Installation
+
+Run the following command to install NixOS to remote host:
+
+```bash
+nixos-anywhere --flake .#cgit root@<host ip>
+```
+
+After installation, run `nixos-rebuild switch` to apply changes. You can also use `--build-host` and `--remote-host` options to build on a different machine.
+
+For first-time setup on new hosting, hardware configuration is required. Use `--generate-hardware-config nixos-generate-config ./servers/cgit-hardware-configuration.nix` to generate it.
+
+## Run locally
+
+You can also run this configuration locally in a VM:
+
+```bash
+nixos-rebuild build-vm --flake .#cgit
+./result/bin/run-cgit-vm
+```
+
+Now you can access the [server](http://localhost:8080/) for debug purposes.
+
+## Nix-related checklist
+
+- [ ] Format all files with `nix run nixpkgs#nixfmt-tree`
+- [ ] Check for any warnings with `nix flake check`
+- [ ] Update lock file (if needed) with `nix flake update`
diff --git a/config/default.nix b/config/default.nix
new file mode 100644
index 0000000..2aeb2dc
--- /dev/null
+++ b/config/default.nix
@@ -0,0 +1,9 @@
+{
+  imports = [
+    ./disko.nix
+    ./nix.nix
+    ./programs
+    ./services
+    ./virtualisation.nix
+  ];
+}
diff --git a/config/disko.nix b/config/disko.nix
new file mode 100644
index 0000000..7366aee
--- /dev/null
+++ b/config/disko.nix
@@ -0,0 +1,33 @@
+{
+  disko.devices.disk.main = {
+    type = "disk";
+    content = {
+      type = "gpt";
+      partitions = {
+        boot = {
+          name = "boot";
+          size = "1M";
+          type = "EF02";
+        };
+        esp = {
+          size = "256M";
+          type = "EF00";
+          content = {
+            type = "filesystem";
+            format = "vfat";
+            mountpoint = "/boot";
+          };
+        };
+        root = {
+          name = "root";
+          size = "100%";
+          content = {
+            type = "filesystem";
+            format = "ext4";
+            mountpoint = "/";
+          };
+        };
+      };
+    };
+  };
+}
diff --git a/config/nix.nix b/config/nix.nix
new file mode 100644
index 0000000..1e0ea0d
--- /dev/null
+++ b/config/nix.nix
@@ -0,0 +1,3 @@
+{
+  system.stateVersion = "26.05";
+}
diff --git a/config/programs/default.nix b/config/programs/default.nix
new file mode 100644
index 0000000..73b5f39
--- /dev/null
+++ b/config/programs/default.nix
@@ -0,0 +1,5 @@
+{
+  imports = [
+    ./neovim.nix
+  ];
+}
diff --git a/config/programs/neovim.nix b/config/programs/neovim.nix
new file mode 100644
index 0000000..b7360ff
--- /dev/null
+++ b/config/programs/neovim.nix
@@ -0,0 +1,8 @@
+{ lib, ... }:
+{
+  programs.neovim = {
+    enable = true;
+    viAlias = true;
+    vimAlias = true;
+  };
+}
diff --git a/config/services/default.nix b/config/services/default.nix
new file mode 100644
index 0000000..366b226
--- /dev/null
+++ b/config/services/default.nix
@@ -0,0 +1,6 @@
+{
+  imports = [
+    ./fail2ban.nix
+    ./ssh.nix
+  ];
+}
diff --git a/config/services/fail2ban.nix b/config/services/fail2ban.nix
new file mode 100644
index 0000000..050fb93
--- /dev/null
+++ b/config/services/fail2ban.nix
@@ -0,0 +1,15 @@
+{
+  services.fail2ban = {
+    enable = true;
+
+    bantime = "30m";
+    maxretry = 5;
+
+    bantime-increment = {
+      enable = true;
+      maxtime = "3d";
+      factor = "4";
+      rndtime = "10m";
+    };
+  };
+}
diff --git a/config/services/ssh.nix b/config/services/ssh.nix
new file mode 100644
index 0000000..2099f7c
--- /dev/null
+++ b/config/services/ssh.nix
@@ -0,0 +1,9 @@
+{
+  services.openssh = {
+    allowSFTP = false;
+    settings = {
+      PermitRootLogin = "no";
+      AllowGroups = [ "wheel" ];
+    };
+  };
+}
diff --git a/config/virtualisation.nix b/config/virtualisation.nix
new file mode 100644
index 0000000..fda58fc
--- /dev/null
+++ b/config/virtualisation.nix
@@ -0,0 +1,18 @@
+{
+  virtualisation.vmVariant.virtualisation = {
+    memorySize = 4 * 1024;
+    cores = 4;
+    forwardPorts =
+      map
+        (port: {
+          from = "host";
+          host.port = port + 8000;
+          guest.port = port;
+        })
+        [
+          22
+          80
+          443
+        ];
+  };
+}
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..c5ec686
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,69 @@
+{
+  "nodes": {
+    "disko": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1781152676,
+        "narHash": "sha256-RxWs5ND31KzTG7wvMM+PMfUjyNpmIEr999lqNARaM5o=",
+        "owner": "nix-community",
+        "repo": "disko",
+        "rev": "ff8702b4de27f72b4c78573dfb89ec74e36abdf1",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "disko",
+        "type": "github"
+      }
+    },
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1782535326,
+        "narHash": "sha256-ZeRxu4yn6shd3SNF5ZUQb4r7BaVo1zBKMjRhfoNSBmw=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "714a5f8c4ead6b31148d829288440ed033ccc041",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-26.05",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "disko": "disko",
+        "nixpkgs": "nixpkgs",
+        "srvos": "srvos"
+      }
+    },
+    "srvos": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1782526166,
+        "narHash": "sha256-t4OVI0LJQZCtYV03nKQeEvWcIxiUN1NInmqMmJ/fI48=",
+        "owner": "nix-community",
+        "repo": "srvos",
+        "rev": "9f3040c7e16880d80c1dffcfd6eb86346f3af467",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "srvos",
+        "type": "github"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..02147fe
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,45 @@
+{
+  description = "LANDAU infrastructure";
+
+  inputs = {
+    nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
+    disko = {
+      url = "github:nix-community/disko";
+      inputs.nixpkgs.follows = "nixpkgs";
+    };
+    srvos = {
+      url = "github:nix-community/srvos";
+      inputs.nixpkgs.follows = "nixpkgs";
+    };
+  };
+
+  outputs =
+    {
+      nixpkgs,
+      disko,
+      srvos,
+      ...
+    }:
+    let
+      makeServerSystem =
+        modules: extraConfig:
+        nixpkgs.lib.nixosSystem {
+          system = "x86_64-linux";
+          modules = [
+            disko.nixosModules.disko
+            srvos.nixosModules.server
+            ./config
+            ./modules
+          ]
+          ++ modules;
+        }
+        // extraConfig;
+    in
+    {
+      nixosConfigurations = {
+        cgit = makeServerSystem [ ./servers/cgit.nix ] { };
+      };
+
+      inherit (nixpkgs) formatter;
+    };
+}
diff --git a/modules/admins.nix b/modules/admins.nix
new file mode 100644
index 0000000..6c000c5
--- /dev/null
+++ b/modules/admins.nix
@@ -0,0 +1,35 @@
+{
+  config,
+  lib,
+  ...
+}:
+
+{
+  options.admins = {
+    all = lib.mkEnableOption "All availiable admins";
+    moskalets = lib.mkEnableOption "Maxim Moskalets admin";
+  };
+
+  config.users.users =
+    let
+      makeAdmin =
+        user: description: extraAttrs:
+        lib.mkIf (config.admins.${user} || config.admins.all) {
+          isNormalUser = true;
+          inherit description;
+          extraGroups = [
+            "wheel"
+          ];
+        }
+        // extraAttrs;
+    in
+    {
+      moskalets = makeAdmin "moskalets" "Maxim Moskalets" {
+        # YubiKey
+        openssh.authorizedKeys.keys = [
+          "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDH+C8vzOOqDx7un96FhGewfE6UufLHys3Y3ke6WxoV05XPWc+d/1T9wCU7escUgdOUI90+Ps/0Os4PzfP0znOE08Xj+6nZsRSkhu+WEFyRu8e86NRoCEIk2u8WNxMhR112taT6bLf/TRWzDyai159sKz7PhuIW/uP/SwsIzpr+AWhBVzzT0Ytz3QVX4JCrRYXyuFwTLNIFRzziKBP69nkl/KKwRdULGIzlGXqHTOzLLL26sSWuGTaZg3ao+DfLV5gmL3VkU9jEyF2OVodsxmQ3qeoRRsHlSy7FmQeCg4I3uhbi/v8bR1xyhfn7YLaKfFkuTnK0EfFfbRTPLyWglwb3yeulkUg3oDc4AKSoks3Dzi53LBSEI//5Yw3nfFu3Hu85UgZQ6A9lRolrkibjKil1s8yodU5vSGKtGkh98U//KzXDEHOLqZ7mfY+hvvY11oQ0KOLYzgYX9hwvMgYTa3dmzADRfs/PMfOqja1TDsVvnHNnIfmjNe8WojbBPzB8ytmTDpMERIAONwyR2p0Bf6fon04hQu/yyc/iE+zbn/JDf9LYbj4+yr6RpRJXbbh5KsfXAJ6vf0XBEkdV5KymD1N6Ni44lGFwg5clDs3rj5K/liSZK4joyqUaUtzGi0DxwT1lypl87iJpw0cThCOr80fVl4FiyEkTjZjMc0UP/cA6BQ== cardno:29_610_165
+"
+        ];
+      };
+    };
+}
diff --git a/modules/default.nix b/modules/default.nix
new file mode 100644
index 0000000..a1f9a42
--- /dev/null
+++ b/modules/default.nix
@@ -0,0 +1,7 @@
+{
+  imports = [
+    ./admins.nix
+    ./hostings
+    ./services
+  ];
+}
diff --git a/modules/hostings/beget.nix b/modules/hostings/beget.nix
new file mode 100644
index 0000000..4ee53ce
--- /dev/null
+++ b/modules/hostings/beget.nix
@@ -0,0 +1,34 @@
+{
+  config,
+  lib,
+  ...
+}:
+
+{
+  options.hostings.beget.enable = lib.mkEnableOption "Server on Beget platform";
+
+  # See https://beget.com/ru/kb/faq/cloud/sozdanie-servera-iz-svoego-obraza
+  config = lib.mkIf config.hostings.beget.enable {
+    disko.devices.disk.main.device = "/dev/vda";
+
+    boot.loader.grub.efiSupport = false;
+
+    services.qemuGuest.enable = true;
+    services.cloud-init = {
+      enable = true;
+      network.enable = true;
+      settings = {
+        datasource_list = [
+          "NoCloud"
+          "ConfigDrive"
+        ];
+      };
+    };
+
+    networking = {
+      useDHCP = false;
+      useNetworkd = true;
+      networkmanager.enable = false;
+    };
+  };
+}
diff --git a/modules/hostings/default.nix b/modules/hostings/default.nix
new file mode 100644
index 0000000..cab83b2
--- /dev/null
+++ b/modules/hostings/default.nix
@@ -0,0 +1,6 @@
+{
+  imports = [
+    ./beget.nix
+    ./selectel.nix
+  ];
+}
diff --git a/modules/hostings/selectel.nix b/modules/hostings/selectel.nix
new file mode 100644
index 0000000..0880dbe
--- /dev/null
+++ b/modules/hostings/selectel.nix
@@ -0,0 +1,29 @@
+{
+  config,
+  lib,
+  ...
+}:
+
+{
+  options.hostings.selectel.enable = lib.mkEnableOption "Server on Selectel platform";
+
+  # See https://docs.selectel.ru/en/cloud-servers/images/create-custom-image/
+  config = lib.mkIf config.hostings.selectel.enable {
+    disko.devices.disk.main.device = "/dev/sda";
+
+    boot.loader.grub.efiSupport = false;
+
+    services.qemuGuest.enable = true;
+    services.cloud-init = {
+      enable = true;
+      network.enable = true;
+      settings = {
+        datasource_list = [
+          "ConfigDrive"
+          "Ec2"
+          "None"
+        ];
+      };
+    };
+  };
+}
diff --git a/modules/services/default.nix b/modules/services/default.nix
new file mode 100644
index 0000000..83797f7
--- /dev/null
+++ b/modules/services/default.nix
@@ -0,0 +1,3 @@
+{
+  imports = [ ./landau-cgit.nix ];
+}
diff --git a/modules/services/landau-cgit.nix b/modules/services/landau-cgit.nix
new file mode 100644
index 0000000..c959ea0
--- /dev/null
+++ b/modules/services/landau-cgit.nix
@@ -0,0 +1,44 @@
+{
+  config,
+  lib,
+  ...
+}:
+let
+  host = "git.rulkc.org";
+  mkAssetPath = file: toString (./. + "/../../git.rulkc.org/cgit/${file}");
+in
+{
+  options.services.landau-cgit.enable = lib.mkEnableOption "cgit configured for LANDAU";
+
+  config = lib.mkIf config.services.landau-cgit.enable {
+    services.nginx.virtualHosts.${host}.locations = {
+      "= /cgit.png".alias = mkAssetPath "cgit.png";
+      "= /cgit.css".alias = mkAssetPath "cgit.css";
+      "= /favicon.ico".alias = mkAssetPath "favicon.ico";
+    };
+
+    services.cgit.${host} = {
+      enable = true;
+      scanPath = "/var/lib/git";
+      gitHttpBackend.checkExportOkFiles = false;
+      settings = {
+        # Features
+        enable-git-config = true;
+        enable-http-clone = true;
+        enable-index-owner = true;
+        snapshots = "tar.gz zip";
+
+        # Appearance
+        root-title = "LANDAU git repositories";
+        root-desc = "Git repositories for Linux kernel Advanced for Next-gen Devices & Architectures";
+
+        clone-url = "https://${host}/$CGIT_REPO_URL git://git.rulkc.org/$CGIT_REPO_URL ssh://git@${host}/$CGIT_REPO_URL";
+        section-from-path = 3;
+        max-stats = "quarter";
+        cache-root = "/var/cache/cgit";
+        cache-size = 1000;
+      };
+    };
+    networking.firewall.allowedTCPPorts = [ 80 ];
+  };
+}
diff --git a/modules/services/landau-gitolite.nix b/modules/services/landau-gitolite.nix
new file mode 100644
index 0000000..e69de29
diff --git a/servers/cgit-hardware-configuration.nix b/servers/cgit-hardware-configuration.nix
new file mode 100644
index 0000000..f5108e4
--- /dev/null
+++ b/servers/cgit-hardware-configuration.nix
@@ -0,0 +1,36 @@
+# Do not modify this file!  It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations.  Please make changes
+# to /etc/nixos/configuration.nix instead.
+{
+  config,
+  lib,
+  pkgs,
+  modulesPath,
+  ...
+}:
+
+{
+  imports = [
+    (modulesPath + "/profiles/qemu-guest.nix")
+  ];
+
+  boot.initrd.availableKernelModules = [
+    "ata_piix"
+    "uhci_hcd"
+    "virtio_pci"
+    "sr_mod"
+    "virtio_blk"
+  ];
+  boot.initrd.kernelModules = [ ];
+  boot.kernelModules = [ ];
+  boot.extraModulePackages = [ ];
+
+  # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
+  # (the default) this is the recommended approach. When using systemd-networkd it's
+  # still possible to use this option, but it's recommended to use it in conjunction
+  # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
+  networking.useDHCP = lib.mkDefault true;
+  # networking.interfaces.ens3.useDHCP = lib.mkDefault true;
+
+  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+}
diff --git a/servers/cgit.nix b/servers/cgit.nix
new file mode 100644
index 0000000..54cf2d0
--- /dev/null
+++ b/servers/cgit.nix
@@ -0,0 +1,21 @@
+{
+  config,
+  pkgs,
+  lib,
+  modulesPath,
+  ...
+}:
+{
+  imports = [
+    (modulesPath + "/installer/scan/not-detected.nix")
+    (modulesPath + "/profiles/qemu-guest.nix")
+    ./cgit-hardware-configuration.nix
+  ];
+
+  networking.hostName = "cgit";
+
+  services.landau-cgit.enable = true;
+  hostings.beget.enable = true;
+
+  admins.moskalets = true;
+}
-- 
2.54.0




More information about the rulkc mailing list