umami: init at 2.19.0; nixos/umami: init (#380249)
This commit is contained in:
commit
436a8a1152
@ -23,6 +23,8 @@
|
||||
|
||||
- [Fediwall](https://fediwall.social), a web application for live displaying toots from mastodon, inspired by mastowall. Available as [services.fediwall](#opt-services.fediwall.enable).
|
||||
|
||||
- [umami](https://github.com/umami-software/umami), a simple, fast, privacy-focused alternative to Google Analytics. Available with [services.umami](#opt-services.umami.enable).
|
||||
|
||||
- [FileBrowser](https://filebrowser.org/), a web application for managing and sharing files. Available as [services.filebrowser](#opt-services.filebrowser.enable).
|
||||
|
||||
- Options under [networking.getaddrinfo](#opt-networking.getaddrinfo.enable) are now allowed to declaratively configure address selection and sorting behavior of `getaddrinfo` in dual-stack networks.
|
||||
|
||||
@ -1690,6 +1690,7 @@
|
||||
./services/web-apps/szurubooru.nix
|
||||
./services/web-apps/trilium.nix
|
||||
./services/web-apps/tt-rss.nix
|
||||
./services/web-apps/umami.nix
|
||||
./services/web-apps/vikunja.nix
|
||||
./services/web-apps/wakapi.nix
|
||||
./services/web-apps/weblate.nix
|
||||
|
||||
316
nixos/modules/services/web-apps/umami.nix
Normal file
316
nixos/modules/services/web-apps/umami.nix
Normal file
@ -0,0 +1,316 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
concatStringsSep
|
||||
filterAttrs
|
||||
getExe
|
||||
hasPrefix
|
||||
hasSuffix
|
||||
isString
|
||||
literalExpression
|
||||
maintainers
|
||||
mapAttrs
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
optional
|
||||
optionalString
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.services.umami;
|
||||
|
||||
nonFileSettings = filterAttrs (k: _: !hasSuffix "_FILE" k) cfg.settings;
|
||||
in
|
||||
{
|
||||
options.services.umami = {
|
||||
enable = mkEnableOption "umami";
|
||||
|
||||
package = mkPackageOption pkgs "umami" { } // {
|
||||
apply =
|
||||
pkg:
|
||||
pkg.override {
|
||||
databaseType = cfg.settings.DATABASE_TYPE;
|
||||
collectApiEndpoint = optionalString (
|
||||
cfg.settings.COLLECT_API_ENDPOINT != null
|
||||
) cfg.settings.COLLECT_API_ENDPOINT;
|
||||
trackerScriptNames = cfg.settings.TRACKER_SCRIPT_NAME;
|
||||
basePath = cfg.settings.BASE_PATH;
|
||||
};
|
||||
};
|
||||
|
||||
createPostgresqlDatabase = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Whether to automatically create the database for Umami using PostgreSQL.
|
||||
Both the database name and username will be `umami`, and the connection is
|
||||
made through unix sockets using peer authentication.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
description = ''
|
||||
Additional configuration (environment variables) for Umami, see
|
||||
<https://umami.is/docs/environment-variables> for supported values.
|
||||
'';
|
||||
|
||||
type = types.submodule {
|
||||
freeformType =
|
||||
with types;
|
||||
attrsOf (oneOf [
|
||||
bool
|
||||
int
|
||||
str
|
||||
]);
|
||||
|
||||
options = {
|
||||
APP_SECRET_FILE = mkOption {
|
||||
type = types.nullOr (
|
||||
types.str
|
||||
// {
|
||||
# We don't want users to be able to pass a path literal here but
|
||||
# it should look like a path.
|
||||
check = it: isString it && types.path.check it;
|
||||
}
|
||||
);
|
||||
default = null;
|
||||
example = "/run/secrets/umamiAppSecret";
|
||||
description = ''
|
||||
A file containing a secure random string. This is used for signing user sessions.
|
||||
The contents of the file are read through systemd credentials, therefore the
|
||||
user running umami does not need permissions to read the file.
|
||||
If you wish to set this to a string instead (not recommended since it will be
|
||||
placed world-readable in the Nix store), you can use the APP_SECRET option.
|
||||
'';
|
||||
};
|
||||
DATABASE_URL = mkOption {
|
||||
type = types.nullOr (
|
||||
types.str
|
||||
// {
|
||||
check =
|
||||
it:
|
||||
isString it
|
||||
&& ((hasPrefix "postgresql://" it) || (hasPrefix "postgres://" it) || (hasPrefix "mysql://" it));
|
||||
}
|
||||
);
|
||||
# For some reason, Prisma requires the username in the connection string
|
||||
# and can't derive it from the current user.
|
||||
default =
|
||||
if cfg.createPostgresqlDatabase then
|
||||
"postgresql://umami@localhost/umami?host=/run/postgresql"
|
||||
else
|
||||
null;
|
||||
defaultText = literalExpression ''if config.services.umami.createPostgresqlDatabase then "postgresql://umami@localhost/umami?host=/run/postgresql" else null'';
|
||||
example = "postgresql://root:root@localhost/umami";
|
||||
description = ''
|
||||
Connection string for the database. Must start with `postgresql://`, `postgres://`
|
||||
or `mysql://`.
|
||||
'';
|
||||
};
|
||||
DATABASE_URL_FILE = mkOption {
|
||||
type = types.nullOr (
|
||||
types.str
|
||||
// {
|
||||
# We don't want users to be able to pass a path literal here but
|
||||
# it should look like a path.
|
||||
check = it: isString it && types.path.check it;
|
||||
}
|
||||
);
|
||||
default = null;
|
||||
example = "/run/secrets/umamiDatabaseUrl";
|
||||
description = ''
|
||||
A file containing a connection string for the database. The connection string
|
||||
must start with `postgresql://`, `postgres://` or `mysql://`.
|
||||
If using this, then DATABASE_TYPE must be set to the appropriate value.
|
||||
The contents of the file are read through systemd credentials, therefore the
|
||||
user running umami does not need permissions to read the file.
|
||||
'';
|
||||
};
|
||||
DATABASE_TYPE = mkOption {
|
||||
type = types.nullOr (
|
||||
types.enum [
|
||||
"postgresql"
|
||||
"mysql"
|
||||
]
|
||||
);
|
||||
default =
|
||||
if cfg.settings.DATABASE_URL != null && hasPrefix "mysql://" cfg.settings.DATABASE_URL then
|
||||
"mysql"
|
||||
else
|
||||
"postgresql";
|
||||
defaultText = literalExpression ''if config.services.umami.settings.DATABASE_URL != null && hasPrefix "mysql://" config.services.umami.settings.DATABASE_URL then "mysql" else "postgresql"'';
|
||||
example = "mysql";
|
||||
description = ''
|
||||
The type of database to use. This is automatically inferred from DATABASE_URL, but
|
||||
must be set manually if you are using DATABASE_URL_FILE.
|
||||
'';
|
||||
};
|
||||
COLLECT_API_ENDPOINT = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "/api/alternate-send";
|
||||
description = ''
|
||||
Allows you to send metrics to a location different than the default `/api/send`.
|
||||
'';
|
||||
};
|
||||
TRACKER_SCRIPT_NAME = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [ "tracker.js" ];
|
||||
description = ''
|
||||
Allows you to assign a custom name to the tracker script different from the default `script.js`.
|
||||
'';
|
||||
};
|
||||
BASE_PATH = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "/analytics";
|
||||
description = ''
|
||||
Allows you to host Umami under a subdirectory.
|
||||
You may need to update your reverse proxy settings to correctly handle the BASE_PATH prefix.
|
||||
'';
|
||||
};
|
||||
DISABLE_UPDATES = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Disables the check for new versions of Umami.
|
||||
'';
|
||||
};
|
||||
DISABLE_TELEMETRY = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Umami collects completely anonymous telemetry data in order help improve the application.
|
||||
You can choose to disable this if you don't want to participate.
|
||||
'';
|
||||
};
|
||||
HOSTNAME = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
example = "0.0.0.0";
|
||||
description = ''
|
||||
The address to listen on.
|
||||
'';
|
||||
};
|
||||
PORT = mkOption {
|
||||
type = types.port;
|
||||
default = 3000;
|
||||
example = 3010;
|
||||
description = ''
|
||||
The port to listen on.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
default = { };
|
||||
|
||||
example = {
|
||||
APP_SECRET_FILE = "/run/secrets/umamiAppSecret";
|
||||
DISABLE_TELEMETRY = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = (cfg.settings.APP_SECRET_FILE != null) != (cfg.settings ? APP_SECRET);
|
||||
message = "One (and only one) of services.umami.settings.APP_SECRET_FILE and services.umami.settings.APP_SECRET must be set.";
|
||||
}
|
||||
{
|
||||
assertion = (cfg.settings.DATABASE_URL_FILE != null) != (cfg.settings.DATABASE_URL != null);
|
||||
message = "One (and only one) of services.umami.settings.DATABASE_URL_FILE and services.umami.settings.DATABASE_URL must be set.";
|
||||
}
|
||||
{
|
||||
assertion =
|
||||
cfg.createPostgresqlDatabase
|
||||
-> cfg.settings.DATABASE_URL == "postgresql://umami@localhost/umami?host=/run/postgresql";
|
||||
message = "The option config.services.umami.createPostgresqlDatabase is enabled, but config.services.umami.settings.DATABASE_URL has been modified.";
|
||||
}
|
||||
];
|
||||
|
||||
services.postgresql = mkIf cfg.createPostgresqlDatabase {
|
||||
enable = true;
|
||||
ensureDatabases = [ "umami" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "umami";
|
||||
ensureDBOwnership = true;
|
||||
ensureClauses.login = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
systemd.services.umami = {
|
||||
environment = mapAttrs (_: toString) nonFileSettings;
|
||||
|
||||
description = "Umami: a simple, fast, privacy-focused alternative to Google Analytics";
|
||||
after = [ "network.target" ] ++ (optional (cfg.createPostgresqlDatabase) "postgresql.service");
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
script =
|
||||
let
|
||||
loadCredentials =
|
||||
(optional (
|
||||
cfg.settings.APP_SECRET_FILE != null
|
||||
) ''export APP_SECRET="$(systemd-creds cat appSecret)"'')
|
||||
++ (optional (
|
||||
cfg.settings.DATABASE_URL_FILE != null
|
||||
) ''export DATABASE_URL="$(systemd-creds cat databaseUrl)"'');
|
||||
in
|
||||
''
|
||||
${concatStringsSep "\n" loadCredentials}
|
||||
${getExe cfg.package}
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 3;
|
||||
DynamicUser = true;
|
||||
|
||||
LoadCredential =
|
||||
(optional (cfg.settings.APP_SECRET_FILE != null) "appSecret:${cfg.settings.APP_SECRET_FILE}")
|
||||
++ (optional (
|
||||
cfg.settings.DATABASE_URL_FILE != null
|
||||
) "databaseUrl:${cfg.settings.DATABASE_URL_FILE}");
|
||||
|
||||
# Hardening
|
||||
CapabilityBoundingSet = "";
|
||||
NoNewPrivileges = true;
|
||||
PrivateUsers = true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
PrivateMounts = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
RestrictAddressFamilies = (optional cfg.createPostgresqlDatabase "AF_UNIX") ++ [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ diogotcorreia ];
|
||||
}
|
||||
@ -1509,6 +1509,7 @@ in
|
||||
ucarp = runTest ./ucarp.nix;
|
||||
udisks2 = runTest ./udisks2.nix;
|
||||
ulogd = runTest ./ulogd/ulogd.nix;
|
||||
umami = runTest ./web-apps/umami.nix;
|
||||
umurmur = runTest ./umurmur.nix;
|
||||
unbound = runTest ./unbound.nix;
|
||||
unifi = runTest ./unifi.nix;
|
||||
|
||||
45
nixos/tests/web-apps/umami.nix
Normal file
45
nixos/tests/web-apps/umami.nix
Normal file
@ -0,0 +1,45 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "umami-nixos";
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ diogotcorreia ];
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.umami = {
|
||||
enable = true;
|
||||
settings = {
|
||||
APP_SECRET = "very_secret";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
import json
|
||||
|
||||
machine.wait_for_unit("umami.service")
|
||||
|
||||
machine.wait_for_open_port(3000)
|
||||
machine.succeed("curl --fail http://localhost:3000/")
|
||||
machine.succeed("curl --fail http://localhost:3000/script.js")
|
||||
|
||||
res = machine.succeed("""
|
||||
curl -f --json '{ "username": "admin", "password": "umami" }' http://localhost:3000/api/auth/login
|
||||
""")
|
||||
token = json.loads(res)['token']
|
||||
|
||||
res = machine.succeed("""
|
||||
curl -f -H 'Authorization: Bearer %s' --json '{ "domain": "localhost", "name": "Test" }' http://localhost:3000/api/websites
|
||||
""" % token)
|
||||
print(res)
|
||||
websiteId = json.loads(res)['id']
|
||||
|
||||
res = machine.succeed("""
|
||||
curl -f -H 'Authorization: Bearer %s' http://localhost:3000/api/websites/%s
|
||||
""" % (token, websiteId))
|
||||
website = json.loads(res)
|
||||
assert website["name"] == "Test"
|
||||
assert website["domain"] == "localhost"
|
||||
'';
|
||||
}
|
||||
201
pkgs/by-name/um/umami/package.nix
Normal file
201
pkgs/by-name/um/umami/package.nix
Normal file
@ -0,0 +1,201 @@
|
||||
{
|
||||
lib,
|
||||
stdenvNoCC,
|
||||
fetchFromGitHub,
|
||||
fetchurl,
|
||||
makeWrapper,
|
||||
nixosTests,
|
||||
nodejs,
|
||||
pnpm_10,
|
||||
prisma-engines,
|
||||
openssl,
|
||||
rustPlatform,
|
||||
# build variables
|
||||
databaseType ? "postgresql",
|
||||
collectApiEndpoint ? "",
|
||||
trackerScriptNames ? [ ],
|
||||
basePath ? "",
|
||||
}:
|
||||
let
|
||||
sources = lib.importJSON ./sources.json;
|
||||
pnpm = pnpm_10;
|
||||
|
||||
geocities = stdenvNoCC.mkDerivation {
|
||||
pname = "umami-geocities";
|
||||
version = sources.geocities.date;
|
||||
src = fetchurl {
|
||||
url = "https://raw.githubusercontent.com/GitSquared/node-geolite2-redist/${sources.geocities.rev}/redist/GeoLite2-City.tar.gz";
|
||||
inherit (sources.geocities) hash;
|
||||
};
|
||||
|
||||
doBuild = false;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp ./GeoLite2-City.mmdb $out/GeoLite2-City.mmdb
|
||||
'';
|
||||
|
||||
meta.license = lib.licenses.cc-by-40;
|
||||
};
|
||||
|
||||
# Pin the specific version of prisma to the one used by upstream
|
||||
# to guarantee compatibility.
|
||||
prisma-engines' = prisma-engines.overrideAttrs (old: rec {
|
||||
version = "6.7.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "prisma";
|
||||
repo = "prisma-engines";
|
||||
tag = version;
|
||||
hash = "sha256-Ty8BqWjZluU6a5xhSAVb2VoTVY91UUj6zoVXMKeLO4o=";
|
||||
};
|
||||
cargoHash = "sha256-HjDoWa/JE6izUd+hmWVI1Yy3cTBlMcvD9ANsvqAoHBI=";
|
||||
|
||||
cargoDeps = rustPlatform.fetchCargoVendor {
|
||||
inherit (old) pname;
|
||||
inherit src version;
|
||||
hash = cargoHash;
|
||||
};
|
||||
});
|
||||
in
|
||||
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
pname = "umami";
|
||||
version = "2.19.0";
|
||||
|
||||
nativeBuildInputs = [
|
||||
makeWrapper
|
||||
nodejs
|
||||
pnpm.configHook
|
||||
];
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "umami-software";
|
||||
repo = "umami";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-luiwGmCujbFGWANSCOiHIov56gsMQ6M+Bj0stcz9he8=";
|
||||
};
|
||||
|
||||
# install dev dependencies as well, for rollup
|
||||
pnpmInstallFlags = [ "--prod=false" ];
|
||||
|
||||
pnpmDeps = pnpm.fetchDeps {
|
||||
inherit (finalAttrs)
|
||||
pname
|
||||
pnpmInstallFlags
|
||||
version
|
||||
src
|
||||
;
|
||||
fetcherVersion = 2;
|
||||
hash = "sha256-2GiCeCt/mU5Dm5YHQgJF3127WPHq5QLX8JRcUv6B6lE=";
|
||||
};
|
||||
|
||||
env.CYPRESS_INSTALL_BINARY = "0";
|
||||
env.NODE_ENV = "production";
|
||||
env.NEXT_TELEMETRY_DISABLED = "1";
|
||||
|
||||
# copy-db-files uses this variable to decide which Prisma schema to use
|
||||
env.DATABASE_TYPE = databaseType;
|
||||
|
||||
env.COLLECT_API_ENDPOINT = collectApiEndpoint;
|
||||
env.TRACKER_SCRIPT_NAME = lib.concatStringsSep "," trackerScriptNames;
|
||||
env.BASE_PATH = basePath;
|
||||
|
||||
# Allow prisma-cli to find prisma-engines without having to download them
|
||||
env.PRISMA_QUERY_ENGINE_LIBRARY = "${prisma-engines'}/lib/libquery_engine.node";
|
||||
env.PRISMA_SCHEMA_ENGINE_BINARY = "${prisma-engines'}/bin/schema-engine";
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
pnpm copy-db-files
|
||||
pnpm build-db-client # prisma generate
|
||||
|
||||
pnpm build-tracker
|
||||
pnpm build-app
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
checkPhase = ''
|
||||
runHook preCheck
|
||||
|
||||
pnpm test
|
||||
|
||||
runHook postCheck
|
||||
'';
|
||||
|
||||
doCheck = true;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mv .next/standalone $out
|
||||
mv .next/static $out/.next/static
|
||||
|
||||
# Include prisma cli in next standalone build.
|
||||
# This is preferred to using the prisma in nixpkgs because it guarantees
|
||||
# the version matches.
|
||||
# See https://nextjs-forum.com/post/1280550687998083198
|
||||
# and https://nextjs.org/docs/pages/api-reference/config/next-config-js/output#caveats
|
||||
# Unfortunately, using outputFileTracingIncludes doesn't work because of pnpm's symlink structure,
|
||||
# so we just copy the files manually.
|
||||
mkdir -p $out/node_modules/.bin
|
||||
cp node_modules/.bin/prisma $out/node_modules/.bin
|
||||
cp -a node_modules/prisma $out/node_modules
|
||||
cp -a node_modules/.pnpm/@prisma* $out/node_modules/.pnpm
|
||||
cp -a node_modules/.pnpm/prisma* $out/node_modules/.pnpm
|
||||
# remove broken symlinks (some dependencies that are not relevant for running migrations)
|
||||
find "$out"/node_modules/.pnpm/@prisma* -xtype l -exec rm {} \;
|
||||
find "$out"/node_modules/.pnpm/prisma* -xtype l -exec rm {} \;
|
||||
|
||||
cp -R public $out/public
|
||||
cp -R prisma $out/prisma
|
||||
|
||||
ln -s ${geocities} $out/geo
|
||||
|
||||
mkdir -p $out/bin
|
||||
# Run database migrations before starting umami.
|
||||
# Add openssl to PATH since it is required for prisma to make SSL connections.
|
||||
# Force working directory to $out because umami assumes many paths are relative to it (e.g., prisma and geolite).
|
||||
makeWrapper ${nodejs}/bin/node $out/bin/umami-server \
|
||||
--set NODE_ENV production \
|
||||
--set NEXT_TELEMETRY_DISABLED 1 \
|
||||
--set PRISMA_QUERY_ENGINE_LIBRARY "${prisma-engines'}/lib/libquery_engine.node" \
|
||||
--set PRISMA_SCHEMA_ENGINE_BINARY "${prisma-engines'}/bin/schema-engine" \
|
||||
--prefix PATH : ${
|
||||
lib.makeBinPath [
|
||||
openssl
|
||||
nodejs
|
||||
]
|
||||
} \
|
||||
--chdir $out \
|
||||
--run "$out/node_modules/.bin/prisma migrate deploy" \
|
||||
--add-flags "$out/server.js"
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
passthru = {
|
||||
tests = {
|
||||
inherit (nixosTests) umami;
|
||||
};
|
||||
inherit
|
||||
sources
|
||||
geocities
|
||||
;
|
||||
prisma-engines = prisma-engines';
|
||||
updateScript = ./update.sh;
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
changelog = "https://github.com/umami-software/umami/releases/tag/v${finalAttrs.version}";
|
||||
description = "Simple, easy to use, self-hosted web analytics solution";
|
||||
homepage = "https://umami.is/";
|
||||
license = with lib.licenses; [
|
||||
mit
|
||||
cc-by-40 # geocities
|
||||
];
|
||||
platforms = lib.platforms.linux;
|
||||
mainProgram = "umami-server";
|
||||
maintainers = with maintainers; [ diogotcorreia ];
|
||||
};
|
||||
})
|
||||
7
pkgs/by-name/um/umami/sources.json
Normal file
7
pkgs/by-name/um/umami/sources.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"geocities": {
|
||||
"rev": "0817bc800279e26e9ff045b7b129385e5b23012e",
|
||||
"date": "2025-07-29",
|
||||
"hash": "sha256-Rw9UEvUu7rtXFvHEqKza6kn9LwT6C17zJ/ljoN+t6Ek="
|
||||
}
|
||||
}
|
||||
50
pkgs/by-name/um/umami/update.sh
Executable file
50
pkgs/by-name/um/umami/update.sh
Executable file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p curl jq prefetch-yarn-deps nix-prefetch-github coreutils nix-update
|
||||
# shellcheck shell=bash
|
||||
|
||||
# This script exists to update geocities version and pin prisma-engines version
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
|
||||
|
||||
old_version=$(nix-instantiate --eval -A 'umami.version' default.nix | tr -d '"' || echo "0.0.1")
|
||||
version=$(curl -s "https://api.github.com/repos/umami-software/umami/releases/latest" | jq -r ".tag_name")
|
||||
version="${version#v}"
|
||||
|
||||
echo "Updating to $version"
|
||||
|
||||
if [[ "$old_version" == "$version" ]]; then
|
||||
echo "Already up to date!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
nix-update --version "$version" umami
|
||||
|
||||
echo "Fetching geolite"
|
||||
geocities_rev_date=$(curl https://api.github.com/repos/GitSquared/node-geolite2-redist/branches/master | jq -r ".commit.sha, .commit.commit.author.date")
|
||||
geocities_rev=$(echo "$geocities_rev_date" | head -1)
|
||||
geocities_date=$(echo "$geocities_rev_date" | tail -1 | sed 's/T.*//')
|
||||
|
||||
# upstream is kind enough to provide a file with the hash of the tar.gz archive
|
||||
geocities_hash=$(curl -s "https://raw.githubusercontent.com/GitSquared/node-geolite2-redist/$geocities_rev/redist/GeoLite2-City.tar.gz.sha256")
|
||||
geocities_hash_sri=$(nix-hash --to-sri --type sha256 "$geocities_hash")
|
||||
|
||||
cat <<EOF > "$SCRIPT_DIR/sources.json"
|
||||
{
|
||||
"geocities": {
|
||||
"rev": "$geocities_rev",
|
||||
"date": "$geocities_date",
|
||||
"hash": "$geocities_hash_sri"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "Pinning Prisma version"
|
||||
upstream_src="https://raw.githubusercontent.com/umami-software/umami/v$version"
|
||||
|
||||
lock=$(mktemp)
|
||||
curl -s -o "$lock" "$upstream_src/pnpm-lock.yaml"
|
||||
prisma_version=$(grep "@prisma/engines@" "$lock" | head -n1 | awk -F"[@']" '{print $4}')
|
||||
rm "$lock"
|
||||
|
||||
nix-update --version "$prisma_version" umami.prisma-engines
|
||||
Loading…
x
Reference in New Issue
Block a user