summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorAzat Bahawi <azat@bahawi.net>2023-09-20 15:26:47 +0300
committerAzat Bahawi <azat@bahawi.net>2023-09-20 15:26:47 +0300
commit837fc97b30a41d766dd53a2370f6cb1d26364f9a (patch)
tree63ae83af789930c9a2035b9f9e43fbee166ab27b /modules
parent59858431bc7b80d4114056ea95099066be6e4643 (diff)
2023-09-20
Diffstat (limited to 'modules')
-rw-r--r--modules/common/emacs/default.nix2
-rw-r--r--modules/common/emacs/doom/config.el11
-rw-r--r--modules/common/vscode.nix2
-rw-r--r--modules/nixos/clickhouse.nix18
-rw-r--r--modules/nixos/default.nix2
-rw-r--r--modules/nixos/git/default.nix4
-rw-r--r--modules/nixos/nsd.nix1
-rw-r--r--modules/nixos/plausible-nixpkgs-override.nix312
-rw-r--r--modules/nixos/plausible.nix144
9 files changed, 481 insertions, 15 deletions
diff --git a/modules/common/emacs/default.nix b/modules/common/emacs/default.nix
index ed25536..1d205b9 100644
--- a/modules/common/emacs/default.nix
+++ b/modules/common/emacs/default.nix
@@ -92,7 +92,7 @@ in {
jre # :lang plantuml
libtool # :term vterm
libxml2 # :lang data
- nixd # :lang (nix +lsp)
+ nil # :lang (nix +lsp)
nodePackages.bash-language-server # :lang (sh +lsp)
nodePackages.eslint # :lang (json +lsp)
nodePackages.js-beautify # :lang web
diff --git a/modules/common/emacs/doom/config.el b/modules/common/emacs/doom/config.el
index e7e0bd4..015954b 100644
--- a/modules/common/emacs/doom/config.el
+++ b/modules/common/emacs/doom/config.el
@@ -79,17 +79,6 @@
(setq lsp-haskell-formatting-provider "ormolu")
;;
-;;; Nix
-;;
-
-(after! lsp-mode
- (add-to-list 'lsp-language-id-configuration '(nix-mode . "nix"))
- (lsp-register-client
- (make-lsp-client :new-connection (lsp-stdio-connection '("nixd"))
- :major-modes '(nix-mode)
- :server-id 'nix)))
-
-;;
;;; YAML
;;
diff --git a/modules/common/vscode.nix b/modules/common/vscode.nix
index d90d301..ab55acc 100644
--- a/modules/common/vscode.nix
+++ b/modules/common/vscode.nix
@@ -178,7 +178,7 @@ in {
nix = {
enableLanguageServer = true;
- serverPath = "${pkgs.rnix-lsp}/bin/rnix-lsp";
+ serverPath = "${pkgs.nil}/bin/nil";
};
python = with pkgs.python311Packages; {
diff --git a/modules/nixos/clickhouse.nix b/modules/nixos/clickhouse.nix
new file mode 100644
index 0000000..4fae683
--- /dev/null
+++ b/modules/nixos/clickhouse.nix
@@ -0,0 +1,18 @@
+{
+ config,
+ lib,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.clickhouse;
+in {
+ options.nixfiles.modules.clickhouse = {
+ enable = mkEnableOption "Clickhouse";
+ };
+
+ config = mkIf cfg.enable {
+ services.clickhouse = {
+ enable = true;
+ };
+ };
+}
diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix
index 466e2e0..5b9a3be 100644
--- a/modules/nixos/default.nix
+++ b/modules/nixos/default.nix
@@ -6,6 +6,7 @@ _: {
./beets.nix
./bluetooth.nix
./chromium.nix
+ ./clickhouse.nix
./common
./discord.nix
./docker.nix
@@ -41,6 +42,7 @@ _: {
./ntfy.nix
./nullmailer.nix
./openssh.nix
+ ./plausible.nix
./podman.nix
./postgresql.nix
./profiles
diff --git a/modules/nixos/git/default.nix b/modules/nixos/git/default.nix
index 5fe4391..9fb43db 100644
--- a/modules/nixos/git/default.nix
+++ b/modules/nixos/git/default.nix
@@ -73,9 +73,9 @@ in {
fastcgi_param QUERY_STRING $args;
fastcgi_param HTTP_HOST $server_name;
- # This makes `go get ...` work.
+ # This makes `go get ...` work and adds analytics.
sub_filter '</head>'
- '<meta name="go-import" content="$host$uri git https://$host$uri"></head>';
+ '<meta name="go-import" content="$host$uri git https://$host$uri"><script defer data-domain="${cfg.server.domain}" src="https://plausible.shire.net/js/script.js"></script></head>';
sub_filter_once on;
'';
"~* ^.+(cgit.css|robots.txt)$".extraConfig = ''
diff --git a/modules/nixos/nsd.nix b/modules/nixos/nsd.nix
index 0060a14..2266ea5 100644
--- a/modules/nixos/nsd.nix
+++ b/modules/nixos/nsd.nix
@@ -137,6 +137,7 @@ in {
grafana = manwe;
loki = manwe;
ntfy = manwe;
+ plausible = manwe;
prometheus = manwe;
radicale = manwe;
rss-bridge = manwe;
diff --git a/modules/nixos/plausible-nixpkgs-override.nix b/modules/nixos/plausible-nixpkgs-override.nix
new file mode 100644
index 0000000..67fffdc
--- /dev/null
+++ b/modules/nixos/plausible-nixpkgs-override.nix
@@ -0,0 +1,312 @@
+{
+ lib,
+ pkgs,
+ config,
+ ...
+}:
+with lib; let
+ cfg = config.services.plausible;
+in {
+ options.services.plausible = {
+ enable = mkEnableOption (lib.mdDoc "plausible");
+
+ package = mkPackageOptionMD pkgs "plausible" {};
+
+ releaseCookiePath = mkOption {
+ type = with types; either str path;
+ description = lib.mdDoc ''
+ The path to the file with release cookie. (used for remote connection to the running node).
+ '';
+ };
+
+ adminUser = {
+ name = mkOption {
+ default = "admin";
+ type = types.str;
+ description = lib.mdDoc ''
+ Name of the admin user that plausible will created on initial startup.
+ '';
+ };
+
+ email = mkOption {
+ type = types.str;
+ example = "admin@localhost";
+ description = lib.mdDoc ''
+ Email-address of the admin-user.
+ '';
+ };
+
+ passwordFile = mkOption {
+ type = types.either types.str types.path;
+ description = lib.mdDoc ''
+ Path to the file which contains the password of the admin user.
+ '';
+ };
+
+ activate = mkEnableOption (lib.mdDoc "activating the freshly created admin-user");
+ };
+
+ database = {
+ clickhouse = {
+ setup = mkEnableOption (lib.mdDoc "creating a clickhouse instance") // {default = true;};
+ url = mkOption {
+ default = "http://localhost:8123/default";
+ type = types.str;
+ description = lib.mdDoc ''
+ The URL to be used to connect to `clickhouse`.
+ '';
+ };
+ };
+ postgres = {
+ setup = mkEnableOption (lib.mdDoc "creating a postgresql instance") // {default = true;};
+ dbname = mkOption {
+ default = "plausible";
+ type = types.str;
+ description = lib.mdDoc ''
+ Name of the database to use.
+ '';
+ };
+ socket = mkOption {
+ default = "/run/postgresql";
+ type = types.str;
+ description = lib.mdDoc ''
+ Path to the UNIX domain-socket to communicate with `postgres`.
+ '';
+ };
+ };
+ };
+
+ server = {
+ disableRegistration = mkOption {
+ default = true;
+ type = types.bool;
+ description = lib.mdDoc ''
+ Whether to prohibit creating an account in plausible's UI.
+ '';
+ };
+ secretKeybaseFile = mkOption {
+ type = types.either types.path types.str;
+ description = lib.mdDoc ''
+ Path to the secret used by the `phoenix`-framework. Instructions
+ how to generate one are documented in the
+ [
+ framework docs](https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Secret.html#content).
+ '';
+ };
+ port = mkOption {
+ default = 8000;
+ type = types.port;
+ description = lib.mdDoc ''
+ Port where the service should be available.
+ '';
+ };
+ baseUrl = mkOption {
+ type = types.str;
+ description = lib.mdDoc ''
+ Public URL where plausible is available.
+
+ Note that `/path` components are currently ignored:
+ [
+ https://github.com/plausible/analytics/issues/1182
+ ](https://github.com/plausible/analytics/issues/1182).
+ '';
+ };
+ };
+
+ mail = {
+ email = mkOption {
+ default = "hello@plausible.local";
+ type = types.str;
+ description = lib.mdDoc ''
+ The email id to use for as *from* address of all communications
+ from Plausible.
+ '';
+ };
+ smtp = {
+ hostAddr = mkOption {
+ default = "localhost";
+ type = types.str;
+ description = lib.mdDoc ''
+ The host address of your smtp server.
+ '';
+ };
+ hostPort = mkOption {
+ default = 25;
+ type = types.port;
+ description = lib.mdDoc ''
+ The port of your smtp server.
+ '';
+ };
+ user = mkOption {
+ default = null;
+ type = types.nullOr types.str;
+ description = lib.mdDoc ''
+ The username/email in case SMTP auth is enabled.
+ '';
+ };
+ passwordFile = mkOption {
+ default = null;
+ type = with types; nullOr (either str path);
+ description = lib.mdDoc ''
+ The path to the file with the password in case SMTP auth is enabled.
+ '';
+ };
+ enableSSL = mkEnableOption (lib.mdDoc "SSL when connecting to the SMTP server");
+ retries = mkOption {
+ type = types.ints.unsigned;
+ default = 2;
+ description = lib.mdDoc ''
+ Number of retries to make until mailer gives up.
+ '';
+ };
+ };
+ };
+ };
+
+ 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;
+ };
+
+ clickhouse = mkIf cfg.database.clickhouse.setup {
+ enable = true;
+ };
+
+ epmd.enable = true;
+ };
+
+ environment.systemPackages = [cfg.package];
+
+ systemd.services = mkMerge [
+ {
+ plausible = {
+ inherit (cfg.package.meta) description;
+ documentation = ["https://plausible.io/docs/self-hosting"];
+ wantedBy = ["multi-user.target"];
+ after =
+ optional cfg.database.clickhouse.setup "clickhouse.service"
+ ++ optionals cfg.database.postgres.setup [
+ "postgresql.service"
+ "plausible-postgres.service"
+ ];
+ requires =
+ optional cfg.database.clickhouse.setup "clickhouse.service"
+ ++ optionals cfg.database.postgres.setup [
+ "postgresql.service"
+ "plausible-postgres.service"
+ ];
+
+ environment =
+ {
+ # NixOS specific option to avoid that it's trying to write into its store-path.
+ # See also https://github.com/lau/tzdata#data-directory-and-releases
+ STORAGE_DIR = "/var/lib/plausible/elixir_tzdata";
+
+ # Configuration options from
+ # https://plausible.io/docs/self-hosting-configuration
+ PORT = toString cfg.server.port;
+ DISABLE_REGISTRATION = boolToString cfg.server.disableRegistration;
+
+ RELEASE_TMP = "/var/lib/plausible/tmp";
+ # 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;
+ CLICKHOUSE_DATABASE_URL = cfg.database.clickhouse.url;
+
+ BASE_URL = cfg.server.baseUrl;
+
+ MAILER_EMAIL = cfg.mail.email;
+ SMTP_HOST_ADDR = cfg.mail.smtp.hostAddr;
+ SMTP_HOST_PORT = toString cfg.mail.smtp.hostPort;
+ SMTP_RETRIES = toString cfg.mail.smtp.retries;
+ SMTP_HOST_SSL_ENABLED = boolToString cfg.mail.smtp.enableSSL;
+
+ SELFHOST = "true";
+ }
+ // (optionalAttrs (cfg.mail.smtp.user != null) {
+ SMTP_USER_NAME = cfg.mail.smtp.user;
+ });
+
+ path =
+ [cfg.package]
+ ++ optional cfg.database.postgres.setup config.services.postgresql.package;
+ script = ''
+ export RELEASE_COOKIE="$(< $CREDENTIALS_DIRECTORY/RELEASE_COOKIE )"
+ 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)
+ ''export SMTP_USER_PWD="$(< $CREDENTIALS_DIRECTORY/SMTP_USER_PWD )"''}
+
+ # setup
+ ${cfg.package}/createdb.sh
+ ${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
+ '';
+
+ serviceConfig = {
+ DynamicUser = true;
+ PrivateTmp = true;
+ WorkingDirectory = "/var/lib/plausible";
+ StateDirectory = "plausible";
+ LoadCredential =
+ [
+ "ADMIN_USER_PWD:${cfg.adminUser.passwordFile}"
+ "SECRET_KEY_BASE:${cfg.server.secretKeybaseFile}"
+ "RELEASE_COOKIE:${cfg.releaseCookiePath}"
+ ]
+ ++ lib.optionals (cfg.mail.smtp.passwordFile != null) ["SMTP_USER_PWD:${cfg.mail.smtp.passwordFile}"];
+ };
+ };
+ }
+ (mkIf cfg.database.postgres.setup {
+ # `plausible' requires the `citext'-extension.
+ plausible-postgres = {
+ after = ["postgresql.service"];
+ partOf = ["plausible.service"];
+ serviceConfig = {
+ Type = "oneshot";
+ User = config.services.postgresql.superUser;
+ RemainAfterExit = true;
+ };
+ script = with cfg.database.postgres; ''
+ PSQL() {
+ ${config.services.postgresql.package}/bin/psql --port=5432 "$@"
+ }
+ # check if the database already exists
+ if ! PSQL -lqt | ${pkgs.coreutils}/bin/cut -d \| -f 1 | ${pkgs.gnugrep}/bin/grep -qw ${dbname} ; then
+ PSQL -tAc "CREATE ROLE plausible WITH LOGIN;"
+ PSQL -tAc "CREATE DATABASE ${dbname} WITH OWNER plausible;"
+ PSQL -d ${dbname} -tAc "CREATE EXTENSION IF NOT EXISTS citext;"
+ fi
+ '';
+ };
+ })
+ ];
+ };
+
+ meta.maintainers = with maintainers; [ma27];
+ meta.doc = ./plausible.md;
+}
diff --git a/modules/nixos/plausible.nix b/modules/nixos/plausible.nix
new file mode 100644
index 0000000..856b318
--- /dev/null
+++ b/modules/nixos/plausible.nix
@@ -0,0 +1,144 @@
+{
+ config,
+ inputs,
+ lib,
+ pkgsPr,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.plausible;
+in {
+ disabledModules = ["services/web-apps/plausible.nix"];
+ imports = [
+ # TODO Wait for https://github.com/NixOS/nixpkgs/pull/253687
+ ./plausible-nixpkgs-override.nix
+ ];
+
+ options.nixfiles.modules.plausible = {
+ enable = mkEnableOption "Plausible Analytics";
+
+ port = mkOption {
+ description = "Port.";
+ type = with types; port;
+ default = 8000;
+ };
+
+ domain = mkOption {
+ description = "Domain name sans protocol scheme.";
+ type = with types; nullOr str;
+ default = "plausible.${config.networking.domain}";
+ };
+ };
+
+ config = let
+ db = "plausible";
+ in
+ mkIf cfg.enable {
+ secrets = {
+ plausible-key = {
+ file = "${inputs.self}/secrets/plausible-key";
+ mode = "0444"; # The user is dynamic so the file must be world-readable.
+ };
+ plausible-admin-password = {
+ file = "${inputs.self}/secrets/plausible-admin-password";
+ mode = "0444"; # The user is dynamic so the file must be world-readable.
+ };
+ plausible-smtp-password = {
+ file = "${inputs.self}/secrets/smtp-password";
+ mode = "0444"; # The user is dynamic so the file must be world-readable.
+ };
+ plausible-release-cookie = {
+ file = "${inputs.self}/secrets/plausible-release-cookie";
+ mode = "0444"; # The user is dynamic so the file must be world-readable.
+ };
+ };
+
+ nixfiles.modules = {
+ nginx = {
+ enable = true;
+ upstreams.plausible.servers."127.0.0.1:${toString cfg.port}" = {};
+ virtualHosts.${cfg.domain} = {
+ locations."/" = {
+ proxyPass = "http://plausible";
+ proxyWebsockets = true;
+ };
+ extraConfig = nginxInternalOnly;
+ };
+ };
+ postgresql = {
+ enable = true;
+ extraPostStart = [
+ ''
+ $PSQL "${db}" -tAc 'GRANT ALL ON SCHEMA "public" TO "${db}"'
+ $PSQL "${db}" -tAc 'CREATE EXTENSION IF NOT EXISTS citext'
+ ''
+ ];
+ };
+ clickhouse.enable = true;
+ };
+
+ services.postgresql = {
+ ensureDatabases = [db];
+ ensureUsers = [
+ {
+ name = db;
+ ensurePermissions."DATABASE \"${db}\"" = "ALL";
+ }
+ ];
+ };
+
+ services.plausible = {
+ enable = true;
+
+ # TODO Wait for https://github.com/NixOS/nixpkgs/pull/253687
+ package = (pkgsPr 253687 "sha256-36nXNVmZDgf//MrM6/VC7W4Vm013tJ6MlXvYQElhRRw=").plausible;
+
+ adminUser = {
+ name = "admin";
+ email = "admin@${my.domain.shire}";
+ passwordFile = config.secrets.plausible-admin-password.path;
+ activate = false;
+ };
+
+ mail = {
+ email = "admin+plausible@${my.domain.shire}";
+ smtp = {
+ hostAddr = my.domain.shire;
+ hostPort = 465;
+ enableSSL = true;
+ user = "azahi@${my.domain.shire}";
+ passwordFile = config.secrets.plausible-smtp-password.path;
+ };
+ };
+
+ database = {
+ clickhouse = {
+ setup = false;
+ url = "http://127.0.0.1:8123/default";
+ };
+
+ postgres = {
+ setup = true;
+ dbname = db;
+ };
+ };
+
+ server = {
+ baseUrl = "https://${cfg.domain}";
+ disableRegistration = true;
+ inherit (cfg) port;
+ secretKeybaseFile = config.secrets.plausible-key.path;
+ };
+
+ releaseCookiePath = config.secrets.plausible-release-cookie.path;
+ };
+
+ systemd.services.plausible = rec {
+ after = [
+ "postgresql.service"
+ "clickhouse.service"
+ ];
+ requires = after;
+ };
+ };
+}