nixpkgs/nixos/modules/services/misc/gogs.nix
pennae 2e751c0772 treewide: automatically md-convert option descriptions
the conversion procedure is simple:

 - find all things that look like options, ie calls to either `mkOption`
   or `lib.mkOption` that take an attrset. remember the attrset as the
   option
 - for all options, find a `description` attribute who's value is not a
   call to `mdDoc` or `lib.mdDoc`
 - textually convert the entire value of the attribute to MD with a few
   simple regexes (the set from mdize-module.sh)
 - if the change produced a change in the manual output, discard
 - if the change kept the manual unchanged, add some text to the
   description to make sure we've actually found an option. if the
   manual changes this time, keep the converted description

this procedure converts 80% of nixos options to markdown. around 2000
options remain to be inspected, but most of those fail the "does not
change the manual output check": currently the MD conversion process
does not faithfully convert docbook tags like <code> and <package>, so
any option using such tags will not be converted at all.
2022-07-30 15:16:34 +02:00

274 lines
7.7 KiB
Nix

{ config, lib, options, pkgs, ... }:
with lib;
let
cfg = config.services.gogs;
opt = options.services.gogs;
configFile = pkgs.writeText "app.ini" ''
APP_NAME = ${cfg.appName}
RUN_USER = ${cfg.user}
RUN_MODE = prod
[database]
DB_TYPE = ${cfg.database.type}
HOST = ${cfg.database.host}:${toString cfg.database.port}
NAME = ${cfg.database.name}
USER = ${cfg.database.user}
PASSWD = #dbpass#
PATH = ${cfg.database.path}
[repository]
ROOT = ${cfg.repositoryRoot}
[server]
DOMAIN = ${cfg.domain}
HTTP_ADDR = ${cfg.httpAddress}
HTTP_PORT = ${toString cfg.httpPort}
ROOT_URL = ${cfg.rootUrl}
[session]
COOKIE_NAME = session
COOKIE_SECURE = ${boolToString cfg.cookieSecure}
[security]
SECRET_KEY = #secretkey#
INSTALL_LOCK = true
[log]
ROOT_PATH = ${cfg.stateDir}/log
${cfg.extraConfig}
'';
in
{
options = {
services.gogs = {
enable = mkOption {
default = false;
type = types.bool;
description = lib.mdDoc "Enable Go Git Service.";
};
useWizard = mkOption {
default = false;
type = types.bool;
description = lib.mdDoc "Do not generate a configuration and use Gogs' installation wizard instead. The first registered user will be administrator.";
};
stateDir = mkOption {
default = "/var/lib/gogs";
type = types.str;
description = lib.mdDoc "Gogs data directory.";
};
user = mkOption {
type = types.str;
default = "gogs";
description = lib.mdDoc "User account under which Gogs runs.";
};
group = mkOption {
type = types.str;
default = "gogs";
description = lib.mdDoc "Group account under which Gogs runs.";
};
database = {
type = mkOption {
type = types.enum [ "sqlite3" "mysql" "postgres" ];
example = "mysql";
default = "sqlite3";
description = lib.mdDoc "Database engine to use.";
};
host = mkOption {
type = types.str;
default = "127.0.0.1";
description = lib.mdDoc "Database host address.";
};
port = mkOption {
type = types.int;
default = 3306;
description = lib.mdDoc "Database host port.";
};
name = mkOption {
type = types.str;
default = "gogs";
description = lib.mdDoc "Database name.";
};
user = mkOption {
type = types.str;
default = "gogs";
description = lib.mdDoc "Database user.";
};
password = mkOption {
type = types.str;
default = "";
description = lib.mdDoc ''
The password corresponding to {option}`database.user`.
Warning: this is stored in cleartext in the Nix store!
Use {option}`database.passwordFile` instead.
'';
};
passwordFile = mkOption {
type = types.nullOr types.path;
default = null;
example = "/run/keys/gogs-dbpassword";
description = lib.mdDoc ''
A file containing the password corresponding to
{option}`database.user`.
'';
};
path = mkOption {
type = types.str;
default = "${cfg.stateDir}/data/gogs.db";
defaultText = literalExpression ''"''${config.${opt.stateDir}}/data/gogs.db"'';
description = lib.mdDoc "Path to the sqlite3 database file.";
};
};
appName = mkOption {
type = types.str;
default = "Gogs: Go Git Service";
description = lib.mdDoc "Application name.";
};
repositoryRoot = mkOption {
type = types.str;
default = "${cfg.stateDir}/repositories";
defaultText = literalExpression ''"''${config.${opt.stateDir}}/repositories"'';
description = lib.mdDoc "Path to the git repositories.";
};
domain = mkOption {
type = types.str;
default = "localhost";
description = lib.mdDoc "Domain name of your server.";
};
rootUrl = mkOption {
type = types.str;
default = "http://localhost:3000/";
description = lib.mdDoc "Full public URL of Gogs server.";
};
httpAddress = mkOption {
type = types.str;
default = "0.0.0.0";
description = lib.mdDoc "HTTP listen address.";
};
httpPort = mkOption {
type = types.int;
default = 3000;
description = lib.mdDoc "HTTP listen port.";
};
cookieSecure = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Marks session cookies as "secure" as a hint for browsers to only send
them via HTTPS. This option is recommend, if Gogs is being served over HTTPS.
'';
};
extraConfig = mkOption {
type = types.str;
default = "";
description = lib.mdDoc "Configuration lines appended to the generated Gogs configuration file.";
};
};
};
config = mkIf cfg.enable {
systemd.services.gogs = {
description = "Gogs (Go Git Service)";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = [ pkgs.gogs ];
preStart = let
runConfig = "${cfg.stateDir}/custom/conf/app.ini";
secretKey = "${cfg.stateDir}/custom/conf/secret_key";
in ''
mkdir -p ${cfg.stateDir}
# copy custom configuration and generate a random secret key if needed
${optionalString (cfg.useWizard == false) ''
mkdir -p ${cfg.stateDir}/custom/conf
cp -f ${configFile} ${runConfig}
if [ ! -e ${secretKey} ]; then
head -c 16 /dev/urandom | base64 > ${secretKey}
fi
KEY=$(head -n1 ${secretKey})
DBPASS=$(head -n1 ${cfg.database.passwordFile})
sed -e "s,#secretkey#,$KEY,g" \
-e "s,#dbpass#,$DBPASS,g" \
-i ${runConfig}
chmod 440 ${runConfig} ${secretKey}
''}
mkdir -p ${cfg.repositoryRoot}
# update all hooks' binary paths
HOOKS=$(find ${cfg.repositoryRoot} -mindepth 4 -maxdepth 4 -type f -wholename "*git/hooks/*")
if [ "$HOOKS" ]
then
sed -ri 's,/nix/store/[a-z0-9.-]+/bin/gogs,${pkgs.gogs}/bin/gogs,g' $HOOKS
sed -ri 's,/nix/store/[a-z0-9.-]+/bin/env,${pkgs.coreutils}/bin/env,g' $HOOKS
sed -ri 's,/nix/store/[a-z0-9.-]+/bin/bash,${pkgs.bash}/bin/bash,g' $HOOKS
sed -ri 's,/nix/store/[a-z0-9.-]+/bin/perl,${pkgs.perl}/bin/perl,g' $HOOKS
fi
'';
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
WorkingDirectory = cfg.stateDir;
ExecStart = "${pkgs.gogs}/bin/gogs web";
Restart = "always";
};
environment = {
USER = cfg.user;
HOME = cfg.stateDir;
GOGS_WORK_DIR = cfg.stateDir;
};
};
users = mkIf (cfg.user == "gogs") {
users.gogs = {
description = "Go Git Service";
uid = config.ids.uids.gogs;
group = "gogs";
home = cfg.stateDir;
createHome = true;
shell = pkgs.bash;
};
groups.gogs.gid = config.ids.gids.gogs;
};
warnings = optional (cfg.database.password != "")
''config.services.gogs.database.password will be stored as plaintext
in the Nix store. Use database.passwordFile instead.'';
# Create database passwordFile default when password is configured.
services.gogs.database.passwordFile =
(mkDefault (toString (pkgs.writeTextFile {
name = "gogs-database-password";
text = cfg.database.password;
})));
};
}