added a bunch of stuff from mossnet, and music
This commit is contained in:
parent
f7cd8ad493
commit
f8edbfe092
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.direnv/
|
|
@ -1,6 +1,12 @@
|
||||||
{pkgs, ...}:
|
{ pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
hardware.bluetooth.enable = true;
|
hardware.bluetooth.enable = true;
|
||||||
services.blueman.enable = true;
|
services.blueman.enable = true;
|
||||||
|
# A2DP protocol
|
||||||
|
hardware.bluetooth.settings = {
|
||||||
|
General = {
|
||||||
|
Enable = "Source,Sink,Media,Socket";
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
34
profiles/borg/default.nix
Normal file
34
profiles/borg/default.nix
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
# Assumes the remote borg backup server has already been initialized
|
||||||
|
# borg init --encryption-key=repokey-blake2 -rsh 'ssh -i /run/keys/id_ed25519_borgbase' 20779@hk-s020.rsync.net:<borg-archive>
|
||||||
|
services.borgbackup.jobs = {
|
||||||
|
backupTaskwarriorRsync = {
|
||||||
|
paths = [ "/var/lib/taskserver" ];
|
||||||
|
doInit = true;
|
||||||
|
repo = "20779@hk-s020.rsync.net:taskwarrior";
|
||||||
|
encryption = {
|
||||||
|
mode = "repokey-blake2";
|
||||||
|
passCommand = "cat /run/keys/rsync";
|
||||||
|
};
|
||||||
|
environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_borgbase"; };
|
||||||
|
compression = "auto,lzma";
|
||||||
|
startAt = "weekly";
|
||||||
|
extraArgs = "--remote-path=borg1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.borgbackup.jobs = {
|
||||||
|
backupShaarliRsync = {
|
||||||
|
paths = [ "/var/www/shaarli-config/data/datastore.php" "/var/www/shaarli-config/config" "/var/www/shaarli-config/.json.config" ];
|
||||||
|
doInit = true;
|
||||||
|
repo = "20779@hk-s020.rsync.net:shaarli";
|
||||||
|
encryption = {
|
||||||
|
mode = "repokey-blake2";
|
||||||
|
passCommand = "cat /run/keys/rsync";
|
||||||
|
};
|
||||||
|
environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_borgbase"; };
|
||||||
|
compression = "auto,lzma";
|
||||||
|
startAt = "weekly";
|
||||||
|
extraArgs = "--remote-path=borg1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
16
profiles/dns/defalut.nix
Normal file
16
profiles/dns/defalut.nix
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
{
|
||||||
|
services.dnsmasq.enable = true;
|
||||||
|
services.dnsmasq.extraConfig = ''
|
||||||
|
domain-needed
|
||||||
|
no-resolv
|
||||||
|
local=/lan/
|
||||||
|
local=/moss/
|
||||||
|
cache-size=5000
|
||||||
|
addn-hosts=/ec/adblock.hosts
|
||||||
|
'';
|
||||||
|
services.dnsmasq.servers = [ "45.90.30.49" "45.90.28.49" "1.1.1.1" "8.8.8.8" ];
|
||||||
|
networking.hosts = { "172.16.11.240" = [ "mossnet.lan" "links.mossnet.lan" "read.mossnet.lan" "stats.mossnet.lan" "music.moss" "tasks.moss" "headphones.moss" "cloud.moss" "links.moss" "read.moss" "stats.moss" "rss.moss" ]; };
|
||||||
|
networking.firewall.allowedTCPPorts = [ 53 ];
|
||||||
|
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||||
|
}
|
12
profiles/gonic/default.nix
Normal file
12
profiles/gonic/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
{
|
||||||
|
services.gonic.enable = true;
|
||||||
|
services.gonic.settings = ''
|
||||||
|
music-path /data/music
|
||||||
|
podcast-path /data/music
|
||||||
|
cache-path /data/cache
|
||||||
|
'';
|
||||||
|
services.gonic.group = "audio";
|
||||||
|
services.gonic.user = "headphones";
|
||||||
|
networking.firewall.allowedTCPPorts = [ 4747 ];
|
||||||
|
}
|
110
profiles/gonic/module-gonic.nix
Normal file
110
profiles/gonic/module-gonic.nix
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.gonic;
|
||||||
|
configFile = "/etc/gonic/config";
|
||||||
|
dataFolder = "/var/lib/gonic";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.gonic = {
|
||||||
|
enable = mkEnableOption "Gonic music server and streamer";
|
||||||
|
|
||||||
|
settings = lib.mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = { };
|
||||||
|
example = literalExample ''
|
||||||
|
music-path <path to your music dir>
|
||||||
|
podcast-path <path to your podcasts dir>
|
||||||
|
cache-path <path to cache dir>
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Configuration for Gonic, see <link xlink:href="https://github.com/sentriz/gonic"/> for supported values.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "gonic";
|
||||||
|
description = "User account under which gonic runs.";
|
||||||
|
};
|
||||||
|
|
||||||
|
group = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "gonic";
|
||||||
|
description = "Group account under which gonic runs.";
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
environment.etc."gonic/config".text = cfg.settings;
|
||||||
|
|
||||||
|
systemd.services.gonic = {
|
||||||
|
description = "gonic Music Server and Streamer compatible with Subsonic/Airsonic";
|
||||||
|
after = [ "remote-fs.target" "network.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
environment = {
|
||||||
|
#GONIC_MUSIC_PATH
|
||||||
|
#GONIC_PODCAST_PATH
|
||||||
|
#GONIC_CACHE_PATH
|
||||||
|
#GONIC_DB_PATH
|
||||||
|
GONIC_SCAN_INTERVAL = "800";
|
||||||
|
#...
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${pkgs.gonic}/bin/gonic -config-path /etc/gonic/config";
|
||||||
|
WorkingDirectory = dataFolder;
|
||||||
|
TimeoutStopSec = "20";
|
||||||
|
KillMode = "process";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = "10";
|
||||||
|
User = cfg.user;
|
||||||
|
Group = cfg.group;
|
||||||
|
DevicePolicy = "closed";
|
||||||
|
NoNewPrivileges = " yes";
|
||||||
|
PrivateTmp = "yes";
|
||||||
|
PrivateUsers = "yes";
|
||||||
|
ProtectControlGroups = "yes";
|
||||||
|
ProtectKernelModules = "yes";
|
||||||
|
ProtectKernelTunables = "yes";
|
||||||
|
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||||
|
RestrictNamespaces = "yes";
|
||||||
|
RestrictRealtime = "yes";
|
||||||
|
SystemCallFilter = "~@clock @debug @module @mount @obsolete @privileged @reboot @setuid @swap";
|
||||||
|
ReadWritePaths = dataFolder;
|
||||||
|
StateDirectory = baseNameOf dataFolder;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users = optionalAttrs (cfg.user == "gonic") ({
|
||||||
|
gonic = {
|
||||||
|
description = "gonic service user";
|
||||||
|
name = cfg.user;
|
||||||
|
group = cfg.group;
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
users.groups = optionalAttrs (cfg.group == "gonic") ({
|
||||||
|
gonic = { };
|
||||||
|
});
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."music.mossnet.lan" = {
|
||||||
|
enableACME = false;
|
||||||
|
forceSSL = false;
|
||||||
|
|
||||||
|
locations."/" = {
|
||||||
|
extraConfig = ''
|
||||||
|
proxy_pass http://localhost:4747/;
|
||||||
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
12
profiles/headphones/default.nix
Normal file
12
profiles/headphones/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
{
|
||||||
|
services.headphones = {
|
||||||
|
enable = true;
|
||||||
|
host = "172.16.11.240";
|
||||||
|
port = 8181;
|
||||||
|
user = "headphones";
|
||||||
|
group = "audio";
|
||||||
|
dataDir = "/data/music";
|
||||||
|
};
|
||||||
|
networking.firewall.allowedTCPPorts = [ 8181 ];
|
||||||
|
}
|
59
profiles/monitoring/default.nix
Normal file
59
profiles/monitoring/default.nix
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
{ config, pkgs, ... }: {
|
||||||
|
# grafana configuration
|
||||||
|
services.grafana = {
|
||||||
|
enable = true;
|
||||||
|
domain = "stats.mossnet.lan";
|
||||||
|
port = 2342;
|
||||||
|
addr = "127.0.0.1";
|
||||||
|
};
|
||||||
|
|
||||||
|
# nginx reverse proxy
|
||||||
|
services.nginx.virtualHosts.${config.services.grafana.domain} = {
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://127.0.0.1:${toString config.services.grafana.port}";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.prometheus = {
|
||||||
|
enable = true;
|
||||||
|
port = 9001;
|
||||||
|
exporters = {
|
||||||
|
node = {
|
||||||
|
enable = true;
|
||||||
|
enabledCollectors = [ "systemd" ];
|
||||||
|
port = 9002;
|
||||||
|
};
|
||||||
|
dnsmasq = {
|
||||||
|
enable = true;
|
||||||
|
port = 9153;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
scrapeConfigs = [
|
||||||
|
{
|
||||||
|
job_name = "box";
|
||||||
|
static_configs = [{ targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.node.port}" ]; }];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
job_name = "dns";
|
||||||
|
static_configs = [{ targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.dnsmasq.port}" ]; }];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.loki = {
|
||||||
|
enable = true;
|
||||||
|
configFile = /var/loki-config.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.promtail = {
|
||||||
|
description = "Promtail service for Loki";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = ''
|
||||||
|
${pkgs.grafana-loki}/bin/promtail --config.file ${/var/promtail.yaml}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
41
profiles/music/default.nix
Normal file
41
profiles/music/default.nix
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
helm
|
||||||
|
surge
|
||||||
|
distrho
|
||||||
|
orca-c
|
||||||
|
carla
|
||||||
|
sunvox
|
||||||
|
vcv-rack
|
||||||
|
reaper
|
||||||
|
renoise
|
||||||
|
projectm # milkdrop visualizer
|
||||||
|
]
|
||||||
|
|
||||||
|
hardware.pulseaudio.enable = lib.mkForce false;
|
||||||
|
security.rtkit.enable = true;
|
||||||
|
|
||||||
|
services.pipewire = {
|
||||||
|
enable = true;
|
||||||
|
alsa.enable = true;
|
||||||
|
alsa.support32Bit = true;
|
||||||
|
pulse.enable = true;
|
||||||
|
config = {
|
||||||
|
pipewire."context.properties"."default.clock.rate" = "192000";
|
||||||
|
pipewire-pulse."stream.properties"."resample.quality" = 15;
|
||||||
|
client."stream.properties"."resample.quality" = 15;
|
||||||
|
client-rt."stream.properties"."resample.quality" = 15;
|
||||||
|
};
|
||||||
|
media-session.config.bluez-monitor.properties = {
|
||||||
|
"bluez5.headset-roles" = [ "hsp_hs" "hsp_ag" ];
|
||||||
|
"bluez5.codecs" = [ "aac" "ldac" "aptx_hd" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.bluethoot.serviceConfig.ExecStart = [
|
||||||
|
""
|
||||||
|
"${config.hardware.bluetooth.package}/libexec/bluetooth/bluetoothd --noplugin=sap"
|
||||||
|
];
|
||||||
|
}
|
57
profiles/nextcloud/default.nix
Normal file
57
profiles/nextcloud/default.nix
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
{ pkgs, config, ... }:
|
||||||
|
{
|
||||||
|
age.secrets.nextcloud-db.file = "/etc/nixos/secrets/nextcloud-db.age";
|
||||||
|
age.secrets.nextcloud-admin.file = "/etc/nixos/secrets/nextcloud-admin.age";
|
||||||
|
services.nextcloud = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "mossnet.lan";
|
||||||
|
home = "/data/nextcloud";
|
||||||
|
package = pkgs.nextcloud21;
|
||||||
|
|
||||||
|
# Use HTTPS for links
|
||||||
|
https = false;
|
||||||
|
|
||||||
|
# Auto-update Nextcloud Apps
|
||||||
|
autoUpdateApps.enable = true;
|
||||||
|
# Set what time makes sense for you
|
||||||
|
autoUpdateApps.startAt = "05:00:00";
|
||||||
|
|
||||||
|
config = {
|
||||||
|
# Further forces Nextcloud to use HTTPS
|
||||||
|
# overwriteProtocol = "https";
|
||||||
|
|
||||||
|
# Nextcloud PostegreSQL database configuration, recommended over using SQLite
|
||||||
|
dbtype = "pgsql";
|
||||||
|
dbuser = "nextcloud";
|
||||||
|
dbhost = "/run/postgresql"; # nextcloud will add /.s.PGSQL.5432 by itself
|
||||||
|
dbname = "nextcloud";
|
||||||
|
dbpassFile = "/run/secrets/nextcloud-db";
|
||||||
|
adminpassFile = "/run/secrets/nextcloud-admin";
|
||||||
|
adminuser = "admin";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable PostgreSQL
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
# Ensure the database, user, and permissions always exist
|
||||||
|
ensureDatabases = [ "nextcloud" ];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = "nextcloud";
|
||||||
|
ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Ensure that postgres is running before running the setup
|
||||||
|
systemd.services."nextcloud-setup" = {
|
||||||
|
requires = [ "postgresql.service" ];
|
||||||
|
after = [ "postgresql.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
|
||||||
|
#nixpkgs.config.permittedInsecurePackages = [ "nextcloud-19.0.6"];
|
||||||
|
}
|
114
profiles/shaarli/default.nix
Normal file
114
profiles/shaarli/default.nix
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
{ pkgs, config, ... }:
|
||||||
|
let
|
||||||
|
dataDir = "/var/www/shaarli-config";
|
||||||
|
name = "shaarli";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"links.mossnet.lan" = {
|
||||||
|
forceSSL = false;
|
||||||
|
enableACME = false;
|
||||||
|
root = "${dataDir}";
|
||||||
|
extraConfig = ''
|
||||||
|
index index.php;
|
||||||
|
'';
|
||||||
|
locations = {
|
||||||
|
"/".extraConfig = ''
|
||||||
|
try_files $uri $uri/ index.php$is_args$args;
|
||||||
|
'';
|
||||||
|
|
||||||
|
"~ (index)\\.php$".extraConfig = ''
|
||||||
|
try_files $uri =404;
|
||||||
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||||
|
|
||||||
|
fastcgi_pass unix:${config.services.phpfpm.pools."${name}".socket};
|
||||||
|
fastcgi_index index.php;
|
||||||
|
|
||||||
|
fastcgi_param QUERY_STRING $query_string;
|
||||||
|
fastcgi_param REQUEST_METHOD $request_method;
|
||||||
|
fastcgi_param CONTENT_TYPE $content_type;
|
||||||
|
fastcgi_param CONTENT_LENGTH $content_length;
|
||||||
|
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
|
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
|
||||||
|
fastcgi_param REQUEST_URI $request_uri;
|
||||||
|
fastcgi_param DOCUMENT_URI $document_uri;
|
||||||
|
fastcgi_param DOCUMENT_ROOT $document_root;
|
||||||
|
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
||||||
|
|
||||||
|
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
||||||
|
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||||
|
|
||||||
|
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||||
|
fastcgi_param REMOTE_PORT $remote_port;
|
||||||
|
fastcgi_param SERVER_ADDR $server_addr;
|
||||||
|
fastcgi_param SERVER_PORT $server_port;
|
||||||
|
fastcgi_param SERVER_NAME $server_name;
|
||||||
|
'';
|
||||||
|
|
||||||
|
"~ \\.php$".extraConfig = ''
|
||||||
|
deny all;
|
||||||
|
'';
|
||||||
|
|
||||||
|
"^~ /tpl/".extraConfig = "alias ${pkgs.shaarli}/tpl/;";
|
||||||
|
|
||||||
|
"^~ /plugins/".extraConfig = "alias ${pkgs.shaarli}/plugins/;";
|
||||||
|
|
||||||
|
"~* \\.(?:ico|css|js|gif|jpe?g|png)$".extraConfig = ''
|
||||||
|
expires max;
|
||||||
|
add_header Pragma public;
|
||||||
|
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.phpfpm = {
|
||||||
|
pools = {
|
||||||
|
"${name}" = {
|
||||||
|
user = "nginx";
|
||||||
|
group = "nginx";
|
||||||
|
#listen = "/run/phpfpm/php.sock";
|
||||||
|
settings = {
|
||||||
|
"listen.owner" = "nginx";
|
||||||
|
"listen.group" = "nginx";
|
||||||
|
"user" = "nginx";
|
||||||
|
"pm" = "dynamic";
|
||||||
|
"pm.max_children" = "4";
|
||||||
|
"pm.min_spare_servers" = "1";
|
||||||
|
"pm.max_spare_servers" = "4";
|
||||||
|
"pm.max_requests" = "32";
|
||||||
|
"catch_workers_output" = "1";
|
||||||
|
"php_admin_value[error_log]" = "/var/log/nginx/${name}-phpfpm-error.log";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
users.extraUsers."${name}" = { group = "${name}"; };
|
||||||
|
users.extraGroups."${name}" = { };
|
||||||
|
users.users.shaarli.isSystemUser = true;
|
||||||
|
systemd.services.shaarli-install = {
|
||||||
|
serviceConfig.Type = "oneshot";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
script = ''
|
||||||
|
if [ ! -d "${dataDir}" ]; then
|
||||||
|
#cp -R ${pkgs.shaarli}/data.orig/.htaccess ${dataDir}/cache/
|
||||||
|
#cp -R ${pkgs.shaarli}/data.orig/.htaccess ${dataDir}/data/
|
||||||
|
#cp -R ${pkgs.shaarli}/data.orig/.htaccess ${dataDir}/pagecache/
|
||||||
|
#cp -R ${pkgs.shaarli}/data.orig/.htaccess ${dataDir}/tmp/
|
||||||
|
mkdir -p ${dataDir}/{cache,data,pagecache,tmp}
|
||||||
|
ln -s ${pkgs.shaarli}/* ${dataDir}
|
||||||
|
fi
|
||||||
|
chown -Rc nginx:nginx ${dataDir}
|
||||||
|
find ${dataDir} -type d ! -perm 0700 -exec chmod 0700 {} \; -exec chmod g-s {} \;
|
||||||
|
find ${dataDir} -type f ! -perm 0600 -exec chmod 0600 {} \;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
# TODO: Write the configuration file here?
|
||||||
|
#networking.firewall.allowedTCPPorts = [ 80 ];
|
||||||
|
}
|
9
profiles/taskd/default.nix
Normal file
9
profiles/taskd/default.nix
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.taskserver.enable = true;
|
||||||
|
services.taskserver.fqdn = "task.moss";
|
||||||
|
services.taskserver.listenHost = "172.16.11.240";
|
||||||
|
services.taskserver.listenPort = 53589;
|
||||||
|
services.taskserver.organisations.mossnet.users = [ "anish" ];
|
||||||
|
}
|
99
profiles/wallabag/default.nix
Normal file
99
profiles/wallabag/default.nix
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
{ pkgs, config, lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
# Ensure the database, user, and permissions always exist
|
||||||
|
ensureDatabases = [ "wallabag" ];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = "wallabag";
|
||||||
|
ensurePermissions."DATABASE wallabag" = "ALL PRIVILEGES";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.wallabag = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "read.mossnet.lan";
|
||||||
|
package = pkgs.callPackage ./pkg-wallabag.nix { };
|
||||||
|
conf = ''
|
||||||
|
# This file is a "template" of what your parameters.yml file should look like
|
||||||
|
parameters:
|
||||||
|
# Uncomment these settings or manually update your parameters.yml
|
||||||
|
# to use docker-compose
|
||||||
|
#
|
||||||
|
# database_driver: %env.database_driver%
|
||||||
|
# database_host: %env.database_host%
|
||||||
|
# database_port: %env.database_port%
|
||||||
|
# database_name: %env.database_name%
|
||||||
|
# database_user: %env.database_user%
|
||||||
|
# database_password: %env.database_password%
|
||||||
|
|
||||||
|
database_driver: pdo_pgsql
|
||||||
|
database_host: localhost
|
||||||
|
database_port: ~
|
||||||
|
database_name: wallabag
|
||||||
|
database_user: wallabag
|
||||||
|
database_password: wallabag
|
||||||
|
# For SQLite, database_path should be "%kernel.project_dir%/data/db/wallabag.sqlite"
|
||||||
|
database_path: ~
|
||||||
|
database_table_prefix: wallabag_
|
||||||
|
database_socket: null
|
||||||
|
# with PostgreSQL and SQLite, you must set "utf8"
|
||||||
|
database_charset: utf8
|
||||||
|
|
||||||
|
domain_name: http://read.mossnet.lan
|
||||||
|
server_name: "mossnet wallabag instance"
|
||||||
|
|
||||||
|
mailer_transport: smtp
|
||||||
|
mailer_user: ~
|
||||||
|
mailer_password: ~
|
||||||
|
mailer_host: 127.0.0.1
|
||||||
|
mailer_port: false
|
||||||
|
mailer_encryption: ~
|
||||||
|
mailer_auth_mode: ~
|
||||||
|
|
||||||
|
locale: en
|
||||||
|
|
||||||
|
# A secret key that's used to generate certain security-related tokens
|
||||||
|
secret: SAFGOECRIlfal89oe6u0(*^dsaaih961
|
||||||
|
|
||||||
|
# two factor stuff
|
||||||
|
twofactor_auth: true
|
||||||
|
twofactor_sender: no-reply@wallabag.org
|
||||||
|
|
||||||
|
# fosuser stuff
|
||||||
|
fosuser_registration: true
|
||||||
|
fosuser_confirmation: true
|
||||||
|
|
||||||
|
# how long the access token should live in seconds for the API
|
||||||
|
fos_oauth_server_access_token_lifetime: 3600
|
||||||
|
# how long the refresh token should life in seconds for the API
|
||||||
|
fos_oauth_server_refresh_token_lifetime: 1209600
|
||||||
|
|
||||||
|
from_email: no-reply@wallabag.org
|
||||||
|
|
||||||
|
rss_limit: 50
|
||||||
|
|
||||||
|
# RabbitMQ processing
|
||||||
|
rabbitmq_host: localhost
|
||||||
|
rabbitmq_port: 5672
|
||||||
|
rabbitmq_user: guest
|
||||||
|
rabbitmq_password: guest
|
||||||
|
rabbitmq_prefetch_count: 10
|
||||||
|
|
||||||
|
# Redis processing
|
||||||
|
redis_scheme: tcp
|
||||||
|
redis_host: localhost
|
||||||
|
redis_port: 6379
|
||||||
|
redis_path: null
|
||||||
|
redis_password: null
|
||||||
|
|
||||||
|
# sentry logging
|
||||||
|
sentry_dsn: ~
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
# networking.firewall.allowedTCPPorts = [ 8080 ];
|
||||||
|
}
|
221
profiles/wallabag/mod-wallabag.nix
Normal file
221
profiles/wallabag/mod-wallabag.nix
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
{ config, options, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.services.wallabag;
|
||||||
|
|
||||||
|
poolName = "wallabag";
|
||||||
|
|
||||||
|
configFile = pkgs.writeTextFile {
|
||||||
|
name = "wallabag-config";
|
||||||
|
text = cfg.conf;
|
||||||
|
destination = "/config/parameters.yml";
|
||||||
|
};
|
||||||
|
|
||||||
|
appDir = pkgs.buildEnv {
|
||||||
|
name = "wallabag-app-dir";
|
||||||
|
ignoreCollisions = true;
|
||||||
|
checkCollisionContents = false;
|
||||||
|
paths = [ configFile "${cfg.package}/app" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.wallabag = {
|
||||||
|
enable = mkEnableOption "wallabag";
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "nginx";
|
||||||
|
description = ''
|
||||||
|
User account under which both the update daemon and the web-application run.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dataDir = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/var/lib/wallabag";
|
||||||
|
description = ''
|
||||||
|
Data directory.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.wallabag;
|
||||||
|
description = ''
|
||||||
|
Wallabag package to use.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
hostName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Name of the nginx virtualhost to use and setup.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
poolConfig = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = ''
|
||||||
|
pm = dynamic
|
||||||
|
pm.max_children = 75
|
||||||
|
pm.start_servers = 1
|
||||||
|
pm.min_spare_servers = 1
|
||||||
|
pm.max_spare_servers = 20
|
||||||
|
pm.max_requests = 500
|
||||||
|
catch_workers_output = 1
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Options for wallabag's PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
conf = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Contents of the wallabag configuration file (parameters.yml)
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
services.phpfpm.pools."${poolName}" = {
|
||||||
|
user = "${cfg.user}";
|
||||||
|
group = "nginx";
|
||||||
|
settings = {
|
||||||
|
"listen.owner" = "nginx";
|
||||||
|
"listen.group" = "nginx";
|
||||||
|
"listen.mode" = "0600";
|
||||||
|
"user" = "${cfg.user}";
|
||||||
|
"group" = "nginx";
|
||||||
|
"env[WALLABAG_DATA]" = "${cfg.dataDir}";
|
||||||
|
"pm" = "dynamic";
|
||||||
|
"pm.max_children" = "75";
|
||||||
|
"pm.min_spare_servers" = "5";
|
||||||
|
"pm.max_spare_servers" = "20";
|
||||||
|
"pm.max_requests" = "10";
|
||||||
|
"catch_workers_output" = "1";
|
||||||
|
"php_admin_value[error_log]" = "/var/log/nginx/${poolName}-phpfpm-error.log";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.phpfpm.phpOptions = ''
|
||||||
|
max_execution_time = 120
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.nginx.enable = mkDefault true;
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."${cfg.hostName}" = {
|
||||||
|
enableACME = false;
|
||||||
|
forceSSL = false;
|
||||||
|
root = "${cfg.package}/web";
|
||||||
|
|
||||||
|
extraConfig = ''
|
||||||
|
add_header X-Frame-Options SAMEORIGIN;
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
'';
|
||||||
|
|
||||||
|
locations."/" = {
|
||||||
|
extraConfig = ''
|
||||||
|
try_files $uri /app.php$is_args$args;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
locations."/assets".root = "${cfg.dataDir}/web";
|
||||||
|
|
||||||
|
locations."~ ^/app\\.php(/|$)" = {
|
||||||
|
extraConfig = ''
|
||||||
|
fastcgi_pass unix:${config.services.phpfpm.pools."${poolName}".socket};
|
||||||
|
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||||
|
|
||||||
|
fastcgi_param SCRIPT_FILENAME ${cfg.package}/web/$fastcgi_script_name;
|
||||||
|
fastcgi_param DOCUMENT_ROOT ${cfg.package}/web;
|
||||||
|
fastcgi_read_timeout 120;
|
||||||
|
|
||||||
|
fastcgi_param QUERY_STRING $query_string;
|
||||||
|
fastcgi_param REQUEST_METHOD $request_method;
|
||||||
|
fastcgi_param CONTENT_TYPE $content_type;
|
||||||
|
fastcgi_param CONTENT_LENGTH $content_length;
|
||||||
|
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
|
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
|
||||||
|
fastcgi_param REQUEST_URI $request_uri;
|
||||||
|
fastcgi_param DOCUMENT_URI $document_uri;
|
||||||
|
fastcgi_param SERVER_PROTOCOL $server_protocol;
|
||||||
|
|
||||||
|
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
|
||||||
|
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||||
|
|
||||||
|
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||||
|
fastcgi_param REMOTE_PORT $remote_port;
|
||||||
|
fastcgi_param SERVER_ADDR $server_addr;
|
||||||
|
fastcgi_param SERVER_PORT $server_port;
|
||||||
|
fastcgi_param SERVER_NAME $server_name;
|
||||||
|
|
||||||
|
internal;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
locations."~ /(?!app)\\.php$" = {
|
||||||
|
extraConfig = ''
|
||||||
|
return 404;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.wallabag-install = {
|
||||||
|
description = "Wallabag install service";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
before = [ "phpfpm-wallabag.service" ];
|
||||||
|
after = [ "mysql.service" "postgresql.service" ];
|
||||||
|
path = with pkgs; [ coreutils php phpPackages.composer ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
User = cfg.user;
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = "yes";
|
||||||
|
PermissionsStartOnly = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
mkdir -p "${cfg.dataDir}"
|
||||||
|
chown ${cfg.user}:nginx "${cfg.dataDir}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
echo "Setting up wallabag files in ${cfg.dataDir} ..."
|
||||||
|
cd "${cfg.dataDir}"
|
||||||
|
|
||||||
|
rm -rf var/cache/*
|
||||||
|
rm -f app
|
||||||
|
ln -sf ${appDir} app
|
||||||
|
ln -sf ${cfg.package}/composer.{json,lock} .
|
||||||
|
|
||||||
|
export WALLABAG_DATA="${cfg.dataDir}"
|
||||||
|
if [ ! -f installed ]; then
|
||||||
|
php ${cfg.package}/bin/console --env=prod doctrine:database:create --if-not-exists --no-interaction
|
||||||
|
php ${cfg.package}/bin/console --env=prod doctrine:migrations:migrate --no-interaction
|
||||||
|
# Until https://github.com/wallabag/wallabag/issues/3662 is fixed
|
||||||
|
# yes no | php ${cfg.package}/bin/console --env=prod wallabag:install
|
||||||
|
touch installed
|
||||||
|
else
|
||||||
|
php ${cfg.package}/bin/console --env=prod doctrine:migrations:migrate --no-interaction
|
||||||
|
fi
|
||||||
|
php ${cfg.package}/bin/console --env=prod cache:clear
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = with stdenv.lib; {
|
||||||
|
maintainers = with maintainers; [ nadrieril ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,9 +2,12 @@ let
|
||||||
# set ssh public keys here for your system and user
|
# set ssh public keys here for your system and user
|
||||||
user = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIItTdCyYVur6LzRQf08JZUcEAr23H7fTRRmDJOzoOc6A anish@curve";
|
user = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIItTdCyYVur6LzRQf08JZUcEAr23H7fTRRmDJOzoOc6A anish@curve";
|
||||||
system = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMPcqWQ/L5nLTsBFHArl3AJb9xynhfsKenb5h0NNuMV root@curve";
|
system = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMPcqWQ/L5nLTsBFHArl3AJb9xynhfsKenb5h0NNuMV root@curve";
|
||||||
|
mossnet = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAA0bsVbdQR6iWNLKIiID57A1+dVXC58Dtf5cSXg6/JF root@box";
|
||||||
allKeys = [ system user ];
|
allKeys = [ system user ];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
"fastmail.age".publicKeys = allKeys;
|
"fastmail.age".publicKeys = allKeys;
|
||||||
"mossnet.age".publicKeys = allKeys;
|
"mossnet.age".publicKeys = allKeys;
|
||||||
|
"nextcloud-db.age".publicKeys = mossnet;
|
||||||
|
"nextcloud-admin.age".publicKeys = mossnet;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
{pkgs, config, ...}:
|
{ pkgs, config, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
# TODO modularize
|
||||||
#imports = [ ./xdg.nix ];
|
#imports = [ ./xdg.nix ];
|
||||||
|
|
||||||
home-manager.users.anish.xdg.enable = true; # This doesn't seem to do anything so we have below
|
home-manager.users.anish.xdg.enable = true; # This doesn't seem to do anything so we have below
|
||||||
home-manager.users.anish.xdg.configHome = "/home/anish/.config"; # TODO bad hard coded
|
home-manager.users.anish.xdg.configHome = "/home/anish/.config"; # TODO bad hard coded
|
||||||
environment.sessionVariables = rec {
|
environment.sessionVariables = rec {
|
||||||
XDG_CACHE_HOME = "\${HOME}/.cache";
|
XDG_CACHE_HOME = "\${HOME}/.cache";
|
||||||
XDG_CONFIG_HOME = "\${HOME}/.config";
|
XDG_CONFIG_HOME = "\${HOME}/.config";
|
||||||
XDG_BIN_HOME = "\${HOME}/.local/bin";
|
XDG_BIN_HOME = "\${HOME}/.local/bin";
|
||||||
XDG_DATA_HOME = "\${HOME}/.local/share";
|
XDG_DATA_HOME = "\${HOME}/.local/share";
|
||||||
|
|
||||||
PATH = [
|
PATH = [
|
||||||
"\${XDG_BIN_HOME}"
|
"\${XDG_BIN_HOME}"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
@ -19,7 +20,7 @@
|
||||||
# TODO move somewhere meaningful
|
# TODO move somewhere meaningful
|
||||||
tdesktop # TODO get rid of this once bridged on sealight
|
tdesktop # TODO get rid of this once bridged on sealight
|
||||||
sublime-music
|
sublime-music
|
||||||
nheko
|
nheko
|
||||||
newsflash
|
newsflash
|
||||||
zeal
|
zeal
|
||||||
xclip
|
xclip
|
||||||
|
@ -120,37 +121,37 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
xresources.properties = {
|
xresources.properties = {
|
||||||
"Xcursor.theme"= "Paper";
|
"Xcursor.theme" = "Paper";
|
||||||
#"Xcursor.size"= 64;
|
#"Xcursor.size"= 64;
|
||||||
"*.foreground"= "#e6e1cf";
|
"*.foreground" = "#e6e1cf";
|
||||||
"*.background"= "#0f1419";
|
"*.background" = "#0f1419";
|
||||||
"*.cursorColor"= "#f29718";
|
"*.cursorColor" = "#f29718";
|
||||||
# Black
|
# Black
|
||||||
"*.color0"= "#000000";
|
"*.color0" = "#000000";
|
||||||
"*.color8"= "#323232";
|
"*.color8" = "#323232";
|
||||||
# Red
|
# Red
|
||||||
"*.color1"= "#ff3333";
|
"*.color1" = "#ff3333";
|
||||||
"*.color9"= "#ff6565";
|
"*.color9" = "#ff6565";
|
||||||
# Green
|
# Green
|
||||||
"*.color2"= "#b8cc52";
|
"*.color2" = "#b8cc52";
|
||||||
"*.color10"= "#eafe84";
|
"*.color10" = "#eafe84";
|
||||||
# Yellow
|
# Yellow
|
||||||
"*.color3"= "#e7c547";
|
"*.color3" = "#e7c547";
|
||||||
"*.color11"= "#fff779";
|
"*.color11" = "#fff779";
|
||||||
# Blue
|
# Blue
|
||||||
"*.color4"= "#36a3d9";
|
"*.color4" = "#36a3d9";
|
||||||
"*.color12"= "#68d5ff";
|
"*.color12" = "#68d5ff";
|
||||||
# Magenta
|
# Magenta
|
||||||
"*.color5"= "#f07178";
|
"*.color5" = "#f07178";
|
||||||
"*.color13"= "#ffa3aa";
|
"*.color13" = "#ffa3aa";
|
||||||
# Cyan
|
# Cyan
|
||||||
"*.color6"= "#95e6cb";
|
"*.color6" = "#95e6cb";
|
||||||
"*.color14"= "#c7fffd";
|
"*.color14" = "#c7fffd";
|
||||||
# White
|
# White
|
||||||
"*.color7"= "#ffffff";
|
"*.color7" = "#ffffff";
|
||||||
"*.color15"= "#ffffff";
|
"*.color15" = "#ffffff";
|
||||||
# Bold, Italic, Underline
|
# Bold, Italic, Underline
|
||||||
"*.colorBD"= "#e6e1cf";
|
"*.colorBD" = "#e6e1cf";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Move required config files around
|
# Move required config files around
|
||||||
|
@ -182,7 +183,7 @@
|
||||||
gtk-xft-hintstyle=hintfull
|
gtk-xft-hintstyle=hintfull
|
||||||
gtk-xft-rgba=none
|
gtk-xft-rgba=none
|
||||||
'';
|
'';
|
||||||
# GTK2 global theme (widget and icon theme)
|
# GTK2 global theme (widget and icon theme)
|
||||||
".config/gtk-2.0/gtkrc".text = ''
|
".config/gtk-2.0/gtkrc".text = ''
|
||||||
gtk-theme-name=Dracula
|
gtk-theme-name=Dracula
|
||||||
gtk-icon-theme-name=Paper
|
gtk-icon-theme-name=Paper
|
||||||
|
@ -193,28 +194,30 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
# Compositor
|
# Compositor
|
||||||
services.picom = {
|
services.picom = {
|
||||||
enable = true;
|
enable = true;
|
||||||
fade = true;
|
fade = true;
|
||||||
fadeDelta = 1;
|
fadeDelta = 1;
|
||||||
fadeSteps = [ "0.01" "0.022" ];
|
fadeSteps = [ "0.01" "0.022" ];
|
||||||
shadow = true;
|
shadow = true;
|
||||||
shadowOffsets = [ (-10) (-10) ];
|
shadowOffsets = [ (-10) (-10) ];
|
||||||
shadowOpacity = "0.22";
|
shadowOpacity = "0.22";
|
||||||
# activeOpacity = "1.00";
|
# activeOpacity = "1.00";
|
||||||
# inactiveOpacity = "0.92";
|
# inactiveOpacity = "0.92";
|
||||||
extraOptions = ''
|
extraOptions = ''
|
||||||
shadow-radius = 12;
|
shadow-radius = 12;
|
||||||
# blur-background = true;
|
# blur-background = true;
|
||||||
# blur-background-frame = true;
|
# blur-background-frame = true;
|
||||||
# blur-background-fixed = true;
|
# blur-background-fixed = true;
|
||||||
blur-kern = "7x7box";
|
blur-kern = "7x7box";
|
||||||
blur-strength = 320;
|
blur-strength = 320;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.autorandr.enable = true;
|
programs.autorandr.enable = true;
|
||||||
services.udiskie.automount = true;
|
services.udiskie.automount = true;
|
||||||
|
|
||||||
|
services.mpris-proxy.enable = true; # bluetooth media control
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
age.secrets.fastmail.file = "/etc/nixos/secrets/fastmail.age";
|
age.secrets.fastmail.file = "/etc/nixos/secrets/fastmail.age";
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
services.mbsync = {
|
services.mbsync = {
|
||||||
enable = true;
|
enable = true;
|
||||||
frequency = "*:0/30";
|
frequency = "*:0/30";
|
||||||
postExec = "${pkgs.notmuch}/bin/notmuch index";
|
postExec = "${pkgs.notmuch}/bin/notmuch new";
|
||||||
};
|
};
|
||||||
programs.mbsync.enable = true;
|
programs.mbsync.enable = true;
|
||||||
programs.msmtp.enable = true;
|
programs.msmtp.enable = true;
|
||||||
|
@ -20,211 +20,218 @@
|
||||||
programs.neomutt = {
|
programs.neomutt = {
|
||||||
enable = true;
|
enable = true;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
# Shamelessly Stolen from https://gideonwolfe.com/posts/workflow/neomutt/intro/
|
# Shamelessly Stolen from https://gideonwolfe.com/posts/workflow/neomutt/intro/
|
||||||
# set editor to neovim
|
# set editor to neovim
|
||||||
set editor = "nvim"
|
set editor = "nvim"
|
||||||
# Folder with emails
|
|
||||||
set folder = "~/Mail/anish"
|
|
||||||
# Type of mailbox
|
|
||||||
set mbox_type = Maildir
|
|
||||||
# Directory to poll for new mail
|
|
||||||
set spoolfile = +Inbox
|
|
||||||
# Directory to save sent messages into
|
|
||||||
set record = +Sent
|
|
||||||
# Sets the drafts folder
|
|
||||||
set postponed = +Drafts
|
|
||||||
# File that headers will be cached
|
|
||||||
# set header_cache = ~/.cache/mutt
|
|
||||||
|
|
||||||
set my_name = "Anish"
|
#set virtual_spoolfile=yes
|
||||||
set imap_check_subscribed
|
set folder="~/Mail/"
|
||||||
|
set mbox_type = Maildir
|
||||||
|
#virtual-mailboxes "inbox" "notmuch://?query=tag:inbox"
|
||||||
|
#virtual-mailboxes "archive" "notmuch://?query=tag:archive"
|
||||||
|
#virtual-mailboxes "sent" "notmuch://?query=tag:sent"
|
||||||
|
|
||||||
|
## Folder with emails
|
||||||
|
#set folder = "~/Mail/anish"
|
||||||
|
## Type of mailbox
|
||||||
|
## Directory to poll for new mail
|
||||||
|
#set spoolfile = +Inbox
|
||||||
|
## Directory to save sent messages into
|
||||||
|
#set record = +Sent
|
||||||
|
## Sets the drafts folder
|
||||||
|
#set postponed = +Drafts
|
||||||
|
## File that headers will be cached
|
||||||
|
## set header_cache = ~/.cache/mutt
|
||||||
|
|
||||||
# Set preffered view modes
|
#set my_name = "Anish"
|
||||||
auto_view text/html text/calendar application/ics # view html automatically
|
#set imap_check_subscribed
|
||||||
# alternative_order text/html text/plain text/enriched text/*
|
|
||||||
|
|
||||||
# main options
|
## Set preffered view modes
|
||||||
set envelope_from
|
#auto_view text/html text/calendar application/ics # view html automatically
|
||||||
set edit_headers # show headers when composing
|
## alternative_order text/html text/plain text/enriched text/*
|
||||||
set fast_reply # skip to compose when replying
|
|
||||||
set askcc # ask for CC:
|
|
||||||
set fcc_attach # save attachments with the body
|
|
||||||
set forward_format = "Fwd: %s" # format of subject when forwarding
|
|
||||||
set forward_decode # decode when forwarding
|
|
||||||
set attribution = "On %d, %n wrote:" # format of quoting header
|
|
||||||
set reply_to # reply to Reply to: field
|
|
||||||
set reverse_name # reply as whomever it was to
|
|
||||||
set include # include message in replies
|
|
||||||
set forward_quote # include message in forwards
|
|
||||||
set text_flowed
|
|
||||||
unset sig_dashes # no dashes before sig
|
|
||||||
unset mime_forward # forward attachments as part of body
|
|
||||||
unset help # No help bar at the top of index
|
|
||||||
# set status_on_top # Status bar on top of index
|
|
||||||
set tmpdir = ~/Programs/neomutt/temp # where to keep temp files
|
|
||||||
|
|
||||||
unset confirmappend # don't ask, just do!
|
## main options
|
||||||
set quit # don't ask, just do!!
|
##set envelope_from
|
||||||
unset mark_old # read/new is good enough for me
|
##set edit_headers # show headers when composing
|
||||||
#set beep_new # bell on new mails
|
##set fast_reply # skip to compose when replying
|
||||||
set pipe_decode # strip headers and eval mimes when piping
|
##set askcc # ask for CC:
|
||||||
set thorough_search # strip headers and eval mimes before searching
|
##set fcc_attach # save attachments with the body
|
||||||
set timeout = 0
|
##set forward_format = "Fwd: %s" # format of subject when forwarding
|
||||||
|
##set forward_decode # decode when forwarding
|
||||||
|
##set attribution = "On %d, %n wrote:" # format of quoting header
|
||||||
|
##set reply_to # reply to Reply to: field
|
||||||
|
##set reverse_name # reply as whomever it was to
|
||||||
|
##set include # include message in replies
|
||||||
|
##set forward_quote # include message in forwards
|
||||||
|
##set text_flowed
|
||||||
|
##unset sig_dashes # no dashes before sig
|
||||||
|
##unset mime_forward # forward attachments as part of body
|
||||||
|
##unset help # No help bar at the top of index
|
||||||
|
### set status_on_top # Status bar on top of index
|
||||||
|
##set tmpdir = ~/Programs/neomutt/temp # where to keep temp files
|
||||||
|
|
||||||
# status bar, date format, finding stuff etc.
|
#unset confirmappend # don't ask, just do!
|
||||||
set status_chars = " *%A"
|
#set quit # don't ask, just do!!
|
||||||
set status_format = "[ Folder: %f ] [%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]%>─%?p?( %p postponed )?"
|
#unset mark_old # read/new is good enough for me
|
||||||
set date_format = "%d.%m.%Y %H:%M"
|
##set beep_new # bell on new mails
|
||||||
set sort = threads
|
#set pipe_decode # strip headers and eval mimes when piping
|
||||||
set sort_aux = reverse-last-date-received
|
#set thorough_search # strip headers and eval mimes before searching
|
||||||
set uncollapse_jump
|
#set timeout = 0
|
||||||
set sort_re
|
|
||||||
set reply_regexp = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"
|
|
||||||
set quote_regexp = "^( {0,4}[>|:#%]| {0,4}[a-z0-9]+[>|]+)+"
|
|
||||||
set send_charset = "utf-8:iso-8859-1:us-ascii"
|
|
||||||
set charset = "utf-8"
|
|
||||||
set arrow_cursor = "no" # Change `color indicator` depending
|
|
||||||
|
|
||||||
# Pager View Options
|
## status bar, date format, finding stuff etc.
|
||||||
set pager_index_lines = 10 # Shows 10 lines of index when pager is active
|
#set status_chars = " *%A"
|
||||||
set pager_context = 3
|
#set status_format = "[ Folder: %f ] [%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]%>─%?p?( %p postponed )?"
|
||||||
set pager_stop
|
#set date_format = "%d.%m.%Y %H:%M"
|
||||||
set menu_scroll
|
##set sort = threads
|
||||||
set tilde
|
##set sort_aux = reverse-last-date-received
|
||||||
unset markers
|
##set uncollapse_jump
|
||||||
|
##set sort_re
|
||||||
|
#set reply_regexp = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"
|
||||||
|
#set quote_regexp = "^( {0,4}[>|:#%]| {0,4}[a-z0-9]+[>|]+)+"
|
||||||
|
#set send_charset = "utf-8:iso-8859-1:us-ascii"
|
||||||
|
#set charset = "utf-8"
|
||||||
|
#set arrow_cursor = "no" # Change `color indicator` depending
|
||||||
|
|
||||||
#set mailcap_path = ~/.config/neomutt/mailcap
|
## Pager View Options
|
||||||
#set header_cache = "~/.cache/mutt"
|
#set pager_index_lines = 10 # Shows 10 lines of index when pager is active
|
||||||
#set message_cachedir = "~/.cache/mutt"
|
#set pager_context = 3
|
||||||
|
#set pager_stop
|
||||||
|
#set menu_scroll
|
||||||
|
#set tilde
|
||||||
|
#unset markers
|
||||||
|
|
||||||
set query_command = "khard email --parsable --search-in-source-files '%s'"
|
##set mailcap_path = ~/.config/neomutt/mailcap
|
||||||
|
##set header_cache = "~/.cache/mutt"
|
||||||
|
##set message_cachedir = "~/.cache/mutt"
|
||||||
|
|
||||||
### Color Settings
|
#set query_command = "khard email --parsable --search-in-source-files '%s'"
|
||||||
# Header colors:
|
|
||||||
color header blue default ".*"
|
|
||||||
color header brightmagenta default "^(From)"
|
|
||||||
color header brightcyan default "^(Subject)"
|
|
||||||
color header brightwhite default "^(CC|BCC)"
|
|
||||||
|
|
||||||
mono bold bold
|
#### Color Settings
|
||||||
mono underline underline
|
## Header colors:
|
||||||
mono indicator reverse
|
#color header blue default ".*"
|
||||||
mono error bold
|
#color header brightmagenta default "^(From)"
|
||||||
color normal default default
|
#color header brightcyan default "^(Subject)"
|
||||||
color indicator brightyellow default # currently selected message. default makes bar clear, disabled arrow to save space.
|
#color header brightwhite default "^(CC|BCC)"
|
||||||
color sidebar_highlight red default
|
|
||||||
color sidebar_divider brightblack black
|
|
||||||
color sidebar_flagged red black
|
|
||||||
color sidebar_new green black
|
|
||||||
color normal brightyellow default
|
|
||||||
color error red default
|
|
||||||
color tilde black default
|
|
||||||
color message cyan default
|
|
||||||
color markers red white
|
|
||||||
color attachment white default
|
|
||||||
color search brightmagenta default
|
|
||||||
color status brightyellow black
|
|
||||||
color hdrdefault brightgreen default
|
|
||||||
color quoted green default
|
|
||||||
color quoted1 blue default
|
|
||||||
color quoted2 cyan default
|
|
||||||
color quoted3 yellow default
|
|
||||||
color quoted4 red default
|
|
||||||
color quoted5 brightred default
|
|
||||||
color signature brightgreen default
|
|
||||||
color bold black default
|
|
||||||
color underline black default
|
|
||||||
color normal default default
|
|
||||||
|
|
||||||
color body brightred default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+" # Email addresses
|
#mono bold bold
|
||||||
color body brightblue default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+" # URL
|
#mono underline underline
|
||||||
color body green default "\`[^\`]*\`" # Green text between ` and `
|
#mono indicator reverse
|
||||||
color body brightblue default "^# \.*" # Headings as bold blue
|
#mono error bold
|
||||||
color body brightcyan default "^## \.*" # Subheadings as bold cyan
|
#color normal default default
|
||||||
color body brightgreen default "^### \.*" # Subsubheadings as bold green
|
#color indicator brightyellow default # currently selected message. default makes bar clear, disabled arrow to save space.
|
||||||
color body yellow default "^(\t| )*(-|\\*) \.*" # List items as yellow
|
#color sidebar_highlight red default
|
||||||
color body brightcyan default "[;:][-o][)/(|]" # emoticons
|
#color sidebar_divider brightblack black
|
||||||
color body brightcyan default "[;:][)(|]" # emoticons
|
#color sidebar_flagged red black
|
||||||
color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon?
|
#color sidebar_new green black
|
||||||
color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon?
|
#color normal brightyellow default
|
||||||
color body red default "(BAD signature)"
|
#color error red default
|
||||||
color body cyan default "(Good signature)"
|
#color tilde black default
|
||||||
color body brightblack default "^gpg: Good signature .*"
|
#color message cyan default
|
||||||
color body brightyellow default "^gpg: "
|
#color markers red white
|
||||||
color body brightyellow red "^gpg: BAD signature from.*"
|
#color attachment white default
|
||||||
mono body bold "^gpg: Good signature"
|
#color search brightmagenta default
|
||||||
mono body bold "^gpg: BAD signature from.*"
|
#color status brightyellow black
|
||||||
color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
|
#color hdrdefault brightgreen default
|
||||||
|
#color quoted green default
|
||||||
|
#color quoted1 blue default
|
||||||
|
#color quoted2 cyan default
|
||||||
|
#color quoted3 yellow default
|
||||||
|
#color quoted4 red default
|
||||||
|
#color quoted5 brightred default
|
||||||
|
#color signature brightgreen default
|
||||||
|
#color bold black default
|
||||||
|
#color underline black default
|
||||||
|
#color normal default default
|
||||||
|
|
||||||
# Default index colors:
|
#color body brightred default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+" # Email addresses
|
||||||
color index yellow default '.*'
|
#color body brightblue default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+" # URL
|
||||||
color index_author red default '.*'
|
#color body green default "\`[^\`]*\`" # Green text between ` and `
|
||||||
color index_number blue default
|
#color body brightblue default "^# \.*" # Headings as bold blue
|
||||||
color index_subject cyan default '.*'
|
#color body brightcyan default "^## \.*" # Subheadings as bold cyan
|
||||||
|
#color body brightgreen default "^### \.*" # Subsubheadings as bold green
|
||||||
|
#color body yellow default "^(\t| )*(-|\\*) \.*" # List items as yellow
|
||||||
|
#color body brightcyan default "[;:][-o][)/(|]" # emoticons
|
||||||
|
#color body brightcyan default "[;:][)(|]" # emoticons
|
||||||
|
#color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon?
|
||||||
|
#color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon?
|
||||||
|
#color body red default "(BAD signature)"
|
||||||
|
#color body cyan default "(Good signature)"
|
||||||
|
#color body brightblack default "^gpg: Good signature .*"
|
||||||
|
#color body brightyellow default "^gpg: "
|
||||||
|
#color body brightyellow red "^gpg: BAD signature from.*"
|
||||||
|
#mono body bold "^gpg: Good signature"
|
||||||
|
#mono body bold "^gpg: BAD signature from.*"
|
||||||
|
#color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
|
||||||
|
|
||||||
# For new mail:
|
## Default index colors:
|
||||||
color index brightyellow black "~N"
|
#color index yellow default '.*'
|
||||||
color index_author brightred black "~N"
|
#color index_author red default '.*'
|
||||||
color index_subject brightcyan black "~N"
|
#color index_number blue default
|
||||||
|
#color index_subject cyan default '.*'
|
||||||
|
|
||||||
color progress black cyan
|
## For new mail:
|
||||||
|
#color index brightyellow black "~N"
|
||||||
|
#color index_author brightred black "~N"
|
||||||
|
#color index_subject brightcyan black "~N"
|
||||||
|
|
||||||
### Mappings Settings
|
#color progress black cyan
|
||||||
|
|
||||||
# General rebindings
|
#### Mappings Settings
|
||||||
bind attach <return> view-mailcap
|
#
|
||||||
bind attach l view-mailcap
|
## General rebindings
|
||||||
bind editor <space> noop
|
#bind attach <return> view-mailcap
|
||||||
bind pager c imap-fetch-mail
|
#bind attach l view-mailcap
|
||||||
bind index G last-entry
|
#bind editor <space> noop
|
||||||
bind index g noop
|
#bind pager c imap-fetch-mail
|
||||||
bind index gg first-entry
|
#bind index G last-entry
|
||||||
bind pager,attach h exit
|
#bind index g noop
|
||||||
bind pager j next-line
|
#bind index gg first-entry
|
||||||
bind pager k previous-line
|
#bind pager,attach h exit
|
||||||
bind pager l view-attachments
|
#bind pager j next-line
|
||||||
bind index D delete-message
|
#bind pager k previous-line
|
||||||
bind index U undelete-message
|
#bind pager l view-attachments
|
||||||
bind index L limit
|
#bind index D delete-message
|
||||||
bind index h noop
|
#bind index U undelete-message
|
||||||
bind index l display-message
|
#bind index L limit
|
||||||
bind browser h goto-parent
|
#bind index h noop
|
||||||
bind browser l select-entry
|
#bind index l display-message
|
||||||
bind pager,browser gg top-page
|
#bind browser h goto-parent
|
||||||
bind pager,browser G bottom-page
|
#bind browser l select-entry
|
||||||
bind index,pager,browser d half-down
|
#bind pager,browser gg top-page
|
||||||
bind index,pager,browser u half-up
|
#bind pager,browser G bottom-page
|
||||||
bind index,pager R group-reply
|
#bind index,pager,browser d half-down
|
||||||
bind index \031 previous-undeleted # Mouse wheel
|
#bind index,pager,browser u half-up
|
||||||
bind index \005 next-undeleted # Mouse wheel
|
#bind index,pager R group-reply
|
||||||
bind pager \031 previous-line # Mouse wheel
|
#bind index \031 previous-undeleted # Mouse wheel
|
||||||
bind pager \005 next-line # Mouse wheel
|
#bind index \005 next-undeleted # Mouse wheel
|
||||||
bind editor <Tab> complete-query
|
#bind pager \031 previous-line # Mouse wheel
|
||||||
|
#bind pager \005 next-line # Mouse wheel
|
||||||
|
#bind editor <Tab> complete-query
|
||||||
|
|
||||||
|
|
||||||
# sidebar mappings
|
## sidebar mappings
|
||||||
bind index,pager \Ck sidebar-prev
|
#bind index,pager \Ck sidebar-prev
|
||||||
bind index,pager \Cj sidebar-next
|
#bind index,pager \Cj sidebar-next
|
||||||
bind index,pager \Co sidebar-open
|
#bind index,pager \Co sidebar-open
|
||||||
bind index,pager \Cp sidebar-prev-new
|
#bind index,pager \Cp sidebar-prev-new
|
||||||
bind index,pager \Cn sidebar-next-new
|
#bind index,pager \Cn sidebar-next-new
|
||||||
bind index,pager B sidebar-toggle-visible
|
#bind index,pager B sidebar-toggle-visible
|
||||||
|
|
||||||
# global index and pager shortcuts
|
## global index and pager shortcuts
|
||||||
bind index,pager @ compose-to-sender
|
#bind index,pager @ compose-to-sender
|
||||||
bind index,pager D purge-message
|
#bind index,pager D purge-message
|
||||||
bind index <tab> sync-mailbox
|
#bind index <tab> sync-mailbox
|
||||||
bind index <space> collapse-thread
|
#bind index <space> collapse-thread
|
||||||
|
|
||||||
# Email completion bindings
|
## Email completion bindings
|
||||||
bind editor <Tab> complete-query
|
#bind editor <Tab> complete-query
|
||||||
bind editor ^T complete
|
#bind editor ^T complete
|
||||||
|
|
||||||
# Press A to add contact to Khard address book
|
## Press A to add contact to Khard address book
|
||||||
macro index,pager A \
|
#macro index,pager A \
|
||||||
"<pipe-message>khard add-email<return>" \
|
#"<pipe-message>khard add-email<return>" \
|
||||||
"add the sender email address to khard"
|
#"add the sender email address to khard"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
services.imapnotify.enable = true;
|
services.imapnotify.enable = true;
|
||||||
home.packages = [ pkgs.neomutt pkgs.evolution ];
|
home.packages = [ pkgs.neomutt pkgs.evolution ];
|
||||||
|
|
Loading…
Reference in a new issue