From moskalets at landau.one Fri Oct 9 22:25:50 2026 From: moskalets at landau.one (Maxim Moskalets) Date: Fri, 9 Oct 2026 22:25:50 +0300 Subject: [rulkc] [PATCH v6] nix: introduce initial generic configuration Message-ID: <20261009192556.17826-1-moskalets@landau.one> From: Maxim Moskalets Add a NixOS configuration for cgit server as initial. Services added: - cgit (over HTTP) - gitolite - git-daemon - 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 --- .gitignore | 3 + README.md | 30 +++ config/admins.nix | 16 ++ config/default.nix | 10 + 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 | 10 + config/virtualisation.nix | 15 ++ flake.lock | 69 +++++++ flake.nix | 47 +++++ modules/default.nix | 6 + modules/hostings/beget.nix | 34 ++++ modules/hostings/default.nix | 6 + modules/hostings/selectel.nix | 29 +++ modules/services/cgit.nix | 85 +++++++++ modules/services/default.nix | 7 + modules/services/gitolite.nix | 237 ++++++++++++++++++++++++ modules/services/grokmirror.nix | 19 ++ pkgs/by-name/gr/grokmirror/package.nix | 33 ++++ pkgs/default.nix | 7 + servers/cgit-hardware-configuration.nix | 36 ++++ servers/cgit.nix | 23 +++ 26 files changed, 792 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 config/admins.nix 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/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/cgit.nix create mode 100644 modules/services/default.nix create mode 100644 modules/services/gitolite.nix create mode 100644 modules/services/grokmirror.nix create mode 100644 pkgs/by-name/gr/grokmirror/package.nix create mode 100644 pkgs/default.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..e881a75 --- /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@ +``` + +After installation, run `nixos-rebuild switch` to apply changes. You can also use `--build-host` and `--target-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/admins.nix b/config/admins.nix new file mode 100644 index 0000000..625186f --- /dev/null +++ b/config/admins.nix @@ -0,0 +1,16 @@ +{ + users.users = { + moskalets = { + isNormalUser = true; + description = "Maxim Moskalets"; + extraGroups = [ + "wheel" + ]; + openssh.authorizedKeys.keys = [ + # YubiKey + "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" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDorHQviBgliQSwdk0b/vLbGdRADutxkz58hexR8MfNv RULKC gitolite" + ]; + }; + }; +} diff --git a/config/default.nix b/config/default.nix new file mode 100644 index 0000000..7a7be0f --- /dev/null +++ b/config/default.nix @@ -0,0 +1,10 @@ +{ + imports = [ + ./admins.nix + ./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..46164ef --- /dev/null +++ b/config/services/ssh.nix @@ -0,0 +1,10 @@ +{ lib, ... }: +{ + services.openssh = { + allowSFTP = false; + settings = { + PermitRootLogin = "no"; + AllowGroups = lib.mkDefault [ "wheel" ]; + }; + }; +} diff --git a/config/virtualisation.nix b/config/virtualisation.nix new file mode 100644 index 0000000..498aa43 --- /dev/null +++ b/config/virtualisation.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: +{ + virtualisation.vmVariant = { + services.getty.autologinUser = "root"; + virtualisation = { + memorySize = 4 * 1024; + cores = 4; + forwardPorts = map (port: { + from = "host"; + host.port = port + 8000; + guest.port = port; + }) config.networking.firewall.allowedTCPPorts; + }; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..bc12d19 --- /dev/null +++ b/flake.lock @@ -0,0 +1,69 @@ +{ + "nodes": { + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1789770686, + "narHash": "sha256-uZkBR7yHdIKUFB5SZdfgh1qkGfI3XmYmI/lTiquxbck=", + "owner": "nix-community", + "repo": "disko", + "rev": "725ea35e410ad83be4931d1bff7e090eacaf3563", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1791353474, + "narHash": "sha256-v72qr4LsSz61tQki/41nHKZKPY6NSeZavtGlAInOCng=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2efa67fd26b6df417c33e4603185c701f260dd83", + "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": 1791167327, + "narHash": "sha256-R2FYN0UwfpmJBN8pew/7GxZUohmlvnZrHgj4+afSETo=", + "owner": "nix-community", + "repo": "srvos", + "rev": "6c23e3049d72339dbca8325afbb2a383fd9016c8", + "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..4c6b9da --- /dev/null +++ b/flake.nix @@ -0,0 +1,47 @@ +{ + 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, + ... + }@attrs: + let + makeServerSystem = + modules: extraConfig: + nixpkgs.lib.nixosSystem { + specialArgs = attrs; + system = "x86_64-linux"; + modules = [ + disko.nixosModules.disko + srvos.nixosModules.server + ./config + ./modules + ./pkgs + ] + ++ modules; + } + // extraConfig; + in + { + nixosConfigurations = { + cgit = makeServerSystem [ ./servers/cgit.nix ] { }; + }; + + inherit (nixpkgs) formatter; + }; +} diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..59a8985 --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./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/cgit.nix b/modules/services/cgit.nix new file mode 100644 index 0000000..f95d7f7 --- /dev/null +++ b/modules/services/cgit.nix @@ -0,0 +1,85 @@ +{ + config, + pkgs, + lib, + ... +}: +let + host = "git.rulkc.org"; + assets = pkgs.stdenv.mkDerivation { + pname = "git-rulkc-org-assets"; + version = "1.0"; + src = ./. + "/../../git.rulkc.org/cgit/"; + + dontUnpack = true; + + installPhase = '' + cp -r $src $out + ''; + }; + mkAssetPath = file: "${assets}/${file}"; + + reposPath = "/var/lib/${config.services.gitolite.user}/repositories/"; +in +{ + options.landau.services.cgit.enable = lib.mkEnableOption "cgit configured for LANDAU"; + + config = lib.mkIf config.landau.services.cgit.enable { + services.nginx.virtualHosts.${host} = { + addSSL = true; + enableACME = true; + locations = { + "= /cgit.png".alias = mkAssetPath "cgit.png"; + "= /cgit.css".alias = mkAssetPath "cgit.css"; + "= /favicon.ico".alias = mkAssetPath "favicon.ico"; + }; + }; + security.acme = { + acceptTerms = true; + defaults.email = "moskalets at landau.one"; + }; + + environment.systemPackages = [ assets ]; + + services.cgit.${host} = { + enable = true; + user = config.services.gitolite.user; + group = config.services.gitolite.group; + scanPath = reposPath; + 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://${host}/$CGIT_REPO_URL" + + (lib.strings.optionalString config.landau.services.gitolite.enable " ssh://${config.services.gitolite.user}@${host}/$CGIT_REPO_URL"); + section-from-path = 3; + max-stats = "quarter"; + cache-root = "/var/cache/cgit"; + cache-size = 1000; + }; + }; + + services.gitDaemon = { + enable = true; + basePath = reposPath; + exportAll = true; + user = config.services.gitolite.user; + group = config.services.gitolite.group; + }; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + 9418 + ]; + }; +} diff --git a/modules/services/default.nix b/modules/services/default.nix new file mode 100644 index 0000000..2658d86 --- /dev/null +++ b/modules/services/default.nix @@ -0,0 +1,7 @@ +{ + imports = [ + ./cgit.nix + ./gitolite.nix + ./grokmirror.nix + ]; +} diff --git a/modules/services/gitolite.nix b/modules/services/gitolite.nix new file mode 100644 index 0000000..c180161 --- /dev/null +++ b/modules/services/gitolite.nix @@ -0,0 +1,237 @@ +{ config, lib, ... }: +{ + options.landau.services.gitolite = { + enable = lib.mkEnableOption "gitolite configured for LANDAU"; + projectList = lib.mkOption { + description = "Path to projects.list for gitweb"; + type = lib.types.str; + default = "/var/lib/gitolite/projects.list"; + }; + }; + + config = lib.mkIf config.landau.services.gitolite.enable { + services.openssh = { + enable = lib.mkForce true; + settings.AllowGroups = lib.mkForce null; + }; + services.gitolite = { + enable = true; + adminPubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDorHQviBgliQSwdk0b/vLbGdRADutxkz58hexR8MfNv RULKC gitolite"; + extraGitoliteRc = '' + # configuration variables for gitolite + + # This file is in perl syntax. But you do NOT need to know perl to edit it -- + # just mind the commas, use single quotes unless you know what you're doing, + # and make sure the brackets and braces stay matched up! + + # (Tip: perl allows a comma after the last item in a list also!) + + # HELP for commands can be had by running the command with "-h". + + # HELP for all the other FEATURES can be found in the documentation (look for + # "list of non-core programs shipped with gitolite" in the master index) or + # directly in the corresponding source file. + + %RC = ( + + # ------------------------------------------------------------------ + + # default umask gives you perms of '0700'; see the rc file docs for + # how/why you might change this + UMASK => 0027, + + # look for "git-config" in the documentation + GIT_CONFIG_KEYS => 'gitweb\..*', + + # comment out if you don't need all the extra detail in the logfile + LOG_EXTRA => 1, + # logging options + # 1. leave this section as is for 'normal' gitolite logging (default) + # 2. uncomment this line to log ONLY to syslog: + # LOG_DEST => 'syslog', + # 3. uncomment this line to log to syslog and the normal gitolite log: + # LOG_DEST => 'syslog,normal', + # 4. prefixing "repo-log," to any of the above will **also** log just the + # update records to "gl-log" in the bare repo directory: + # LOG_DEST => 'repo-log,normal', + # LOG_DEST => 'repo-log,syslog', + # LOG_DEST => 'repo-log,syslog,normal', + # syslog 'facility': defaults to 'local0', uncomment if needed. For example: + # LOG_FACILITY => 'local4', + + # roles. add more roles (like MANAGER, TESTER, ...) here. + # WARNING: if you make changes to this hash, you MUST run 'gitolite + # compile' afterward, and possibly also 'gitolite trigger POST_COMPILE' + ROLES => { + READERS => 1, + WRITERS => 1, + }, + + # enable caching (currently only Redis). PLEASE RTFM BEFORE USING!!! + # CACHE => 'Redis', + + # ------------------------------------------------------------------ + + # rc variables used by various features + + # the 'info' command prints this as additional info, if it is set + # SITE_INFO => 'Please see http://blahblah/gitolite for more help', + + # the CpuTime feature uses these + # display user, system, and elapsed times to user after each git operation + # DISPLAY_CPU_TIME => 1, + # display a warning if total CPU times (u, s, cu, cs) crosses this limit + # CPU_TIME_WARN_LIMIT => 0.1, + + # the Mirroring feature needs this + # HOSTNAME => "foo", + + # TTL for redis cache; PLEASE SEE DOCUMENTATION BEFORE UNCOMMENTING! + # CACHE_TTL => 600, + + # ------------------------------------------------------------------ + + # suggested locations for site-local gitolite code (see cust.html) + + # this one is managed directly on the server + # LOCAL_CODE => "$ENV{HOME}/local", + + # or you can use this, which lets you put everything in a subdirectory + # called "local" in your gitolite-admin repo. For a SECURITY WARNING + # on this, see http://gitolite.com/gitolite/non-core.html#pushcode + # LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local", + + # ------------------------------------------------------------------ + + # List of commands and features to enable + + ENABLE => [ + + # COMMANDS + + # These are the commands enabled by default + 'help', + 'desc', + 'info', + 'perms', + 'writable', + + # Uncomment or add new commands here. + 'create', + 'fork', + 'mirror', + 'readme', + 'sudo', + # 'sskm', + 'D', + 'symbolic-ref', + + # These FEATURES are enabled by default. + + # essential (unless you're using smart-http mode) + 'ssh-authkeys', + + # creates git-config entries from gitolite.conf file entries like 'config foo.bar = baz' + 'git-config', + + # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out + 'daemon', + + # creates projects.list file; if you don't use gitweb, comment this out + 'gitweb', + + # These FEATURES are disabled by default; uncomment to enable. If you + # need to add new ones, ask on the mailing list :-) + + # user-visible behaviour + + # prevent wild repos auto-create on fetch/clone + # 'no-create-on-read', + # no auto-create at all (don't forget to enable the 'create' command!) + # 'no-auto-create', + + # access a repo by another (possibly legacy) name + # 'Alias', + + # give some users direct shell access. See documentation in + # sts.html for details on the following two choices. + # "Shell $ENV{HOME}/.gitolite.shell-users", + # 'Shell alice bob', + + # set default roles from lines like 'option default.roles-1 = ...', etc. + # 'set-default-roles', + + # show more detailed messages on deny + # 'expand-deny-messages', + + # show a message of the day + # 'Motd', + + # system admin stuff + + # enable mirroring (don't forget to set the HOSTNAME too!) + # 'Mirroring', + + # allow people to submit pub files with more than one key in them + # 'ssh-authkeys-split', + + # selective read control hack + # 'partial-copy', + + # manage local, gitolite-controlled, copies of read-only upstream repos + # 'upstream', + + # updates 'description' file instead of 'gitweb.description' config item + # 'cgit', + + # allow repo-specific hooks to be added + # 'repo-specific-hooks', + + # performance, logging, monitoring... + + # be nice + # 'renice 10', + + # log CPU times (user, system, cumulative user, cumulative system) + # 'CpuTime', + + # syntactic_sugar for gitolite.conf and included files + + # allow backslash-escaped continuation lines in gitolite.conf + # 'continuation-lines', + + # create implicit user groups from directory names in keydir/ + # 'keysubdirs-as-groups', + + # allow simple line-oriented macros + # 'macros', + + # Kindergarten mode + + # disallow various things that sensible people shouldn't be doing anyway + # 'Kindergarten', + ], + + POST_COMPILE => + [ + 'post-compile/ssh-authkeys', + 'post-compile/update-git-configs', + 'post-compile/update-gitweb-access-list', + 'post-compile/update-git-daemon-access-list', + ], + ); + + $GITWEB_PROJECTS_LIST = "${config.landau.services.gitolite.projectList}"; + + # ------------------------------------------------------------------------------ + # per perl rules, this should be the last line in such a file: + 1; + + # Local variables: + # mode: perl + # End: + # vim: set syn=perl: + ''; + }; + }; +} diff --git a/modules/services/grokmirror.nix b/modules/services/grokmirror.nix new file mode 100644 index 0000000..fbb00a8 --- /dev/null +++ b/modules/services/grokmirror.nix @@ -0,0 +1,19 @@ +{ config, lib, ... }: +{ + options.landau.services.grokmirror.enable = lib.mkEnableOption "grokmirror configured for LANDAU"; + + config = lib.mkIf config.landau.services.grokmirror.enable { + systemd.services.my-custom-service = { + description = "My Custom NixOS Service"; + wantedBy = [ "multi-user.target" ]; # Starts automatically at boot + after = [ "network.target" ]; # Waits for network to be up + + serviceConfig = { + Type = "simple"; + ExecStart = "${pkgs.hello}/bin/hello"; # Use absolute paths/packages + Restart = "on-failure"; + User = "root"; # Optional: run as specific user + }; + }; + }; +} diff --git a/pkgs/by-name/gr/grokmirror/package.nix b/pkgs/by-name/gr/grokmirror/package.nix new file mode 100644 index 0000000..866758d --- /dev/null +++ b/pkgs/by-name/gr/grokmirror/package.nix @@ -0,0 +1,33 @@ +{ + lib, + stdenv, + python3Packages, + fetchFromGitHub, +}: + +python3Packages.buildPythonPackage (finalAttrs: { + pname = "grokmirror"; + version = "2.0.12"; + format = "setuptools"; + + __structuredAttrs = true; + + src = fetchFromGitHub { + owner = "mricon"; + repo = "grokmirror"; + tag = "v${finalAttrs.version}"; + hash = "sha256-4UwVcE5IYUmAkgbLTFg5Rw5yZUZWkok3iw7LO8pplV4="; + }; + + propagatedBuildInputs = with python3Packages; [ + packaging + requests + ]; + + meta = { + homepage = "https://github.com/mricon/grokmirror"; + description = "Framework to smartly mirror git repositories"; + license = lib.licenses.gpl3Only; + maintainers = with lib.maintainers; [ maxmosk ]; + }; +}) diff --git a/pkgs/default.nix b/pkgs/default.nix new file mode 100644 index 0000000..4617bf9 --- /dev/null +++ b/pkgs/default.nix @@ -0,0 +1,7 @@ +{ nixpkgs, ... }: +let + by-name-overlay = import "${nixpkgs}/pkgs/top-level/by-name-overlay.nix" ./by-name; +in +{ + nixpkgs.overlays = [ by-name-overlay ]; +} 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..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..e5a32da --- /dev/null +++ b/servers/cgit.nix @@ -0,0 +1,23 @@ +{ + config, + pkgs, + lib, + modulesPath, + ... +}: +{ + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + (modulesPath + "/profiles/qemu-guest.nix") + ./cgit-hardware-configuration.nix + ]; + + networking.hostName = "cgit"; + + landau.services = { + cgit.enable = true; + gitolite.enable = true; + }; + + hostings.beget.enable = true; +} -- 2.54.0 From moskalets at landau.one Fri Oct 9 22:32:16 2026 From: moskalets at landau.one (Maxim Moskalets) Date: Fri, 9 Oct 2026 22:32:16 +0300 Subject: [rulkc] [PATCH v7] nix: introduce initial generic configuration Message-ID: <20261009193217.19557-1-moskalets@landau.one> From: Maxim Moskalets Add a NixOS configuration for cgit server as initial. Services added: - cgit (over HTTP) - gitolite - git-daemon - 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 --- .gitignore | 3 + README.md | 30 +++ config/admins.nix | 16 ++ config/default.nix | 10 + 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 | 10 + config/virtualisation.nix | 15 ++ flake.lock | 69 +++++++ flake.nix | 47 +++++ modules/default.nix | 6 + modules/hostings/beget.nix | 35 ++++ modules/hostings/default.nix | 6 + modules/hostings/selectel.nix | 29 +++ modules/services/cgit.nix | 85 +++++++++ modules/services/default.nix | 7 + modules/services/gitolite.nix | 237 ++++++++++++++++++++++++ modules/services/grokmirror.nix | 103 ++++++++++ pkgs/by-name/gr/grokmirror/package.nix | 33 ++++ pkgs/default.nix | 7 + servers/cgit-hardware-configuration.nix | 36 ++++ servers/cgit.nix | 24 +++ 26 files changed, 878 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 config/admins.nix 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/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/cgit.nix create mode 100644 modules/services/default.nix create mode 100644 modules/services/gitolite.nix create mode 100644 modules/services/grokmirror.nix create mode 100644 pkgs/by-name/gr/grokmirror/package.nix create mode 100644 pkgs/default.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..e881a75 --- /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@ +``` + +After installation, run `nixos-rebuild switch` to apply changes. You can also use `--build-host` and `--target-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/admins.nix b/config/admins.nix new file mode 100644 index 0000000..625186f --- /dev/null +++ b/config/admins.nix @@ -0,0 +1,16 @@ +{ + users.users = { + moskalets = { + isNormalUser = true; + description = "Maxim Moskalets"; + extraGroups = [ + "wheel" + ]; + openssh.authorizedKeys.keys = [ + # YubiKey + "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" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDorHQviBgliQSwdk0b/vLbGdRADutxkz58hexR8MfNv RULKC gitolite" + ]; + }; + }; +} diff --git a/config/default.nix b/config/default.nix new file mode 100644 index 0000000..7a7be0f --- /dev/null +++ b/config/default.nix @@ -0,0 +1,10 @@ +{ + imports = [ + ./admins.nix + ./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..46164ef --- /dev/null +++ b/config/services/ssh.nix @@ -0,0 +1,10 @@ +{ lib, ... }: +{ + services.openssh = { + allowSFTP = false; + settings = { + PermitRootLogin = "no"; + AllowGroups = lib.mkDefault [ "wheel" ]; + }; + }; +} diff --git a/config/virtualisation.nix b/config/virtualisation.nix new file mode 100644 index 0000000..498aa43 --- /dev/null +++ b/config/virtualisation.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: +{ + virtualisation.vmVariant = { + services.getty.autologinUser = "root"; + virtualisation = { + memorySize = 4 * 1024; + cores = 4; + forwardPorts = map (port: { + from = "host"; + host.port = port + 8000; + guest.port = port; + }) config.networking.firewall.allowedTCPPorts; + }; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..bc12d19 --- /dev/null +++ b/flake.lock @@ -0,0 +1,69 @@ +{ + "nodes": { + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1789770686, + "narHash": "sha256-uZkBR7yHdIKUFB5SZdfgh1qkGfI3XmYmI/lTiquxbck=", + "owner": "nix-community", + "repo": "disko", + "rev": "725ea35e410ad83be4931d1bff7e090eacaf3563", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1791353474, + "narHash": "sha256-v72qr4LsSz61tQki/41nHKZKPY6NSeZavtGlAInOCng=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2efa67fd26b6df417c33e4603185c701f260dd83", + "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": 1791167327, + "narHash": "sha256-R2FYN0UwfpmJBN8pew/7GxZUohmlvnZrHgj4+afSETo=", + "owner": "nix-community", + "repo": "srvos", + "rev": "6c23e3049d72339dbca8325afbb2a383fd9016c8", + "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..4c6b9da --- /dev/null +++ b/flake.nix @@ -0,0 +1,47 @@ +{ + 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, + ... + }@attrs: + let + makeServerSystem = + modules: extraConfig: + nixpkgs.lib.nixosSystem { + specialArgs = attrs; + system = "x86_64-linux"; + modules = [ + disko.nixosModules.disko + srvos.nixosModules.server + ./config + ./modules + ./pkgs + ] + ++ modules; + } + // extraConfig; + in + { + nixosConfigurations = { + cgit = makeServerSystem [ ./servers/cgit.nix ] { }; + }; + + inherit (nixpkgs) formatter; + }; +} diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..59a8985 --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./hostings + ./services + ]; +} diff --git a/modules/hostings/beget.nix b/modules/hostings/beget.nix new file mode 100644 index 0000000..13151ed --- /dev/null +++ b/modules/hostings/beget.nix @@ -0,0 +1,35 @@ +{ + 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" + ]; + preserve_hostname = true; + }; + }; + + 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/cgit.nix b/modules/services/cgit.nix new file mode 100644 index 0000000..f95d7f7 --- /dev/null +++ b/modules/services/cgit.nix @@ -0,0 +1,85 @@ +{ + config, + pkgs, + lib, + ... +}: +let + host = "git.rulkc.org"; + assets = pkgs.stdenv.mkDerivation { + pname = "git-rulkc-org-assets"; + version = "1.0"; + src = ./. + "/../../git.rulkc.org/cgit/"; + + dontUnpack = true; + + installPhase = '' + cp -r $src $out + ''; + }; + mkAssetPath = file: "${assets}/${file}"; + + reposPath = "/var/lib/${config.services.gitolite.user}/repositories/"; +in +{ + options.landau.services.cgit.enable = lib.mkEnableOption "cgit configured for LANDAU"; + + config = lib.mkIf config.landau.services.cgit.enable { + services.nginx.virtualHosts.${host} = { + addSSL = true; + enableACME = true; + locations = { + "= /cgit.png".alias = mkAssetPath "cgit.png"; + "= /cgit.css".alias = mkAssetPath "cgit.css"; + "= /favicon.ico".alias = mkAssetPath "favicon.ico"; + }; + }; + security.acme = { + acceptTerms = true; + defaults.email = "moskalets at landau.one"; + }; + + environment.systemPackages = [ assets ]; + + services.cgit.${host} = { + enable = true; + user = config.services.gitolite.user; + group = config.services.gitolite.group; + scanPath = reposPath; + 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://${host}/$CGIT_REPO_URL" + + (lib.strings.optionalString config.landau.services.gitolite.enable " ssh://${config.services.gitolite.user}@${host}/$CGIT_REPO_URL"); + section-from-path = 3; + max-stats = "quarter"; + cache-root = "/var/cache/cgit"; + cache-size = 1000; + }; + }; + + services.gitDaemon = { + enable = true; + basePath = reposPath; + exportAll = true; + user = config.services.gitolite.user; + group = config.services.gitolite.group; + }; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + 9418 + ]; + }; +} diff --git a/modules/services/default.nix b/modules/services/default.nix new file mode 100644 index 0000000..2658d86 --- /dev/null +++ b/modules/services/default.nix @@ -0,0 +1,7 @@ +{ + imports = [ + ./cgit.nix + ./gitolite.nix + ./grokmirror.nix + ]; +} diff --git a/modules/services/gitolite.nix b/modules/services/gitolite.nix new file mode 100644 index 0000000..c180161 --- /dev/null +++ b/modules/services/gitolite.nix @@ -0,0 +1,237 @@ +{ config, lib, ... }: +{ + options.landau.services.gitolite = { + enable = lib.mkEnableOption "gitolite configured for LANDAU"; + projectList = lib.mkOption { + description = "Path to projects.list for gitweb"; + type = lib.types.str; + default = "/var/lib/gitolite/projects.list"; + }; + }; + + config = lib.mkIf config.landau.services.gitolite.enable { + services.openssh = { + enable = lib.mkForce true; + settings.AllowGroups = lib.mkForce null; + }; + services.gitolite = { + enable = true; + adminPubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDorHQviBgliQSwdk0b/vLbGdRADutxkz58hexR8MfNv RULKC gitolite"; + extraGitoliteRc = '' + # configuration variables for gitolite + + # This file is in perl syntax. But you do NOT need to know perl to edit it -- + # just mind the commas, use single quotes unless you know what you're doing, + # and make sure the brackets and braces stay matched up! + + # (Tip: perl allows a comma after the last item in a list also!) + + # HELP for commands can be had by running the command with "-h". + + # HELP for all the other FEATURES can be found in the documentation (look for + # "list of non-core programs shipped with gitolite" in the master index) or + # directly in the corresponding source file. + + %RC = ( + + # ------------------------------------------------------------------ + + # default umask gives you perms of '0700'; see the rc file docs for + # how/why you might change this + UMASK => 0027, + + # look for "git-config" in the documentation + GIT_CONFIG_KEYS => 'gitweb\..*', + + # comment out if you don't need all the extra detail in the logfile + LOG_EXTRA => 1, + # logging options + # 1. leave this section as is for 'normal' gitolite logging (default) + # 2. uncomment this line to log ONLY to syslog: + # LOG_DEST => 'syslog', + # 3. uncomment this line to log to syslog and the normal gitolite log: + # LOG_DEST => 'syslog,normal', + # 4. prefixing "repo-log," to any of the above will **also** log just the + # update records to "gl-log" in the bare repo directory: + # LOG_DEST => 'repo-log,normal', + # LOG_DEST => 'repo-log,syslog', + # LOG_DEST => 'repo-log,syslog,normal', + # syslog 'facility': defaults to 'local0', uncomment if needed. For example: + # LOG_FACILITY => 'local4', + + # roles. add more roles (like MANAGER, TESTER, ...) here. + # WARNING: if you make changes to this hash, you MUST run 'gitolite + # compile' afterward, and possibly also 'gitolite trigger POST_COMPILE' + ROLES => { + READERS => 1, + WRITERS => 1, + }, + + # enable caching (currently only Redis). PLEASE RTFM BEFORE USING!!! + # CACHE => 'Redis', + + # ------------------------------------------------------------------ + + # rc variables used by various features + + # the 'info' command prints this as additional info, if it is set + # SITE_INFO => 'Please see http://blahblah/gitolite for more help', + + # the CpuTime feature uses these + # display user, system, and elapsed times to user after each git operation + # DISPLAY_CPU_TIME => 1, + # display a warning if total CPU times (u, s, cu, cs) crosses this limit + # CPU_TIME_WARN_LIMIT => 0.1, + + # the Mirroring feature needs this + # HOSTNAME => "foo", + + # TTL for redis cache; PLEASE SEE DOCUMENTATION BEFORE UNCOMMENTING! + # CACHE_TTL => 600, + + # ------------------------------------------------------------------ + + # suggested locations for site-local gitolite code (see cust.html) + + # this one is managed directly on the server + # LOCAL_CODE => "$ENV{HOME}/local", + + # or you can use this, which lets you put everything in a subdirectory + # called "local" in your gitolite-admin repo. For a SECURITY WARNING + # on this, see http://gitolite.com/gitolite/non-core.html#pushcode + # LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local", + + # ------------------------------------------------------------------ + + # List of commands and features to enable + + ENABLE => [ + + # COMMANDS + + # These are the commands enabled by default + 'help', + 'desc', + 'info', + 'perms', + 'writable', + + # Uncomment or add new commands here. + 'create', + 'fork', + 'mirror', + 'readme', + 'sudo', + # 'sskm', + 'D', + 'symbolic-ref', + + # These FEATURES are enabled by default. + + # essential (unless you're using smart-http mode) + 'ssh-authkeys', + + # creates git-config entries from gitolite.conf file entries like 'config foo.bar = baz' + 'git-config', + + # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out + 'daemon', + + # creates projects.list file; if you don't use gitweb, comment this out + 'gitweb', + + # These FEATURES are disabled by default; uncomment to enable. If you + # need to add new ones, ask on the mailing list :-) + + # user-visible behaviour + + # prevent wild repos auto-create on fetch/clone + # 'no-create-on-read', + # no auto-create at all (don't forget to enable the 'create' command!) + # 'no-auto-create', + + # access a repo by another (possibly legacy) name + # 'Alias', + + # give some users direct shell access. See documentation in + # sts.html for details on the following two choices. + # "Shell $ENV{HOME}/.gitolite.shell-users", + # 'Shell alice bob', + + # set default roles from lines like 'option default.roles-1 = ...', etc. + # 'set-default-roles', + + # show more detailed messages on deny + # 'expand-deny-messages', + + # show a message of the day + # 'Motd', + + # system admin stuff + + # enable mirroring (don't forget to set the HOSTNAME too!) + # 'Mirroring', + + # allow people to submit pub files with more than one key in them + # 'ssh-authkeys-split', + + # selective read control hack + # 'partial-copy', + + # manage local, gitolite-controlled, copies of read-only upstream repos + # 'upstream', + + # updates 'description' file instead of 'gitweb.description' config item + # 'cgit', + + # allow repo-specific hooks to be added + # 'repo-specific-hooks', + + # performance, logging, monitoring... + + # be nice + # 'renice 10', + + # log CPU times (user, system, cumulative user, cumulative system) + # 'CpuTime', + + # syntactic_sugar for gitolite.conf and included files + + # allow backslash-escaped continuation lines in gitolite.conf + # 'continuation-lines', + + # create implicit user groups from directory names in keydir/ + # 'keysubdirs-as-groups', + + # allow simple line-oriented macros + # 'macros', + + # Kindergarten mode + + # disallow various things that sensible people shouldn't be doing anyway + # 'Kindergarten', + ], + + POST_COMPILE => + [ + 'post-compile/ssh-authkeys', + 'post-compile/update-git-configs', + 'post-compile/update-gitweb-access-list', + 'post-compile/update-git-daemon-access-list', + ], + ); + + $GITWEB_PROJECTS_LIST = "${config.landau.services.gitolite.projectList}"; + + # ------------------------------------------------------------------------------ + # per perl rules, this should be the last line in such a file: + 1; + + # Local variables: + # mode: perl + # End: + # vim: set syn=perl: + ''; + }; + }; +} diff --git a/modules/services/grokmirror.nix b/modules/services/grokmirror.nix new file mode 100644 index 0000000..ec851e1 --- /dev/null +++ b/modules/services/grokmirror.nix @@ -0,0 +1,103 @@ +{ + config, + lib, + pkgs, + ... +}: +let + configPath = "/etc/grokmirror.conf"; +in +{ + options.landau.services.grokmirror.enable = lib.mkEnableOption "grokmirror configured for LANDAU"; + + config = lib.mkIf config.landau.services.grokmirror.enable { + systemd.services."grokmirror" = { + description = "git repos sync"; + serviceConfig = { + Type = "oneshot"; + User = "gitolite"; + }; + script = '' + GITBIN=${lib.getExe pkgs.git} ${lib.getExe' pkgs.grokmirror "grok-pull"} -v -p -c ${configPath} + GITBIN=${lib.getExe pkgs.git} ${lib.getExe' pkgs.grokmirror "grok-dumb-pull"} -v /var/lib/gitolite/repositories/pub/scm/ + ''; + }; + + systemd.timers."grokmirror" = { + description = "Timer for grokmirror"; + wantedBy = [ "timers.target" ]; + timerConfig = { + OnBootSec = "5m"; + OnUnitActiveSec = "30m"; + Unit = "grokmirror.service"; + Persistent = true; + }; + }; + + environment.etc.${configPath}.text = '' + [core] + # Where are we going to put the mirror on our disk? + toplevel = /var/lib/gitolite/ + + # Where do we store our own manifest? Usually in the toplevel. + manifest = ''${toplevel}/manifest.js.gz + + # Where do we put the logs? + #log = /dev/stderr + + # Log level can be "info" or "debug" + loglevel = debug + + # To prevent multiple grok-pull instances from running at the same + # time, we first obtain an exclusive lock. + lock = /var/lock/kernelorg.lock + + # Object storage for forks (saves disk space) + objstore = /var/lib/gitolite/_objstore + + [remote] + # The source mirror + site = https://git.kernel.org + + # Manifest location on the remote site + manifest = ''${site}/manifest.js.gz + + [pull] + # Default owner for repositories + default_owner = Grokmirror User + + # Generate a project list for external tools (like cgit) + projectslist = ''${"core:toplevel"}/projects.list + + # Trim this prefix from paths in projectslist + projectslist_trimtop = /pub/scm/ + + # Use shell-globbing to list the repositories you would like to mirror. + # If you want to mirror everything, just say "*". Separate multiple entries + # with newline. + # + # mirror just the main kernel sources: + include = /pub/scm/linux/kernel/git/torvalds/linux.git + /pub/scm/linux/kernel/git/stable/linux.git + /pub/scm/linux/kernel/git/next/linux-next.git + + # Exclude patterns (none for now) + exclude = + + # Remove repositories not in remote manifest + # purge = + + # Protect against accidental mass purge (5% threshold) + # purgeprotect = + + # Number of parallel threads for fetching + pull_threads = 10 + + # Retry failed fetches up to 3 times + retries = 3 + + # Timeout for git operations (seconds) + timeout = 100 + ''; + }; +} diff --git a/pkgs/by-name/gr/grokmirror/package.nix b/pkgs/by-name/gr/grokmirror/package.nix new file mode 100644 index 0000000..866758d --- /dev/null +++ b/pkgs/by-name/gr/grokmirror/package.nix @@ -0,0 +1,33 @@ +{ + lib, + stdenv, + python3Packages, + fetchFromGitHub, +}: + +python3Packages.buildPythonPackage (finalAttrs: { + pname = "grokmirror"; + version = "2.0.12"; + format = "setuptools"; + + __structuredAttrs = true; + + src = fetchFromGitHub { + owner = "mricon"; + repo = "grokmirror"; + tag = "v${finalAttrs.version}"; + hash = "sha256-4UwVcE5IYUmAkgbLTFg5Rw5yZUZWkok3iw7LO8pplV4="; + }; + + propagatedBuildInputs = with python3Packages; [ + packaging + requests + ]; + + meta = { + homepage = "https://github.com/mricon/grokmirror"; + description = "Framework to smartly mirror git repositories"; + license = lib.licenses.gpl3Only; + maintainers = with lib.maintainers; [ maxmosk ]; + }; +}) diff --git a/pkgs/default.nix b/pkgs/default.nix new file mode 100644 index 0000000..4617bf9 --- /dev/null +++ b/pkgs/default.nix @@ -0,0 +1,7 @@ +{ nixpkgs, ... }: +let + by-name-overlay = import "${nixpkgs}/pkgs/top-level/by-name-overlay.nix" ./by-name; +in +{ + nixpkgs.overlays = [ by-name-overlay ]; +} 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..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..6d3bbf3 --- /dev/null +++ b/servers/cgit.nix @@ -0,0 +1,24 @@ +{ + config, + pkgs, + lib, + modulesPath, + ... +}: +{ + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + (modulesPath + "/profiles/qemu-guest.nix") + ./cgit-hardware-configuration.nix + ]; + + networking.hostName = "cgit"; + + landau.services = { + cgit.enable = true; + gitolite.enable = true; + grokmirror.enable = true; + }; + + hostings.beget.enable = true; +} -- 2.54.0