feat(nix-patches): Switch to upstream version

This commit is contained in:
Tom Hubrecht 2023-09-24 13:03:23 +02:00
parent ed883a7bcc
commit eb329666ce
9 changed files with 92 additions and 7831 deletions

View file

@ -25,11 +25,16 @@ let
}; };
mkNixpkgs = node: mkNixpkgs = node:
let version = "nixos-${metadata.nodes.${node}.nixpkgs}"; in let
(import sources.${version} { }).applyPatches { version = "nixos-${metadata.nodes.${node}.nixpkgs}";
pkgs = import sources.${version} { };
in pkgs.applyPatches {
name = "${version}-patched"; name = "${version}-patched";
src = sources.${version}; src = sources.${version};
patches = (import ./nix-patches).${version} or [ ]; patches = (import sources.nix-patches {
inherit pkgs;
patchFile = ./patches;
}).mkPatches version;
}; };
mkNixpkgs' = node: import (mkNixpkgs node) { }; mkNixpkgs' = node: import (mkNixpkgs node) { };

View file

@ -1,31 +0,0 @@
From d7e721f614aef3e6bd7f4dfb6c1526e00d257fad Mon Sep 17 00:00:00 2001
From: Raito Bezarius <masterancpp@gmail.com>
Date: Sun, 2 Jul 2023 17:03:53 +0200
Subject: [PATCH] plausible: fix admin user password seed and SMTP passwords
LoadCredential was misused as it is not building any environment variable,
it is the responsibility of our preStart to do it so
Plausible's script can pick it up.
---
nixos/modules/services/web-apps/plausible.nix | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/nixos/modules/services/web-apps/plausible.nix b/nixos/modules/services/web-apps/plausible.nix
index 893dfa10acbc0..911daa53e6587 100644
--- a/nixos/modules/services/web-apps/plausible.nix
+++ b/nixos/modules/services/web-apps/plausible.nix
@@ -238,9 +238,12 @@ in {
path = [ cfg.package ]
++ optional cfg.database.postgres.setup config.services.postgresql.package;
script = ''
- export CONFIG_DIR=$CREDENTIALS_DIRECTORY
-
export RELEASE_COOKIE="$(< $CREDENTIALS_DIRECTORY/RELEASE_COOKIE )"
+ export ADMIN_USER_PWD="$(< $CREDENTIALS_DIRECTORY/ADMIN_USER_PWD )"
+ export SECRET_KEY_BASE="$(< $CREDENTIALS_DIRECTORY/SECRET_KEY_BASE )"
+
+ ${lib.optionalString (cfg.mail.smtp.passwordFile != null)
+ ''export SMTP_USER_PWD="$(< $CREDENTIALS_DIRECTORY/SMTP_USER_PWD )"''}
# setup
${cfg.package}/createdb.sh

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,914 +0,0 @@
From 8d374cebcd8736d19c289e6d1166ab0b7428adc7 Mon Sep 17 00:00:00 2001
From: emilylange <git@emilylange.de>
Date: Sun, 6 Aug 2023 18:40:02 +0200
Subject: [PATCH 1/3] nixos/forgejo: init
Following a decicion from both the gitea and forgejo maintainers in
nixpkgs.
This means, that forgejo will no longer co-use the nixos/gitea module
via `services.gitea.package = pkgs.forgejo`.
---
nixos/modules/module-list.nix | 1 +
nixos/modules/services/misc/forgejo.nix | 668 ++++++++++++++++++++++++
2 files changed, 669 insertions(+)
create mode 100644 nixos/modules/services/misc/forgejo.nix
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 29fcabaefad51e..6ea859b201e475 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -640,6 +640,7 @@
./services/misc/etesync-dav.nix
./services/misc/evdevremapkeys.nix
./services/misc/felix.nix
+ ./services/misc/forgejo.nix
./services/misc/freeswitch.nix
./services/misc/fstrim.nix
./services/misc/gammu-smsd.nix
diff --git a/nixos/modules/services/misc/forgejo.nix b/nixos/modules/services/misc/forgejo.nix
new file mode 100644
index 00000000000000..f26658b7bcb440
--- /dev/null
+++ b/nixos/modules/services/misc/forgejo.nix
@@ -0,0 +1,668 @@
+{ config, lib, options, pkgs, ... }:
+
+let
+ cfg = config.services.forgejo;
+ opt = options.services.forgejo;
+ format = pkgs.formats.ini { };
+
+ exe = lib.getExe cfg.package;
+
+ pg = config.services.postgresql;
+ useMysql = cfg.database.type == "mysql";
+ usePostgresql = cfg.database.type == "postgres";
+ useSqlite = cfg.database.type == "sqlite3";
+
+ inherit (lib)
+ literalExpression
+ mdDoc
+ mkChangedOptionModule
+ mkDefault
+ mkEnableOption
+ mkIf
+ mkMerge
+ mkOption
+ mkPackageOptionMD
+ mkRemovedOptionModule
+ mkRenamedOptionModule
+ optionalAttrs
+ optionals
+ optionalString
+ types
+ ;
+in
+{
+ imports = [
+ (mkRenamedOptionModule [ "services" "forgejo" "appName" ] [ "services" "forgejo" "settings" "DEFAULT" "APP_NAME" ])
+ (mkRemovedOptionModule [ "services" "forgejo" "extraConfig" ] "services.forgejo.extraConfig has been removed. Please use the freeform services.forgejo.settings option instead")
+ (mkRemovedOptionModule [ "services" "forgejo" "database" "password" ] "services.forgejo.database.password has been removed. Please use services.forgejo.database.passwordFile instead")
+
+ # copied from services.gitea; remove at some point
+ (mkRenamedOptionModule [ "services" "forgejo" "cookieSecure" ] [ "services" "forgejo" "settings" "session" "COOKIE_SECURE" ])
+ (mkRenamedOptionModule [ "services" "forgejo" "disableRegistration" ] [ "services" "forgejo" "settings" "service" "DISABLE_REGISTRATION" ])
+ (mkRenamedOptionModule [ "services" "forgejo" "domain" ] [ "services" "forgejo" "settings" "server" "DOMAIN" ])
+ (mkRenamedOptionModule [ "services" "forgejo" "httpAddress" ] [ "services" "forgejo" "settings" "server" "HTTP_ADDR" ])
+ (mkRenamedOptionModule [ "services" "forgejo" "httpPort" ] [ "services" "forgejo" "settings" "server" "HTTP_PORT" ])
+ (mkRenamedOptionModule [ "services" "forgejo" "log" "level" ] [ "services" "forgejo" "settings" "log" "LEVEL" ])
+ (mkRenamedOptionModule [ "services" "forgejo" "log" "rootPath" ] [ "services" "forgejo" "settings" "log" "ROOT_PATH" ])
+ (mkRenamedOptionModule [ "services" "forgejo" "rootUrl" ] [ "services" "forgejo" "settings" "server" "ROOT_URL" ])
+ (mkRenamedOptionModule [ "services" "forgejo" "ssh" "clonePort" ] [ "services" "forgejo" "settings" "server" "SSH_PORT" ])
+ (mkRenamedOptionModule [ "services" "forgejo" "staticRootPath" ] [ "services" "forgejo" "settings" "server" "STATIC_ROOT_PATH" ])
+ (mkChangedOptionModule [ "services" "forgejo" "enableUnixSocket" ] [ "services" "forgejo" "settings" "server" "PROTOCOL" ] (
+ config: if config.services.forgejo.enableUnixSocket then "http+unix" else "http"
+ ))
+ (mkRemovedOptionModule [ "services" "forgejo" "ssh" "enable" ] "services.forgejo.ssh.enable has been migrated into freeform setting services.forgejo.settings.server.DISABLE_SSH. Keep in mind that the setting is inverted")
+ ];
+
+ options = {
+ services.forgejo = {
+ enable = mkEnableOption (mdDoc "Forgejo");
+
+ package = mkPackageOptionMD pkgs "forgejo" { };
+
+ useWizard = mkOption {
+ default = false;
+ type = types.bool;
+ description = mdDoc ''
+ Whether to use the built-in installation wizard instead of
+ declaratively managing the {file}`app.ini` config file in nix.
+ '';
+ };
+
+ stateDir = mkOption {
+ default = "/var/lib/forgejo";
+ type = types.str;
+ description = mdDoc "Forgejo data directory.";
+ };
+
+ customDir = mkOption {
+ default = "${cfg.stateDir}/custom";
+ defaultText = literalExpression ''"''${config.${opt.stateDir}}/custom"'';
+ type = types.str;
+ description = mdDoc ''
+ Base directory for custom templates and other options.
+
+ If {option}`${opt.useWizard}` is disabled (default), this directory will also
+ hold secrets and the resulting {file}`app.ini` config at runtime.
+ '';
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "forgejo";
+ description = mdDoc "User account under which Forgejo runs.";
+ };
+
+ group = mkOption {
+ type = types.str;
+ default = "forgejo";
+ description = mdDoc "Group under which Forgejo runs.";
+ };
+
+ database = {
+ type = mkOption {
+ type = types.enum [ "sqlite3" "mysql" "postgres" ];
+ example = "mysql";
+ default = "sqlite3";
+ description = mdDoc "Database engine to use.";
+ };
+
+ host = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = mdDoc "Database host address.";
+ };
+
+ port = mkOption {
+ type = types.port;
+ default = if !usePostgresql then 3306 else pg.port;
+ defaultText = literalExpression ''
+ if config.${opt.database.type} != "postgresql"
+ then 3306
+ else config.${options.services.postgresql.port}
+ '';
+ description = mdDoc "Database host port.";
+ };
+
+ name = mkOption {
+ type = types.str;
+ default = "forgejo";
+ description = mdDoc "Database name.";
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "forgejo";
+ description = mdDoc "Database user.";
+ };
+
+ passwordFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ example = "/run/keys/forgejo-dbpassword";
+ description = mdDoc ''
+ A file containing the password corresponding to
+ {option}`${opt.database.user}`.
+ '';
+ };
+
+ socket = mkOption {
+ type = types.nullOr types.path;
+ default = if (cfg.database.createDatabase && usePostgresql) then "/run/postgresql" else if (cfg.database.createDatabase && useMysql) then "/run/mysqld/mysqld.sock" else null;
+ defaultText = literalExpression "null";
+ example = "/run/mysqld/mysqld.sock";
+ description = mdDoc "Path to the unix socket file to use for authentication.";
+ };
+
+ path = mkOption {
+ type = types.str;
+ default = "${cfg.stateDir}/data/forgejo.db";
+ defaultText = literalExpression ''"''${config.${opt.stateDir}}/data/forgejo.db"'';
+ description = mdDoc "Path to the sqlite3 database file.";
+ };
+
+ createDatabase = mkOption {
+ type = types.bool;
+ default = true;
+ description = mdDoc "Whether to create a local database automatically.";
+ };
+ };
+
+ dump = {
+ enable = mkEnableOption (mdDoc "periodic dumps via the [built-in {command}`dump` command](https://forgejo.org/docs/latest/admin/command-line/#dump)");
+
+ interval = mkOption {
+ type = types.str;
+ default = "04:31";
+ example = "hourly";
+ description = mdDoc ''
+ Run a Forgejo dump at this interval. Runs by default at 04:31 every day.
+
+ The format is described in
+ {manpage}`systemd.time(7)`.
+ '';
+ };
+
+ backupDir = mkOption {
+ type = types.str;
+ default = "${cfg.stateDir}/dump";
+ defaultText = literalExpression ''"''${config.${opt.stateDir}}/dump"'';
+ description = mdDoc "Path to the directory where the dump archives will be stored.";
+ };
+
+ type = mkOption {
+ type = types.enum [ "zip" "tar" "tar.sz" "tar.gz" "tar.xz" "tar.bz2" "tar.br" "tar.lz4" "tar.zst" ];
+ default = "zip";
+ description = mdDoc "Archive format used to store the dump file.";
+ };
+
+ file = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = mdDoc "Filename to be used for the dump. If `null` a default name is chosen by forgejo.";
+ example = "forgejo-dump";
+ };
+ };
+
+ lfs = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = mdDoc "Enables git-lfs support.";
+ };
+
+ contentDir = mkOption {
+ type = types.str;
+ default = "${cfg.stateDir}/data/lfs";
+ defaultText = literalExpression ''"''${config.${opt.stateDir}}/data/lfs"'';
+ description = mdDoc "Where to store LFS files.";
+ };
+ };
+
+ repositoryRoot = mkOption {
+ type = types.str;
+ default = "${cfg.stateDir}/repositories";
+ defaultText = literalExpression ''"''${config.${opt.stateDir}}/repositories"'';
+ description = mdDoc "Path to the git repositories.";
+ };
+
+ mailerPasswordFile = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "/run/keys/forgejo-mailpw";
+ description = mdDoc "Path to a file containing the SMTP password.";
+ };
+
+ settings = mkOption {
+ default = { };
+ description = mdDoc ''
+ Free-form settings written directly to the `app.ini` configfile file.
+ Refer to <https://forgejo.org/docs/latest/admin/config-cheat-sheet/> for supported values.
+ '';
+ example = literalExpression ''
+ {
+ DEFAULT = {
+ RUN_MODE = "dev";
+ };
+ "cron.sync_external_users" = {
+ RUN_AT_START = true;
+ SCHEDULE = "@every 24h";
+ UPDATE_EXISTING = true;
+ };
+ mailer = {
+ ENABLED = true;
+ MAILER_TYPE = "sendmail";
+ FROM = "do-not-reply@example.org";
+ SENDMAIL_PATH = "''${pkgs.system-sendmail}/bin/sendmail";
+ };
+ other = {
+ SHOW_FOOTER_VERSION = false;
+ };
+ }
+ '';
+ type = types.submodule {
+ freeformType = format.type;
+ options = {
+ log = {
+ ROOT_PATH = mkOption {
+ default = "${cfg.stateDir}/log";
+ defaultText = literalExpression ''"''${config.${opt.stateDir}}/log"'';
+ type = types.str;
+ description = mdDoc "Root path for log files.";
+ };
+ LEVEL = mkOption {
+ default = "Info";
+ type = types.enum [ "Trace" "Debug" "Info" "Warn" "Error" "Critical" ];
+ description = mdDoc "General log level.";
+ };
+ };
+
+ server = {
+ PROTOCOL = mkOption {
+ type = types.enum [ "http" "https" "fcgi" "http+unix" "fcgi+unix" ];
+ default = "http";
+ description = mdDoc ''Listen protocol. `+unix` means "over unix", not "in addition to."'';
+ };
+
+ HTTP_ADDR = mkOption {
+ type = types.either types.str types.path;
+ default = if lib.hasSuffix "+unix" cfg.settings.server.PROTOCOL then "/run/forgejo/forgejo.sock" else "0.0.0.0";
+ defaultText = literalExpression ''if lib.hasSuffix "+unix" cfg.settings.server.PROTOCOL then "/run/forgejo/forgejo.sock" else "0.0.0.0"'';
+ description = mdDoc "Listen address. Must be a path when using a unix socket.";
+ };
+
+ HTTP_PORT = mkOption {
+ type = types.port;
+ default = 3000;
+ description = mdDoc "Listen port. Ignored when using a unix socket.";
+ };
+
+ DOMAIN = mkOption {
+ type = types.str;
+ default = "localhost";
+ description = mdDoc "Domain name of your server.";
+ };
+
+ ROOT_URL = mkOption {
+ type = types.str;
+ default = "http://${cfg.settings.server.DOMAIN}:${toString cfg.settings.server.HTTP_PORT}/";
+ defaultText = literalExpression ''"http://''${config.services.forgejo.settings.server.DOMAIN}:''${toString config.services.forgejo.settings.server.HTTP_PORT}/"'';
+ description = mdDoc "Full public URL of Forgejo server.";
+ };
+
+ STATIC_ROOT_PATH = mkOption {
+ type = types.either types.str types.path;
+ default = cfg.package.data;
+ defaultText = literalExpression "config.${opt.package}.data";
+ example = "/var/lib/forgejo/data";
+ description = mdDoc "Upper level of template and static files path.";
+ };
+
+ DISABLE_SSH = mkOption {
+ type = types.bool;
+ default = false;
+ description = mdDoc "Disable external SSH feature.";
+ };
+
+ SSH_PORT = mkOption {
+ type = types.port;
+ default = 22;
+ example = 2222;
+ description = mdDoc ''
+ SSH port displayed in clone URL.
+ The option is required to configure a service when the external visible port
+ differs from the local listening port i.e. if port forwarding is used.
+ '';
+ };
+ };
+
+ session = {
+ COOKIE_SECURE = mkOption {
+ type = types.bool;
+ default = false;
+ description = mdDoc ''
+ Marks session cookies as "secure" as a hint for browsers to only send
+ them via HTTPS. This option is recommend, if Forgejo is being served over HTTPS.
+ '';
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = cfg.database.createDatabase -> useSqlite || cfg.database.user == cfg.user;
+ message = "services.forgejo.database.user must match services.forgejo.user if the database is to be automatically provisioned";
+ }
+ ];
+
+ services.forgejo.settings = {
+ DEFAULT = {
+ RUN_MODE = mkDefault "prod";
+ RUN_USER = mkDefault cfg.user;
+ WORK_PATH = mkDefault cfg.stateDir;
+ };
+
+ database = mkMerge [
+ {
+ DB_TYPE = cfg.database.type;
+ }
+ (mkIf (useMysql || usePostgresql) {
+ HOST = if cfg.database.socket != null then cfg.database.socket else cfg.database.host + ":" + toString cfg.database.port;
+ NAME = cfg.database.name;
+ USER = cfg.database.user;
+ PASSWD = "#dbpass#";
+ })
+ (mkIf useSqlite {
+ PATH = cfg.database.path;
+ })
+ (mkIf usePostgresql {
+ SSL_MODE = "disable";
+ })
+ ];
+
+ repository = {
+ ROOT = cfg.repositoryRoot;
+ };
+
+ server = mkIf cfg.lfs.enable {
+ LFS_START_SERVER = true;
+ LFS_JWT_SECRET = "#lfsjwtsecret#";
+ };
+
+ session = {
+ COOKIE_NAME = mkDefault "session";
+ };
+
+ security = {
+ SECRET_KEY = "#secretkey#";
+ INTERNAL_TOKEN = "#internaltoken#";
+ INSTALL_LOCK = true;
+ };
+
+ mailer = mkIf (cfg.mailerPasswordFile != null) {
+ PASSWD = "#mailerpass#";
+ };
+
+ oauth2 = {
+ JWT_SECRET = "#oauth2jwtsecret#";
+ };
+
+ lfs = mkIf cfg.lfs.enable {
+ PATH = cfg.lfs.contentDir;
+ };
+ };
+
+ services.postgresql = optionalAttrs (usePostgresql && cfg.database.createDatabase) {
+ enable = mkDefault true;
+
+ ensureDatabases = [ cfg.database.name ];
+ ensureUsers = [
+ {
+ name = cfg.database.user;
+ ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; };
+ }
+ ];
+ };
+
+ services.mysql = optionalAttrs (useMysql && cfg.database.createDatabase) {
+ enable = mkDefault true;
+ package = mkDefault pkgs.mariadb;
+
+ ensureDatabases = [ cfg.database.name ];
+ ensureUsers = [
+ {
+ name = cfg.database.user;
+ ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
+ }
+ ];
+ };
+
+ systemd.tmpfiles.rules = [
+ "d '${cfg.dump.backupDir}' 0750 ${cfg.user} ${cfg.group} - -"
+ "z '${cfg.dump.backupDir}' 0750 ${cfg.user} ${cfg.group} - -"
+ "d '${cfg.repositoryRoot}' 0750 ${cfg.user} ${cfg.group} - -"
+ "z '${cfg.repositoryRoot}' 0750 ${cfg.user} ${cfg.group} - -"
+ "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -"
+ "d '${cfg.stateDir}/conf' 0750 ${cfg.user} ${cfg.group} - -"
+ "d '${cfg.customDir}' 0750 ${cfg.user} ${cfg.group} - -"
+ "d '${cfg.customDir}/conf' 0750 ${cfg.user} ${cfg.group} - -"
+ "d '${cfg.stateDir}/data' 0750 ${cfg.user} ${cfg.group} - -"
+ "d '${cfg.stateDir}/log' 0750 ${cfg.user} ${cfg.group} - -"
+ "z '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -"
+ "z '${cfg.stateDir}/.ssh' 0700 ${cfg.user} ${cfg.group} - -"
+ "z '${cfg.stateDir}/conf' 0750 ${cfg.user} ${cfg.group} - -"
+ "z '${cfg.customDir}' 0750 ${cfg.user} ${cfg.group} - -"
+ "z '${cfg.customDir}/conf' 0750 ${cfg.user} ${cfg.group} - -"
+ "z '${cfg.stateDir}/data' 0750 ${cfg.user} ${cfg.group} - -"
+ "z '${cfg.stateDir}/log' 0750 ${cfg.user} ${cfg.group} - -"
+
+ # If we have a folder or symlink with Forgejo locales, remove it
+ # And symlink the current Forgejo locales in place
+ "L+ '${cfg.stateDir}/conf/locale' - - - - ${cfg.package.out}/locale"
+
+ ] ++ optionals cfg.lfs.enable [
+ "d '${cfg.lfs.contentDir}' 0750 ${cfg.user} ${cfg.group} - -"
+ "z '${cfg.lfs.contentDir}' 0750 ${cfg.user} ${cfg.group} - -"
+ ];
+
+ systemd.services.forgejo = {
+ description = "Forgejo (Beyond coding. We forge.)";
+ after = [
+ "network.target"
+ ] ++ optionals usePostgresql [
+ "postgresql.service"
+ ] ++ optionals useMysql [
+ "mysql.service"
+ ];
+ requires = optionals (cfg.database.createDatabase && usePostgresql) [
+ "postgresql.service"
+ ] ++ optionals (cfg.database.createDatabase && useMysql) [
+ "mysql.service"
+ ];
+ wantedBy = [ "multi-user.target" ];
+ path = [ cfg.package pkgs.git pkgs.gnupg ];
+
+ # In older versions the secret naming for JWT was kind of confusing.
+ # The file jwt_secret hold the value for LFS_JWT_SECRET and JWT_SECRET
+ # wasn't persistent at all.
+ # To fix that, there is now the file oauth2_jwt_secret containing the
+ # values for JWT_SECRET and the file jwt_secret gets renamed to
+ # lfs_jwt_secret.
+ # We have to consider this to stay compatible with older installations.
+ preStart =
+ let
+ runConfig = "${cfg.customDir}/conf/app.ini";
+ secretKey = "${cfg.customDir}/conf/secret_key";
+ oauth2JwtSecret = "${cfg.customDir}/conf/oauth2_jwt_secret";
+ oldLfsJwtSecret = "${cfg.customDir}/conf/jwt_secret"; # old file for LFS_JWT_SECRET
+ lfsJwtSecret = "${cfg.customDir}/conf/lfs_jwt_secret"; # new file for LFS_JWT_SECRET
+ internalToken = "${cfg.customDir}/conf/internal_token";
+ replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret";
+ in
+ ''
+ # copy custom configuration and generate random secrets if needed
+ ${lib.optionalString (!cfg.useWizard) ''
+ function forgejo_setup {
+ cp -f '${format.generate "app.ini" cfg.settings}' '${runConfig}'
+
+ if [ ! -s '${secretKey}' ]; then
+ ${exe} generate secret SECRET_KEY > '${secretKey}'
+ fi
+
+ # Migrate LFS_JWT_SECRET filename
+ if [[ -s '${oldLfsJwtSecret}' && ! -s '${lfsJwtSecret}' ]]; then
+ mv '${oldLfsJwtSecret}' '${lfsJwtSecret}'
+ fi
+
+ if [ ! -s '${oauth2JwtSecret}' ]; then
+ ${exe} generate secret JWT_SECRET > '${oauth2JwtSecret}'
+ fi
+
+ ${optionalString cfg.lfs.enable ''
+ if [ ! -s '${lfsJwtSecret}' ]; then
+ ${exe} generate secret LFS_JWT_SECRET > '${lfsJwtSecret}'
+ fi
+ ''}
+
+ if [ ! -s '${internalToken}' ]; then
+ ${exe} generate secret INTERNAL_TOKEN > '${internalToken}'
+ fi
+
+ chmod u+w '${runConfig}'
+ ${replaceSecretBin} '#secretkey#' '${secretKey}' '${runConfig}'
+ ${replaceSecretBin} '#oauth2jwtsecret#' '${oauth2JwtSecret}' '${runConfig}'
+ ${replaceSecretBin} '#internaltoken#' '${internalToken}' '${runConfig}'
+
+ ${optionalString cfg.lfs.enable ''
+ ${replaceSecretBin} '#lfsjwtsecret#' '${lfsJwtSecret}' '${runConfig}'
+ ''}
+
+ ${optionalString (cfg.database.passwordFile != null) ''
+ ${replaceSecretBin} '#dbpass#' '${cfg.database.passwordFile}' '${runConfig}'
+ ''}
+
+ ${optionalString (cfg.mailerPasswordFile != null) ''
+ ${replaceSecretBin} '#mailerpass#' '${cfg.mailerPasswordFile}' '${runConfig}'
+ ''}
+ chmod u-w '${runConfig}'
+ }
+ (umask 027; forgejo_setup)
+ ''}
+
+ # run migrations/init the database
+ ${exe} migrate
+
+ # update all hooks' binary paths
+ ${exe} admin regenerate hooks
+
+ # update command option in authorized_keys
+ if [ -r ${cfg.stateDir}/.ssh/authorized_keys ]
+ then
+ ${exe} admin regenerate keys
+ fi
+ '';
+
+ serviceConfig = {
+ Type = "simple";
+ User = cfg.user;
+ Group = cfg.group;
+ WorkingDirectory = cfg.stateDir;
+ ExecStart = "${exe} web --pid /run/forgejo/forgejo.pid";
+ Restart = "always";
+ # Runtime directory and mode
+ RuntimeDirectory = "forgejo";
+ RuntimeDirectoryMode = "0755";
+ # Proc filesystem
+ ProcSubset = "pid";
+ ProtectProc = "invisible";
+ # Access write directories
+ ReadWritePaths = [ cfg.customDir cfg.dump.backupDir cfg.repositoryRoot cfg.stateDir cfg.lfs.contentDir ];
+ UMask = "0027";
+ # Capabilities
+ CapabilityBoundingSet = "";
+ # Security
+ NoNewPrivileges = true;
+ # Sandboxing
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ PrivateUsers = true;
+ ProtectHostname = true;
+ ProtectClock = true;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectKernelLogs = true;
+ ProtectControlGroups = true;
+ RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
+ RestrictNamespaces = true;
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ RemoveIPC = true;
+ PrivateMounts = true;
+ # System Call Filtering
+ SystemCallArchitectures = "native";
+ SystemCallFilter = [ "~@cpu-emulation @debug @keyring @mount @obsolete @privileged @setuid" "setrlimit" ];
+ };
+
+ environment = {
+ USER = cfg.user;
+ HOME = cfg.stateDir;
+ # `GITEA_` prefix until https://codeberg.org/forgejo/forgejo/issues/497
+ # is resolved.
+ GITEA_WORK_DIR = cfg.stateDir;
+ GITEA_CUSTOM = cfg.customDir;
+ };
+ };
+
+ users.users = mkIf (cfg.user == "forgejo") {
+ forgejo = {
+ home = cfg.stateDir;
+ useDefaultShell = true;
+ group = cfg.group;
+ isSystemUser = true;
+ };
+ };
+
+ users.groups = mkIf (cfg.group == "forgejo") {
+ forgejo = { };
+ };
+
+ systemd.services.forgejo-dump = mkIf cfg.dump.enable {
+ description = "forgejo dump";
+ after = [ "forgejo.service" ];
+ path = [ cfg.package ];
+
+ environment = {
+ USER = cfg.user;
+ HOME = cfg.stateDir;
+ # `GITEA_` prefix until https://codeberg.org/forgejo/forgejo/issues/497
+ # is resolved.
+ GITEA_WORK_DIR = cfg.stateDir;
+ GITEA_CUSTOM = cfg.customDir;
+ };
+
+ serviceConfig = {
+ Type = "oneshot";
+ User = cfg.user;
+ ExecStart = "${exe} dump --type ${cfg.dump.type}" + optionalString (cfg.dump.file != null) " --file ${cfg.dump.file}";
+ WorkingDirectory = cfg.dump.backupDir;
+ };
+ };
+
+ systemd.timers.forgejo-dump = mkIf cfg.dump.enable {
+ description = "Forgejo dump timer";
+ partOf = [ "forgejo-dump.service" ];
+ wantedBy = [ "timers.target" ];
+ timerConfig.OnCalendar = cfg.dump.interval;
+ };
+ };
+
+ meta.maintainers = with lib.maintainers; [ bendlas emilylange ];
+}
From 02601e17a53eadd488bd8ca16dbb656fd46d1764 Mon Sep 17 00:00:00 2001
From: emilylange <git@emilylange.de>
Date: Sun, 6 Aug 2023 18:41:37 +0200
Subject: [PATCH 2/3] nixosTests.forgejo: fork from nixosTests.gitea
---
nixos/tests/all-tests.nix | 2 +-
nixos/tests/forgejo.nix | 157 ++++++++++++++++++++++++++++++++++++++
2 files changed, 158 insertions(+), 1 deletion(-)
create mode 100644 nixos/tests/forgejo.nix
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 3b4a39f5ff96b8..d9aa9eccac02d2 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -280,7 +280,7 @@ in {
fluentd = handleTest ./fluentd.nix {};
fluidd = handleTest ./fluidd.nix {};
fontconfig-default-fonts = handleTest ./fontconfig-default-fonts.nix {};
- forgejo = handleTest ./gitea.nix { giteaPackage = pkgs.forgejo; };
+ forgejo = handleTest ./forgejo.nix { };
freenet = handleTest ./freenet.nix {};
freeswitch = handleTest ./freeswitch.nix {};
freshrss-sqlite = handleTest ./freshrss-sqlite.nix {};
diff --git a/nixos/tests/forgejo.nix b/nixos/tests/forgejo.nix
new file mode 100644
index 00000000000000..b326819e319064
--- /dev/null
+++ b/nixos/tests/forgejo.nix
@@ -0,0 +1,157 @@
+{ system ? builtins.currentSystem
+, config ? { }
+, pkgs ? import ../.. { inherit system config; }
+}:
+
+with import ../lib/testing-python.nix { inherit system pkgs; };
+with pkgs.lib;
+
+let
+ ## gpg --faked-system-time='20230301T010000!' --quick-generate-key snakeoil ed25519 sign
+ signingPrivateKey = ''
+ -----BEGIN PGP PRIVATE KEY BLOCK-----
+
+ lFgEY/6jkBYJKwYBBAHaRw8BAQdADXiZRV8RJUyC9g0LH04wLMaJL9WTc+szbMi7
+ 5fw4yP8AAQCl8EwGfzSLm/P6fCBfA3I9znFb3MEHGCCJhJ6VtKYyRw7ktAhzbmFr
+ ZW9pbIiUBBMWCgA8FiEE+wUM6VW/NLtAdSixTWQt6LZ4x50FAmP+o5ACGwMFCQPC
+ ZwAECwkIBwQVCgkIBRYCAwEAAh4FAheAAAoJEE1kLei2eMedFTgBAKQs1oGFZrCI
+ TZP42hmBTKxGAI1wg7VSdDEWTZxut/2JAQDGgo2sa4VHMfj0aqYGxrIwfP2B7JHO
+ GCqGCRf9O/hzBA==
+ =9Uy3
+ -----END PGP PRIVATE KEY BLOCK-----
+ '';
+ signingPrivateKeyId = "4D642DE8B678C79D";
+
+ supportedDbTypes = [ "mysql" "postgres" "sqlite3" ];
+ makeGForgejoTest = type: nameValuePair type (makeTest {
+ name = "forgejo-${type}";
+ meta.maintainers = with maintainers; [ bendlas emilylange ];
+
+ nodes = {
+ server = { config, pkgs, ... }: {
+ virtualisation.memorySize = 2047;
+ services.forgejo = {
+ enable = true;
+ database = { inherit type; };
+ settings.service.DISABLE_REGISTRATION = true;
+ settings."repository.signing".SIGNING_KEY = signingPrivateKeyId;
+ settings.actions.ENABLED = true;
+ };
+ environment.systemPackages = [ config.services.forgejo.package pkgs.gnupg pkgs.jq ];
+ services.openssh.enable = true;
+
+ specialisation.runner = {
+ inheritParentConfig = true;
+ configuration.services.gitea-actions-runner.instances."test" = {
+ enable = true;
+ name = "ci";
+ url = "http://localhost:3000";
+ labels = [
+ # don't require docker/podman
+ "native:host"
+ ];
+ tokenFile = "/var/lib/forgejo/runner_token";
+ };
+ };
+ };
+ client1 = { config, pkgs, ... }: {
+ environment.systemPackages = [ pkgs.git ];
+ };
+ client2 = { config, pkgs, ... }: {
+ environment.systemPackages = [ pkgs.git ];
+ };
+ };
+
+ testScript = { nodes, ... }:
+ let
+ inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey;
+ serverSystem = nodes.server.system.build.toplevel;
+ in
+ ''
+ GIT_SSH_COMMAND = "ssh -i $HOME/.ssh/privk -o StrictHostKeyChecking=no"
+ REPO = "forgejo@server:test/repo"
+ PRIVK = "${snakeOilPrivateKey}"
+
+ start_all()
+
+ client1.succeed("mkdir /tmp/repo")
+ client1.succeed("mkdir -p $HOME/.ssh")
+ client1.succeed(f"cat {PRIVK} > $HOME/.ssh/privk")
+ client1.succeed("chmod 0400 $HOME/.ssh/privk")
+ client1.succeed("git -C /tmp/repo init")
+ client1.succeed("echo hello world > /tmp/repo/testfile")
+ client1.succeed("git -C /tmp/repo add .")
+ client1.succeed("git config --global user.email test@localhost")
+ client1.succeed("git config --global user.name test")
+ client1.succeed("git -C /tmp/repo commit -m 'Initial import'")
+ client1.succeed(f"git -C /tmp/repo remote add origin {REPO}")
+
+ server.wait_for_unit("forgejo.service")
+ server.wait_for_open_port(3000)
+ server.wait_for_open_port(22)
+ server.succeed("curl --fail http://localhost:3000/")
+
+ server.succeed(
+ "su -l forgejo -c 'gpg --homedir /var/lib/forgejo/data/home/.gnupg "
+ + "--import ${toString (pkgs.writeText "forgejo.key" signingPrivateKey)}'"
+ )
+
+ assert "BEGIN PGP PUBLIC KEY BLOCK" in server.succeed("curl http://localhost:3000/api/v1/signing-key.gpg")
+
+ server.succeed(
+ "curl --fail http://localhost:3000/user/sign_up | grep 'Registration is disabled. "
+ + "Please contact your site administrator.'"
+ )
+ server.succeed(
+ "su -l forgejo -c 'GITEA_WORK_DIR=/var/lib/forgejo gitea admin user create "
+ + "--username test --password totallysafe --email test@localhost'"
+ )
+
+ api_token = server.succeed(
+ "curl --fail -X POST http://test:totallysafe@localhost:3000/api/v1/users/test/tokens "
+ + "-H 'Accept: application/json' -H 'Content-Type: application/json' -d "
+ + "'{\"name\":\"token\",\"scopes\":[\"all\"]}' | jq '.sha1' | xargs echo -n"
+ )
+
+ server.succeed(
+ "curl --fail -X POST http://localhost:3000/api/v1/user/repos "
+ + "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+ + f"-H 'Authorization: token {api_token}'"
+ + ' -d \'{"auto_init":false, "description":"string", "license":"mit", "name":"repo", "private":false}\'''
+ )
+
+ server.succeed(
+ "curl --fail -X POST http://localhost:3000/api/v1/user/keys "
+ + "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+ + f"-H 'Authorization: token {api_token}'"
+ + ' -d \'{"key":"${snakeOilPublicKey}","read_only":true,"title":"SSH"}\'''
+ )
+
+ client1.succeed(
+ f"GIT_SSH_COMMAND='{GIT_SSH_COMMAND}' git -C /tmp/repo push origin master"
+ )
+
+ client2.succeed("mkdir -p $HOME/.ssh")
+ client2.succeed(f"cat {PRIVK} > $HOME/.ssh/privk")
+ client2.succeed("chmod 0400 $HOME/.ssh/privk")
+ client2.succeed(f"GIT_SSH_COMMAND='{GIT_SSH_COMMAND}' git clone {REPO}")
+ client2.succeed('test "$(cat repo/testfile | xargs echo -n)" = "hello world"')
+
+ server.wait_until_succeeds(
+ 'test "$(curl http://localhost:3000/api/v1/repos/test/repo/commits '
+ + '-H "Accept: application/json" | jq length)" = "1"',
+ timeout=10
+ )
+
+ with subtest("Testing runner registration"):
+ server.succeed(
+ "su -l forgejo -c 'GITEA_WORK_DIR=/var/lib/forgejo gitea actions generate-runner-token' | sed 's/^/TOKEN=/' | tee /var/lib/forgejo/runner_token"
+ )
+ server.succeed("${serverSystem}/specialisation/runner/bin/switch-to-configuration test")
+ server.wait_for_unit("gitea-runner-test.service")
+ server.succeed("journalctl -o cat -u gitea-runner-test.service | grep -q 'Runner registered successfully'")
+ '';
+ });
+in
+
+listToAttrs (map makeGForgejoTest supportedDbTypes)
From 7b786b39cb0d42949720482b78c31fcfe35b41c7 Mon Sep 17 00:00:00 2001
From: emilylange <git@emilylange.de>
Date: Sun, 6 Aug 2023 18:43:08 +0200
Subject: [PATCH 3/3] CODEOWNERS: init forgejo
---
.github/CODEOWNERS | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 98a7022088eb22..829ce356f9db37 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -288,6 +288,10 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/nixos/modules/services/misc/matrix-conduit.nix @piegamesde
/nixos/tests/matrix-conduit.nix @piegamesde
+# Forgejo
+nixos/modules/services/misc/forgejo.nix @bendlas @emilylange
+pkgs/applications/version-management/forgejo @bendlas @emilylange
+
# Dotnet
/pkgs/build-support/dotnet @IvarWithoutBones
/pkgs/development/compilers/dotnet @IvarWithoutBones

View file

@ -1,18 +0,0 @@
{
"nixos-23.05" = [
# Plausible fix
./241126.patch
# Kanidm 1.1.0-beta.13
./246564.patch
# Forgejo 1.20.4-0
./forgejo.patch
# Forgejo module
./248310.patch
# php: add new Composer builder
./248184.patch
];
}

View file

@ -54,6 +54,19 @@
"url": null, "url": null,
"hash": "1ymx3ayi189xcinpc6r71qvwgqsvz96y7dwdxzlrjawr08c95wm2" "hash": "1ymx3ayi189xcinpc6r71qvwgqsvz96y7dwdxzlrjawr08c95wm2"
}, },
"nix-patches": {
"type": "GitRelease",
"repository": {
"type": "Git",
"url": "https://git.hubrecht.ovh/hubrecht/nix-patches"
},
"pre_releases": false,
"version_upper_bound": null,
"version": "v0.2.0",
"revision": "6d47298262bd256b02281281ecf58bbf15ed21ba",
"url": null,
"hash": "14w7w327m8rf7yrjflqvbnmwx04l36n7j0nca5ilpvzrr8f2gg6l"
},
"nixos-23.05": { "nixos-23.05": {
"type": "Channel", "type": "Channel",
"name": "nixos-23.05", "name": "nixos-23.05",

69
patches/default.nix Normal file
View file

@ -0,0 +1,69 @@
{
"nixos-23.05" = [
# plausible: fix admin user password seed and SMTP passwords
{
id = 241126;
hash = "sha256-TcGuB3k8SeA8PRb/OdZ8ESw9/7yYKPftR96boK7Hmvc=";
}
# fetchMixDeps: sha256 -> hash
{
id = 235733;
hash = "sha256-oHGZFXwOJ9ngZNJBTd93abgI+eNPsCBJPgFxt41728o=";
includes = [
"pkgs/development/beam-modules/fetch-mix-deps.nix"
"pkgs/servers/web-apps/plausible/default.nix"
];
}
# python3Packages.nix-prefetch-github: 6.0.1 -> 7.0.0
# Only keep the files related to plausible
{
id = 243018;
hash = "sha256-/7jid8tKo2JbVyEmeVxt+9VRqc/2YWkUeagyrMqqb70=";
includes = [ "pkgs/servers/web-apps/plausible/*" ];
}
# plausible: 1.4.4 -> 1.5.1
{
id = 229201;
hash = "sha256-wJ3qQbX5Yn7PZ5gpJYAeCIkblPaaVgUGg3XJb5C8ccY=";
}
# plausible: 1.5.1 -> 2.0.0
{
id = 253687;
hash = "sha256-yXZn16+J+UhLoH6R+ir5Tk2vYer4ItFgKN2oefXSYDs=";
}
# dbip-country-lite: init at 2023-06
{
id = 235774;
hash = "sha256-M0oktrBKxezhBQh3gKHKXrWF7UjACX3PcpSzoq8HkW0=";
}
# kanidm: 1.1.0-alpha.12 -> 1.1.0-beta.13
{
id = 246564;
hash = "sha256-Q/G6w4iXthhC6JI/erOx0HBJ25aLQLtZSusAOdT6dYc=";
}
# Forgejo v1.19.4-0 -> v1.20.4-1
{
_type = "static";
path = ./forgejo.patch;
}
# nixos/forgejo: fork from nixos/gitea
{
id = 248310;
hash = "sha256-6cLMDbzYRKZrFulkS48dPznAap4bVCLsb1APaud9nV8=";
}
# garage: add environmentFile
{
id = 257043;
hash = "sha256-etzGZRFgFZra5KmL2pUQnIFBFiAudePDmNTVA4VDiBs=";
}
];
}

View file

@ -16,7 +16,7 @@ index d21097df07b..2ee652d8785 100644
buildGoModule rec { buildGoModule rec {
pname = "forgejo"; pname = "forgejo";
- version = "1.19.4-0"; - version = "1.19.4-0";
+ version = "1.20.4-0"; + version = "1.20.4-1";
src = fetchFromGitea { src = fetchFromGitea {
domain = "codeberg.org"; domain = "codeberg.org";
@ -24,7 +24,7 @@ index d21097df07b..2ee652d8785 100644
repo = "forgejo"; repo = "forgejo";
rev = "v${version}"; rev = "v${version}";
- hash = "sha256-pTcnST8A4gADPBkNago9uwRFEmTx8vNONL/Emer4xLI="; - hash = "sha256-pTcnST8A4gADPBkNago9uwRFEmTx8vNONL/Emer4xLI=";
+ hash = "sha256-guKU3VG1Wyhr5p6w0asL/CopQ5b7HiNi26Tw8WCEpwE="; + hash = "sha256-Fxlj+ckw1LSgiQDex3ZizHakIKd52U6JcdTurJj8YWg=";
}; };
- vendorHash = "sha256-LKxhNbSIRaP4EGWX6mE26G9CWfoFTrPRjrL4ShpRHWo="; - vendorHash = "sha256-LKxhNbSIRaP4EGWX6mE26G9CWfoFTrPRjrL4ShpRHWo=";