diff options
author | pennae <82953136+pennae@users.noreply.github.com> | 2022-09-01 16:10:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-01 16:10:09 +0200 |
commit | 3bddcf5f9002814a8bec50025418faa3fd3f6138 (patch) | |
tree | 5ae3ebf10acce3ad00d4a2468f8e64c41a2c749b /nixos | |
parent | 1d41cff3dc4c8f37bb5841f51fcbff705e169178 (diff) | |
parent | e7312d54f184e5c3e0f1ef29028f6dae8fa34a97 (diff) | |
download | nixlib-3bddcf5f9002814a8bec50025418faa3fd3f6138.tar nixlib-3bddcf5f9002814a8bec50025418faa3fd3f6138.tar.gz nixlib-3bddcf5f9002814a8bec50025418faa3fd3f6138.tar.bz2 nixlib-3bddcf5f9002814a8bec50025418faa3fd3f6138.tar.lz nixlib-3bddcf5f9002814a8bec50025418faa3fd3f6138.tar.xz nixlib-3bddcf5f9002814a8bec50025418faa3fd3f6138.tar.zst nixlib-3bddcf5f9002814a8bec50025418faa3fd3f6138.zip |
Merge branch 'master' into option-docs-md
Diffstat (limited to 'nixos')
26 files changed, 886 insertions, 68 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml index a951835a0764..e3c76918911a 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml @@ -258,6 +258,14 @@ <link xlink:href="options.html#opt-services.patroni.enable">services.patroni</link>. </para> </listitem> + <listitem> + <para> + <link xlink:href="https://writefreely.org">WriteFreely</link>, + a simple blogging platform with ActivityPub support. Available + as + <link xlink:href="options.html#opt-services.writefreely.enable">services.writefreely</link>. + </para> + </listitem> </itemizedlist> </section> <section xml:id="sec-release-22.11-incompatibilities"> @@ -428,6 +436,12 @@ due to upstream dropping support. </para> </listitem> + <listitem> + <para> + <literal>k3s</literal> supports <literal>clusterInit</literal> + option, and it is enabled by default, for servers. + </para> + </listitem> </itemizedlist> </section> <section xml:id="sec-release-22.11-notable-changes"> diff --git a/nixos/doc/manual/release-notes/rl-2211.section.md b/nixos/doc/manual/release-notes/rl-2211.section.md index 73348007cb73..afeaa7aaac73 100644 --- a/nixos/doc/manual/release-notes/rl-2211.section.md +++ b/nixos/doc/manual/release-notes/rl-2211.section.md @@ -92,6 +92,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [Patroni](https://github.com/zalando/patroni), a template for PostgreSQL HA with ZooKeeper, etcd or Consul. Available as [services.patroni](options.html#opt-services.patroni.enable). +- [WriteFreely](https://writefreely.org), a simple blogging platform with ActivityPub support. Available as [services.writefreely](options.html#opt-services.writefreely.enable). + <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> ## Backward Incompatibilities {#sec-release-22.11-incompatibilities} @@ -150,6 +152,8 @@ Use `configure.packages` instead. - `k3s` no longer supports docker as runtime due to upstream dropping support. +- `k3s` supports `clusterInit` option, and it is enabled by default, for servers. + <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> ## Other Notable Changes {#sec-release-22.11-notable-changes} diff --git a/nixos/lib/qemu-common.nix b/nixos/lib/qemu-common.nix index fc3dcb24ab9c..3f4d674e9a93 100644 --- a/nixos/lib/qemu-common.nix +++ b/nixos/lib/qemu-common.nix @@ -4,29 +4,61 @@ let zeroPad = n: lib.optionalString (n < 16) "0" + - (if n > 255 - then throw "Can't have more than 255 nets or nodes!" - else lib.toHexString n); + (if n > 255 + then throw "Can't have more than 255 nets or nodes!" + else lib.toHexString n); in rec { qemuNicMac = net: machine: "52:54:00:12:${zeroPad net}:${zeroPad machine}"; qemuNICFlags = nic: net: machine: - [ "-device virtio-net-pci,netdev=vlan${toString nic},mac=${qemuNicMac net machine}" + [ + "-device virtio-net-pci,netdev=vlan${toString nic},mac=${qemuNicMac net machine}" ''-netdev vde,id=vlan${toString nic},sock="$QEMU_VDE_SOCKET_${toString net}"'' ]; - qemuSerialDevice = if pkgs.stdenv.hostPlatform.isx86 || pkgs.stdenv.hostPlatform.isRiscV then "ttyS0" - else if (with pkgs.stdenv.hostPlatform; isAarch || isPower) then "ttyAMA0" - else throw "Unknown QEMU serial device for system '${pkgs.stdenv.hostPlatform.system}'"; + qemuSerialDevice = + if pkgs.stdenv.hostPlatform.isx86 || pkgs.stdenv.hostPlatform.isRiscV then "ttyS0" + else if (with pkgs.stdenv.hostPlatform; isAarch || isPower) then "ttyAMA0" + else throw "Unknown QEMU serial device for system '${pkgs.stdenv.hostPlatform.system}'"; - qemuBinary = qemuPkg: { - x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu max"; - armv7l-linux = "${qemuPkg}/bin/qemu-system-arm -machine virt,accel=kvm:tcg -cpu max"; - aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -machine virt,gic-version=max,accel=kvm:tcg -cpu max"; - powerpc64le-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv"; - powerpc64-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv"; - x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu max"; - }.${pkgs.stdenv.hostPlatform.system} or "${qemuPkg}/bin/qemu-kvm"; + qemuBinary = qemuPkg: + let + hostStdenv = qemuPkg.stdenv; + hostSystem = hostStdenv.system; + guestSystem = pkgs.stdenv.hostPlatform.system; + + linuxHostGuestMatrix = { + x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu max"; + armv7l-linux = "${qemuPkg}/bin/qemu-system-arm -machine virt,accel=kvm:tcg -cpu max"; + aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -machine virt,gic-version=max,accel=kvm:tcg -cpu max"; + powerpc64le-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv"; + powerpc64-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv"; + x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu max"; + }; + otherHostGuestMatrix = { + aarch64-darwin = { + aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -machine virt,gic-version=2,accel=hvf:tcg -cpu max"; + }; + x86_64-darwin = { + x86_64-linux = "${qemuPkg}/bin/qemu-system-x86_64 -machine type=q35,accel=hvf:tcg -cpu max"; + }; + }; + + throwUnsupportedHostSystem = + let + supportedSystems = [ "linux" ] ++ (lib.attrNames otherHostGuestMatrix); + in + throw "Unsupported host system ${hostSystem}, supported: ${lib.concatStringsSep ", " supportedSystems}"; + throwUnsupportedGuestSystem = guestMap: + throw "Unsupported guest system ${guestSystem} for host ${hostSystem}, supported: ${lib.concatStringsSep ", " (lib.attrNames guestMap)}"; + in + if hostStdenv.isLinux then + linuxHostGuestMatrix.${guestSystem} or "${qemuPkg}/bin/qemu-kvm" + else + let + guestMap = (otherHostGuestMatrix.${hostSystem} or throwUnsupportedHostSystem); + in + (guestMap.${guestSystem} or (throwUnsupportedGuestSystem guestMap)); } diff --git a/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixos/modules/installer/tools/nix-fallback-paths.nix index 0035ceca6fc9..4700895cec8e 100644 --- a/nixos/modules/installer/tools/nix-fallback-paths.nix +++ b/nixos/modules/installer/tools/nix-fallback-paths.nix @@ -1,7 +1,7 @@ { - x86_64-linux = "/nix/store/3af6g226v4hsv6x7xzh23d6wqyq0nzjp-nix-2.10.3"; - i686-linux = "/nix/store/43xxh2jip6rpdhylc5z9a5fxx54dw206-nix-2.10.3"; - aarch64-linux = "/nix/store/6qw3r57nra08ars8j8zyj3fl8lz4cvnd-nix-2.10.3"; - x86_64-darwin = "/nix/store/3b7qrm0qjw57fmznrsvm0ai568i89hc2-nix-2.10.3"; - aarch64-darwin = "/nix/store/gp7k17iy1n7hgf97qwnxw28c6v9nhb1i-nix-2.10.3"; + x86_64-linux = "/nix/store/nmq5zcd93qb1yskx42rs910ff0247nn2-nix-2.11.0"; + i686-linux = "/nix/store/ja6im1sw9a8lzczi10lc0iddffl9kzmn-nix-2.11.0"; + aarch64-linux = "/nix/store/myr6fcqa9y4y2fb83zz73dck52vcn81z-nix-2.11.0"; + x86_64-darwin = "/nix/store/2pfjz9b22k9997gh7cb0hjk1qa4lxrvy-nix-2.11.0"; + aarch64-darwin = "/nix/store/lr32i0bdarx1iqsch4sy24jj1jkfw9vf-nix-2.11.0"; } diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 6e95c45f0d56..cb3599589cfe 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -204,6 +204,7 @@ ./programs/plotinus.nix ./programs/proxychains.nix ./programs/qt5ct.nix + ./programs/rust-motd.nix ./programs/screen.nix ./programs/sedutil.nix ./programs/seahorse.nix @@ -1119,6 +1120,7 @@ ./services/web-apps/wiki-js.nix ./services/web-apps/whitebophir.nix ./services/web-apps/wordpress.nix + ./services/web-apps/writefreely.nix ./services/web-apps/youtrack.nix ./services/web-apps/zabbix.nix ./services/web-servers/agate.nix diff --git a/nixos/modules/programs/gnupg.nix b/nixos/modules/programs/gnupg.nix index 1028ef53bae1..1a9006aad14e 100644 --- a/nixos/modules/programs/gnupg.nix +++ b/nixos/modules/programs/gnupg.nix @@ -129,12 +129,14 @@ in environment.interactiveShellInit = '' # Bind gpg-agent to this TTY if gpg commands are used. export GPG_TTY=$(tty) + ''; - '' + (optionalString cfg.agent.enableSSHSupport '' - # SSH agent protocol doesn't support changing TTYs, so bind the agent - # to every new TTY. - ${cfg.package}/bin/gpg-connect-agent --quiet updatestartuptty /bye > /dev/null - ''); + programs.ssh.extraConfig = optionalString cfg.agent.enableSSHSupport '' + # The SSH agent protocol doesn't have support for changing TTYs; however we + # can simulate this with the `exec` feature of openssh (see ssh_config(5)) + # that hooks a command to the shell currently running the ssh program. + Match host * exec "${cfg.package}/bin/gpg-connect-agent --quiet updatestartuptty /bye > /dev/null" + ''; environment.extraInit = mkIf cfg.agent.enableSSHSupport '' if [ -z "$SSH_AUTH_SOCK" ]; then diff --git a/nixos/modules/programs/rust-motd.nix b/nixos/modules/programs/rust-motd.nix new file mode 100644 index 000000000000..671e701cd195 --- /dev/null +++ b/nixos/modules/programs/rust-motd.nix @@ -0,0 +1,92 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.rust-motd; + format = pkgs.formats.toml { }; +in { + options.programs.rust-motd = { + enable = mkEnableOption "rust-motd"; + enableMotdInSSHD = mkOption { + default = true; + type = types.bool; + description = mdDoc '' + Whether to let `openssh` print the + result when entering a new `ssh`-session. + By default either nothing or a static file defined via + [](#opt-users.motd) is printed. Because of that, + the latter option is incompatible with this module. + ''; + }; + refreshInterval = mkOption { + default = "*:0/5"; + type = types.str; + description = mdDoc '' + Interval in which the {manpage}`motd(5)` file is refreshed. + For possible formats, please refer to {manpage}`systemd.time(7)`. + ''; + }; + settings = mkOption { + type = types.submodule { + freeformType = format.type; + }; + description = mdDoc '' + Settings on what to generate. Please read the + [upstream documentation](https://github.com/rust-motd/rust-motd/blob/main/README.md#configuration) + for further information. + ''; + }; + }; + config = mkIf cfg.enable { + assertions = [ + { assertion = config.users.motd == null; + message = '' + `programs.rust-motd` is incompatible with `users.motd`! + ''; + } + ]; + systemd.services.rust-motd = { + path = with pkgs; [ bash ]; + documentation = [ "https://github.com/rust-motd/rust-motd/blob/v${pkgs.rust-motd.version}/README.md" ]; + description = "motd generator"; + serviceConfig = { + ExecStart = "${pkgs.writeShellScript "update-motd" '' + ${pkgs.rust-motd}/bin/rust-motd ${format.generate "motd.conf" cfg.settings} > motd + ''}"; + CapabilityBoundingSet = [ "" ]; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectKernelTunables = true; + ProtectSystem = "full"; + StateDirectory = "rust-motd"; + RestrictAddressFamilies = "none"; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + RemoveIPC = true; + WorkingDirectory = "/var/lib/rust-motd"; + }; + }; + systemd.timers.rust-motd = { + wantedBy = [ "timers.target" ]; + timerConfig.OnCalendar = cfg.refreshInterval; + }; + security.pam.services.sshd.text = mkIf cfg.enableMotdInSSHD (mkDefault (mkAfter '' + session optional ${pkgs.pam}/lib/security/pam_motd.so motd=/var/lib/rust-motd/motd + '')); + services.openssh.extraConfig = mkIf (cfg.settings ? last_login && cfg.settings.last_login != {}) '' + PrintLastLog no + ''; + }; + meta.maintainers = with maintainers; [ ma27 ]; +} diff --git a/nixos/modules/services/cluster/k3s/default.nix b/nixos/modules/services/cluster/k3s/default.nix index 0876f4ad955d..693f388de14a 100644 --- a/nixos/modules/services/cluster/k3s/default.nix +++ b/nixos/modules/services/cluster/k3s/default.nix @@ -25,7 +25,17 @@ in role = mkOption { description = lib.mdDoc '' Whether k3s should run as a server or agent. - Note that the server, by default, also runs as an agent. + + If it's a server: + + - By default it also runs workloads as an agent. + - Starts by default as a standalone server using an embedded sqlite datastore. + - Configure `clusterInit = true` to switch over to embedded etcd datastore and enable HA mode. + - Configure `serverAddr` to join an already-initialized HA cluster. + + If it's an agent: + + - `serverAddr` is required. ''; default = "server"; type = types.enum [ "server" "agent" ]; @@ -33,15 +43,44 @@ in serverAddr = mkOption { type = types.str; - description = lib.mdDoc "The k3s server to connect to. This option only makes sense for an agent."; + description = lib.mdDoc '' + The k3s server to connect to. + + Servers and agents need to communicate each other. Read + [the networking docs](https://rancher.com/docs/k3s/latest/en/installation/installation-requirements/#networking) + to know how to configure the firewall. + ''; example = "https://10.0.0.10:6443"; default = ""; }; + clusterInit = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Initialize HA cluster using an embedded etcd datastore. + + If this option is `false` and `role` is `server` + + On a server that was using the default embedded sqlite backend, + enabling this option will migrate to an embedded etcd DB. + + If an HA cluster using the embedded etcd datastore was already initialized, + this option has no effect. + + This option only makes sense in a server that is not connecting to another server. + + If you are configuring an HA cluster with an embedded etcd, + the 1st server must have `clusterInit = true` + and other servers must connect to it using `serverAddr`. + ''; + }; + token = mkOption { type = types.str; description = lib.mdDoc '' - The k3s token to use when connecting to the server. This option only makes sense for an agent. + The k3s token to use when connecting to a server. + WARNING: This option will expose store your token unencrypted world-readable in the nix store. If this is undesired use the tokenFile option instead. ''; @@ -50,7 +89,7 @@ in tokenFile = mkOption { type = types.nullOr types.path; - description = lib.mdDoc "File path containing k3s token to use when connecting to the server. This option only makes sense for an agent."; + description = lib.mdDoc "File path containing k3s token to use when connecting to the server."; default = null; }; @@ -86,6 +125,14 @@ in assertion = cfg.role == "agent" -> cfg.configPath != null || cfg.tokenFile != null || cfg.token != ""; message = "token or tokenFile or configPath (with 'token' or 'token-file' keys) should be set if role is 'agent'"; } + { + assertion = cfg.role == "agent" -> !cfg.disableAgent; + message = "disableAgent must be false if role is 'agent'"; + } + { + assertion = cfg.role == "agent" -> !cfg.clusterInit; + message = "clusterInit must be false if role is 'agent'"; + } ]; environment.systemPackages = [ config.services.k3s.package ]; @@ -111,6 +158,7 @@ in [ "${cfg.package}/bin/k3s ${cfg.role}" ] + ++ (optional cfg.clusterInit "--cluster-init") ++ (optional cfg.disableAgent "--disable-agent") ++ (optional (cfg.serverAddr != "") "--server ${cfg.serverAddr}") ++ (optional (cfg.token != "") "--token ${cfg.token}") diff --git a/nixos/modules/services/networking/kea.nix b/nixos/modules/services/networking/kea.nix index 8a98c0ceafc6..f39b149dd609 100644 --- a/nixos/modules/services/networking/kea.nix +++ b/nixos/modules/services/networking/kea.nix @@ -298,7 +298,7 @@ in ]; serviceConfig = { - ExecStart = "${package}/bin/kea-ctrl-agent -c /etc/kea/ctrl-agent.conf ${lib.escapeShellArgs cfg.dhcp4.extraArgs}"; + ExecStart = "${package}/bin/kea-ctrl-agent -c /etc/kea/ctrl-agent.conf ${lib.escapeShellArgs cfg.ctrl-agent.extraArgs}"; KillMode = "process"; Restart = "on-failure"; } // commonServiceConfig; diff --git a/nixos/modules/services/networking/keepalived/default.nix b/nixos/modules/services/networking/keepalived/default.nix index 768c8e4b13c7..1ab25c879916 100644 --- a/nixos/modules/services/networking/keepalived/default.nix +++ b/nixos/modules/services/networking/keepalived/default.nix @@ -264,6 +264,19 @@ in ''; }; + secretFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/keys/keepalived.env"; + description = '' + Environment variables from this file will be interpolated into the + final config file using envsubst with this syntax: <literal>$ENVIRONMENT</literal> + or <literal>''${VARIABLE}</literal>. + The file should contain lines formatted as <literal>SECRET_VAR=SECRET_VALUE</literal>. + This is useful to avoid putting secrets into the nix store. + ''; + }; + }; }; @@ -282,7 +295,9 @@ in }; }; - systemd.services.keepalived = { + systemd.services.keepalived = let + finalConfigFile = if cfg.secretFile == null then keepalivedConf else "/run/keepalived/keepalived.conf"; + in { description = "Keepalive Daemon (LVS and VRRP)"; after = [ "network.target" "network-online.target" "syslog.target" ]; wants = [ "network-online.target" ]; @@ -290,8 +305,15 @@ in Type = "forking"; PIDFile = pidFile; KillMode = "process"; + RuntimeDirectory = "keepalived"; + EnvironmentFile = lib.optional (cfg.secretFile != null) cfg.secretFile; + ExecStartPre = lib.optional (cfg.secretFile != null) + (pkgs.writeShellScript "keepalived-pre-start" '' + umask 077 + ${pkgs.envsubst}/bin/envsubst -i "${keepalivedConf}" > ${finalConfigFile} + ''); ExecStart = "${pkgs.keepalived}/sbin/keepalived" - + " -f ${keepalivedConf}" + + " -f ${finalConfigFile}" + " -p ${pidFile}" + optionalString cfg.snmp.enable " --snmp"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; diff --git a/nixos/modules/services/networking/searx.nix b/nixos/modules/services/networking/searx.nix index e594d0083d4f..214b6c6a787a 100644 --- a/nixos/modules/services/networking/searx.nix +++ b/nixos/modules/services/networking/searx.nix @@ -192,7 +192,10 @@ in ExecStart = "${cfg.package}/bin/searx-run"; } // optionalAttrs (cfg.environmentFile != null) { EnvironmentFile = builtins.toPath cfg.environmentFile; }; - environment.SEARX_SETTINGS_PATH = cfg.settingsFile; + environment = { + SEARX_SETTINGS_PATH = cfg.settingsFile; + SEARXNG_SETTINGS_PATH = cfg.settingsFile; + }; }; systemd.services.uwsgi = mkIf (cfg.runInUwsgi) diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix index 26641618fb43..0b6b4bf9e5c7 100644 --- a/nixos/modules/services/networking/syncthing.nix +++ b/nixos/modules/services/networking/syncthing.nix @@ -268,10 +268,10 @@ in { { versioning = { type = "staggered"; + fsPath = "/syncthing/backup"; params = { cleanInterval = "3600"; maxAge = "31536000"; - versionsPath = "/syncthing/backup"; }; }; } @@ -296,6 +296,14 @@ in { See <https://docs.syncthing.net/users/versioning.html>. ''; }; + fsPath = mkOption { + default = ""; + type = either str path; + description = mdDoc '' + Path to the versioning folder. + See <https://docs.syncthing.net/users/versioning.html>. + ''; + }; params = mkOption { type = attrsOf (either str path); description = mdDoc '' diff --git a/nixos/modules/services/security/vaultwarden/default.nix b/nixos/modules/services/security/vaultwarden/default.nix index 0df0e5d211bb..7e4863dd871e 100644 --- a/nixos/modules/services/security/vaultwarden/default.nix +++ b/nixos/modules/services/security/vaultwarden/default.nix @@ -196,6 +196,7 @@ in { ProtectSystem = "strict"; AmbientCapabilities = "CAP_NET_BIND_SERVICE"; StateDirectory = "bitwarden_rs"; + StateDirectoryMode = "0700"; }; wantedBy = [ "multi-user.target" ]; }; diff --git a/nixos/modules/services/web-apps/keycloak.nix b/nixos/modules/services/web-apps/keycloak.nix index 301efe7e5d94..da53d4ea76f4 100644 --- a/nixos/modules/services/web-apps/keycloak.nix +++ b/nixos/modules/services/web-apps/keycloak.nix @@ -25,6 +25,7 @@ let catAttrs collect splitString + hasPrefix ; inherit (builtins) @@ -312,8 +313,9 @@ in http-relative-path = mkOption { type = str; - default = ""; + default = "/"; example = "/auth"; + apply = x: if !(hasPrefix "/") x then "/" + x else x; description = lib.mdDoc '' The path relative to `/` for serving resources. @@ -636,7 +638,7 @@ in '' + '' export KEYCLOAK_ADMIN=admin export KEYCLOAK_ADMIN_PASSWORD=${cfg.initialAdminPassword} - kc.sh start + kc.sh start --optimized ''; }; diff --git a/nixos/modules/services/web-apps/writefreely.nix b/nixos/modules/services/web-apps/writefreely.nix new file mode 100644 index 000000000000..c363760d5c2d --- /dev/null +++ b/nixos/modules/services/web-apps/writefreely.nix @@ -0,0 +1,485 @@ +{ config, lib, pkgs, ... }: + +let + inherit (builtins) toString; + inherit (lib) types mkIf mkOption mkDefault; + inherit (lib) optional optionals optionalAttrs optionalString; + + inherit (pkgs) sqlite; + + format = pkgs.formats.ini { + mkKeyValue = key: value: + let + value' = if builtins.isNull value then + "" + else if builtins.isBool value then + if value == true then "true" else "false" + else + toString value; + in "${key} = ${value'}"; + }; + + cfg = config.services.writefreely; + + isSqlite = cfg.database.type == "sqlite3"; + isMysql = cfg.database.type == "mysql"; + isMysqlLocal = isMysql && cfg.database.createLocally == true; + + hostProtocol = if cfg.acme.enable then "https" else "http"; + + settings = cfg.settings // { + app = cfg.settings.app or { } // { + host = cfg.settings.app.host or "${hostProtocol}://${cfg.host}"; + }; + + database = if cfg.database.type == "sqlite3" then { + type = "sqlite3"; + filename = cfg.settings.database.filename or "writefreely.db"; + database = cfg.database.name; + } else { + type = "mysql"; + username = cfg.database.user; + password = "#dbpass#"; + database = cfg.database.name; + host = cfg.database.host; + port = cfg.database.port; + tls = cfg.database.tls; + }; + + server = cfg.settings.server or { } // { + bind = cfg.settings.server.bind or "localhost"; + gopher_port = cfg.settings.server.gopher_port or 0; + autocert = !cfg.nginx.enable && cfg.acme.enable; + templates_parent_dir = + cfg.settings.server.templates_parent_dir or cfg.package.src; + static_parent_dir = cfg.settings.server.static_parent_dir or assets; + pages_parent_dir = + cfg.settings.server.pages_parent_dir or cfg.package.src; + keys_parent_dir = cfg.settings.server.keys_parent_dir or cfg.stateDir; + }; + }; + + configFile = format.generate "config.ini" settings; + + assets = pkgs.stdenvNoCC.mkDerivation { + pname = "writefreely-assets"; + + inherit (cfg.package) version src; + + nativeBuildInputs = with pkgs.nodePackages; [ less ]; + + buildPhase = '' + mkdir -p $out + + cp -r static $out/ + ''; + + installPhase = '' + less_dir=$src/less + css_dir=$out/static/css + + lessc $less_dir/app.less $css_dir/write.css + lessc $less_dir/fonts.less $css_dir/fonts.css + lessc $less_dir/icons.less $css_dir/icons.css + lessc $less_dir/prose.less $css_dir/prose.css + ''; + }; + + withConfigFile = text: '' + db_pass=${ + optionalString (cfg.database.passwordFile != null) + "$(head -n1 ${cfg.database.passwordFile})" + } + + cp -f ${configFile} '${cfg.stateDir}/config.ini' + sed -e "s,#dbpass#,$db_pass,g" -i '${cfg.stateDir}/config.ini' + chmod 440 '${cfg.stateDir}/config.ini' + + ${text} + ''; + + withMysql = text: + withConfigFile '' + query () { + local result=$(${config.services.mysql.package}/bin/mysql \ + --user=${cfg.database.user} \ + --password=$db_pass \ + --database=${cfg.database.name} \ + --silent \ + --raw \ + --skip-column-names \ + --execute "$1" \ + ) + + echo $result + } + + ${text} + ''; + + withSqlite = text: + withConfigFile '' + query () { + local result=$(${sqlite}/bin/sqlite3 \ + '${cfg.stateDir}/${settings.database.filename}' + "$1" \ + ) + + echo $result + } + + ${text} + ''; +in { + options.services.writefreely = { + enable = + lib.mkEnableOption "Writefreely, build a digital writing community"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.writefreely; + defaultText = lib.literalExpression "pkgs.writefreely"; + description = "Writefreely package to use."; + }; + + stateDir = mkOption { + type = types.path; + default = "/var/lib/writefreely"; + description = "The state directory where keys and data are stored."; + }; + + user = mkOption { + type = types.str; + default = "writefreely"; + description = "User under which Writefreely is ran."; + }; + + group = mkOption { + type = types.str; + default = "writefreely"; + description = "Group under which Writefreely is ran."; + }; + + host = mkOption { + type = types.str; + default = ""; + description = "The public host name to serve."; + example = "example.com"; + }; + + settings = mkOption { + default = { }; + description = '' + Writefreely configuration (<filename>config.ini</filename>). Refer to + <link xlink:href="https://writefreely.org/docs/latest/admin/config" /> + for details. + ''; + + type = types.submodule { + freeformType = format.type; + + options = { + app = { + theme = mkOption { + type = types.str; + default = "write"; + description = "The theme to apply."; + }; + }; + + server = { + port = mkOption { + type = types.port; + default = if cfg.nginx.enable then 18080 else 80; + defaultText = "80"; + description = "The port WriteFreely should listen on."; + }; + }; + }; + }; + }; + + database = { + type = mkOption { + type = types.enum [ "sqlite3" "mysql" ]; + default = "sqlite3"; + description = "The database provider to use."; + }; + + name = mkOption { + type = types.str; + default = "writefreely"; + description = "The name of the database to store data in."; + }; + + user = mkOption { + type = types.nullOr types.str; + default = if cfg.database.type == "mysql" then "writefreely" else null; + defaultText = "writefreely"; + description = "The database user to connect as."; + }; + + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + description = "The file to load the database password from."; + }; + + host = mkOption { + type = types.str; + default = "localhost"; + description = "The database host to connect to."; + }; + + port = mkOption { + type = types.port; + default = 3306; + description = "The port used when connecting to the database host."; + }; + + tls = mkOption { + type = types.bool; + default = false; + description = + "Whether or not TLS should be used for the database connection."; + }; + + migrate = mkOption { + type = types.bool; + default = true; + description = + "Whether or not to automatically run migrations on startup."; + }; + + createLocally = mkOption { + type = types.bool; + default = false; + description = '' + When <option>services.writefreely.database.type</option> is set to + <code>"mysql"</code>, this option will enable the MySQL service locally. + ''; + }; + }; + + admin = { + name = mkOption { + type = types.nullOr types.str; + description = "The name of the first admin user."; + default = null; + }; + + initialPasswordFile = mkOption { + type = types.path; + description = '' + Path to a file containing the initial password for the admin user. + If not provided, the default password will be set to <code>nixos</code>. + ''; + default = pkgs.writeText "default-admin-pass" "nixos"; + defaultText = "/nix/store/xxx-default-admin-pass"; + }; + }; + + nginx = { + enable = mkOption { + type = types.bool; + default = false; + description = + "Whether or not to enable and configure nginx as a proxy for WriteFreely."; + }; + + forceSSL = mkOption { + type = types.bool; + default = false; + description = "Whether or not to force the use of SSL."; + }; + }; + + acme = { + enable = mkOption { + type = types.bool; + default = false; + description = + "Whether or not to automatically fetch and configure SSL certs."; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = cfg.host != ""; + message = "services.writefreely.host must be set"; + } + { + assertion = isMysqlLocal -> cfg.database.passwordFile != null; + message = + "services.writefreely.database.passwordFile must be set if services.writefreely.database.createLocally is set to true"; + } + { + assertion = isSqlite -> !cfg.database.createLocally; + message = + "services.writefreely.database.createLocally has no use when services.writefreely.database.type is set to sqlite3"; + } + ]; + + users = { + users = optionalAttrs (cfg.user == "writefreely") { + writefreely = { + group = cfg.group; + home = cfg.stateDir; + isSystemUser = true; + }; + }; + + groups = + optionalAttrs (cfg.group == "writefreely") { writefreely = { }; }; + }; + + systemd.tmpfiles.rules = + [ "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -" ]; + + systemd.services.writefreely = { + after = [ "network.target" ] + ++ optional isSqlite "writefreely-sqlite-init.service" + ++ optional isMysql "writefreely-mysql-init.service" + ++ optional isMysqlLocal "mysql.service"; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + Type = "simple"; + User = cfg.user; + Group = cfg.group; + WorkingDirectory = cfg.stateDir; + Restart = "always"; + RestartSec = 20; + ExecStart = + "${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' serve"; + AmbientCapabilities = + optionalString (settings.server.port < 1024) "cap_net_bind_service"; + }; + + preStart = '' + if ! test -d "${cfg.stateDir}/keys"; then + mkdir -p ${cfg.stateDir}/keys + + # Key files end up with the wrong permissions by default. + # We need to correct them so that Writefreely can read them. + chmod -R 750 "${cfg.stateDir}/keys" + + ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' keys generate + fi + ''; + }; + + systemd.services.writefreely-sqlite-init = mkIf isSqlite { + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + Type = "oneshot"; + User = cfg.user; + Group = cfg.group; + WorkingDirectory = cfg.stateDir; + ReadOnlyPaths = optional (cfg.admin.initialPasswordFile != null) + cfg.admin.initialPasswordFile; + }; + + script = let + migrateDatabase = optionalString cfg.database.migrate '' + ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db migrate + ''; + + createAdmin = optionalString (cfg.admin.name != null) '' + if [[ $(query "SELECT COUNT(*) FROM users") == 0 ]]; then + admin_pass=$(head -n1 ${cfg.admin.initialPasswordFile}) + + ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' --create-admin ${cfg.admin.name}:$admin_pass + fi + ''; + in withSqlite '' + if ! test -f '${settings.database.filename}'; then + ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db init + fi + + ${migrateDatabase} + + ${createAdmin} + ''; + }; + + systemd.services.writefreely-mysql-init = mkIf isMysql { + wantedBy = [ "multi-user.target" ]; + after = optional isMysqlLocal "mysql.service"; + + serviceConfig = { + Type = "oneshot"; + User = cfg.user; + Group = cfg.group; + WorkingDirectory = cfg.stateDir; + ReadOnlyPaths = optional isMysqlLocal cfg.database.passwordFile + ++ optional (cfg.admin.initialPasswordFile != null) + cfg.admin.initialPasswordFile; + }; + + script = let + updateUser = optionalString isMysqlLocal '' + # WriteFreely currently *requires* a password for authentication, so we + # need to update the user in MySQL accordingly. By default MySQL users + # authenticate with auth_socket or unix_socket. + # See: https://github.com/writefreely/writefreely/issues/568 + ${config.services.mysql.package}/bin/mysql --skip-column-names --execute "ALTER USER '${cfg.database.user}'@'localhost' IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('$db_pass'); FLUSH PRIVILEGES;" + ''; + + migrateDatabase = optionalString cfg.database.migrate '' + ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db migrate + ''; + + createAdmin = optionalString (cfg.admin.name != null) '' + if [[ $(query 'SELECT COUNT(*) FROM users') == 0 ]]; then + admin_pass=$(head -n1 ${cfg.admin.initialPasswordFile}) + ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' --create-admin ${cfg.admin.name}:$admin_pass + fi + ''; + in withMysql '' + ${updateUser} + + if [[ $(query "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '${cfg.database.name}'") == 0 ]]; then + ${cfg.package}/bin/writefreely -c '${cfg.stateDir}/config.ini' db init + fi + + ${migrateDatabase} + + ${createAdmin} + ''; + }; + + services.mysql = mkIf isMysqlLocal { + enable = true; + package = mkDefault pkgs.mariadb; + ensureDatabases = [ cfg.database.name ]; + ensureUsers = [{ + name = cfg.database.user; + ensurePermissions = { + "${cfg.database.name}.*" = "ALL PRIVILEGES"; + # WriteFreely requires the use of passwords, so we need permissions + # to `ALTER` the user to add password support and also to reload + # permissions so they can be used. + "*.*" = "CREATE USER, RELOAD"; + }; + }]; + }; + + services.nginx = lib.mkIf cfg.nginx.enable { + enable = true; + recommendedProxySettings = true; + + virtualHosts."${cfg.host}" = { + enableACME = cfg.acme.enable; + forceSSL = cfg.nginx.forceSSL; + + locations."/" = { + proxyPass = "http://127.0.0.1:${toString settings.server.port}"; + }; + }; + }; + }; +} diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix index 1d557fb5f33d..b0508c3b4f79 100644 --- a/nixos/modules/services/x11/display-managers/lightdm.nix +++ b/nixos/modules/services/x11/display-managers/lightdm.nix @@ -311,7 +311,6 @@ in home = "/var/lib/lightdm"; group = "lightdm"; uid = config.ids.uids.lightdm; - shell = pkgs.bash; }; systemd.tmpfiles.rules = [ diff --git a/nixos/modules/services/x11/window-managers/awesome.nix b/nixos/modules/services/x11/window-managers/awesome.nix index 5bb74fd15910..c1231d3fbf38 100644 --- a/nixos/modules/services/x11/window-managers/awesome.nix +++ b/nixos/modules/services/x11/window-managers/awesome.nix @@ -6,7 +6,7 @@ let cfg = config.services.xserver.windowManager.awesome; awesome = cfg.package; - getLuaPath = lib : dir : "${lib}/${dir}/lua/${pkgs.luaPackages.lua.luaversion}"; + getLuaPath = lib: dir: "${lib}/${dir}/lua/${awesome.lua.luaversion}"; makeSearchPath = lib.concatMapStrings (path: " --search " + (getLuaPath path "share") + " --search " + (getLuaPath path "lib") diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py index 77280a9680e3..5398ef6b84eb 100644 --- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py +++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py @@ -240,11 +240,11 @@ def main() -> None: if "@graceful@" == "1": flags.append("--graceful") - subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@"] + flags + ["install"]) + subprocess.check_call(["@systemd@/bin/bootctl", "--esp-path=@efiSysMountPoint@"] + flags + ["install"]) else: # Update bootloader to latest if needed available_out = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[2] - installed_out = subprocess.check_output(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True) + installed_out = subprocess.check_output(["@systemd@/bin/bootctl", "--esp-path=@efiSysMountPoint@", "status"], universal_newlines=True) # See status_binaries() in systemd bootctl.c for code which generates this installed_match = re.search(r"^\W+File:.*/EFI/(?:BOOT|systemd)/.*\.efi \(systemd-boot ([\d.]+[^)]*)\)$", @@ -263,7 +263,7 @@ def main() -> None: if installed_version < available_version: print("updating systemd-boot from %s to %s" % (installed_version, available_version)) - subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "update"]) + subprocess.check_call(["@systemd@/bin/bootctl", "--esp-path=@efiSysMountPoint@", "update"]) mkdir_p("@efiSysMountPoint@/efi/nixos") mkdir_p("@efiSysMountPoint@/loader/entries") diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index a0b433889d66..0b38a94c25fd 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -879,6 +879,15 @@ let (assertValueOneOf "OnLink" boolValues) ]; + sectionIPv6RoutePrefix = checkUnitConfig "IPv6RoutePrefix" [ + (assertOnlyFields [ + "Route" + "LifetimeSec" + ]) + (assertHasField "Route") + (assertInt "LifetimeSec") + ]; + sectionDHCPServerStaticLease = checkUnitConfig "DHCPServerStaticLease" [ (assertOnlyFields [ "MACAddress" @@ -1242,6 +1251,22 @@ let }; }; + ipv6RoutePrefixOptions = { + options = { + ipv6RoutePrefixConfig = mkOption { + default = {}; + example = { Route = "fd00::/64"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6RoutePrefix; + description = '' + Each attribute in this set specifies an option in the + <literal>[IPv6RoutePrefix]</literal> section of the unit. See + <citerefentry><refentrytitle>systemd.network</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + ''; + }; + }; + }; + dhcpServerStaticLeaseOptions = { options = { dhcpServerStaticLeaseConfig = mkOption { @@ -1384,6 +1409,17 @@ let ''; }; + ipv6RoutePrefixes = mkOption { + default = []; + example = [ { Route = "fd00::/64"; LifetimeSec = 3600; } ]; + type = with types; listOf (submodule ipv6RoutePrefixOptions); + description = '' + A list of ipv6RoutePrefix sections to be added to the unit. See + <citerefentry><refentrytitle>systemd.network</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + ''; + }; + name = mkOption { type = types.nullOr types.str; default = null; @@ -1775,6 +1811,10 @@ let [IPv6Prefix] ${attrsToSection x.ipv6PrefixConfig} '') + + flip concatMapStrings def.ipv6RoutePrefixes (x: '' + [IPv6RoutePrefix] + ${attrsToSection x.ipv6RoutePrefixConfig} + '') + flip concatMapStrings def.dhcpServerStaticLeases (x: '' [DHCPServerStaticLease] ${attrsToSection x.dhcpServerStaticLeaseConfig} diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index 956844352f9a..fb9c19d79c13 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -11,20 +11,6 @@ in maintainers = [ ] ++ lib.teams.podman.members; }; - - imports = [ - ( - lib.mkRemovedOptionModule - [ "virtualisation" "containers" "users" ] - "All users with `isNormalUser = true` set now get appropriate subuid/subgid mappings." - ) - ( - lib.mkRemovedOptionModule - [ "virtualisation" "containers" "containersConf" "extraConfig" ] - "Use virtualisation.containers.containersConf.settings instead." - ) - ]; - options.virtualisation.containers = { enable = diff --git a/nixos/modules/virtualisation/cri-o.nix b/nixos/modules/virtualisation/cri-o.nix index 89aa60fbd791..95ce1fea58bb 100644 --- a/nixos/modules/virtualisation/cri-o.nix +++ b/nixos/modules/virtualisation/cri-o.nix @@ -11,10 +11,6 @@ let cfgFile = format.generate "00-default.conf" cfg.settings; in { - imports = [ - (mkRenamedOptionModule [ "virtualisation" "cri-o" "registries" ] [ "virtualisation" "containers" "registries" "search" ]) - ]; - meta = { maintainers = teams.podman.members; }; diff --git a/nixos/modules/virtualisation/podman/default.nix b/nixos/modules/virtualisation/podman/default.nix index 376555ed2015..118bf82cdd66 100644 --- a/nixos/modules/virtualisation/podman/default.nix +++ b/nixos/modules/virtualisation/podman/default.nix @@ -46,7 +46,6 @@ in imports = [ ./dnsname.nix ./network-socket.nix - (lib.mkRenamedOptionModule [ "virtualisation" "podman" "libpod" ] [ "virtualisation" "containers" "containersConf" ]) ]; meta = { diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index 7d9ec5875803..0207bfba82ad 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -102,7 +102,9 @@ let # Shell script to start the VM. startVM = '' - #! ${pkgs.runtimeShell} + #! ${cfg.host.pkgs.runtimeShell} + + export PATH=${makeBinPath [ cfg.host.pkgs.coreutils ]}''${PATH:+:}$PATH set -e @@ -575,11 +577,24 @@ in description = lib.mdDoc "Primary IP address used in /etc/hosts."; }; + virtualisation.host.pkgs = mkOption { + type = options.nixpkgs.pkgs.type; + default = pkgs; + defaultText = "pkgs"; + example = literalExpression '' + import pkgs.path { system = "x86_64-darwin"; } + ''; + description = '' + pkgs set to use for the host-specific packages of the vm runner. + Changing this to e.g. a Darwin package set allows running NixOS VMs on Darwin. + ''; + }; + virtualisation.qemu = { package = mkOption { type = types.package; - default = pkgs.qemu_kvm; + default = cfg.host.pkgs.qemu_kvm; example = "pkgs.qemu_test"; description = lib.mdDoc "QEMU package to use."; }; @@ -1076,14 +1091,14 @@ in services.qemuGuest.enable = cfg.qemu.guestAgent.enable; - system.build.vm = pkgs.runCommand "nixos-vm" { + system.build.vm = cfg.host.pkgs.runCommand "nixos-vm" { preferLocalBuild = true; meta.mainProgram = "run-${config.system.name}-vm"; } '' mkdir -p $out/bin ln -s ${config.system.build.toplevel} $out/system - ln -s ${pkgs.writeScript "run-nixos-vm" startVM} $out/bin/run-${config.system.name}-vm + ln -s ${cfg.host.pkgs.writeScript "run-nixos-vm" startVM} $out/bin/run-${config.system.name}-vm ''; # When building a regular system configuration, override whatever diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 7e1ba8f5ed91..1cf310cb3321 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -621,6 +621,7 @@ in { wmderland = handleTest ./wmderland.nix {}; wpa_supplicant = handleTest ./wpa_supplicant.nix {}; wordpress = handleTest ./wordpress.nix {}; + writefreely = handleTest ./web-apps/writefreely.nix {}; xandikos = handleTest ./xandikos.nix {}; xautolock = handleTest ./xautolock.nix {}; xfce = handleTest ./xfce.nix {}; diff --git a/nixos/tests/k3s/multi-node.nix b/nixos/tests/k3s/multi-node.nix index afb8c78f2339..ae9609fbccc9 100644 --- a/nixos/tests/k3s/multi-node.nix +++ b/nixos/tests/k3s/multi-node.nix @@ -53,9 +53,10 @@ import ../make-test-python.nix ({ pkgs, ... }: enable = true; role = "server"; package = pkgs.k3s; + clusterInit = true; extraFlags = "--no-deploy coredns,servicelb,traefik,local-storage,metrics-server --pause-image test.local/pause:local --node-ip 192.168.1.1"; }; - networking.firewall.allowedTCPPorts = [ 6443 ]; + networking.firewall.allowedTCPPorts = [ 2379 2380 6443 ]; networking.firewall.allowedUDPPorts = [ 8472 ]; networking.firewall.trustedInterfaces = [ "flannel.1" ]; networking.useDHCP = false; @@ -65,6 +66,28 @@ import ../make-test-python.nix ({ pkgs, ... }: ]; }; + server2 = { pkgs, ... }: { + environment.systemPackages = with pkgs; [ gzip jq ]; + virtualisation.memorySize = 1536; + virtualisation.diskSize = 4096; + + services.k3s = { + inherit tokenFile; + enable = true; + serverAddr = "https://192.168.1.1:6443"; + clusterInit = false; + extraFlags = "--no-deploy coredns,servicelb,traefik,local-storage,metrics-server --pause-image test.local/pause:local --node-ip 192.168.1.3"; + }; + networking.firewall.allowedTCPPorts = [ 2379 2380 6443 ]; + networking.firewall.allowedUDPPorts = [ 8472 ]; + networking.firewall.trustedInterfaces = [ "flannel.1" ]; + networking.useDHCP = false; + networking.defaultGateway = "192.168.1.3"; + networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [ + { address = "192.168.1.3"; prefixLength = 24; } + ]; + }; + agent = { pkgs, ... }: { virtualisation.memorySize = 1024; virtualisation.diskSize = 2048; @@ -72,7 +95,7 @@ import ../make-test-python.nix ({ pkgs, ... }: inherit tokenFile; enable = true; role = "agent"; - serverAddr = "https://192.168.1.1:6443"; + serverAddr = "https://192.168.1.3:6443"; extraFlags = "--pause-image test.local/pause:local --node-ip 192.168.1.2"; }; networking.firewall.allowedTCPPorts = [ 6443 ]; @@ -91,9 +114,9 @@ import ../make-test-python.nix ({ pkgs, ... }: }; testScript = '' - start_all() - machines = [server, agent] + machines = [server, server2, agent] for m in machines: + m.start() m.wait_for_unit("k3s") # wait for the agent to show up diff --git a/nixos/tests/web-apps/writefreely.nix b/nixos/tests/web-apps/writefreely.nix new file mode 100644 index 000000000000..ce614909706b --- /dev/null +++ b/nixos/tests/web-apps/writefreely.nix @@ -0,0 +1,44 @@ +{ system ? builtins.currentSystem, config ? { } +, pkgs ? import ../../.. { inherit system config; } }: + +with import ../../lib/testing-python.nix { inherit system pkgs; }; +with pkgs.lib; + +let + writefreelyTest = { name, type }: + makeTest { + name = "writefreely-${name}"; + + nodes.machine = { config, pkgs, ... }: { + services.writefreely = { + enable = true; + host = "localhost:3000"; + admin.name = "nixos"; + + database = { + inherit type; + createLocally = type == "mysql"; + passwordFile = pkgs.writeText "db-pass" "pass"; + }; + + settings.server.port = 3000; + }; + }; + + testScript = '' + start_all() + machine.wait_for_unit("writefreely.service") + machine.wait_for_open_port(3000) + machine.succeed("curl --fail http://localhost:3000") + ''; + }; +in { + sqlite = writefreelyTest { + name = "sqlite"; + type = "sqlite3"; + }; + mysql = writefreelyTest { + name = "mysql"; + type = "mysql"; + }; +} |