diff options
Diffstat (limited to 'nixpkgs/pkgs/servers/web-apps/discourse/default.nix')
-rw-r--r-- | nixpkgs/pkgs/servers/web-apps/discourse/default.nix | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/default.nix new file mode 100644 index 000000000000..900d69210923 --- /dev/null +++ b/nixpkgs/pkgs/servers/web-apps/discourse/default.nix @@ -0,0 +1,234 @@ +{ stdenv, makeWrapper, runCommandNoCC, lib, nixosTests +, fetchFromGitHub, bundlerEnv, ruby, replace, gzip, gnutar, git +, util-linux, gawk, imagemagick, optipng, pngquant, libjpeg, jpegoptim +, gifsicle, libpsl, redis, postgresql, which, brotli, procps +, nodePackages, v8 +}: + +let + version = "2.6.3"; + + src = fetchFromGitHub { + owner = "discourse"; + repo = "discourse"; + rev = "v${version}"; + sha256 = "sha256-lAIhVxvmjxEiru1KNxbFV+eDMLUGza/Dma3WU0ex0xs="; + }; + + runtimeDeps = [ + # For backups, themes and assets + rubyEnv.wrappedRuby + gzip + gnutar + git + brotli + + # Misc required system utils + which + procps # For ps and kill + util-linux # For renice + gawk + + # Image optimization + imagemagick + optipng + pngquant + libjpeg + jpegoptim + gifsicle + nodePackages.svgo + ]; + + runtimeEnv = { + HOME = "/run/discourse/home"; + RAILS_ENV = "production"; + UNICORN_LISTENER = "/run/discourse/sockets/unicorn.sock"; + }; + + rake = runCommandNoCC "discourse-rake" { + nativeBuildInputs = [ makeWrapper ]; + } '' + mkdir -p $out/bin + makeWrapper ${rubyEnv}/bin/rake $out/bin/discourse-rake \ + ${lib.concatStrings (lib.mapAttrsToList (name: value: "--set ${name} '${value}' ") runtimeEnv)} \ + --prefix PATH : ${lib.makeBinPath runtimeDeps} \ + --set RAKEOPT '-f ${discourse}/share/discourse/Rakefile' \ + --run 'cd ${discourse}/share/discourse' + ''; + + rubyEnv = bundlerEnv { + name = "discourse-ruby-env-${version}"; + inherit version ruby; + gemdir = ./rubyEnv; + gemset = + let + gems = import ./rubyEnv/gemset.nix; + in + gems // { + mini_racer = gems.mini_racer // { + buildInputs = [ v8 ]; + dontBuild = false; + # The Ruby extension makefile generator assumes the source + # is C, when it's actually C++ ¯\_(ツ)_/¯ + postPatch = '' + substituteInPlace ext/mini_racer_extension/extconf.rb \ + --replace '" -std=c++0x"' \ + '" -x c++ -std=c++0x"' + ''; + }; + mini_suffix = gems.mini_suffix // { + propagatedBuildInputs = [ libpsl ]; + dontBuild = false; + # Use our libpsl instead of the vendored one, which isn't + # available for aarch64 + postPatch = '' + cp $(readlink -f ${libpsl}/lib/libpsl.so) vendor/libpsl.so + ''; + }; + }; + + groups = [ + "default" "assets" "development" "test" + ]; + }; + + assets = stdenv.mkDerivation { + pname = "discourse-assets"; + inherit version src; + + nativeBuildInputs = [ + rubyEnv.wrappedRuby + postgresql + redis + which + brotli + procps + nodePackages.uglify-js + ]; + + # We have to set up an environment that is close enough to + # production ready or the assets:precompile task refuses to + # run. This means that Redis and PostgreSQL has to be running and + # database migrations performed. + preBuild = '' + redis-server >/dev/null & + + initdb -A trust $NIX_BUILD_TOP/postgres >/dev/null + postgres -D $NIX_BUILD_TOP/postgres -k $NIX_BUILD_TOP >/dev/null & + export PGHOST=$NIX_BUILD_TOP + + echo "Waiting for Redis and PostgreSQL to be ready.." + while ! redis-cli --scan >/dev/null || ! psql -l >/dev/null; do + sleep 0.1 + done + + psql -d postgres -tAc 'CREATE USER "discourse"' + psql -d postgres -tAc 'CREATE DATABASE "discourse" OWNER "discourse"' + psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm" + psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS hstore" + + # Create a temporary home dir to stop bundler from complaining + mkdir $NIX_BUILD_TOP/tmp_home + export HOME=$NIX_BUILD_TOP/tmp_home + + export RAILS_ENV=production + + bundle exec rake db:migrate >/dev/null + rm -r tmp/* + ''; + + buildPhase = '' + runHook preBuild + + bundle exec rake assets:precompile + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mv public/assets $out + + runHook postInstall + ''; + }; + + discourse = stdenv.mkDerivation { + pname = "discourse"; + inherit version src; + + buildInputs = [ + rubyEnv rubyEnv.wrappedRuby rubyEnv.bundler + ]; + + patches = [ + # Load a separate NixOS site settings file + ./nixos_defaults.patch + + # Add a noninteractive admin creation task + ./admin_create.patch + + # Disable jhead, which is currently marked as vulnerable + ./disable_jhead.patch + + # Add the path to the CA cert bundle to make TLS work + ./action_mailer_ca_cert.patch + + # Log Unicorn messages to the journal and make request timeout + # configurable + ./unicorn_logging_and_timeout.patch + ]; + + postPatch = '' + # Always require lib-files and application.rb through their store + # path, not their relative state directory path. This gets rid of + # warnings and means we don't have to link back to lib from the + # state directory. + find config -type f -execdir sed -Ei "s,(\.\./)+(lib|app)/,$out/share/discourse/\2/," {} \; + + ${replace}/bin/replace-literal -f -r -e 'File.rename(temp_destination, destination)' "FileUtils.mv(temp_destination, destination)" . + ''; + + buildPhase = '' + runHook preBuild + + mv config config.dist + mv public public.dist + mv plugins plugins.dist + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/share + cp -r . $out/share/discourse + rm -r $out/share/discourse/log + ln -sf /var/log/discourse $out/share/discourse/log + ln -sf /run/discourse/tmp $out/share/discourse/tmp + ln -sf /run/discourse/config $out/share/discourse/config + ln -sf /run/discourse/assets/javascripts/plugins $out/share/discourse/app/assets/javascripts/plugins + ln -sf /run/discourse/public $out/share/discourse/public + ln -sf /run/discourse/plugins $out/share/discourse/plugins + ln -sf ${assets} $out/share/discourse/public.dist/assets + + runHook postInstall + ''; + + meta = with lib; { + homepage = "https://www.discourse.org/"; + platforms = platforms.linux; + maintainers = with maintainers; [ talyz ]; + license = licenses.gpl2Plus; + description = "Discourse is an open source discussion platform"; + }; + + passthru = { + inherit rubyEnv runtimeEnv runtimeDeps rake; + ruby = rubyEnv.wrappedRuby; + tests = nixosTests.discourse; + }; + }; +in discourse |