plausible: 2.0.0 -> 2.1.4

This commit is contained in:
Alexander Sieg 2024-11-22 14:52:18 +02:00
commit e8c9fa5bc8
6 changed files with 115 additions and 164 deletions

View file

@ -15,15 +15,6 @@ After that, `plausible` can be deployed like this:
{
services.plausible = {
enable = true;
adminUser = {
# activate is used to skip the email verification of the admin-user that's
# automatically created by plausible. This is only supported if
# postgresql is configured by the module. This is done by default, but
# can be turned off with services.plausible.database.postgres.setup.
activate = true;
email = "admin@localhost";
passwordFile = "/run/secrets/plausible-admin-pwd";
};
server = {
baseUrl = "http://analytics.example.org";
# secretKeybaseFile is a path to the file which contains the secret generated

View file

@ -11,33 +11,6 @@ in {
package = mkPackageOption pkgs "plausible" { };
adminUser = {
name = mkOption {
default = "admin";
type = types.str;
description = ''
Name of the admin user that plausible will created on initial startup.
'';
};
email = mkOption {
type = types.str;
example = "admin@localhost";
description = ''
Email-address of the admin-user.
'';
};
passwordFile = mkOption {
type = types.either types.str types.path;
description = ''
Path to the file which contains the password of the admin user.
'';
};
activate = mkEnableOption "activating the freshly created admin-user";
};
database = {
clickhouse = {
setup = mkEnableOption "creating a clickhouse instance" // { default = true; };
@ -164,18 +137,13 @@ in {
imports = [
(mkRemovedOptionModule [ "services" "plausible" "releaseCookiePath" ] "Plausible uses no distributed Erlang features, so this option is no longer necessary and was removed")
(mkRemovedOptionModule [ "services" "plausible" "adminUser" "name" ] "Admin user is now created using first start wizard")
(mkRemovedOptionModule [ "services" "plausible" "adminUser" "email" ] "Admin user is now created using first start wizard")
(mkRemovedOptionModule [ "services" "plausible" "adminUser" "passwordFile" ] "Admin user is now created using first start wizard")
(mkRemovedOptionModule [ "services" "plausible" "adminUser" "activate" ] "Admin user is now created using first start wizard")
];
config = mkIf cfg.enable {
assertions = [
{ assertion = cfg.adminUser.activate -> cfg.database.postgres.setup;
message = ''
Unable to automatically activate the admin-user if no locally managed DB for
postgres (`services.plausible.database.postgres.setup') is enabled!
'';
}
];
services.postgresql = mkIf cfg.database.postgres.setup {
enable = true;
};
@ -243,11 +211,7 @@ in {
# Home is needed to connect to the node with iex
HOME = "/var/lib/plausible";
ADMIN_USER_NAME = cfg.adminUser.name;
ADMIN_USER_EMAIL = cfg.adminUser.email;
DATABASE_SOCKET_DIR = cfg.database.postgres.socket;
DATABASE_NAME = cfg.database.postgres.dbname;
DATABASE_URL = "postgresql:///${cfg.database.postgres.dbname}?host=${cfg.database.postgres.socket}";
CLICKHOUSE_DATABASE_URL = cfg.database.clickhouse.url;
BASE_URL = cfg.server.baseUrl;
@ -270,7 +234,6 @@ in {
# even though we set `RELEASE_DISTRIBUTION=none` so the cookie should be unused.
# Thus, make a random one, which should then be ignored.
export RELEASE_COOKIE=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 20)
export ADMIN_USER_PWD="$(< $CREDENTIALS_DIRECTORY/ADMIN_USER_PWD )"
export SECRET_KEY_BASE="$(< $CREDENTIALS_DIRECTORY/SECRET_KEY_BASE )"
${lib.optionalString (cfg.mail.smtp.passwordFile != null)
@ -283,10 +246,6 @@ in {
${cfg.package}/migrate.sh
export IP_GEOLOCATION_DB=${pkgs.dbip-country-lite}/share/dbip/dbip-country-lite.mmdb
${cfg.package}/bin/plausible eval "(Plausible.Release.prepare() ; Plausible.Auth.create_user(\"$ADMIN_USER_NAME\", \"$ADMIN_USER_EMAIL\", \"$ADMIN_USER_PWD\"))"
${optionalString cfg.adminUser.activate ''
psql -d plausible <<< "UPDATE users SET email_verified=true where email = '$ADMIN_USER_EMAIL';"
''}
exec plausible start
'';
@ -297,7 +256,6 @@ in {
WorkingDirectory = "/var/lib/plausible";
StateDirectory = "plausible";
LoadCredential = [
"ADMIN_USER_PWD:${cfg.adminUser.passwordFile}"
"SECRET_KEY_BASE:${cfg.server.secretKeybaseFile}"
] ++ lib.optionals (cfg.mail.smtp.passwordFile != null) [ "SMTP_USER_PWD:${cfg.mail.smtp.passwordFile}"];
};

View file

@ -1,18 +1,13 @@
import ./make-test-python.nix ({ pkgs, lib, ... }: {
import ./make-test-python.nix ({ lib, ... }: {
name = "plausible";
meta = with lib.maintainers; {
maintainers = [ ];
meta = {
maintainers = lib.teams.cyberus.members;
};
nodes.machine = { pkgs, ... }: {
virtualisation.memorySize = 4096;
services.plausible = {
enable = true;
adminUser = {
email = "admin@example.org";
passwordFile = "${pkgs.writeText "pwd" "foobar"}";
activate = true;
};
server = {
baseUrl = "http://localhost:8000";
secretKeybaseFile = "${pkgs.writeText "dont-try-this-at-home" "nannannannannannannannannannannannannannannannannannannan_batman!"}";
@ -32,21 +27,5 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
machine.succeed("curl -f localhost:8000 >&2")
machine.succeed("curl -f localhost:8000/js/script.js >&2")
csrf_token = machine.succeed(
"curl -c /tmp/cookies localhost:8000/login | grep '_csrf_token' | sed -E 's,.*value=\"(.*)\".*,\\1,g'"
)
machine.succeed(
f"curl -b /tmp/cookies -f -X POST localhost:8000/login -F email=admin@example.org -F password=foobar -F _csrf_token={csrf_token.strip()} -D headers"
)
# By ensuring that the user is redirected to the dashboard after login, we
# also make sure that the automatic verification of the module works.
machine.succeed(
"[[ $(grep 'location: ' headers | cut -d: -f2- | xargs echo) == /sites* ]]"
)
machine.shutdown()
'';
})

View file

@ -1,35 +1,51 @@
{ lib
, beamPackages
, buildNpmPackage
, fetchFromGitHub
, nodejs
, nixosTests
, ...
{
lib,
beamPackages,
buildNpmPackage,
rustPlatform,
fetchFromGitHub,
nodejs,
runCommand,
nixosTests,
npm-lockfile-fix,
brotli,
tailwindcss,
esbuild,
...
}:
let
pname = "plausible";
version = "2.0.0";
version = "2.1.4";
mixEnv = "ce";
src = fetchFromGitHub {
owner = "plausible";
repo = "analytics";
rev = "v${version}";
hash = "sha256-yrTwxBguAZbfEKucUL+w49Hr6D7v9/2OjY1h27+w5WI=";
};
# TODO consider using `mix2nix` as soon as it supports git dependencies.
mixFodDeps = beamPackages.fetchMixDeps {
pname = "${pname}-deps";
inherit src version;
hash = "sha256-CAyZLpjmw1JreK3MopqI0XsWhP+fJEMpXlww7CibSaM=";
hash = "sha256-wV2zzRKJM5pQ06pF8vt1ieFqv6s3HvCzNT5Hed29Owk=";
postFetch = ''
${lib.getExe npm-lockfile-fix} $out/assets/package-lock.json
sed -ie '
/defp deps do/ {
n
/\[/ a\
\{:rustler, ">= 0.0.0", optional: true \},
}
' $out/mix.exs
cat >> $out/config/config.exs <<EOF
config :mjml, Mjml.Native,
crate: :mjml_nif,
skip_compilation?: true
EOF
'';
};
assets = buildNpmPackage {
pname = "${pname}-assets";
inherit version;
src = "${src}/assets";
npmDepsHash = "sha256-2t1M6RQhBjZxx36qawVUVC+ob9SvQIq5dy4HgVeY2Eo=";
npmDepsHash = "sha256-Rf1+G9F/CMK09KEh022vHe02FADJtARKX4QEVbmvSqk=";
dontNpmBuild = true;
installPhase = ''
runHook preInstall
@ -42,7 +58,7 @@ let
pname = "${pname}-tracker";
inherit version;
src = "${src}/tracker";
npmDepsHash = "sha256-y09jVSwUrxF0nLpLqS1yQweYL+iMF6jVx0sUdQtvrpc=";
npmDepsHash = "sha256-ng0YpBZc0vcg5Bsr1LmgXtzNCtNV6hJIgLt3m3yRdh4=";
dontNpmBuild = true;
installPhase = ''
runHook preInstall
@ -50,37 +66,92 @@ let
runHook postInstall
'';
};
mixFodDeps = beamPackages.fetchMixDeps {
inherit
pname
version
src
mixEnv
;
hash = "sha256-N6cYlYwNss2FPYcljANJYbXobmLFauZ64F7Sf/+7Ctg=";
};
mjmlNif = rustPlatform.buildRustPackage {
pname = "mjml-native";
version = "";
src = "${mixFodDeps}/mjml/native/mjml_nif";
cargoHash = "sha256-W4r8W+JGTE6j4gDogL5Yulr0mbaXjDbwDTwhzMbbDcQ=";
doCheck = false;
env = {
RUSTLER_PRECOMPILED_FORCE_BUILD_ALL = "true";
RUSTLER_PRECOMPILED_GLOBAL_CACHE_PATH = "unused-but-required";
};
};
patchedMixFodDeps = runCommand mixFodDeps.name { } ''
mkdir $out
cp -r --no-preserve=mode ${mixFodDeps}/. $out
mkdir -p $out/mjml/priv/native
for lib in ${mjmlNif}/lib/*
do
# normalies suffix to .so, otherswise build would fail on darwin
file=''${lib##*/}
base=''${file%.*}
ln -s "$lib" $out/mjml/priv/native/$base.so
done
'';
in
beamPackages.mixRelease {
inherit pname version src mixFodDeps;
beamPackages.mixRelease rec {
inherit
pname
version
src
mixEnv
;
nativeBuildInputs = [
nodejs
brotli
];
mixFodDeps = patchedMixFodDeps;
passthru = {
tests = { inherit (nixosTests) plausible; };
tests = {
inherit (nixosTests) plausible;
};
updateScript = ./update.sh;
inherit assets tracker;
};
postPatch = ''
substituteInPlace lib/plausible_release.ex --replace 'defp prepare do' 'def prepare do'
'';
env = {
APP_VERSION = version;
RUSTLER_PRECOMPILED_FORCE_BUILD_ALL = "true";
RUSTLER_PRECOMPILED_GLOBAL_CACHE_PATH = "unused-but-required";
};
preBuild = ''
rm -r assets tracker
cp -r ${assets} assets
cp --no-preserve=mode -r ${assets} assets
cp -r ${tracker} tracker
cat >> config/config.exs <<EOF
config :tailwind, path: "${lib.getExe tailwindcss}"
config :esbuild, path: "${lib.getExe esbuild}"
EOF
'';
postBuild = ''
export NODE_OPTIONS=--openssl-legacy-provider # required for webpack compatibility with OpenSSL 3 (https://github.com/webpack/webpack/issues/14532)
npm run deploy --prefix ./assets
npm run deploy --prefix ./tracker
# for external task you need a workaround for the no deps check flag
# https://github.com/phoenixframework/phoenix/issues/2690
mix do deps.loadpaths --no-deps-check, phx.digest
mix do deps.loadpaths --no-deps-check, assets.deploy
mix do deps.loadpaths --no-deps-check, phx.digest priv/static
'';
meta = with lib; {

View file

@ -1,62 +1,14 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p jq nix-prefetch-github yarn yarn2nix-moretea.yarn2nix moreutils
# NOTE: please check on new releases which steps aren't necessary anymore!
# Currently the following things are done:
#
# * Add correct `name`/`version` field to `package.json`, otherwise `yarn2nix` fails to
# find required dependencies.
# * Adjust `file:`-dependencies a bit for the structure inside a Nix build.
# * Update hashes for the tarball & the fixed-output drv with all `mix`-dependencies.
# * Generate `yarn.lock` & `yarn.nix` in a temporary directory.
#!nix-shell -i bash -p nix-update jq elixir npm-lockfile-fix nixfmt-rfc-style
set -euxo pipefail
dir="$(realpath $(dirname "$0"))"
export latest="$(curl -q https://api.github.com/repos/plausible/analytics/releases/latest \
| jq -r '.tag_name')"
nix_version="$(cut -c2- <<< "$latest")"
nix-update plausible
if [[ "$(nix-instantiate -A plausible.version --eval --json | jq -r)" = "$nix_version" ]];
then
echo "Already using version $latest, skipping"
exit 0
fi
version="$(nix-instantiate -A plausible.version --eval --json | jq -r)"
source_url="$(nix-instantiate -A plausible.src.url --eval --json | jq -r)"
SRC="https://raw.githubusercontent.com/plausible/analytics/${latest}"
nix-update --url "$source_url" --version "$version" plausible.tracker
nix-update --url "$source_url" --version "$version" plausible.assets
package_json="$(curl -qf "$SRC/assets/package.json")"
echo "$package_json" \
| jq '. + {"name":"plausible","version": $ENV.latest}' \
| sed -e 's,../deps/,../../tmp/deps/,g' \
> $dir/package.json
tarball_meta="$(nix-prefetch-github plausible analytics --rev "$latest")"
tarball_hash="$(jq -r '.hash' <<< "$tarball_meta")"
tarball_path="$(nix-build -E 'with import ./. {}; { p }: fetchFromGitHub (builtins.fromJSON p)' --argstr p "$tarball_meta")"
fake_hash="$(nix-instantiate --eval -A lib.fakeHash | xargs echo)"
sed -i "$dir/default.nix" \
-e 's,version = ".*",version = "'"$nix_version"'",' \
-e '/^ src = fetchFromGitHub/,+4{;s#hash = "\(.*\)"#hash = "'"$tarball_hash"'"#}' \
-e '/^ mixFodDeps =/,+3{;s#hash = "\(.*\)"#hash = "'"$fake_hash"'"#}'
mix_hash="$(nix-build -A plausible.mixFodDeps 2>&1 | tail -n3 | grep 'got:' | cut -d: -f2- | xargs echo || true)"
sed -i "$dir/default.nix" -e '/^ mixFodDeps =/,+3{;s#hash = "\(.*\)"#hash = "'"$mix_hash"'"#}'
tmp_setup_dir="$(mktemp -d)"
trap "rm -rf $tmp_setup_dir" EXIT
cp -r $tarball_path/* $tmp_setup_dir/
cp -r "$(nix-build -A plausible.mixFodDeps)" "$tmp_setup_dir/deps"
chmod -R u+rwx "$tmp_setup_dir"
pushd $tmp_setup_dir/assets
yarn
yarn2nix > "$dir/yarn.nix"
cp yarn.lock "$dir/yarn.lock"
popd
nix-build -A plausible

View file

@ -1955,8 +1955,8 @@ with pkgs;
lukesmithxyz-bible-kjv = callPackage ../applications/misc/kjv/lukesmithxyz-kjv.nix { };
plausible = callPackage ../servers/web-apps/plausible {
elixir = elixir_1_14;
beamPackages = beamPackages.extend (self: super: { elixir = elixir_1_14; });
elixir = elixir_1_17;
beamPackages = beamPackages.extend (self: super: { elixir = elixir_1_17; });
};
reattach-to-user-namespace = callPackage ../os-specific/darwin/reattach-to-user-namespace { };