commit a4da04692c1062bf07512dc9d874e6cf7646d12e Author: Julien Hémono Date: Sat Jun 15 11:51:28 2024 +0200 Initial commit diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..d1a3f6b --- /dev/null +++ b/flake.lock @@ -0,0 +1,70 @@ +{ + "nodes": { + "mysecrets": { + "flake": false, + "locked": { + "lastModified": 1718444757, + "narHash": "sha256-EufXYrqS48HNTBT5D7lQQ3hHcLtDyWB1X62B0ao3Glo=", + "ref": "main", + "rev": "5e3eaefbe92be3049a995c076ff4f4eed27b50db", + "shallow": true, + "type": "git", + "url": "ssh://forgejo@git.hemono.fr/jhemono/nix-secrets.git" + }, + "original": { + "ref": "main", + "shallow": true, + "type": "git", + "url": "ssh://forgejo@git.hemono.fr/jhemono/nix-secrets.git" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1718208800, + "narHash": "sha256-US1tAChvPxT52RV8GksWZS415tTS7PV42KTc2PNDBmc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "cc54fb41d13736e92229c21627ea4f22199fee6b", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "mysecrets": "mysecrets", + "nixpkgs": "nixpkgs", + "sops-nix": "sops-nix" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1718137936, + "narHash": "sha256-psA+1Q5fPaK6yI3vzlLINNtb6EeXj111zQWnZYyJS9c=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "c279dec105dd53df13a5e57525da97905cc0f0d6", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..e5ed6ef --- /dev/null +++ b/flake.nix @@ -0,0 +1,36 @@ +{ + description = "Nixos config flake"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05"; + + # Secrets management + sops-nix = { + url = "github:Mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.nixpkgs-stable.follows = "nixpkgs"; + }; + + # home-manager = { + # url = "github:nix-community/home-manager"; + # inputs.nixpkgs.follows = "nixpkgs"; + # }; + + mysecrets = { + url = "git+ssh://forgejo@git.hemono.fr/jhemono/nix-secrets.git?ref=main&shallow=1"; + flake = false; + }; + }; + + outputs = { self, nixpkgs, ... }@inputs: { + nixosConfigurations = { + sesame = nixpkgs.lib.nixosSystem { + specialArgs = {inherit inputs;}; + modules = [ + ./hosts/sesame/configuration.nix + # inputs.home-manager.nixosModules.default + ]; + }; + }; + }; +} diff --git a/hosts/sesame/bois-ar.nix b/hosts/sesame/bois-ar.nix new file mode 100644 index 0000000..3359195 --- /dev/null +++ b/hosts/sesame/bois-ar.nix @@ -0,0 +1,108 @@ +{ pkgs, lib, config, ... }: +let + app = "boisar"; + # domain = "bois-ar.com"; + domain = "bois-ar.hemono.fr"; + dataDir = "/srv/http/${app}"; +in { + services.phpfpm.pools.${app} = { + user = app; + settings = { + "listen.owner" = config.services.nginx.user; + "pm" = "dynamic"; + "pm.max_children" = 15; + "pm.max_requests" = 500; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 1; + "pm.max_spare_servers" = 3; + "php_admin_value[error_log]" = "stderr"; + "php_admin_flag[log_errors]" = true; + "catch_workers_output" = true; + }; + phpEnv."PATH" = lib.makeBinPath [ pkgs.php ]; + }; + services.nginx = { + enable = true; + virtualHosts.${domain} = { + # serverAliases = ["www.bois-ar.com"]; + forceSSL = true; + enableACME = true; + root = dataDir; + locations = { + "= /favicon.ico" = { + extraConfig = '' + log_not_found off; + access_log off; + ''; + }; + "= /robots.txt" = { + extraConfig = '' + allow all; + log_not_found off; + access_log off; + ''; + }; + "~ \.php$" = { + tryFiles = "$uri =404"; + extraConfig = '' + fastcgi_pass unix:${config.services.phpfpm.pools.${app}.socket}; + include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_intercept_errors on; + ''; + }; + "~* \.(js|css|png|jpg|jpeg|gif|ico)$" = { + extraConfig = '' + expires max; + log_not_found off; + ''; + }; + }; + # WP Super Cache rules. + # Designed to be included from a 'wordpress-ms-...' configuration file. + extraConfig = '' + index index.php; # Not related to super cache + set $cache_uri $request_uri; + # POST requests and urls with a query string should always go to PHP + if ($request_method = POST) { + set $cache_uri 'null cache'; + } + if ($query_string != "") { + set $cache_uri 'null cache'; + } + # Don't cache uris containing the following segments + if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") { + set $cache_uri 'null cache'; + } + # Don't use the cache for logged in users or recent commenters + if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") { + set $cache_uri 'null cache'; + } + ''; + # Use cached or actual file if they exists, otherwise pass request to WordPress + locations."/" = { + tryFiles = "/wp-content/cache/supercache/$http_host/$cache_uri/index-$scheme.html $uri $uri/ /index.php?$args"; + }; + }; + }; + users.users.${app} = { + isSystemUser = true; + createHome = true; + home = dataDir; + homeMode = "750"; + group = app; + }; + users.groups.${app} = {}; + users.users.nginx.extraGroups = [ app ]; + services.mysql = { + enable = true; + ensureDatabases = [ app ]; + ensureUsers = [ + { + name = app; + ensurePermissions = { + "${app}.*" = "ALL PRIVILEGES"; + }; + } + ]; + }; +} diff --git a/hosts/sesame/buckets.nix b/hosts/sesame/buckets.nix new file mode 100644 index 0000000..b16f7c3 --- /dev/null +++ b/hosts/sesame/buckets.nix @@ -0,0 +1,65 @@ +{ inputs, pkgs, lib, config, ... }: +let + endpoint = "s3.${region}.backblazeb2.com"; + region = "eu-central-003"; + accessKeyId = "0030c2377ff19920000000002"; + + inherit (config.sops) secrets; +in { + imports = [ ./sops.nix ]; + + # Forgejo + + services.forgejo.settings.storage = { + STORAGE_TYPE = "minio"; + MINIO_USE_SSL = true; + MINIO_ENDPOINT = endpoint; + MINIO_ACCESS_KEY_ID = accessKeyId; + MINIO_SECRET_ACCESS_KEY = "#BACKBLAZE_APPLICATION_SECRET#"; + MINIO_BUCKET = "jhemono-forgejo"; + MINIO_LOCATION = region; + }; + + sops.secrets = { + forgejo_backblaze_application_secret = { + key = "backblaze_application_secret"; + owner = config.services.forgejo.user; + inherit (config.services.forgejo) group; + }; + }; + + # Replace the placefoler for the secret with actual value on pre-start + systemd.services.forgejo = { + preStart = let + runConfig = "${config.services.forgejo.customDir}/conf/app.ini"; + replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret"; + storageSettings = config.services.forgejo.settings.storage; + in '' + chmod u+w '${runConfig}' + ${replaceSecretBin} '${storageSettings.MINIO_SECRET_ACCESS_KEY}' '${secrets.forgejo_backblaze_application_secret.path}' '${runConfig}' + chmod u-w '${runConfig}' + ''; + }; + + # Nextcloud + sops.secrets = { + nextcloud_backblaze_application_secret = { + key = "backblaze_application_secret"; + owner = "nextcloud"; + group = "nextcloud"; + }; + }; + + services.nextcloud.config.objectstore.s3 = { + enable = true; + bucket = "seitan-nextcloud"; + autocreate = true; + key = accessKeyId; + secretFile = secrets.nextcloud_backblaze_application_secret.path; + hostname = endpoint; + useSsl = true; + port = 443; + region = region; + }; + +} diff --git a/hosts/sesame/configuration.nix b/hosts/sesame/configuration.nix new file mode 100644 index 0000000..06c14f7 --- /dev/null +++ b/hosts/sesame/configuration.nix @@ -0,0 +1,98 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page, on +# https://search.nixos.org/options and in the NixOS manual (`nixos-help`). + +{ config, lib, pkgs, ... }: + +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + # Supporting + ./buckets.nix + # Services + ./suite.nix + ./bois-ar.nix + ./forgejo.nix + ./transmission.nix + ./lemorillon.nix + ]; + + # Boot configuration + boot.loader.systemd-boot.enable = true; + boot.loader.systemd-boot.configurationLimit = 10; + boot.loader.efi.canTouchEfiVariables = true; + + # Networking + networking.hostName = "sesame"; + networking.domain = "hemono.fr"; + + # Set your time zone. + time.timeZone = "Europe/Paris"; + + # Console + console = { + keyMap = "fr"; + }; + + # User account + users.users.jhemono = { + isNormalUser = true; + extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + openssh = { + authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC8Q2lWsqvoqoIxqb8HM96IpvZkFhnwcPdEo+m5peH5N/0PZloEp/NfLbzktXGNACe+bwfweR1Kokjs/Ep0tQQggGtgqB0jAopd1Yw0wzlFWYGqJsGyuFBGP4SljsQvGhU2IwgvuJFIRrOVu+gRTIM1DYGQOveNqlRU/QoqOZDQPvHsoQCLvwmZBzzi7DLktBQZ7h/CJ3GrzD2YUuIyulZGbhfM86i0p7NQ5+TSxuo7Yotbwzrzi7hAROO22ghRfv0vxAPip9SCF1SKIZpSDd8s7Nk6dkDE+95N5cMOkFwokWWsxaTM+EgZfTjQZon1L1/X3UC3hK6C+7GLusoNe8xdjm14e9LA5qG5ZRtLrmIrI2bW5KBj/8iTxRmXpE9x70d2Hl6jtHBQv4rQOAO3BET0TjlNAXchNDOcDbNX1ZqEwyImoF4c3kbr5M2ezWCDltAdvd74mMMiaenxwYkZeZbR3EJPbtC1v//9QQ9S7OzKa5utwjhZFlh0g79GKq8DiU6W8IzzmD7pGi8MIV3wOh1NGlcIlPaIyJY60XN0iRNI9NhMASAF493xPfMlVWl7Tly1VDVcPp5pC47vHU6/2mBbx5tnVShNPnkf4OwF3nC8i0DT+dRKXAxjfpoM5iYIrSHrNj9EKKFE4qNbqtAPTNGGtxJ0fUdWOgXLf5BMfYmaiQ== jhemono@gwiad" + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFWZ1MF5Srp1AkfgzO/19RCeYfCU+HtJFYESS9PhQrQYhUwZtoHExHYyD1nf71+jGFu6HJjXAPDD5ZW1XqYEh8kFvkx8uXw+kKHOVwuVhkcIYduQlsR8e8kbu8y6OABPe3SWmmtiA2HdWCwlZNoyTL1X4+LsA+Hbs0EHn1p+RQ4YeOSuZV/5VETt1Mcu/d0GyFBlnoCtu3VwexBdZgsVkw/kOpjNrY0RhqEwiO7P9J+jXT6HB8wvus6MzgvNPzoFo6hAXqRGu3SvCQJnVkE/AulHBfWLFCwdIrekGCKMv9v51dUJ5pgHxWyZZQhYNFpE2qTj8meExBDfnnYl7MFQ3j termbot" + ]; + }; + # packages = with pkgs; [ + # firefox + # tree + # ]; + }; + + # System packages + environment.systemPackages = with pkgs; [ + git + htop + jq + ncdu + tmux + tree + unzip + vim + ]; + + environment.variables.EDITOR = "vim"; + + # Nix configuration + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + nix.gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 1w"; + }; + nix.settings.auto-optimise-store = true; + + # OpenSSH + services.openssh = { + enable = true; + settings = { + PermitRootLogin = "no"; + PasswordAuthentication = false; + }; + }; + + # HTTPS + security.acme = { + acceptTerms = true; + defaults.email = "julien@hemono.fr"; + }; + + # Firewall + networking.firewall.allowedTCPPorts = [ 80 443 ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + + system.stateVersion = "23.11"; + +} diff --git a/hosts/sesame/forgejo.nix b/hosts/sesame/forgejo.nix new file mode 100644 index 0000000..5d94109 --- /dev/null +++ b/hosts/sesame/forgejo.nix @@ -0,0 +1,44 @@ +{ lib, pkgs, config, ... }: +let + cfg = config.services.forgejo; + srv = cfg.settings.server; +in +{ + services.nginx = { + virtualHosts.${cfg.settings.server.DOMAIN} = { + forceSSL = true; + enableACME = true; + extraConfig = '' + client_max_body_size 512M; + ''; + locations."/".proxyPass = "http://localhost:${toString srv.HTTP_PORT}"; + }; + }; + + services.forgejo = { + enable = true; + database = { + type = "mysql"; + createDatabase = true; + }; + # Enable support for Git Large File Storage + lfs.enable = true; + settings = { + server = { + DOMAIN = "git.hemono.fr"; + # You need to specify this to remove the port from URLs in the web UI. + ROOT_URL = "https://${srv.DOMAIN}/"; + HTTP_PORT = 3000; + }; + service.DISABLE_REGISTRATION = true; + # Add support for actions, based on act: https://github.com/nektos/act + actions = { + ENABLED = true; + DEFAULT_ACTIONS_URL = "github"; + }; + }; + }; + + services.mysql.package = pkgs.mariadb; + +} diff --git a/hosts/sesame/hardware-configuration.nix b/hosts/sesame/hardware-configuration.nix new file mode 100644 index 0000000..df9de8b --- /dev/null +++ b/hosts/sesame/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 = [ "xhci_pci" "virtio_pci" "virtio_scsi" "usbhid" "sr_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/2ab6f83b-71d1-4cb4-bc20-1e27e7fa2fe5"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/F0B7-7CDC"; + fsType = "vfat"; + }; + + swapDevices = [ ]; + + # 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.enp1s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; +} diff --git a/hosts/sesame/lemorillon.nix b/hosts/sesame/lemorillon.nix new file mode 100644 index 0000000..b1700dd --- /dev/null +++ b/hosts/sesame/lemorillon.nix @@ -0,0 +1,24 @@ +{ pkgs, lib, config, ... }: +let + app = "lemorillon"; + domain = "${app}.hemono.fr"; + dataDir = "/srv/http/${app}"; +in { + services.nginx = { + enable = true; + virtualHosts.${domain} = { + forceSSL = true; + enableACME = true; + root = dataDir; + locations = { + "/" = { + index = "index.htm"; + }; + }; + }; + }; + systemd.tmpfiles.rules = [ + "d ${dataDir} 0700 ${config.services.nginx.user} ${config.services.nginx.group}" + ]; +} + diff --git a/hosts/sesame/sops.nix b/hosts/sesame/sops.nix new file mode 100644 index 0000000..2364b16 --- /dev/null +++ b/hosts/sesame/sops.nix @@ -0,0 +1,24 @@ +{ inputs, pkgs, lib, config, ... }: +let + secretspath = builtins.toString inputs.mysecrets; +in +{ + imports = [ + inputs.sops-nix.nixosModules.sops + ]; + + sops = { + defaultSopsFile = "${secretspath}/secrets.yaml"; + validateSopsFiles = false; + + age = { + # automatically import host SSH keys as age keys + sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; + # this will use an age key that is expecte to already be in the filesystem + keyFile = "/var/lib/sops-nix/key.txt"; + # generate a new key if the key specified above does not exist + generateKey = true; + }; + }; + +} diff --git a/hosts/sesame/suite.nix b/hosts/sesame/suite.nix new file mode 100644 index 0000000..3fc11a9 --- /dev/null +++ b/hosts/sesame/suite.nix @@ -0,0 +1,30 @@ +{ config, lib, pkgs, ... }: + +{ + # Nextcloud + services.nextcloud = { + enable = true; + package = pkgs.nextcloud29; + hostName = "suite.hemono.fr"; + https = true; + # phpOptions = { + # memory_limit = lib.mkForce "3G"; + # }; + configureRedis = true; + database.createLocally = true; + config = { + adminuser = "jhemono"; + adminpassFile = "/etc/nextcloud-admin-pass"; + dbtype = "mysql"; + }; + # appstoreEnable = true; + extraApps = { + inherit (config.services.nextcloud.package.packages.apps) calendar contacts; + }; + }; + + services.nginx.virtualHosts.${config.services.nextcloud.hostName} = { + forceSSL = true; + enableACME = true; + }; +} diff --git a/hosts/sesame/transmission.nix b/hosts/sesame/transmission.nix new file mode 100644 index 0000000..b7d016b --- /dev/null +++ b/hosts/sesame/transmission.nix @@ -0,0 +1,8 @@ +{ config, lib, pkgs, ... }: + +{ + services.transmission = { + enable = true; + openPeerPorts = true; + }; +}