Module for gitit
This commit is contained in:
commit
78340b56f7
27
flake.lock
generated
Normal file
27
flake.lock
generated
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1640871638,
|
||||
"narHash": "sha256-ty6sGnJUQEkCd43At5U3DRQZD7rPARz5VginSW6hZ3k=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5b091d4fbe3b7b7493c3b46fe0842e4b30ea24b3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
54
flake.nix
Normal file
54
flake.nix
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
outputs = { self, nixpkgs }: rec {
|
||||
overlay = final: prev: {
|
||||
gitit = prev.callPackage ./gitit.nix {};
|
||||
};
|
||||
|
||||
# Provide module for gitit
|
||||
nixosModules = builtins.listToAttrs (map (x: {
|
||||
name = x;
|
||||
value = import (./modules + "/${x}");
|
||||
}) (builtins.attrNames (builtins.readDir ./modules)));
|
||||
|
||||
# Provide the gitit binary. nixpkgs does provide the binary as well, but
|
||||
# it's built from a version that has a critical bug, login doesn't work
|
||||
packages.x86_64-linux.gitit = with nixpkgs.legacyPackages.x86_64-linux;
|
||||
callPackage ./gitit {};
|
||||
defaultPackage.x86_64-linux = packages.x86_64-linux.gitit;
|
||||
|
||||
# Nixos integration tests for basic functionality
|
||||
checks.x86_64-linux.gitit =
|
||||
nixpkgs.legacyPackages.x86_64-linux.nixosTest (
|
||||
import ./test.nix { modules = builtins.attrValues self.nixosModules; }
|
||||
);
|
||||
|
||||
# For playing around in a container
|
||||
# sudo nixos-container create gitit --flake .
|
||||
nixosConfigurations.container = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules =
|
||||
[ ({ pkgs, ... }: {
|
||||
imports = builtins.attrValues self.nixosModules ++ [];
|
||||
boot.isContainer = true;
|
||||
environment.systemPackages = [
|
||||
];
|
||||
|
||||
|
||||
# Let 'nixos-version --json' know about the Git revision
|
||||
# of this flake.
|
||||
system.configurationRevision = nixpkgs.lib.mkIf (self ? rev) self.rev;
|
||||
|
||||
# Network configuration.
|
||||
networking.useDHCP = false;
|
||||
networking.firewall.allowedTCPPorts = [ 5001 ];
|
||||
|
||||
services.gitit = {
|
||||
enable = true;
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
}
|
40
gitit/cabal.nix
Normal file
40
gitit/cabal.nix
Normal file
@ -0,0 +1,40 @@
|
||||
{ mkDerivation, aeson, base, base64-bytestring, blaze-html
|
||||
, bytestring, ConfigFile, containers, directory, doctemplates, feed
|
||||
, fetchgit, filepath, filestore, ghc, ghc-paths, happstack-server
|
||||
, hoauth2, hslogger, HStringTemplate, HTTP, http-client-tls
|
||||
, http-conduit, json, lib, mtl, network, network-bsd, network-uri
|
||||
, old-locale, old-time, pandoc, pandoc-types, parsec, pretty
|
||||
, process, random, recaptcha, safe, SHA, skylighting, split, syb
|
||||
, tagsoup, temporary, text, time, uri-bytestring, url, utf8-string
|
||||
, uuid, xhtml, xml, xml-conduit, xml-types, xss-sanitize, zlib
|
||||
}:
|
||||
mkDerivation {
|
||||
pname = "gitit";
|
||||
version = "0.15.1.0";
|
||||
src = fetchgit {
|
||||
url = "https://github.com/jgm/gitit";
|
||||
sha256 = "0rzjgi6q338n6cv74438q81v322x2wjrpa7zdvp47z6hrilwpqaa";
|
||||
rev = "11a18b034cc49ddaca652ac745fd308405a1fdad";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
isLibrary = true;
|
||||
isExecutable = true;
|
||||
enableSeparateDataOutput = true;
|
||||
libraryHaskellDepends = [
|
||||
aeson base base64-bytestring blaze-html bytestring ConfigFile
|
||||
containers directory doctemplates feed filepath filestore ghc
|
||||
ghc-paths happstack-server hoauth2 hslogger HStringTemplate HTTP
|
||||
http-client-tls http-conduit json mtl network network-bsd
|
||||
network-uri old-locale old-time pandoc pandoc-types parsec pretty
|
||||
process random recaptcha safe SHA skylighting split syb tagsoup
|
||||
temporary text time uri-bytestring url utf8-string uuid xhtml xml
|
||||
xml-conduit xml-types xss-sanitize zlib
|
||||
];
|
||||
executableHaskellDepends = [
|
||||
base bytestring directory filepath hslogger HTTP mtl network
|
||||
network-uri syb text url utf8-string
|
||||
];
|
||||
description = "Wiki using happstack, git or darcs, and pandoc";
|
||||
license = "GPL";
|
||||
}
|
||||
|
62
gitit/default.nix
Normal file
62
gitit/default.nix
Normal file
@ -0,0 +1,62 @@
|
||||
{ lib, haskellPackages, haskell, removeReferencesTo
|
||||
# “Plugins” are a fancy way of saying gitit will invoke
|
||||
# GHC at *runtime*, which in turn makes it pull GHC
|
||||
# into its runtime closure. Only enable if you really need
|
||||
# that feature. But if you do you’ll want to use gitit
|
||||
# as a library anyway.
|
||||
, pluginSupport ? false
|
||||
}:
|
||||
|
||||
# this is similar to what we do with the pandoc executable
|
||||
|
||||
let
|
||||
plain = haskellPackages.callPackage ./cabal.nix {};
|
||||
plugins =
|
||||
if pluginSupport
|
||||
then plain
|
||||
else haskell.lib.compose.disableCabalFlag "plugins" plain;
|
||||
static = haskell.lib.compose.justStaticExecutables plugins;
|
||||
|
||||
in
|
||||
(haskell.lib.compose.overrideCabal (drv: {
|
||||
buildTools = (drv.buildTools or []) ++ [ removeReferencesTo ];
|
||||
}) static).overrideAttrs (drv: {
|
||||
|
||||
# These libraries are still referenced, because they generate
|
||||
# a `Paths_*` module for figuring out their version.
|
||||
# The `Paths_*` module is generated by Cabal, and contains the
|
||||
# version, but also paths to e.g. the data directories, which
|
||||
# lead to a transitive runtime dependency on the whole GHC distribution.
|
||||
# This should ideally be fixed in haskellPackages (or even Cabal),
|
||||
# but a minimal gitit is important enough to patch it manually.
|
||||
disallowedReferences = [
|
||||
haskellPackages.pandoc-types
|
||||
haskellPackages.HTTP
|
||||
haskellPackages.pandoc
|
||||
haskellPackages.happstack-server
|
||||
haskellPackages.filestore
|
||||
];
|
||||
postInstall = ''
|
||||
remove-references-to \
|
||||
-t ${haskellPackages.pandoc-types} \
|
||||
$out/bin/gitit
|
||||
remove-references-to \
|
||||
-t ${haskellPackages.HTTP} \
|
||||
$out/bin/gitit
|
||||
remove-references-to \
|
||||
-t ${haskellPackages.pandoc} \
|
||||
$out/bin/gitit
|
||||
remove-references-to \
|
||||
-t ${haskellPackages.happstack-server} \
|
||||
$out/bin/gitit
|
||||
remove-references-to \
|
||||
-t ${haskellPackages.filestore} \
|
||||
$out/bin/gitit
|
||||
'';
|
||||
|
||||
meta = drv.meta // {
|
||||
maintainers = drv.meta.maintainers or []
|
||||
++ [ lib.maintainers.Profpatsch ];
|
||||
};
|
||||
})
|
||||
|
159
modules/gitit/default.nix
Normal file
159
modules/gitit/default.nix
Normal file
@ -0,0 +1,159 @@
|
||||
{ config, lib, pkgs, ...}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.gitit;
|
||||
yesNo = b: if b then "yes" else "no";
|
||||
gititConf = with cfg; pkgs.writeText "gitit.conf" ''
|
||||
address: ${address}
|
||||
port: ${toString port}
|
||||
wiki-title: ${wiki-title}
|
||||
repository-type: Git
|
||||
repository-path: /var/lib/gitit/wikidata
|
||||
require-authentication: ${require-authentication}
|
||||
authentication-method: ${authentication-method}
|
||||
static-dir: ${toString static-dir}
|
||||
templates-dir: ${toString templates-dir}
|
||||
cache-dir: /var/lib/gitit/cache
|
||||
log-file: /var/lib/gitit/gitit.log
|
||||
disable-registration: ${yesNo disable-registration}
|
||||
access-question: ${access-question}
|
||||
access-question-answers: ${access-question-answers}
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options.services.gitit = {
|
||||
enable = mkEnableOption "gitit";
|
||||
address = mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0";
|
||||
description = "Sets the IP address on which the web server will listen.";
|
||||
};
|
||||
port = mkOption {
|
||||
type = lib.types.int;
|
||||
default = 5001;
|
||||
description = "Sets the port on which the web server will run.";
|
||||
};
|
||||
disable-registration = mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "If true, disables registering new users on the wiki";
|
||||
};
|
||||
wiki-title = mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Wiki";
|
||||
description = "The title of the wiki.";
|
||||
};
|
||||
access-question = mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
specifies a question that users must answer when they attempt to create
|
||||
an account, along with a comma-separated list of acceptable answers.
|
||||
This can be used to institute a rudimentary password for signing up as
|
||||
a user on the wiki, or as an alternative to reCAPTCHA.
|
||||
Example:
|
||||
access-question: What is the code given to you by Ms. X?
|
||||
access-question-answers: RED DOG, red dog
|
||||
'';
|
||||
};
|
||||
access-question-answers = mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
specifies the answer that users must answer when they attempt to create
|
||||
an account, along with a comma-separated list of acceptable answers.
|
||||
This can be used to institute a rudimentary password for signing up as
|
||||
a user on the wiki, or as an alternative to reCAPTCHA.
|
||||
Example:
|
||||
access-question: What is the code given to you by Ms. X?
|
||||
access-question-answers: RED DOG, red dog
|
||||
'';
|
||||
};
|
||||
require-authentication = mkOption {
|
||||
type = lib.types.enum ["none" "read" "modify"];
|
||||
default = "modify";
|
||||
description = ''
|
||||
if 'none' login is never required, and pages can be edited anonymously.
|
||||
if 'modify', login is required to modify the wiki (edit, add, delete pages, upload files)
|
||||
if 'read', login is required to see any wiki pages
|
||||
'';
|
||||
};
|
||||
static-dir = mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/gitit/data/static";
|
||||
description = ''
|
||||
specifies the path of the static directory (containing javascript, css,
|
||||
and images). If it does not exist, gitit will create it and populate it
|
||||
with required scripts, stylesheets and images.
|
||||
'';
|
||||
};
|
||||
templates-dir = mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/gitit/data/templates";
|
||||
description = ''
|
||||
specifies the path of the directory containing page templates. If it
|
||||
does not exist, gitit will create it with default templates. Users may
|
||||
with to edit the templates to customize the appearance of their wiki.
|
||||
The template files are HStringTemplate templates. Variables to be
|
||||
interpolated appear between $'s. Literal $'s must be backslash-escaped.
|
||||
'';
|
||||
};
|
||||
authentication-method = mkOption {
|
||||
type = lib.types.enum ["form" "http" "generic"];
|
||||
default = "form";
|
||||
description = ''
|
||||
'form' means that users will be logged in and registered using forms in
|
||||
the gitit web interface.
|
||||
|
||||
'http' means that gitit will assume that HTTP authentication is in
|
||||
place and take the logged in username from the "Authorization" field of
|
||||
the HTTP request header (in addition, the login/logout and registration
|
||||
links will be suppressed).
|
||||
|
||||
'generic' means that gitit will assume that some form of authentication
|
||||
is in place that directly sets REMOTE_USER to the name of the
|
||||
authenticated user (e.g. mod_auth_cas on apache).
|
||||
|
||||
'rpx' means that gitit will attempt to log in through
|
||||
https://rpxnow.com. This requires that 'rpx-domain', 'rpx-key', and
|
||||
'base-url' be set below, and that 'curl' be in the system path.
|
||||
|
||||
'github' means that you are redirected to github website and need to
|
||||
avail gitit to use your credential from there (github name and email).
|
||||
Your email is used to identify you when you push your wiki data to git
|
||||
to identify you as the author
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.users.gitit = {
|
||||
home = "/var/lib/gitit";
|
||||
createHome = true;
|
||||
isSystemUser = true;
|
||||
group = "gitit";
|
||||
};
|
||||
users.groups.gitit = {};
|
||||
systemd.services.gitit = {
|
||||
description = "Git and Pandoc Powered Wiki";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = with pkgs; [ curl git ];
|
||||
preStart = ''
|
||||
chown gitit:gitit -R /var/lib/gitit
|
||||
'';
|
||||
serviceConfig = {
|
||||
User = config.users.users.gitit.name;
|
||||
Group = config.users.groups.gitit.name;
|
||||
ExecStart = "${pkgs.gitit}/bin/gitit -f ${gititConf}";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
57
test.nix
Normal file
57
test.nix
Normal file
@ -0,0 +1,57 @@
|
||||
{ modules }:
|
||||
{
|
||||
machine = { config, pkgs, lib, ... }:
|
||||
{
|
||||
imports = modules;
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.curl
|
||||
];
|
||||
|
||||
services.gitit = {
|
||||
enable = true;
|
||||
port = 4001;
|
||||
wiki-title = "Test Wiki";
|
||||
address = "127.0.0.1";
|
||||
};
|
||||
|
||||
networking.extraHosts = ''
|
||||
127.0.0.1 wiki.local
|
||||
'';
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts."wiki.local" = {
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:4001";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
testScript =
|
||||
let username = "foo";
|
||||
password = "foobar123";
|
||||
form = "'username=${username}&email=&full_name_1=&password=${password}&password2=${password}&destination=%2F_index®ister=Register'";
|
||||
in
|
||||
''
|
||||
start_all()
|
||||
|
||||
machine.wait_for_unit("gitit.service")
|
||||
machine.wait_for_open_port(4001)
|
||||
|
||||
if "Test Wiki" not in machine.succeed("curl -sS http://localhost:4001"):
|
||||
raise Exception("Title not set properly")
|
||||
machine.succeed("curl --data-raw ${form} 'http://localhost:4001/_register?destination=%2F_index'")
|
||||
|
||||
machine.wait_for_unit("nginx.service")
|
||||
machine.wait_for_open_port(80)
|
||||
|
||||
if "Test Wiki" not in machine.succeed("curl -sS http://wiki.local:80"):
|
||||
raise Exception("Wiki not available through nginx")
|
||||
'';
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user