diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b4ad4c4 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +secrets/** diff=sopsdiffer diff --git a/.gitignore b/.gitignore index dcabe15..460da38 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .direnv/ -result \ No newline at end of file +result +.gcroots +.vscode diff --git a/hosts/goldberg/configuration.nix b/hosts/goldberg/configuration.nix index 33f79d8..f5771d4 100644 --- a/hosts/goldberg/configuration.nix +++ b/hosts/goldberg/configuration.nix @@ -6,6 +6,7 @@ ../../services/mumble.nix ../../services/website.nix ../../services/vaultwarden.nix + ../../services/dokuwiki.nix ]; system.stateVersion = "23.05"; diff --git a/hosts/shirley/configuration.nix b/hosts/shirley/configuration.nix index b22230a..f9af652 100644 --- a/hosts/shirley/configuration.nix +++ b/hosts/shirley/configuration.nix @@ -6,6 +6,7 @@ ../../services/mumble.nix ../../services/website.nix ../../services/vaultwarden.nix + ../../services/dokuwiki.nix ]; system.stateVersion = "23.05"; diff --git a/packages/default.nix b/packages/default.nix index 60518b6..6e5464c 100644 --- a/packages/default.nix +++ b/packages/default.nix @@ -1,4 +1,5 @@ final: prev: + { chaos-jetzt-website-pelican = final.stdenv.mkDerivation { name = "chaos-jetzt-website-pelican"; @@ -21,4 +22,134 @@ final: prev: markdown ]; }; + + dokuwiki = prev.dokuwiki.overrideAttrs (oldAttrs: { + installPhase = '' + ${oldAttrs.installPhase} + + runHook postInstall + ''; + }); + + dokuwikiPlugins = { + tag = final.stdenv.mkDerivation rec { + name = "tag"; + pname = "dokuwiki-plugin-tag"; + version = "2022-10-02"; + src = final.fetchFromGitHub { + owner = "dokufreaks"; + repo = "plugin-tag"; + rev = version; + hash = "sha256-DVO3ZtXTtF8pBroF5VQiR2Vqa/FPxVzq81Jv9e9Z2EU="; + }; + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + pagelist = final.stdenv.mkDerivation rec { + name = "pagelist"; + pname = "dokuwiki-plugin-pagelist"; + version = "2022-09-28"; + src = final.fetchFromGitHub { + owner = "dokufreaks"; + repo = "plugin-pagelist"; + rev = version; + hash = "sha256-IzedBYePVTS6jzWZeORpebsZiRgrnP+57t9mstQWnMQ="; + }; + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + smtp = final.stdenv.mkDerivation { + name = "smtp"; + pname = "dokuwiki-plugin-smtp"; + version = "2022-09-11"; + src = final.fetchFromGitHub { + owner = "splitbrain"; + repo = "dokuwiki-plugin-smtp"; + rev = "31226785e712be0c042f824019c08b7824db90ea"; + hash = "sha256-fwhOePzWGORmjS47/p+MZGhu1YstamlhdTjCxftu9eE="; + }; + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + nspages = final.stdenv.mkDerivation { + name = "nspages"; + pname = "dokuwiki-plugin-nspages"; + version = "2022-11-27"; + src = final.fetchFromGitHub { + owner = "gturri"; + repo = "nspages"; + rev = "2aeaf7dff24d8ce62a93477357e34834436634ff"; + hash = "sha256-U/mP8wtT6qE/MqMxePUt8XPD9kkGLErdWW0RCIQZZMI="; + }; + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + move = final.stdenv.mkDerivation rec { + name = "move"; + pname = "dokuwiki-plugin-move"; + version = "2022-01-23"; + src = final.fetchFromGitHub { + owner = "michitux"; + repo = "dokuwiki-plugin-move"; + rev = version; + hash = "sha256-rQmbaRRFXoZhSPZnEYpiQ/sjGwp/Ij4Q9kCFWqbKLTY="; + }; + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + icalevents = final.stdenv.mkDerivation rec { + name = "icalevents"; + pname = "dokuwiki-plugin-icalevents"; + version = "2017-06-16"; + src = final.fetchzip { + stripRoot = false; + url = "https://github.com/real-or-random/dokuwiki-plugin-icalevents/releases/download/${version}/dokuwiki-plugin-icalevents-${version}.zip"; + hash = "sha256-IPs4+qgEfe8AAWevbcCM9PnyI0uoyamtWeg4rEb+9Wc="; + }; + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + oauth = final.stdenv.mkDerivation { + name = "oauth"; + pname = "dokuwiki-plugin-oauth"; + version = "2022-10-25"; + src = final.fetchFromGitHub { + owner = "cosmocode"; + repo = "dokuwiki-plugin-oauth"; + rev = "da4733221ed7b4fb3ac0e2429499b14ece3d5f2d"; # 2022-10-25 + hash = "sha256-CNRlaieYm/KCjZ9+OP9pMo5SGjJ4CUrNNdL4iVktCcU="; + }; + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + oauthkeycloak = final.stdenv.mkDerivation { + name = "oauthkeycloak"; + pname = "dokuwiki-plugin-oauthkeycloak"; + version = "2022-03-17"; + src = final.fetchFromGitHub { + owner = "YoitoFes"; + repo = "dokuwiki-plugin-oauthkeycloak"; + rev = "28892edb0207d128ddb94fa8a0bd216861a5626b"; + hash = "sha256-nZo61nW9QjJiEo3FpYt1Zt7locuIDQ88AOn/ZnjjYUc="; + }; + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + edittable = final.stdenv.mkDerivation rec { + name = "edittable"; + pname = "dokuwiki-plugin-edittable"; + version = "2022-01-22"; + src = final.fetchFromGitHub { + owner = "cosmocode"; + repo = "edittable"; + rev = version; + hash = "sha256-KzNUcZcK/y4SNdzuQACS+GqrrnaZIJlXFWUcYtfSxWY="; + }; + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + anonip = final.stdenv.mkDerivation rec { + name = "anonip"; + pname = "dokuwiki-plugin-anonip"; + version = "2016-07-06"; + src = final.fetchFromGitHub { + owner = "splitbrain"; + repo = "dokuwiki-plugin-anonip"; + rev = version; + hash = "sha256-11a5vxxPRAPPaT4Qrmdx+LkxnsM/FDwyQr1T5Zcb42k="; + }; + installPhase = "mkdir -p $out; cp -R * $out/"; + }; + }; } diff --git a/secrets/all/secrets.yaml b/secrets/all/secrets.yaml index 278a6a6..d27bb15 100644 --- a/secrets/all/secrets.yaml +++ b/secrets/all/secrets.yaml @@ -1,9 +1,9 @@ #ENC[AES256_GCM,data:yZuJDeNL04htjQK/wCi7tDFzkeurKNWtMcX3YO4ZTIjksZBDMG7/mvAEuVeL5ffWa+faIs/uM1cATaRm4JVDCai5fWR7S2//TRUHAhkDbSYIZHDjFUFGqpWd8T7WVT53TPtX,iv:n1zrjd/QCFNXfYbnaeZviUfeDq+x0Z8skkkcS/dP86o=,tag:2sn+f3m2PH3BIKt4qrqVSw==,type:comment] root_user_password: ENC[AES256_GCM,data:hzwnpYfDNN46Hahf8Vlr01AotR6zuUDqFz/z/XxWx+i3G1p4j03stuKmB//wQSF45T8b+Iuh7PMOrCgwwtRyJVVYnm4q2m2xin+pHQ+/ecr5NgNx6XzsU03DtLLORTCzV4XE4DcMZHQA1g==,iv:bN3hgWYiGGkSIyixZdEt8q41GINlIeO/c/Z0CcAzFik=,tag:Y7xf5NQcvfJaoWYbx88eeA==,type:str] -mail: - smtp_user: ENC[AES256_GCM,data:4/tY1GRD0FuJP+R5tDhEoA==,iv:ByE2qie8s1UhYfUoyT1mizJdTelri+jBuxXIdVz65IE=,tag:4TOWZPB0bwJ3jJTAQl5pgA==,type:str] - smtp_pass: ENC[AES256_GCM,data:c/P1B/OPi8T0ViL4xS62K0wobEa/Xw2OHfVV7clNZyxXIYjXddxKBO2elxGHDlL8UclKgPo=,iv:seVlE/F7313v1R1v4k6zVzCc20SSaYAWLwVnMDWwFhA=,tag:mLHfBlWmmjKgiYm4ZA0+CQ==,type:str] - smtp_host: ENC[AES256_GCM,data:6goxZg5vqCihchZq68zuBA==,iv:ZXeM5RHda81av+jL5by6isYaU9WwdfYsI7RxG99NMwE=,tag:nAHpzt2oekZcOyPEO4nwRQ==,type:str] +smtp: + user: ENC[AES256_GCM,data:cyxh+oTM7MdF31+umMplmA==,iv:maKuY4iXQCg10O8TTenBUl6tMJKt54AycfKQW6sheVw=,tag:4DAUiBBgO5H9O7DwLYZJtQ==,type:str] + pass: ENC[AES256_GCM,data:CkpgvLnQGBzShLkDaHtOHgZ9zwlsEJ+9KFBmHLgBol9Pcadww040clNM0WJgz8NfDIoYF8M=,iv:OIxuwC/XQOBBKdkRb6/5X8pNPLJNKAEI/WCYKhFScPw=,tag:CoAFk7n5AeSue18OXZvjKA==,type:str] + host: ENC[AES256_GCM,data:psXf+lg9433jS1GxH6HQQQ==,iv:wyq/VgWLNs4RbzxNHf4Ave8ZDhQeNPpYXJIdjLLMlr4=,tag:pQ4Wmf+PzSBsHO3eigx91Q==,type:str] sops: kms: [] gcp_kms: [] @@ -28,8 +28,8 @@ sops: UXludFJ5UDEvN2pHMEQweWIvN0NYaFEKB7lVKrsB3eX77iKWwFAXp7LVl+fPcGOl 8CkIBa/rkSWMe0xIetew60wIwx2ZVAv5TTDmKIZyQSTayOpbG3zcdg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2022-12-23T21:12:29Z" - mac: ENC[AES256_GCM,data:5BwRMg8GTjWrxR9g0z6qvni2CnJp8yWngPv0izmWu5+zUEZDj8fsUTr2kMutWwac/AY9Q2o8CRgescGApdr/F+kKXYP83dqS9Ka8MaCVMqenNH97PfXh+kMcsKYdYqIGzi2i1PmTDTmowsPZ8kecEVwZXOqKug2NhT+YWy+cZvQ=,iv:4xxHX0qrt4bSo0M2MEfd3X+XgTVkAGuhdLGopbWY/hQ=,tag:RhVR9qitWecMiH0NCilyJQ==,type:str] + lastmodified: "2022-12-24T21:21:02Z" + mac: ENC[AES256_GCM,data:GbEO+lLUeswXR6Dc9kGlR9YJhXWh7Io6Z/qciolwkrzIwZAA6l6kaWCdw6OJ6gSNBGhWNye+VDdDV2Ow1Ix1hjnZdl3MUlY/LEEmzP1uUjPvNnEjZjxC8ebzNg3rgVqT6W6q9S7D9nPmAzJMgMlzypR/b1ZX5QuzodhotsleVNM=,iv:TJX940f70Vka+hsfDSvm7Jj0klFylRwB+9XbA9pFkRo=,tag:uaJi+5UI/bppLw+hOgyiDg==,type:str] pgp: - created_at: "2022-12-23T19:08:38Z" enc: | diff --git a/secrets/goldberg/secrets.yaml b/secrets/goldberg/secrets.yaml index 8662a8d..2705e3f 100644 --- a/secrets/goldberg/secrets.yaml +++ b/secrets/goldberg/secrets.yaml @@ -5,6 +5,8 @@ synapse: murmur: #ENC[AES256_GCM,data:ionYo3rz6G1ZhOmwBDleXPO7/reeF6tpgA==,iv:4iQ1FYTvxyyNaQDPxHErV0fevsnU5p55wT27nOwMStM=,tag:ynCgbQsvX5ow4+vc2Qz8MQ==,type:comment] registry_password: "" +dokuwiki: + keycloak_key: ENC[AES256_GCM,data:/6+NWA==,iv:61M+OdGx3lCR3uFWmArpYUm9Q4L+pv656V8g257YMTw=,tag:fOESdHA6+bpMMDRbWRFn+A==,type:str] vaultwarden: env: ENC[AES256_GCM,data:mDqHHAjisl0din/q67+zH7NMKLXld9qC0Si6ZREhRStXr6HEFD/QwaGLN86AvUI7sHNf9l4nrgKOht7uXNJrkjuidGsFEEJWkuUOjBRnrtipNKV2YK7giPQXEhH7wTdGeaqxqi4sk90Oq/FoKi2vPkFyNWGOQ5vOXkKKXjjHnbyKIQkIRWya2Dy6IN0CXU8UK0OiQXY3kgEFOyJoqt4sx/HOScHNKkaLb8U+0rpfzxSVyP3oY4o/DFkE51bnd/CNKg3ZK4Ynp/5m7Rs=,iv:aWpDXSp6Ds7cfdw/vfM3I5wcHz0MytnhpIIWEa24LBE=,tag:5YZKo4ZCT57gji8iyBMAiQ==,type:str] sops: @@ -22,8 +24,8 @@ sops: U1lPUWh4WGlTYWdUb0dlNXZaSk9JWU0Kk5CxVOkZO17h0dYifV9s8g7LujLHcE9G /iSC7EVUx+9cbOUiJf6dcomT+np7CHmhfOykPhm4tzrauaTuPEekew== -----END AGE ENCRYPTED FILE----- - lastmodified: "2022-12-23T23:25:37Z" - mac: ENC[AES256_GCM,data:PRTipNdDCYH1b3G/6tuZi3wbp22xwpBTzUxAf+mH9w3/IiLFgs2Wcrr5sNhS3HR6pXL5QBihTlZt2j+2sImFHtxsUSKOzxwSqq5brmY+W1CNxoveXWIWmwhYzrW1MMO8Vhyjgc69dvGPKNGR513XIpo7dUtWcwFh6ZwtQ4WDdkA=,iv:rlgHNkegTWjV6KJ9JJGZVG+8wy7yzT4ZZ1kF8bp7nZM=,tag:PgHGS17TRmWGT4wJ5shT/g==,type:str] + lastmodified: "2022-12-24T23:32:14Z" + mac: ENC[AES256_GCM,data:H6fvAvgQCx/iXcLnId7KW5wQ/xMpW/IELg9saYOC6UBMngXNMAoneEgTtmo89Dbwvc2e1qo5fzkk7XacBTx6SNOq27gwPUyfsNKD/V+VPpJtAV+PH47CoR83pnS0uPbiyCAIJvp+bXBI9LNMBb6VrrqR7NqKva2BG528n6b3LUQ=,iv:9KyBPOKu4swk6IZCNt/xI9DKqeuwyG7z1aEXIXDxVvg=,tag:hIVSBQd/85C0+sEiCKGQ/w==,type:str] pgp: - created_at: "2022-12-23T19:08:40Z" enc: | diff --git a/services/dokuwiki.nix b/services/dokuwiki.nix new file mode 100644 index 0000000..33e252d --- /dev/null +++ b/services/dokuwiki.nix @@ -0,0 +1,215 @@ +{ + pkgs, + config, + lib, + baseDomain, + ... +}: let + inherit (builtins) any hasAttr isAttrs isBool isInt isList isString; + inherit (lib) boolToString concatMapStringsSep concatStringsSep escapeShellArg flatten mapAttrsToList; + + cfg = config.services.dokuwiki.sites.${dw_domain}; + fpm_pool = "dokuwiki-${dw_domain}"; + fpm_cfg = config.services.phpfpm.pools.${fpm_pool}; + dw_domain = "wiki.${baseDomain}"; + + # Comming from Nextcloud module + # Using opcache to cache the php-files in a precompiled state and thus better performance + phpOptions = { + expose_php = "Off"; + "opcache.interned_strings_buffer" = "8"; + "opcache.max_accelerated_files" = "10000"; + "opcache.memory_consumption" = "64"; + "opcache.revalidate_freq" = "15"; + "opcache.fast_shutdown" = "1"; + }; + phpPackage = pkgs.php81.buildEnv { + extraConfig = toKeyValue phpOptions; + }; + toKeyValue = with lib; + generators.toKeyValue { + mkKeyValue = generators.mkKeyValueDefault {} " = "; + }; + + # Taken + mkPHPValue = v: let + isHasAttr = s: isAttrs v && hasAttr s v; + in + if isString v + then escapeShellArg v + # NOTE: If any value contains a , (comma) this will not get escaped + else if isList v && any lib.strings.isCoercibleToString v + then escapeShellArg (concatMapStringsSep "," toString v) + else if isInt v + then toString v + else if isBool v + then toString (if v then 1 else 0) + else if isHasAttr "_file" + then "trim(file_get_contents(${lib.escapeShellArg v._file}))" + else abort "The dokuwiki settings value ${lib.generators.toPretty {} v} can not be encoded."; + + # Present until https://github.com/NixOS/nixpkgs/pull/208299 is merged + # so we can still use RFC42-Style settings in the meantime + mkPHPAttrVals = v: flatten (mapAttrsToList mkPHPKeyVal v); + mkPHPKeyVal = k: v: let + values = + if (isAttrs v && hasAttr "_file" v) || !isAttrs v + then [" = ${mkPHPValue v};"] + else mkPHPAttrVals v; + in + map (e: "[${escapeShellArg k}]${e}") (flatten values); + mkConfigLines = c: map (v: "$conf${v}") (mkPHPAttrVals c); + + dokuwikiLocalConfig = settings: '' + ${concatStringsSep "\n" (mkConfigLines settings)} + ''; + + acronyms = rec { + "CCC" = "Chaos Computer Club"; + "PR" = "Pull Request"; + "pr" = PR; + "GH" = "GitHub"; + "gh" = GH; + "SSO" = "Single Sign-on"; + "sso" = SSO; + "CTFL" = "Chaostreff Flensburg e.V."; + "ctfl" = SSO; + }; + + acronyms_file = pkgs.writeText "acronyms.local.conf" '' + ${lib.concatStringsSep "\n" (lib.mapAttrsToList (short: long: "${short}\t${long}") acronyms)} + ''; +in { + sops.secrets = let + dw.owner = fpm_cfg.user; # This is hardcoded to dokuwiki right now, however if that changes we should catch that here + dw_all = key: + dw + // { + inherit key; + format = "yaml"; + sopsFile = ../secrets/all/secrets.yaml; + }; + in { + "dokuwiki/smtp_pass" = dw_all "smtp/pass"; + "dokuwiki/smtp_user" = dw_all "smtp/user"; + "dokuwiki/smtp_host" = dw_all "smtp/host"; + "dokuwiki/keycloak_key" = dw; + }; + + services.nginx.virtualHosts.${dw_domain} = { + enableACME = true; + forceSSL = true; + # Disable search engine indexing + # Reasong being that for example a search engine of your choosing can be used to find content + # in relation to peoples (nick)name and stuff. + locations."/robots.txt".return = "200 \"User-agent: *\nDisallow: /\""; + }; + + services.phpfpm.pools.${fpm_pool}.phpPackage = lib.mkForce phpPackage; + + services.dokuwiki.sites.${dw_domain} = { + package = pkgs.dokuwiki.overrideAttrs (oldAttrs: { + name = "dokuwiki-${dw_domain}-with-acronyms-${oldAttrs.version}"; + postInstall = oldAttrs.postInstall or "" + '' + ln -s ${acronyms_file} $out/share/dokuwiki/conf/acronyms.local.conf + ''; + }); + + enable = true; + aclUse = true; + + pluginsConfig = let + plugins = { + "tag" = true; + "pagelist" = true; + "smtp" = true; + "sqlite" = true; + "nspages" = true; + "move" = true; + "icalevents" = true; + "legalnotice" = true; + "oauth" = true; + "oauthkeycloak" = true; + "edittable" = true; + "anonip" = true; + + "extension" = false; + "popularity" = false; + "authad" = false; + "authldap" = false; + "authmysql" = false; + "authpdo" = false; + "authpgsql" = false; + }; + in '' + # Placeholder until https://github.com/NixOS/nixpkgs/pull/208299 is merged + ${concatStringsSep "\n" (mapAttrsToList (n: v: "$plugins['${n}'] = ${boolToString v};") plugins)}; + ''; + + plugins = with pkgs.dokuwikiPlugins; [ + tag + pagelist + smtp + nspages + move + icalevents + oauth + oauthkeycloak + edittable + anonip + ]; + + extraConfig = let + get_secret = name: {_file = config.sops.secrets.${name}.path;}; + settings = rec { + title = "${baseDomain} Wiki"; + lang = "de-informal"; + template = "dokuwiki"; + # authtype = "authplain"; + authtype = "oauth"; + subscribers = 1; + userewrite = 1; + useslash = 1; + im_convert = "${pkgs.imagemagick}/bin/convert"; + superuser = "@admin"; + disableactions = "register"; + signature = "--- // [[name:@USER@|@USER@]] @DATE@"; + + mailfrom = "\"@USER@\" via ${title} }"; + plugin.tag.toolbar_icon = 1; + plugin.smtp = { + smtp_host = get_secret "dokuwiki/smtp_host"; + smtp_user = get_secret "dokuwiki/smtp_host"; + smtp_pass = get_secret "dokuwiki/smtp_host"; + smtp_ssl = "ssl"; + smtp_port = 465; + }; + plugin.icalevents = { + locationUrlPrefix = ""; + "template:default" = '' + === {date}: {summary} === + **Location**: {location_link} + {description}''; + "template:list" = '' + === {date}: {summary} === + **Location: {location}** + {description}''; + "template:custom1" = '' + === {date}: {summary} === + {description} + **Wo?**: {location_link}''; + }; + plugin.oauth = { + register-on-auth = 1; + singleService = "Keycloak"; + }; + plugin.oauthkeycloak = { + key = get_secret "dokuwiki/keycloak_key"; + openidurl = "https://sso.chaos.jetzt/auth/realms/chaos-jetzt/.well-known/openid-configuration"; + }; + }; + in '' + ${dokuwikiLocalConfig settings} + ''; + }; +}