{ config, pkgs, lib, ... }: let domain = "git.25120.org"; giteaCustom = pkgs.callPackage ../packages/directory.nix { name = "gitea-custom"; source = ./gitea-custom; }; in { services.gitea = { enable = true; appName = "${domain}"; database = { type = "postgres"; passwordFile = "/secrets/gitea_db_password"; createDatabase = false; }; domain = "${domain}"; rootUrl = "https://${domain}/"; httpPort = 3001; repositoryRoot = "/data/git/repositories"; lfs = { enable = true; contentDir = "/data/git/data/lfs"; }; settings = let docutils = pkgs.python310.withPackages (ps: with ps; [ docutils # Provides rendering of ReStructured Text files pygments # Provides syntax highlighting ]); nbconvert = pkgs.python310.withPackages (ps: with ps; [ jupyter nbconvert ]); max_cached_jupyter_notebooks = 200; cached_jupyter_preview = pkgs.writeScript "cache_preview" '' #!${pkgs.bash}/bin/bash set -eu input_file="$1" command="${nbconvert}/bin/jupyter nbconvert --stdout --to html --template basic" cache_directory="${config.services.gitea.stateDir}/markup_cache/jupyter" max_cache_file_count="${toString max_cached_jupyter_notebooks}" cache_file="$cache_directory/$(md5sum "$input_file" | cut -d' ' -f1)" if [ -e "$cache_file" ] ; then >&2 echo "Using cached file $cache_file" touch "$cache_file" else ( if cd "$cache_directory" ; then ls -t | tail -n "+$max_cache_file_count" | xargs -r rm else mkdir -p "$cache_directory" fi ) eval "$command \"$input_file\" > \"$cache_file\"" fi cat "$cache_file" ''; in { server.SSH_PORT = lib.head config.services.openssh.ports; service.DISABLE_REGISTRATION = true; session.COOKIE_SECURE = true; "markup.restructuredtext" = { ENABLED = true; FILE_EXTENSIONS = ".rst"; RENDER_COMMAND = "${docutils}/bin/rst2html.py"; IS_INPUT_FILE = false; }; "markup.jupyter" = { ENABLED = true; FILE_EXTENSIONS = ".ipynb"; #RENDER_COMMAND = "\"${nbconvert}/bin/jupyter nbconvert --stdout --to html --template basic \""; RENDER_COMMAND = "\"${cached_jupyter_preview} \""; IS_INPUT_FILE = true; # RENDER_CONTENT_MODE = "iframe"; }; "markup.sanitizer.jupyter.div" = { ELEMENT = "div"; ALLOW_ATTR = "class"; REGEXP = ""; }; "markup.sanitizer.jupyter.span" = { ELEMENT = "span"; ALLOW_ATTR = "class"; REGEXP = ""; }; "markup.sanitizer.jupyter.img" = { ELEMENT = "img"; ALLOW_ATTR = "class"; REGEXP = ""; ALLOW_DATA_URI_IMAGES = "true"; }; "markup.sanitizer.jupyter.svg.width" = { ELEMENT = "svg"; ALLOW_ATTR = "width"; REGEXP = ""; }; "markup.sanitizer.jupyter.svg.height" = { ELEMENT = "svg"; ALLOW_ATTR = "height"; REGEXP = ""; }; "markup.sanitizer.jupyter.svg.viewbox" = { ELEMENT = "svg"; ALLOW_ATTR = "viewbox"; REGEXP = ""; }; "markup.sanitizer.jupyter.svg.use" = { ELEMENT = "use"; ALLOW_ATTR = "transform"; REGEXP = ""; }; "markup.sanitizer.jupyter.svg.g" = { ELEMENT = "g"; ALLOW_ATTR = "class"; REGEXP = ""; }; "markup.sanitizer.jupyter.svg.path.style" = { ELEMENT = "path"; ALLOW_ATTR = "style"; REGEXP = ""; }; "markup.sanitizer.jupyter.svg.path.d" = { ELEMENT = "path"; ALLOW_ATTR = "d"; REGEXP = ""; }; "markup.sanitizer.jupyter.svg.path.transform" = { ELEMENT = "path"; ALLOW_ATTR = "transform"; REGEXP = ""; }; }; }; services.postgresql = { enable = true; authentication = '' local gitea all ident map=gitea-users ''; # Map the gitea user to postgresql identMap = '' gitea-users gitea gitea ''; }; services.nginx = { enable = true; recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; virtualHosts."${domain}" = { enableACME = true; forceSSL = true; locations."/".proxyPass = "http://localhost:3001/"; }; }; # users.users.gitea.extraGroups = [ "keys" ]; systemd.services.gitea = { serviceConfig = { ReadOnlyPaths = [ "/secrets" ]; }; preStart = '' cp -frT "${giteaCustom}/" "${config.services.gitea.stateDir}/custom/" find "${config.services.gitea.stateDir}/custom/" -type d -exec chmod 0750 '{}' + -or -type f -exec chmod 0640 '{}' + ''; }; networking.firewall.allowedTCPPorts = [ 80 443 ]; }