commit 30d21ecd93f3de4789a098f812255be358a51d6e Author: Jeffrey C. Ollie Date: Sat Nov 25 09:47:08 2023 -0600 first diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d02127 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/result* + diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..daa321d --- /dev/null +++ b/flake.lock @@ -0,0 +1,60 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1700612854, + "narHash": "sha256-yrQ8osMD+vDLGFX7pcwsY/Qr5PUd6OmDMYJZzZi0+zc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "19cbff58383a4ae384dea4d1d0c823d72b49d614", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs-unstable": "nixpkgs-unstable" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..ac84318 --- /dev/null +++ b/flake.nix @@ -0,0 +1,754 @@ +{ + description = "Forgejo"; + + inputs = { + nixpkgs-unstable = { + url = "nixpkgs/nixos-unstable"; + }; + flake-utils = { + url = "github:numtide/flake-utils"; + }; + }; + outputs = { + self, + nixpkgs-unstable, + flake-utils, + ... + } @ inputs: + flake-utils.lib.eachDefaultSystem + ( + system: let + pkgs = import nixpkgs-unstable { + inherit system; + }; + in { + packages = { + forgejo = let + pamSupport = true; + sqliteSupport = true; + pname = "forgejo"; + version = "1.21"; + rev = "0fbd099750ee368a271df1d51d511798872646fc"; + hash = "sha256-/zXlm8WsYqPRkc7w9T56lQOo5JV5oGD0jBvV5KbSpNg="; + npmDepsHash = "sha256-sVCx2RpCXHzgpftcTHRh4wLQIWpD9rJ39Jcs0FJ+L2c="; + vendorHash = "sha256-+/wOEF44dSqy7ZThZyd66xyI3wVnFwZbsAd4ujyVku8="; + src = pkgs.fetchFromGitea { + inherit rev hash; + domain = "codeberg.org"; + owner = "forgejo"; + repo = "forgejo"; + }; + frontend = pkgs.buildNpmPackage { + pname = "forgejo-frontend"; + inherit src version npmDepsHash; + + patches = [ + ./package-json-npm-build-frontend.patch + ]; + + # override npmInstallHook + installPhase = '' + mkdir $out + cp -R ./public $out/ + ''; + }; + # data-compressed = pkgs.runCommand + # "forgejo-data-compressed" + # { + # nativeBuildInputs = [ pkgs.brotli pkgs.xorg.lndir ]; + # } + # '' + # mkdir $out + # lndir ${forgejo.data}/ $out/ + + # # Create static gzip and brotli files + # find -L $out -type f -regextype posix-extended -iregex '.*\.(css|html|js|svg|ttf|txt)' \ + # -exec gzip --best --keep --force {} ';' \ + # -exec brotli --best --keep --no-copy-stat {} ';' + # ''; + tags = pkgs.lib.optional pamSupport "pam" ++ pkgs.lib.optionals sqliteSupport ["sqlite" "sqlite_unlock_notify"]; + in + pkgs.buildGo121Module { + inherit pname src version vendorHash; + + subPackages = ["."]; + + outputs = ["out" "data" "compressed"]; + + nativeBuildInputs = [pkgs.makeWrapper pkgs.brotli pkgs.xorg.lndir]; + buildInputs = pkgs.lib.optional pamSupport pkgs.pam; + + patches = [ + ./static-root-path.patch + ]; + + postPatch = '' + substituteInPlace modules/setting/setting.go --subst-var data + ''; + + ldflags = [ + "-s" + "-w" + "-X main.Version=${version}-${rev}" + "-X 'main.Tags=${pkgs.lib.concatStringsSep " " tags}'" + ]; + + preBuild = '' + go run build/merge-forgejo-locales.go + ''; + + postInstall = '' + mkdir $data + cp -R ./{templates,options} ${frontend}/public $data + + mkdir $compressed + lndir $data/ $compressed/ + # Create static gzip and brotli files + find -L $out -type f -regextype posix-extended -iregex '.*\.(css|html|js|svg|ttf|txt)' \ + -exec gzip --best --keep --force {} ';' \ + -exec brotli --best --keep --no-copy-stat {} ';' + + mkdir -p $out + cp -R ./options/locale $out/locale + wrapProgram $out/bin/gitea \ + --prefix PATH : ${pkgs.lib.makeBinPath [pkgs.bash pkgs.git pkgs.gzip pkgs.openssh]} + ''; + + # $data is not available in goModules.drv and preBuild isn't needed + overrideModAttrs = _: { + postPatch = null; + preBuild = null; + }; + + passthru = { + # allow nix-update to handle npmDepsHash + # inherit (frontend) npmDeps; + + # data-compressed = pkgs.runCommand "forgejo-data-compressed" + # { + # nativeBuildInputs = [ pkgs.brotli pkgs.xorg.lndir ]; + # } '' + # mkdir $out + # lndir ${forgejo.data}/ $out/ + + # # Create static gzip and brotli files + # find -L $out -type f -regextype posix-extended -iregex '.*\.(css|html|js|svg|ttf|txt)' \ + # -exec gzip --best --keep --force {} ';' \ + # -exec brotli --best --keep --no-copy-stat {} ';' + # ''; + + # tests = pkgs.nixosTests.forgejo; + # updateScript = pkgs.nix-update-script { }; + }; + + meta = { + description = "A self-hosted lightweight software forge"; + homepage = "https://forgejo.org"; + changelog = "https://codeberg.org/forgejo/forgejo/releases/tag/${src.rev}"; + license = pkgs.lib.licenses.mit; + maintainers = with pkgs.lib.maintainers; [emilylange urandom bendlas adamcstephens]; + broken = pkgs.stdenv.isDarwin; + mainProgram = "gitea"; + }; + }; + }; + } + ); + # // { + # nixosModules.forgejo = { self, config, options, lib, pkgs, name, ... }: + # let + # cfg = config.jcollie.forgejo; + # opt = options.jcollie.forgejo; + # format = pkgs.formats.ini { }; + + # exe = lib.getExe self.packages.${pkgs.system}.forgejo; + + # useMysql = cfg.database.type == "mysql"; + # usePostgresql = cfg.database.type == "postgres"; + # useSqlite = cfg.database.type == "sqlite3"; + # in + # { + # imports = [ + # (mkRenamedOptionModule [ "jcollie" "forgejo" "appName" ] [ "jcollie" "forgejo" "settings" "DEFAULT" "APP_NAME" ]) + # (mkRemovedOptionModule [ "jcollie" "forgejo" "extraConfig" ] "jcollie.forgejo.extraConfig has been removed. Please use the freeform jcollie.forgejo.settings option instead") + # (mkRemovedOptionModule [ "jcollie" "forgejo" "database" "jcollie" ] "services.forgejo.database.password has been removed. Please use jcollie.forgejo.database.passwordFile instead") + + # # copied from services.gitea; remove at some point + # (mkRenamedOptionModule [ "jcollie" "forgejo" "cookieSecure" ] [ "jcollie" "forgejo" "settings" "session" "COOKIE_SECURE" ]) + # (mkRenamedOptionModule [ "jcollie" "forgejo" "disableRegistration" ] [ "jcollie" "forgejo" "settings" "service" "DISABLE_REGISTRATION" ]) + # (mkRenamedOptionModule [ "jcollie" "forgejo" "domain" ] [ "jcollie" "forgejo" "settings" "server" "DOMAIN" ]) + # (mkRenamedOptionModule [ "jcollie" "forgejo" "httpAddress" ] [ "jcollie" "forgejo" "settings" "server" "HTTP_ADDR" ]) + # (mkRenamedOptionModule [ "jcollie" "forgejo" "httpPort" ] [ "jcollie" "forgejo" "settings" "server" "HTTP_PORT" ]) + # (mkRenamedOptionModule [ "jcollie" "forgejo" "log" "level" ] [ "jcollie" "forgejo" "settings" "log" "LEVEL" ]) + # (mkRenamedOptionModule [ "jcollie" "forgejo" "log" "rootPath" ] [ "jcollie" "forgejo" "settings" "log" "ROOT_PATH" ]) + # (mkRenamedOptionModule [ "jcollie" "forgejo" "rootUrl" ] [ "jcollie" "forgejo" "settings" "server" "ROOT_URL" ]) + # (mkRenamedOptionModule [ "jcollie" "forgejo" "ssh" "clonePort" ] [ "jcollie" "forgejo" "settings" "server" "SSH_PORT" ]) + # (mkRenamedOptionModule [ "jcollie" "forgejo" "staticRootPath" ] [ "jcollie" "forgejo" "settings" "server" "STATIC_ROOT_PATH" ]) + # (mkChangedOptionModule [ "jcollie" "forgejo" "enableUnixSocket" ] [ "jcollie" "forgejo" "settings" "server" "PROTOCOL" ] ( + # config: if config.jcollie.forgejo.enableUnixSocket then "http+unix" else "http" + # )) + # (mkRemovedOptionModule [ "jcollie" "forgejo" "ssh" "enable" ] "jcollie.forgejo.ssh.enable has been migrated into freeform setting jcollie.forgejo.settings.server.DISABLE_SSH. Keep in mind that the setting is inverted") + # ]; + + # options = { + # services.forgejo = { + # enable = mkEnableOption (mdDoc "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 = "git"; + # description = mdDoc "User account under which Forgejo runs."; + # }; + + # group = mkOption { + # type = types.str; + # default = "git"; + # 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 usePostgresql then "/run/postgresql" else if 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."; + # }; + # }; + + # 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 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 = [ + + # ]; + + # jcollie.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; + # }; + # }; + + # 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} - -" + # ]; + + # environment.systemPackages = + # let + # forgejo-cli = pkgs.writeScriptBin "forgejo-cli" '' + # export GITEA_WORK_DIR=${cfg.stateDir} + # export GITEA_CUSTOM=${cfg.stateDir}/custom + # export HOME="${cfg.stateDir}"; + # exec ${pkgs.util-linux}/bin/runuser --user ${cfg.user} -- ${exe} forgejo-cli "$@" + # ''; + # in + # with pkgs; [ + # forgejo-cli + # ]; + + # systemd.services.forgejo = { + # description = "Forgejo (Beyond coding. We forge.)"; + # after = [ + # "network.target" + # ]; + # 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 == "git") { + # git = { + # description = "Forgejo"; + # home = cfg.stateDir; + # useDefaultShell = true; + # group = cfg.group; + # isSystemUser = true; + # }; + # }; + + # users.groups = mkIf (cfg.group == "git") { + # git = { }; + # }; + # }; + # }; + # }; +} diff --git a/package-json-npm-build-frontend.patch b/package-json-npm-build-frontend.patch new file mode 100644 index 0000000..57e2b7e --- /dev/null +++ b/package-json-npm-build-frontend.patch @@ -0,0 +1,14 @@ +diff --git a/package.json b/package.json +index 57dcfc2f7..c9f23dbf7 100644 +--- a/package.json ++++ b/package.json +@@ -79,5 +79,8 @@ + "defaults", + "not ie > 0", + "not ie_mob > 0" +- ] ++ ], ++ "scripts": { ++ "build": "node_modules/.bin/webpack" ++ } + } diff --git a/static-root-path.patch b/static-root-path.patch new file mode 100644 index 0000000..7f70329 --- /dev/null +++ b/static-root-path.patch @@ -0,0 +1,13 @@ +diff --git a/modules/setting/server.go b/modules/setting/server.go +index 183906268..fa02e8915 100644 +--- a/modules/setting/server.go ++++ b/modules/setting/server.go +@@ -319,7 +319,7 @@ func loadServerFrom(rootCfg ConfigProvider) { + OfflineMode = sec.Key("OFFLINE_MODE").MustBool() + Log.DisableRouterLog = sec.Key("DISABLE_ROUTER_LOG").MustBool() + if len(StaticRootPath) == 0 { +- StaticRootPath = AppWorkPath ++ StaticRootPath = "@data@" + } + StaticRootPath = sec.Key("STATIC_ROOT_PATH").MustString(StaticRootPath) + StaticCacheTime = sec.Key("STATIC_CACHE_TIME").MustDuration(6 * time.Hour)