forked from pub-solar/os
Compare commits
No commits in common. "f3f9f02d769ab3f5332235c0f9c913a052b2d763" and "6a46d98662baf1338a899345de27a07fb5e7beed" have entirely different histories.
f3f9f02d76
...
6a46d98662
24
flake.lock
24
flake.lock
|
@ -164,29 +164,6 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"invoiceplane-template": {
|
||||
"inputs": {
|
||||
"flake-parts": [
|
||||
"flake-parts"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1718578450,
|
||||
"narHash": "sha256-Nl6/5AzCg6yoU7OlJrOz8h4w2ENXZyj3AuCFXKxZ/W0=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "79b1fdc7af77863a48dd58b22af57f4729660284",
|
||||
"revCount": 29,
|
||||
"type": "git",
|
||||
"url": "https://git.pub.solar/teutat3s/invoiceplane-templates.git"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.pub.solar/teutat3s/invoiceplane-templates.git"
|
||||
}
|
||||
},
|
||||
"nix-darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
@ -305,7 +282,6 @@
|
|||
"flake-compat": "flake-compat",
|
||||
"flake-parts": "flake-parts",
|
||||
"home-manager": "home-manager",
|
||||
"invoiceplane-template": "invoiceplane-template",
|
||||
"nix-darwin": "nix-darwin",
|
||||
"nixos-22-05": "nixos-22-05",
|
||||
"nixos-flake": "nixos-flake",
|
||||
|
|
|
@ -34,10 +34,6 @@
|
|||
|
||||
nixos-hardware.url = "github:nixos/nixos-hardware";
|
||||
|
||||
invoiceplane-template.url = "git+https://git.pub.solar/teutat3s/invoiceplane-templates.git";
|
||||
invoiceplane-template.inputs.nixpkgs.follows = "nixpkgs";
|
||||
invoiceplane-template.inputs.flake-parts.follows = "flake-parts";
|
||||
|
||||
# PubSolarOS additions
|
||||
triton-vmtools.url = "git+https://git.pub.solar/pub-solar/infra-vintage?ref=main&dir=vmtools";
|
||||
triton-vmtools.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
./fae
|
||||
self.nixosModules.pub-solar
|
||||
self.nixosModules.acme
|
||||
self.nixosModules.invoiceplane
|
||||
];
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
{...}: {
|
||||
imports = [
|
||||
./paperless.nix
|
||||
./invoiceplane.nix
|
||||
./fae.nix
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
{
|
||||
flake,
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
psCfg = config.pub-solar;
|
||||
xdg = config.home-manager.users."${psCfg.user.name}".xdg;
|
||||
backupDir = "/var/lib/invoiceplane/backup";
|
||||
in {
|
||||
security.acme.certs = {
|
||||
"billing.faenix.eu" = {};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = {
|
||||
"billing.faenix.eu" = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "billing.faenix.eu";
|
||||
};
|
||||
};
|
||||
|
||||
services.invoiceplane = {
|
||||
webserver = "nginx";
|
||||
sites."billing.faenix.eu" = {
|
||||
enable = true;
|
||||
|
||||
invoiceTemplates = [ flake.self.inputs.invoiceplane-template.packages.${pkgs.system}.invoiceplane-template ];
|
||||
|
||||
settings = {
|
||||
IP_URL = "https://billing.faenix.eu";
|
||||
DISABLE_SETUP = true;
|
||||
SETUP_COMPLETED = true;
|
||||
};
|
||||
|
||||
poolConfig = {
|
||||
"pm" = "dynamic";
|
||||
"pm.max_children" = 32;
|
||||
"pm.max_requests" = 500;
|
||||
"pm.max_spare_servers" = 4;
|
||||
"pm.min_spare_servers" = 2;
|
||||
"pm.start_servers" = 2;
|
||||
"php_admin_value[date.timezone]" = "Europe/Berlin";
|
||||
"php_admin_value[error_log]" = "/var/lib/invoiceplane/billing.faenix.eu/logs/php-error.log";
|
||||
"php_admin_flag[display_errors]" = "off";
|
||||
"php_admin_flag[log_errors]" = "on";
|
||||
"catch_workers_output" = "yes";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d '${backupDir}' 0700 root root - -"
|
||||
];
|
||||
|
||||
#services.restic.backups = {
|
||||
# invoiceplane = {
|
||||
# paths = [
|
||||
# backupDir
|
||||
# "/var/lib/invoiceplane/billing.faenix.eu"
|
||||
# ];
|
||||
# initialize = true;
|
||||
# passwordFile = config.age.secrets."restic-password".path;
|
||||
# # See https://www.hosting.de/blog/verschluesselte-backups-mit-rclone-und-restic-in-nextcloud/
|
||||
# repository = "rclone:cloud.pub.solar:/backups/InvoicePlane";
|
||||
# backupPrepareCommand = ''
|
||||
# PW=$(cat ${config.age.secrets."invoiceplane-db-password".path})
|
||||
# ${pkgs.docker-client}/bin/docker exec -t invoiceplane-db mariadb-dump --all-databases --password=$PW --user=invoiceplane > "${backupDir}/postgres.sql"
|
||||
# '';
|
||||
# rcloneConfigFile = config.age.secrets."rclone-pie.conf".path;
|
||||
# };
|
||||
#};
|
||||
}
|
|
@ -57,9 +57,6 @@ in {
|
|||
|
||||
virtualHosts = {
|
||||
"paperless.faenix.eu" = {
|
||||
#listenAddresses = [
|
||||
# "192.168.13.35"
|
||||
#];
|
||||
forceSSL = true;
|
||||
useACMEHost = "paperless.faenix.eu";
|
||||
locations."/".proxyPass = "http://127.0.0.1:${builtins.toString config.services.paperless.port}";
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
# switch keyboard input language
|
||||
#bindsym $mod+tab exec swaymsg input "1118:1896:Microsoft_Microsoft___SiderWinderTM_X4_Keyboard_Consumer_Control" xkb_switch_layout next
|
||||
bindsym $mod+tab exec swaymsg input "7504:24868:Ultimate_Gadget_Laboratories_UHK_60_v2" xkb_switch_layout next
|
||||
bindsym $mod+tab exec swaymsg input "1118:1896:Microsoft_Microsoft___SiderWinderTM_X4_Keyboard_Consumer_Control" xkb_switch_layout next
|
||||
|
|
|
@ -52,8 +52,6 @@ in {
|
|||
'';
|
||||
};
|
||||
};
|
||||
boot.kernelPackages = pkgs.linuxPackages_testing;
|
||||
|
||||
|
||||
services.fstrim.enable = true;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#email = import ./email;
|
||||
#gaming = import ./gaming;
|
||||
graphical = import ./graphical;
|
||||
invoiceplane = import ./invoiceplane;
|
||||
#invoiceplane = import ./invoiceplane;
|
||||
nix = import ./nix;
|
||||
nextcloud = import ./nextcloud;
|
||||
office = import ./office;
|
||||
|
|
|
@ -4,16 +4,9 @@ let
|
|||
inherit (lib)
|
||||
any
|
||||
attrValues
|
||||
boolToString
|
||||
concatMapStringsSep
|
||||
concatStrings
|
||||
concatStringsSep
|
||||
escapeShellArg
|
||||
flatten
|
||||
isBool
|
||||
isInt
|
||||
isList
|
||||
isString
|
||||
literalExpression
|
||||
mapAttrs'
|
||||
mapAttrsToList
|
||||
|
@ -23,7 +16,6 @@ let
|
|||
mkMerge
|
||||
mkOption
|
||||
nameValuePair
|
||||
optionalString
|
||||
types;
|
||||
|
||||
cfg = config.services.invoiceplane;
|
||||
|
@ -39,7 +31,7 @@ let
|
|||
DB_HOSTNAME=${cfg.database.host}
|
||||
DB_USERNAME=${cfg.database.user}
|
||||
# NOTE: file_get_contents adds newline at the end of returned string
|
||||
DB_PASSWORD=${optionalString (cfg.database.passwordFile != null) "trim(file_get_contents('${cfg.database.passwordFile}'), \"\\r\\n\")"}
|
||||
DB_PASSWORD=${if cfg.database.passwordFile == null then "" else "trim(file_get_contents('${cfg.database.passwordFile}'),\"\\r\\n\")"}
|
||||
DB_DATABASE=${cfg.database.name}
|
||||
DB_PORT=${toString cfg.database.port}
|
||||
SESS_EXPIRATION=864000
|
||||
|
@ -51,28 +43,19 @@ let
|
|||
REMOVE_INDEXPHP=true
|
||||
'';
|
||||
|
||||
mkPhpValue = v:
|
||||
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 boolToString v
|
||||
else abort "The Invoiceplane config value ${lib.generators.toPretty {} v} can not be encoded."
|
||||
;
|
||||
|
||||
extraConfig = hostName: cfg: let
|
||||
settings = mapAttrsToList (k: v: "${k}=${mkPhpValue v}") cfg.settings;
|
||||
in pkgs.writeText "extraConfig.php" (concatStringsSep "\n" settings);
|
||||
extraConfig = hostName: cfg: pkgs.writeText "extraConfig.php" ''
|
||||
${toString cfg.extraConfig}
|
||||
'';
|
||||
|
||||
pkg = hostName: cfg: pkgs.stdenv.mkDerivation rec {
|
||||
pname = "invoiceplane-${hostName}";
|
||||
version = src.version;
|
||||
src = pkgs.invoiceplane;
|
||||
|
||||
postPatch = ''
|
||||
postPhase = ''
|
||||
# Patch index.php file to load additional config file
|
||||
substituteInPlace index.php \
|
||||
--replace-fail "require('vendor/autoload.php');" "require('vendor/autoload.php'); \$dotenv = Dotenv\Dotenv::createImmutable(__DIR__, 'extraConfig.php'); \$dotenv->load();";
|
||||
--replace "require('vendor/autoload.php');" "require('vendor/autoload.php'); \$dotenv = Dotenv\Dotenv::createImmutable(__DIR__, 'extraConfig.php'); \$dotenv->load();";
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
|
@ -96,16 +79,16 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
siteOpts = { name, ... }:
|
||||
siteOpts = { lib, name, ... }:
|
||||
{
|
||||
options = {
|
||||
|
||||
enable = mkEnableOption "InvoicePlane web application";
|
||||
enable = mkEnableOption (lib.mdDoc "InvoicePlane web application");
|
||||
|
||||
stateDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/invoiceplane/${name}";
|
||||
description = ''
|
||||
description = lib.mdDoc ''
|
||||
This directory is used for uploads of attachments and cache.
|
||||
The directory passed here is automatically created and permissions
|
||||
adjusted as required.
|
||||
|
@ -116,32 +99,32 @@ let
|
|||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "localhost";
|
||||
description = "Database host address.";
|
||||
description = lib.mdDoc "Database host address.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 3306;
|
||||
description = "Database host port.";
|
||||
description = lib.mdDoc "Database host port.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = "invoiceplane";
|
||||
description = "Database name.";
|
||||
description = lib.mdDoc "Database name.";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "invoiceplane";
|
||||
description = "Database user.";
|
||||
description = lib.mdDoc "Database user.";
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = "/run/keys/invoiceplane-dbpassword";
|
||||
description = ''
|
||||
description = lib.mdDoc ''
|
||||
A file containing the password corresponding to
|
||||
{option}`database.user`.
|
||||
'';
|
||||
|
@ -150,14 +133,14 @@ let
|
|||
createLocally = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Create the database and database user locally.";
|
||||
description = lib.mdDoc "Create the database and database user locally.";
|
||||
};
|
||||
};
|
||||
|
||||
invoiceTemplates = mkOption {
|
||||
type = types.listOf types.path;
|
||||
default = [];
|
||||
description = ''
|
||||
description = lib.mdDoc ''
|
||||
List of path(s) to respective template(s) which are copied from the 'invoice_templates/pdf' directory.
|
||||
|
||||
::: {.note}
|
||||
|
@ -196,44 +179,45 @@ let
|
|||
"pm.max_spare_servers" = 4;
|
||||
"pm.max_requests" = 500;
|
||||
};
|
||||
description = ''
|
||||
description = lib.mdDoc ''
|
||||
Options for the InvoicePlane PHP pool. See the documentation on `php-fpm.conf`
|
||||
for details on configuration directives.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.attrsOf types.anything;
|
||||
default = {};
|
||||
description = ''
|
||||
Structural InvoicePlane configuration. Refer to
|
||||
<https://github.com/InvoicePlane/InvoicePlane/blob/master/ipconfig.php.example>
|
||||
for details and supported values.
|
||||
extraConfig = mkOption {
|
||||
type = types.nullOr types.lines;
|
||||
default = null;
|
||||
example = ''
|
||||
SETUP_COMPLETED=true
|
||||
DISABLE_SETUP=true
|
||||
IP_URL=https://invoice.example.com
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
SETUP_COMPLETED = true;
|
||||
DISABLE_SETUP = true;
|
||||
IP_URL = "https://invoice.example.com";
|
||||
}
|
||||
description = lib.mdDoc ''
|
||||
InvoicePlane configuration. Refer to
|
||||
<https://github.com/InvoicePlane/InvoicePlane/blob/master/ipconfig.php.example>
|
||||
for details on supported values.
|
||||
'';
|
||||
};
|
||||
|
||||
cron = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
description = lib.mdDoc ''
|
||||
Enable cron service which periodically runs Invoiceplane tasks.
|
||||
Requires key taken from the administration page. Refer to
|
||||
<https://wiki.invoiceplane.com/en/1.0/modules/recurring-invoices>
|
||||
on how to configure it.
|
||||
'';
|
||||
};
|
||||
|
||||
key = mkOption {
|
||||
type = types.str;
|
||||
description = "Cron key taken from the administration page.";
|
||||
description = lib.mdDoc "Cron key taken from the administration page.";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -253,20 +237,20 @@ in
|
|||
options.sites = mkOption {
|
||||
type = types.attrsOf (types.submodule siteOpts);
|
||||
default = {};
|
||||
description = "Specification of one or more WordPress sites to serve";
|
||||
description = lib.mdDoc "Specification of one or more WordPress sites to serve";
|
||||
};
|
||||
|
||||
options.webserver = mkOption {
|
||||
type = types.enum [ "caddy" "nginx" ];
|
||||
type = types.enum [ "caddy" ];
|
||||
default = "caddy";
|
||||
example = "nginx";
|
||||
description = ''
|
||||
Which webserver to use for virtual host management.
|
||||
description = lib.mdDoc ''
|
||||
Which webserver to use for virtual host management. Currently only
|
||||
caddy is supported.
|
||||
'';
|
||||
};
|
||||
};
|
||||
default = {};
|
||||
description = "InvoicePlane configuration.";
|
||||
description = lib.mdDoc "InvoicePlane configuration.";
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -274,8 +258,8 @@ in
|
|||
# implementation
|
||||
config = mkIf (eachSite != {}) (mkMerge [{
|
||||
|
||||
assertions = flatten (mapAttrsToList (hostName: cfg: [
|
||||
{ assertion = cfg.database.createLocally -> cfg.database.user == user;
|
||||
assertions = flatten (mapAttrsToList (hostName: cfg:
|
||||
[{ assertion = cfg.database.createLocally -> cfg.database.user == user;
|
||||
message = ''services.invoiceplane.sites."${hostName}".database.user must be ${user} if the database is to be automatically provisioned'';
|
||||
}
|
||||
{ assertion = cfg.database.createLocally -> cfg.database.passwordFile == null;
|
||||
|
@ -389,43 +373,5 @@ in
|
|||
};
|
||||
})
|
||||
|
||||
(mkIf (cfg.webserver == "nginx") {
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts = mapAttrs' (hostName: cfg: (
|
||||
nameValuePair hostName {
|
||||
root = pkg hostName cfg;
|
||||
extraConfig = ''
|
||||
index index.php index.html index.htm;
|
||||
|
||||
if (!-e $request_filename){
|
||||
rewrite ^(.*)$ /index.php break;
|
||||
}
|
||||
'';
|
||||
|
||||
locations = {
|
||||
"/setup".extraConfig =
|
||||
let
|
||||
scheme = if config.services.nginx.virtualHosts.${hostName}.forceSSL then "https" else "http";
|
||||
in
|
||||
''
|
||||
rewrite ^(.*)$ ${scheme}://${hostName}/ redirect;
|
||||
'';
|
||||
|
||||
"~ .php$" = {
|
||||
extraConfig = ''
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_pass unix:${config.services.phpfpm.pools."invoiceplane-${hostName}".socket};
|
||||
include ${config.services.nginx.package}/conf/fastcgi_params;
|
||||
include ${config.services.nginx.package}/conf/fastcgi.conf;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
)) eachSite;
|
||||
};
|
||||
})
|
||||
|
||||
]);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue