Rewrite modules to options.
This commit is contained in:
parent
fa4b3c31b7
commit
8c7578075f
|
@ -20,7 +20,7 @@
|
||||||
<a href="https://i.imgur.com/H943DFl.jpeg">Wallpaper link</a>
|
<a href="https://i.imgur.com/H943DFl.jpeg">Wallpaper link</a>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
[My current wallpaper](https://git.voronind.com/voronind/nixos/src/branch/main/part/Wallpaper.nix#L2)
|
[My current wallpaper](https://git.voronind.com/voronind/nixos/src/branch/main/module/common/Wallpaper.nix#L2)
|
||||||
|
|
||||||
Color theming based on wallpaper thanks to [Stylix](https://github.com/danth/stylix).
|
Color theming based on wallpaper thanks to [Stylix](https://github.com/danth/stylix).
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{ pkgs, style, util, ... }: {
|
{ pkgs, config, util, ... }: {
|
||||||
font = pkgs.runCommandNoCC "font" {} ''
|
font = pkgs.runCommandNoCC "font" {} ''
|
||||||
cp ${pkgs.nerdfonts.override { fonts = [ "Terminus" ]; }}/share/fonts/truetype/NerdFonts/TerminessNerdFontMono-Regular.ttf $out
|
cp ${pkgs.nerdfonts.override { fonts = [ "Terminus" ]; }}/share/fonts/truetype/NerdFonts/TerminessNerdFontMono-Regular.ttf $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
colors = util.trimTabs ''
|
colors = util.trimTabs ''
|
||||||
background=#${style.color.bg.dark}
|
background=#${config.module.style.color.bg.dark}
|
||||||
foreground=#${style.color.fg.light}
|
foreground=#${config.module.style.color.fg.light}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
initScript = util.trimTabs ''
|
initScript = util.trimTabs ''
|
||||||
|
|
|
@ -1,24 +1,48 @@
|
||||||
{ container, ... } @args: let
|
{ container, lib, config, ... } @args: with lib; let
|
||||||
cfg = container.config.change;
|
cfg = config.container.module.change;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.change = {
|
||||||
];
|
enable = mkEnableOption "Change detection service";
|
||||||
|
address = mkOption {
|
||||||
containers.change = container.mkContainer cfg {
|
default = "10.1.0.41";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/changedetection-io" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
port = mkOption {
|
||||||
isReadOnly = false;
|
default = 5000;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "change.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/change";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
services.changedetection-io = {
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
enable = true;
|
"data"
|
||||||
baseURL = cfg.domain;
|
];
|
||||||
behindProxy = true;
|
|
||||||
listenAddress = cfg.address;
|
containers.change = container.mkContainer cfg {
|
||||||
|
bindMounts = {
|
||||||
|
"/var/lib/changedetection-io" = {
|
||||||
|
hostPath = "${cfg.storage}/data";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.changedetection-io = {
|
||||||
|
enable = true;
|
||||||
|
baseURL = cfg.domain;
|
||||||
|
behindProxy = true;
|
||||||
|
listenAddress = cfg.address;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,45 +1,72 @@
|
||||||
{ container, pkgs, ... } @args: let
|
{ container, pkgs, lib, config, ... } @args: with lib; let
|
||||||
cfg = container.config.cloud;
|
cfg = config.container.module.cloud;
|
||||||
in {
|
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
|
||||||
"data"
|
|
||||||
];
|
|
||||||
|
|
||||||
containers.cloud = container.mkContainer cfg {
|
postgres = config.container.module.postgres;
|
||||||
bindMounts = {
|
proxy = config.container.module.proxy;
|
||||||
"/var/lib/nextcloud" = {
|
in {
|
||||||
hostPath = "${cfg.storage}/data";
|
options = {
|
||||||
isReadOnly = false;
|
container.module.cloud = {
|
||||||
|
enable = mkEnableOption "File cloud service";
|
||||||
|
address = mkOption {
|
||||||
|
default = "10.1.0.13";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
port = mkOption {
|
||||||
|
default = 80;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "cloud.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/cloud";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { config, ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
environment.systemPackages = [ pkgs.postgresql ];
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
services.nextcloud = {
|
"data"
|
||||||
enable = true;
|
];
|
||||||
# package = pkgs.nextcloud29;
|
|
||||||
hostName = cfg.domain;
|
|
||||||
# phpOptions = {
|
|
||||||
# memory_limit = lib.mkForce "20G";
|
|
||||||
# };
|
|
||||||
config = {
|
|
||||||
adminuser = "root";
|
|
||||||
adminpassFile = "${pkgs.writeText "NextcloudPassword" "root"}";
|
|
||||||
|
|
||||||
dbhost = container.config.postgres.address;
|
containers.cloud = container.mkContainer cfg {
|
||||||
dbname = "nextcloud";
|
bindMounts = {
|
||||||
dbpassFile = "${pkgs.writeText "NextcloudDbPassword" "nextcloud"}";
|
"/var/lib/nextcloud" = {
|
||||||
dbtype = "pgsql";
|
hostPath = "${cfg.storage}/data";
|
||||||
dbuser = "nextcloud";
|
isReadOnly = false;
|
||||||
};
|
};
|
||||||
extraApps = {
|
};
|
||||||
inherit (config.services.nextcloud.package.packages.apps) contacts calendar onlyoffice;
|
|
||||||
};
|
config = { config, ... }: container.mkContainerConfig cfg {
|
||||||
extraAppsEnable = true;
|
environment.systemPackages = [ pkgs.postgresql ];
|
||||||
settings = {
|
services.nextcloud = {
|
||||||
trusted_domains = [ cfg.address cfg.domain ];
|
enable = true;
|
||||||
trusted_proxies = [ container.config.proxy.address ];
|
# package = pkgs.nextcloud29;
|
||||||
allow_local_remote_servers = true;
|
hostName = cfg.domain;
|
||||||
|
# phpOptions = {
|
||||||
|
# memory_limit = lib.mkForce "20G";
|
||||||
|
# };
|
||||||
|
config = {
|
||||||
|
adminuser = "root";
|
||||||
|
adminpassFile = "${pkgs.writeText "NextcloudPassword" "root"}";
|
||||||
|
|
||||||
|
dbhost = postgres.address;
|
||||||
|
dbname = "nextcloud";
|
||||||
|
dbpassFile = "${pkgs.writeText "NextcloudDbPassword" "nextcloud"}";
|
||||||
|
dbtype = "pgsql";
|
||||||
|
dbuser = "nextcloud";
|
||||||
|
};
|
||||||
|
extraApps = {
|
||||||
|
inherit (config.services.nextcloud.package.packages.apps) contacts calendar onlyoffice;
|
||||||
|
};
|
||||||
|
extraAppsEnable = true;
|
||||||
|
settings = {
|
||||||
|
trusted_domains = [ cfg.address cfg.domain ];
|
||||||
|
trusted_proxies = [ proxy.address ];
|
||||||
|
allow_local_remote_servers = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,35 +1,53 @@
|
||||||
{ container, domain, ... } @args: let
|
{ container, lib, config, ... } @args: with lib; let
|
||||||
cfg = container.config.ddns;
|
cfg = config.container.module.ddns;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.ddns = {
|
||||||
];
|
enable = mkEnableOption "Dynamic dns client.";
|
||||||
|
address = mkOption {
|
||||||
containers.ddns = container.mkContainer cfg {
|
default = "10.1.0.31";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/data" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
storage = mkOption {
|
||||||
isReadOnly = true;
|
default = "${config.container.storage}/ddns";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
services.cloudflare-dyndns = {
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
enable = true;
|
"data"
|
||||||
apiTokenFile = "/data/token";
|
];
|
||||||
deleteMissing = true;
|
|
||||||
ipv4 = true;
|
containers.ddns = container.mkContainer cfg {
|
||||||
ipv6 = false;
|
bindMounts = {
|
||||||
proxied = false;
|
"/data" = {
|
||||||
domains = [ domain ] ++ map (sub: "${sub}.${domain}") [
|
hostPath = "${cfg.storage}/data";
|
||||||
"cloud"
|
isReadOnly = true;
|
||||||
"git"
|
};
|
||||||
"mail"
|
};
|
||||||
"office"
|
|
||||||
"paste"
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
"play"
|
services.cloudflare-dyndns = {
|
||||||
"vpn"
|
enable = true;
|
||||||
];
|
apiTokenFile = "/data/token";
|
||||||
|
deleteMissing = true;
|
||||||
|
ipv4 = true;
|
||||||
|
ipv6 = false;
|
||||||
|
proxied = false;
|
||||||
|
domains = let
|
||||||
|
domain = config.container.domain;
|
||||||
|
in [ domain ] ++ map (sub: "${sub}.${domain}") [
|
||||||
|
"cloud"
|
||||||
|
"git"
|
||||||
|
"mail"
|
||||||
|
"office"
|
||||||
|
"paste"
|
||||||
|
"play"
|
||||||
|
"vpn"
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,112 +1,129 @@
|
||||||
{ container, pkgs, ... } @args: let
|
{ container, pkgs, lib, config, ... } @args: with lib; let
|
||||||
cfg = container.config.dns;
|
cfg = config.container.module.dns;
|
||||||
in {
|
in {
|
||||||
containers.dns = container.mkContainer cfg {
|
options = {
|
||||||
forwardPorts = [
|
container.module.dns = {
|
||||||
{
|
enable = mkEnableOption "Dns server.";
|
||||||
containerPort = 53;
|
address = mkOption {
|
||||||
hostPort = 53;
|
default = "10.1.0.6";
|
||||||
protocol = "udp";
|
type = types.str;
|
||||||
} {
|
};
|
||||||
containerPort = 53;
|
port = mkOption {
|
||||||
hostPort = 53;
|
default = 53;
|
||||||
protocol = "tcp";
|
type = types.int;
|
||||||
}
|
};
|
||||||
];
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { lib, ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
environment.systemPackages = [
|
containers.dns = container.mkContainer cfg {
|
||||||
pkgs.cloudflared
|
forwardPorts = [
|
||||||
|
{
|
||||||
|
containerPort = cfg.port;
|
||||||
|
hostPort = cfg.port;
|
||||||
|
protocol = "udp";
|
||||||
|
} {
|
||||||
|
containerPort = cfg.port;
|
||||||
|
hostPort = cfg.port;
|
||||||
|
protocol = "tcp";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
systemd.services.cloudflared = {
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
description = "Cloudflare DoH server.";
|
environment.systemPackages = [
|
||||||
enable = true;
|
pkgs.cloudflared
|
||||||
wantedBy = [ "multi-user.target" ];
|
];
|
||||||
serviceConfig = {
|
|
||||||
Type = "simple";
|
|
||||||
ExecStart = "${lib.getExe pkgs.cloudflared} proxy-dns --port 5054";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.blocky = {
|
systemd.services.cloudflared = {
|
||||||
enable = true;
|
description = "Cloudflare DoH server.";
|
||||||
settings = {
|
enable = true;
|
||||||
upstream = {
|
wantedBy = [ "multi-user.target" ];
|
||||||
default = [
|
serviceConfig = {
|
||||||
"0.0.0.0:5054"
|
Type = "simple";
|
||||||
"0.0.0.0:5054"
|
ExecStart = "${getExe pkgs.cloudflared} proxy-dns --port 5054";
|
||||||
];
|
|
||||||
};
|
};
|
||||||
blocking = {
|
};
|
||||||
blackLists = {
|
|
||||||
suspicious = [
|
services.blocky = {
|
||||||
"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"
|
enable = true;
|
||||||
"https://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADhosts.txt"
|
settings = {
|
||||||
"https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Spam/hosts"
|
upstream = {
|
||||||
"https://v.firebog.net/hosts/static/w3kbl.txt"
|
|
||||||
];
|
|
||||||
ads = [
|
|
||||||
"https://easylist-downloads.adblockplus.org/bitblock.txt"
|
|
||||||
"https://adaway.org/hosts.txt"
|
|
||||||
"https://v.firebog.net/hosts/AdguardDNS.txt"
|
|
||||||
"https://v.firebog.net/hosts/Admiral.txt"
|
|
||||||
"https://raw.githubusercontent.com/anudeepND/blacklist/master/adservers.txt"
|
|
||||||
"https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt"
|
|
||||||
"https://v.firebog.net/hosts/Easylist.txt"
|
|
||||||
"https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext"
|
|
||||||
"https://raw.githubusercontent.com/FadeMind/hosts.extras/master/UncheckyAds/hosts"
|
|
||||||
"https://raw.githubusercontent.com/bigdargon/hostsVN/master/hosts"
|
|
||||||
"https://github.com/easylist/ruadlist/blob/master/advblock/adservers.txt"
|
|
||||||
];
|
|
||||||
tracking = [
|
|
||||||
"https://v.firebog.net/hosts/Easyprivacy.txt"
|
|
||||||
"https://v.firebog.net/hosts/Prigent-Ads.txt"
|
|
||||||
"https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.2o7Net/hosts"
|
|
||||||
"https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt"
|
|
||||||
"https://hostfiles.frogeye.fr/firstparty-trackers-hosts.txt"
|
|
||||||
];
|
|
||||||
malicious = [
|
|
||||||
"https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareHosts.txt"
|
|
||||||
"https://osint.digitalside.it/Threat-Intel/lists/latestdomains.txt"
|
|
||||||
"https://s3.amazonaws.com/lists.disconnect.me/simple_malvertising.txt"
|
|
||||||
"https://v.firebog.net/hosts/Prigent-Crypto.txt"
|
|
||||||
"https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Risk/hosts"
|
|
||||||
"https://bitbucket.org/ethanr/dns-blacklists/raw/8575c9f96e5b4a1308f2f12394abd86d0927a4a0/bad_lists/Mandiant_APT1_Report_Appendix_D.txt"
|
|
||||||
"https://phishing.army/download/phishing_army_blocklist_extended.txt"
|
|
||||||
"https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-malware.txt"
|
|
||||||
"https://v.firebog.net/hosts/RPiList-Malware.txt"
|
|
||||||
"https://v.firebog.net/hosts/RPiList-Phishing.txt"
|
|
||||||
"https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt"
|
|
||||||
"https://raw.githubusercontent.com/AssoEchap/stalkerware-indicators/master/generated/hosts"
|
|
||||||
"https://urlhaus.abuse.ch/downloads/hostfile/"
|
|
||||||
];
|
|
||||||
other = [
|
|
||||||
"https://zerodot1.gitlab.io/CoinBlockerLists/hosts_browser"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
# whiteLists = {
|
|
||||||
# other = [
|
|
||||||
# "/.*.vk.com/"
|
|
||||||
# ];
|
|
||||||
# };
|
|
||||||
clientGroupsBlock = {
|
|
||||||
default = [
|
default = [
|
||||||
"suspicious"
|
"0.0.0.0:5054"
|
||||||
"ads"
|
"0.0.0.0:5054"
|
||||||
"tracking"
|
|
||||||
"malicious"
|
|
||||||
"other"
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
blocking = {
|
||||||
customDNS = {
|
blackLists = {
|
||||||
mapping = {
|
suspicious = [
|
||||||
"voronind.com" = "192.168.1.2";
|
"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"
|
||||||
|
"https://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADhosts.txt"
|
||||||
|
"https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Spam/hosts"
|
||||||
|
"https://v.firebog.net/hosts/static/w3kbl.txt"
|
||||||
|
];
|
||||||
|
ads = [
|
||||||
|
"https://easylist-downloads.adblockplus.org/bitblock.txt"
|
||||||
|
"https://adaway.org/hosts.txt"
|
||||||
|
"https://v.firebog.net/hosts/AdguardDNS.txt"
|
||||||
|
"https://v.firebog.net/hosts/Admiral.txt"
|
||||||
|
"https://raw.githubusercontent.com/anudeepND/blacklist/master/adservers.txt"
|
||||||
|
"https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt"
|
||||||
|
"https://v.firebog.net/hosts/Easylist.txt"
|
||||||
|
"https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext"
|
||||||
|
"https://raw.githubusercontent.com/FadeMind/hosts.extras/master/UncheckyAds/hosts"
|
||||||
|
"https://raw.githubusercontent.com/bigdargon/hostsVN/master/hosts"
|
||||||
|
"https://github.com/easylist/ruadlist/blob/master/advblock/adservers.txt"
|
||||||
|
];
|
||||||
|
tracking = [
|
||||||
|
"https://v.firebog.net/hosts/Easyprivacy.txt"
|
||||||
|
"https://v.firebog.net/hosts/Prigent-Ads.txt"
|
||||||
|
"https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.2o7Net/hosts"
|
||||||
|
"https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt"
|
||||||
|
"https://hostfiles.frogeye.fr/firstparty-trackers-hosts.txt"
|
||||||
|
];
|
||||||
|
malicious = [
|
||||||
|
"https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareHosts.txt"
|
||||||
|
"https://osint.digitalside.it/Threat-Intel/lists/latestdomains.txt"
|
||||||
|
"https://s3.amazonaws.com/lists.disconnect.me/simple_malvertising.txt"
|
||||||
|
"https://v.firebog.net/hosts/Prigent-Crypto.txt"
|
||||||
|
"https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Risk/hosts"
|
||||||
|
"https://bitbucket.org/ethanr/dns-blacklists/raw/8575c9f96e5b4a1308f2f12394abd86d0927a4a0/bad_lists/Mandiant_APT1_Report_Appendix_D.txt"
|
||||||
|
"https://phishing.army/download/phishing_army_blocklist_extended.txt"
|
||||||
|
"https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-malware.txt"
|
||||||
|
"https://v.firebog.net/hosts/RPiList-Malware.txt"
|
||||||
|
"https://v.firebog.net/hosts/RPiList-Phishing.txt"
|
||||||
|
"https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt"
|
||||||
|
"https://raw.githubusercontent.com/AssoEchap/stalkerware-indicators/master/generated/hosts"
|
||||||
|
"https://urlhaus.abuse.ch/downloads/hostfile/"
|
||||||
|
];
|
||||||
|
other = [
|
||||||
|
"https://zerodot1.gitlab.io/CoinBlockerLists/hosts_browser"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
# whiteLists = {
|
||||||
|
# other = [
|
||||||
|
# "/.*.vk.com/"
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
clientGroupsBlock = {
|
||||||
|
default = [
|
||||||
|
"suspicious"
|
||||||
|
"ads"
|
||||||
|
"tracking"
|
||||||
|
"malicious"
|
||||||
|
"other"
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
customDNS = {
|
||||||
|
mapping = {
|
||||||
|
# All subdomains to current host.
|
||||||
|
${config.container.domain} = config.container.host;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
port = cfg.port;
|
||||||
|
# httpPort = "80";
|
||||||
};
|
};
|
||||||
port = "53";
|
|
||||||
httpPort = "80";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,29 +1,56 @@
|
||||||
{ container, lib, ... } @args: let
|
{ container, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.download;
|
cfg = config.container.module.download;
|
||||||
memLimit = "4G";
|
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.download = {
|
||||||
];
|
enable = mkEnableOption "Downloader.";
|
||||||
|
address = mkOption {
|
||||||
containers.download = container.mkContainer cfg {
|
default = "10.1.0.12";
|
||||||
enableTun = true;
|
type = types.str;
|
||||||
|
|
||||||
bindMounts = {
|
|
||||||
"/var/lib/deluge/.config/deluge" = {
|
|
||||||
hostPath = "${cfg.storage}/data";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
};
|
||||||
} // container.attachMedia "download" cfg.download false;
|
port = mkOption {
|
||||||
|
default = 8112;
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
type = types.int;
|
||||||
services.deluge = {
|
|
||||||
enable = true;
|
|
||||||
dataDir = "/var/lib/deluge";
|
|
||||||
web.enable = true;
|
|
||||||
};
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "download.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/download";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
memLimit = mkOption {
|
||||||
|
default = "4G";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
systemd.services.deluged.serviceConfig.MemoryLimit = memLimit;
|
config = mkIf cfg.enable {
|
||||||
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
|
"data"
|
||||||
|
];
|
||||||
|
|
||||||
|
containers.download = container.mkContainer cfg {
|
||||||
|
enableTun = true;
|
||||||
|
|
||||||
|
bindMounts = {
|
||||||
|
"/var/lib/deluge/.config/deluge" = {
|
||||||
|
hostPath = "${cfg.storage}/data";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
} // container.attachMedia "download" false;
|
||||||
|
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.deluge = {
|
||||||
|
enable = true;
|
||||||
|
dataDir = "/var/lib/deluge";
|
||||||
|
web.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.deluged.serviceConfig.MemoryLimit = cfg.memLimit;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,73 +1,97 @@
|
||||||
{ container, pkgs, ... } @args: let
|
{ container, pkgs, config, lib, ... }: with lib; let
|
||||||
cfg = container.config.git;
|
cfg = config.container.module.git;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.git = {
|
||||||
];
|
enable = mkEnableOption "Git server.";
|
||||||
|
address = mkOption {
|
||||||
containers.git = container.mkContainer cfg {
|
default = "10.1.0.8";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/gitea" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
port = mkOption {
|
||||||
isReadOnly = false;
|
default = 3000;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "git.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/git";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
environment.systemPackages = with pkgs; [ gitea ];
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
|
"data"
|
||||||
|
];
|
||||||
|
|
||||||
services.gitea = {
|
containers.git = container.mkContainer cfg {
|
||||||
enable = true;
|
bindMounts = {
|
||||||
stateDir = "/var/lib/gitea";
|
"/var/lib/gitea" = {
|
||||||
|
hostPath = "${cfg.storage}/data";
|
||||||
database = let
|
isReadOnly = false;
|
||||||
postgre = container.config.postgres;
|
|
||||||
in {
|
|
||||||
type = "postgres";
|
|
||||||
host = postgre.address;
|
|
||||||
port = postgre.port;
|
|
||||||
user = "gitea";
|
|
||||||
createDatabase = false;
|
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
settings = let
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
gcArgs = "--aggressive --no-cruft --prune=now";
|
environment.systemPackages = with pkgs; [ gitea ];
|
||||||
gcTimeout = 600;
|
|
||||||
in {
|
services.gitea = {
|
||||||
"service".DISABLE_REGISTRATION = true;
|
enable = true;
|
||||||
"log".LEVEL = "Error";
|
stateDir = "/var/lib/gitea";
|
||||||
"server" = {
|
|
||||||
DISABLE_SSH = true;
|
database = let
|
||||||
DOMAIN = cfg.domain;
|
postgre = config.container.module.postgres;
|
||||||
HTTP_ADDR = cfg.address;
|
in {
|
||||||
ROOT_URL = "https://${cfg.domain}";
|
type = "postgres";
|
||||||
|
host = postgre.address;
|
||||||
|
port = postgre.port;
|
||||||
|
user = "gitea";
|
||||||
|
createDatabase = false;
|
||||||
};
|
};
|
||||||
"ui" = {
|
|
||||||
AMBIGUOUS_UNICODE_DETECTION = false;
|
settings = let
|
||||||
|
gcArgs = "--aggressive --no-cruft --prune=now";
|
||||||
|
gcTimeout = 600;
|
||||||
|
in {
|
||||||
|
"service".DISABLE_REGISTRATION = true;
|
||||||
|
"log".LEVEL = "Error";
|
||||||
|
"server" = {
|
||||||
|
DISABLE_SSH = true;
|
||||||
|
DOMAIN = cfg.domain;
|
||||||
|
HTTP_ADDR = cfg.address;
|
||||||
|
ROOT_URL = "https://${cfg.domain}";
|
||||||
|
};
|
||||||
|
"ui" = {
|
||||||
|
AMBIGUOUS_UNICODE_DETECTION = false;
|
||||||
|
};
|
||||||
|
"repository" = {
|
||||||
|
DEFAULT_PRIVATE = "private";
|
||||||
|
DEFAULT_PUSH_CREATE_PRIVATE = true;
|
||||||
|
};
|
||||||
|
"repository.pull-request".DEFAULT_MERGE_STYLE = "rebase";
|
||||||
|
"repository.issue".MAX_PINNED = 99999;
|
||||||
|
"cron" = {
|
||||||
|
ENABLED = true;
|
||||||
|
RUN_AT_START = true;
|
||||||
|
};
|
||||||
|
"repo-archive".ENABLED = false;
|
||||||
|
"cron.update_mirrors".SCHEDULE = "@midnight";
|
||||||
|
"cron.cleanup_actions".ENABLED = true;
|
||||||
|
"cron.git_gc_repos" = {
|
||||||
|
ENABLED = true;
|
||||||
|
SCHEDULE = "@midnight";
|
||||||
|
TIMEOUT = gcTimeout;
|
||||||
|
ARGS = gcArgs;
|
||||||
|
};
|
||||||
|
"git" = {
|
||||||
|
GC_ARGS = gcArgs;
|
||||||
|
};
|
||||||
|
"git.timeout".GC = gcTimeout;
|
||||||
};
|
};
|
||||||
"repository" = {
|
|
||||||
DEFAULT_PRIVATE = "private";
|
|
||||||
DEFAULT_PUSH_CREATE_PRIVATE = true;
|
|
||||||
};
|
|
||||||
"repository.pull-request".DEFAULT_MERGE_STYLE = "rebase";
|
|
||||||
"repository.issue".MAX_PINNED = 99999;
|
|
||||||
"cron" = {
|
|
||||||
ENABLED = true;
|
|
||||||
RUN_AT_START = true;
|
|
||||||
};
|
|
||||||
"repo-archive".ENABLED = false;
|
|
||||||
"cron.update_mirrors".SCHEDULE = "@midnight";
|
|
||||||
"cron.cleanup_actions".ENABLED = true;
|
|
||||||
"cron.git_gc_repos" = {
|
|
||||||
ENABLED = true;
|
|
||||||
SCHEDULE = "@midnight";
|
|
||||||
TIMEOUT = gcTimeout;
|
|
||||||
ARGS = gcArgs;
|
|
||||||
};
|
|
||||||
"git" = {
|
|
||||||
GC_ARGS = gcArgs;
|
|
||||||
};
|
|
||||||
"git.timeout".GC = gcTimeout;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,43 +1,67 @@
|
||||||
# ISSUE: Broken, can't read/write sda device.
|
# ISSUE: Broken, can't read/write sda device.
|
||||||
{ container, pkgs, ... } @args: let
|
{ container, pkgs, config, lib, ... }: with lib; let
|
||||||
cfg = container.config.hdd;
|
cfg = config.container.module.hdd;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.hdd = {
|
||||||
];
|
enable = mkEnableOption "Hdd health monitor.";
|
||||||
|
address = mkOption {
|
||||||
|
default = "10.1.0.10";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
port = mkOption {
|
||||||
|
default = 8080;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "hdd.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/hdd";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
containers.hdd = container.mkContainer cfg {
|
config = mkIf cfg.enable {
|
||||||
# bindMounts = let
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
# attachDrive = hostPath: {
|
"data"
|
||||||
# inherit hostPath;
|
];
|
||||||
# isReadOnly = false;
|
|
||||||
# };
|
|
||||||
# in {
|
|
||||||
# "/opt/scrutiny" = {
|
|
||||||
# hostPath = "${cfg.storage}/data";
|
|
||||||
# isReadOnly = false;
|
|
||||||
# };
|
|
||||||
# "/dev/sda" = attachDrive "/dev/sda";
|
|
||||||
# };
|
|
||||||
|
|
||||||
# allowedDevices = [
|
containers.hdd = container.mkContainer cfg {
|
||||||
# {
|
# bindMounts = let
|
||||||
# modifier = "rwm";
|
# attachDrive = hostPath: {
|
||||||
# node = "/dev/sda";
|
# inherit hostPath;
|
||||||
# }
|
# isReadOnly = false;
|
||||||
# ];
|
# };
|
||||||
|
# in {
|
||||||
|
# "/opt/scrutiny" = {
|
||||||
|
# hostPath = "${cfg.storage}/data";
|
||||||
|
# isReadOnly = false;
|
||||||
|
# };
|
||||||
|
# "/dev/sda" = attachDrive "/dev/sda";
|
||||||
|
# };
|
||||||
|
|
||||||
# additionalCapabilities = [ "CAP_SYS_ADMIN" ];
|
# allowedDevices = [
|
||||||
|
# {
|
||||||
|
# modifier = "rwm";
|
||||||
|
# node = "/dev/sda";
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
# additionalCapabilities = [ "CAP_SYS_ADMIN" ];
|
||||||
environment.systemPackages = with pkgs; [ smartmontools ];
|
|
||||||
|
|
||||||
services.scrutiny = {
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
enable = true;
|
environment.systemPackages = with pkgs; [ smartmontools ];
|
||||||
settings.web = {
|
|
||||||
listen = {
|
services.scrutiny = {
|
||||||
host = cfg.address;
|
enable = true;
|
||||||
port = cfg.port;
|
settings.web = {
|
||||||
|
listen = {
|
||||||
|
host = cfg.address;
|
||||||
|
port = cfg.port;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,22 +1,42 @@
|
||||||
{ container, pkgs, util, ... } @args: let
|
{ container, pkgs, util, lib, config, ... } @args: with lib; let
|
||||||
cfg = container.config.home;
|
cfg = config.container.module.home;
|
||||||
package = (pkgs.callPackage ./homer args);
|
package = (pkgs.callPackage ./homer args);
|
||||||
in {
|
in {
|
||||||
containers.home = container.mkContainer cfg {
|
options = {
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
container.module.home = {
|
||||||
environment.systemPackages = [ package ];
|
enable = mkEnableOption "Dashboard.";
|
||||||
systemd.packages = [ package ];
|
address = mkOption {
|
||||||
|
default = "10.1.0.18";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
port = mkOption {
|
||||||
|
default = 80;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "home.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
services.nginx = {
|
config = mkIf cfg.enable {
|
||||||
enable = true;
|
containers.home = container.mkContainer cfg {
|
||||||
virtualHosts.${cfg.domain} = container.mkServer {
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
default = true;
|
environment.systemPackages = [ package ];
|
||||||
root = "${package}";
|
systemd.packages = [ package ];
|
||||||
|
|
||||||
locations = {
|
services.nginx = {
|
||||||
"/".extraConfig = ''
|
enable = true;
|
||||||
try_files $uri $uri/index.html;
|
virtualHosts.${cfg.domain} = container.mkServer {
|
||||||
'';
|
default = true;
|
||||||
|
root = "${package}";
|
||||||
|
|
||||||
|
locations = {
|
||||||
|
"/".extraConfig = ''
|
||||||
|
try_files $uri $uri/index.html;
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,69 +1,93 @@
|
||||||
{ container, ... } @args: let
|
{ container, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.iot;
|
cfg = config.container.module.iot;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.iot = {
|
||||||
];
|
enable = mkEnableOption "IoT service.";
|
||||||
|
address = mkOption {
|
||||||
|
default = "10.1.0.27";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
port = mkOption {
|
||||||
|
default = 8123;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "iot.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/iot";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
containers.iot = container.mkContainer cfg {
|
config = mkIf cfg.enable {
|
||||||
bindMounts = {
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
"/var/lib/hass" = {
|
"data"
|
||||||
hostPath = "${cfg.storage}/data";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
"/dev/ttyACM0" = {
|
|
||||||
hostPath = "/dev/ttyACM0";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
"/dev/serial/by-id" = {
|
|
||||||
hostPath = "/dev/serial/by-id";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
} // container.attachMedia "photo" cfg.photo true;
|
|
||||||
|
|
||||||
allowedDevices = [
|
|
||||||
{
|
|
||||||
modifier = "rwm";
|
|
||||||
node = "/dev/ttyACM0";
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
containers.iot = container.mkContainer cfg {
|
||||||
# Allow Hass to talk to Zigbee dongle.
|
bindMounts = {
|
||||||
users.users.hass.extraGroups = [ "dialout" "tty" ];
|
"/var/lib/hass" = {
|
||||||
|
hostPath = "${cfg.storage}/data";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/dev/ttyACM0" = {
|
||||||
|
hostPath = "/dev/ttyACM0";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/dev/serial/by-id" = {
|
||||||
|
hostPath = "/dev/serial/by-id";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
} // container.attachMedia "photo" true;
|
||||||
|
|
||||||
services.home-assistant = {
|
allowedDevices = [
|
||||||
# NOTE: Missing: hacs. Inside hacs: `card-mod`, `Clock Weather Card`, `WallPanel` and `Yandex.Station`.
|
{
|
||||||
enable = true;
|
modifier = "rwm";
|
||||||
extraComponents = [
|
node = "/dev/ttyACM0";
|
||||||
"caldav"
|
}
|
||||||
"met"
|
];
|
||||||
"sun"
|
|
||||||
"systemmonitor"
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
"zha"
|
# Allow Hass to talk to Zigbee dongle.
|
||||||
];
|
users.users.hass.extraGroups = [ "dialout" "tty" ];
|
||||||
extraPackages = python3Packages: with python3Packages; [
|
|
||||||
aiodhcpwatcher
|
services.home-assistant = {
|
||||||
aiodiscover
|
# NOTE: Missing: hacs. Inside hacs: `card-mod`, `Clock Weather Card`, `WallPanel` and `Yandex.Station`.
|
||||||
aiogithubapi
|
enable = true;
|
||||||
async-upnp-client
|
extraComponents = [
|
||||||
ha-av
|
"caldav"
|
||||||
ha-ffmpeg
|
"met"
|
||||||
hassil
|
"sun"
|
||||||
home-assistant-intents
|
"systemmonitor"
|
||||||
mutagen
|
"zha"
|
||||||
numpy
|
];
|
||||||
pynacl
|
extraPackages = python3Packages: with python3Packages; [
|
||||||
pyturbojpeg
|
aiodhcpwatcher
|
||||||
python-telegram-bot
|
aiodiscover
|
||||||
zeroconf
|
aiogithubapi
|
||||||
];
|
async-upnp-client
|
||||||
configDir = "/var/lib/hass";
|
ha-av
|
||||||
# lovelaceConfig = {
|
ha-ffmpeg
|
||||||
# title = "Home IoT control center.";
|
hassil
|
||||||
# };
|
home-assistant-intents
|
||||||
# NOTE: Using imperative config because of secrets.
|
mutagen
|
||||||
config = null;
|
numpy
|
||||||
|
pynacl
|
||||||
|
pyturbojpeg
|
||||||
|
python-telegram-bot
|
||||||
|
zeroconf
|
||||||
|
];
|
||||||
|
configDir = "/var/lib/hass";
|
||||||
|
# lovelaceConfig = {
|
||||||
|
# title = "Home IoT control center.";
|
||||||
|
# };
|
||||||
|
# NOTE: Using imperative config because of secrets.
|
||||||
|
config = null;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,48 +1,64 @@
|
||||||
{ container, pkgsJobber, poetry2nixJobber, lib, ... } @args: let
|
{ container, pkgsJobber, poetry2nixJobber, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.jobber;
|
cfg = config.container.module.jobber;
|
||||||
script = import ./jobber { poetry2nix = poetry2nixJobber; pkgs = pkgsJobber; };
|
script = import ./jobber { poetry2nix = poetry2nixJobber; pkgs = pkgsJobber; };
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.jobber = {
|
||||||
];
|
enable = mkEnableOption "Button pusher Stanley.";
|
||||||
|
address = mkOption {
|
||||||
containers.jobber = container.mkContainer cfg {
|
default = "10.1.0.32";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/data" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
storage = mkOption {
|
||||||
isReadOnly = true;
|
default = "${config.container.storage}/jobber";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
enableTun = true;
|
config = mkIf cfg.enable {
|
||||||
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
|
"data"
|
||||||
|
];
|
||||||
|
|
||||||
config = { lib, ... }: let
|
containers.jobber = container.mkContainer cfg {
|
||||||
packages = [ script ] ++ (with pkgsJobber; [
|
bindMounts = {
|
||||||
firefox
|
"/data" = {
|
||||||
geckodriver
|
hostPath = "${cfg.storage}/data";
|
||||||
openvpn
|
isReadOnly = true;
|
||||||
python311
|
};
|
||||||
]);
|
|
||||||
in container.mkContainerConfig cfg {
|
|
||||||
networking = lib.mkForce {
|
|
||||||
nameservers = [
|
|
||||||
"10.9.0.5"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.jobber = {
|
enableTun = true;
|
||||||
description = "My job is pushing the button.";
|
|
||||||
enable = true;
|
config = { lib, ... }: let
|
||||||
wantedBy = [ "multi-user.target" ];
|
packages = [ script ] ++ (with pkgsJobber; [
|
||||||
path = packages;
|
firefox
|
||||||
environment = {
|
geckodriver
|
||||||
PYTHONUNBUFFERED = "1";
|
openvpn
|
||||||
PYTHONDONTWRITEBYTECODE = "1";
|
python311
|
||||||
|
]);
|
||||||
|
in container.mkContainerConfig cfg {
|
||||||
|
networking = lib.mkForce {
|
||||||
|
nameservers = [
|
||||||
|
"10.9.0.5"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
serviceConfig = {
|
|
||||||
Type = "simple";
|
systemd.services.jobber = {
|
||||||
ExecStart = "${script}/bin/jobber -u";
|
description = "My job is pushing the button.";
|
||||||
Restart = "on-failure";
|
enable = true;
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
path = packages;
|
||||||
|
environment = {
|
||||||
|
PYTHONUNBUFFERED = "1";
|
||||||
|
PYTHONDONTWRITEBYTECODE = "1";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = "${script}/bin/jobber -u";
|
||||||
|
Restart = "on-failure";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,177 +1,203 @@
|
||||||
# Guide: https://nixos-mailserver.readthedocs.io/en/latest/setup-guide.html
|
# Guide: https://nixos-mailserver.readthedocs.io/en/latest/setup-guide.html
|
||||||
{ container, domain, pkgs, util, const, ... } @args: let cfg = container.config.mail;
|
{ container, pkgs, util, const, lib, config, ... }: with lib; let
|
||||||
|
cfg = config.container.module.mail;
|
||||||
|
domain = config.container.domain;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.mail = {
|
||||||
# "data/indices"
|
enable = mkEnableOption "Email server.";
|
||||||
# "data/vmail"
|
address = mkOption {
|
||||||
# "data/sieve"
|
default = "10.1.0.5";
|
||||||
# "data/dkim"
|
type = types.str;
|
||||||
];
|
|
||||||
|
|
||||||
containers.mail = container.mkContainer cfg {
|
|
||||||
forwardPorts = [
|
|
||||||
{
|
|
||||||
containerPort = 993;
|
|
||||||
hostPort = 993;
|
|
||||||
protocol = "tcp";
|
|
||||||
} {
|
|
||||||
containerPort = 25;
|
|
||||||
hostPort = 25;
|
|
||||||
protocol = "tcp";
|
|
||||||
} {
|
|
||||||
containerPort = 465;
|
|
||||||
hostPort = 465;
|
|
||||||
protocol = "tcp";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
bindMounts = {
|
|
||||||
"/var/lib/dovecot/indices" = {
|
|
||||||
hostPath = "${cfg.storage}/data/indices";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
};
|
||||||
"/var/vmail" = {
|
port = mkOption {
|
||||||
hostPath = "${cfg.storage}/data/vmail";
|
default = 80;
|
||||||
isReadOnly = false;
|
type = types.int;
|
||||||
};
|
};
|
||||||
"/var/sieve" = {
|
domain = mkOption {
|
||||||
hostPath = "${cfg.storage}/data/sieve";
|
default = "mail.${config.container.domain}";
|
||||||
isReadOnly = false;
|
type = types.str;
|
||||||
};
|
};
|
||||||
"/var/dkim" = {
|
storage = mkOption {
|
||||||
hostPath = "${cfg.storage}/data/dkim";
|
default = "${config.container.storage}/mail";
|
||||||
isReadOnly = false;
|
type = types.str;
|
||||||
};
|
|
||||||
"/acme" = {
|
|
||||||
hostPath = "${container.config.proxy.storage}/letsencrypt";
|
|
||||||
isReadOnly = true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { config, ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
imports = [
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
(builtins.fetchTarball {
|
"data"
|
||||||
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-${const.stateVersion}/nixos-mailserver-nixos-${const.stateVersion}.tar.gz";
|
# "data/indices"
|
||||||
sha256 = "sha256:0clvw4622mqzk1aqw1qn6shl9pai097q62mq1ibzscnjayhp278b";
|
# "data/vmail"
|
||||||
})
|
# "data/sieve"
|
||||||
|
# "data/dkim"
|
||||||
|
];
|
||||||
|
|
||||||
|
containers.mail = container.mkContainer cfg {
|
||||||
|
forwardPorts = [
|
||||||
|
{
|
||||||
|
containerPort = 993;
|
||||||
|
hostPort = 993;
|
||||||
|
protocol = "tcp";
|
||||||
|
} {
|
||||||
|
containerPort = 25;
|
||||||
|
hostPort = 25;
|
||||||
|
protocol = "tcp";
|
||||||
|
} {
|
||||||
|
containerPort = 465;
|
||||||
|
hostPort = 465;
|
||||||
|
protocol = "tcp";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
mailserver = {
|
bindMounts = {
|
||||||
enable = true;
|
"/var/lib/dovecot/indices" = {
|
||||||
fqdn = cfg.domain;
|
hostPath = "${cfg.storage}/data/indices";
|
||||||
domains = [ domain ];
|
isReadOnly = false;
|
||||||
sendingFqdn = domain;
|
};
|
||||||
|
"/var/vmail" = {
|
||||||
|
hostPath = "${cfg.storage}/data/vmail";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/var/sieve" = {
|
||||||
|
hostPath = "${cfg.storage}/data/sieve";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/var/dkim" = {
|
||||||
|
hostPath = "${cfg.storage}/data/dkim";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/acme" = {
|
||||||
|
hostPath = "${config.container.module.proxy.storage}/letsencrypt";
|
||||||
|
isReadOnly = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# Use `mkpasswd -sm bcrypt`.
|
config = { config, ... }: container.mkContainerConfig cfg {
|
||||||
loginAccounts = let
|
imports = [
|
||||||
defaultQuota = "1G";
|
(builtins.fetchTarball {
|
||||||
in {
|
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-${const.stateVersion}/nixos-mailserver-nixos-${const.stateVersion}.tar.gz";
|
||||||
"admin@${domain}" = {
|
sha256 = "sha256:0clvw4622mqzk1aqw1qn6shl9pai097q62mq1ibzscnjayhp278b";
|
||||||
name = "admin";
|
})
|
||||||
hashedPassword = "$2b$05$1O.dxXxaVshcBNybcqDRYuTlnYt3jDBwfPZWoDtP4BjOLoL0StYsi";
|
];
|
||||||
quota = defaultQuota;
|
|
||||||
|
mailserver = {
|
||||||
|
enable = true;
|
||||||
|
domains = [ domain ];
|
||||||
|
fqdn = cfg.domain;
|
||||||
|
sendingFqdn = domain;
|
||||||
|
|
||||||
|
# Use `mkpasswd -sm bcrypt`.
|
||||||
|
loginAccounts = let
|
||||||
|
defaultQuota = "1G";
|
||||||
|
in {
|
||||||
|
"admin@${domain}" = {
|
||||||
|
name = "admin";
|
||||||
|
hashedPassword = "$2b$05$1O.dxXxaVshcBNybcqDRYuTlnYt3jDBwfPZWoDtP4BjOLoL0StYsi";
|
||||||
|
quota = defaultQuota;
|
||||||
|
};
|
||||||
|
"account@${domain}" = {
|
||||||
|
name = "account";
|
||||||
|
hashedPassword = "$2b$05$sCyZHdk98KqQ1qsTIvbrUeRJlNBOwBqDgpdc1QxiSnONlEkZ8xGNO";
|
||||||
|
quota = defaultQuota;
|
||||||
|
};
|
||||||
|
"hi@${domain}" = {
|
||||||
|
name = "hi";
|
||||||
|
hashedPassword = "$2b$05$6fT5hIhzIasNfp9IQr/ds.5RuxH95VKU3QJWlX3hmrAzDF3mExanq";
|
||||||
|
quota = defaultQuota;
|
||||||
|
aliases = [ "voronind@${domain}" ];
|
||||||
|
};
|
||||||
|
"job@${domain}" = {
|
||||||
|
name = "job";
|
||||||
|
hashedPassword = "$2b$05$.sUmv2.9EWPfLwJn/oZw2e1UbR7HrpNQ2THc5jjX3ysy7CY8ZWHUC";
|
||||||
|
quota = defaultQuota;
|
||||||
|
};
|
||||||
|
"trash@${domain}" = {
|
||||||
|
name = "trash";
|
||||||
|
hashedPassword = "$2b$05$kn5ygZjN9NR3LXjnKKRw/.DXaZQNW.1XEottlCFIoKiDpIj.JGLJm";
|
||||||
|
catchAll = [ domain ];
|
||||||
|
quota = defaultQuota;
|
||||||
|
};
|
||||||
|
"noreply@${domain}" = {
|
||||||
|
name = "noreply";
|
||||||
|
hashedPassword = "$2b$05$TaKwoYmcmkAhsRRv6xG5wOkChcz50cB9BP6QPUDKNAcxMbrY6AeMK";
|
||||||
|
sendOnly = true;
|
||||||
|
quota = defaultQuota;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
"account@${domain}" = {
|
|
||||||
name = "account";
|
enableImap = true;
|
||||||
hashedPassword = "$2b$05$sCyZHdk98KqQ1qsTIvbrUeRJlNBOwBqDgpdc1QxiSnONlEkZ8xGNO";
|
enableImapSsl = true;
|
||||||
quota = defaultQuota;
|
enableSubmission = true;
|
||||||
|
enableSubmissionSsl = true;
|
||||||
|
|
||||||
|
virusScanning = false;
|
||||||
|
|
||||||
|
certificateScheme = "manual";
|
||||||
|
keyFile = "/acme/live/${domain}/privkey.pem";
|
||||||
|
certificateFile = "/acme/live/${domain}/cert.pem";
|
||||||
|
|
||||||
|
indexDir = "/var/lib/dovecot/indices";
|
||||||
|
mailDirectory = "/var/vmail";
|
||||||
|
sieveDirectory = "/var/sieve";
|
||||||
|
dkimKeyDirectory = "/var/dkim";
|
||||||
|
|
||||||
|
mailboxes = {
|
||||||
|
Drafts = {
|
||||||
|
auto = "subscribe";
|
||||||
|
specialUse = "Drafts";
|
||||||
|
};
|
||||||
|
Junk = {
|
||||||
|
auto = "subscribe";
|
||||||
|
specialUse = "Junk";
|
||||||
|
};
|
||||||
|
Sent = {
|
||||||
|
auto = "subscribe";
|
||||||
|
specialUse = "Sent";
|
||||||
|
};
|
||||||
|
Trash = {
|
||||||
|
auto = "no";
|
||||||
|
specialUse = "Trash";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
"hi@${domain}" = {
|
|
||||||
name = "hi";
|
dmarcReporting = {
|
||||||
hashedPassword = "$2b$05$6fT5hIhzIasNfp9IQr/ds.5RuxH95VKU3QJWlX3hmrAzDF3mExanq";
|
inherit domain;
|
||||||
quota = defaultQuota;
|
enable = true;
|
||||||
aliases = [ "voronind@${domain}" ];
|
organizationName = "voronind";
|
||||||
};
|
# email = "noreply@${domain}";
|
||||||
"job@${domain}" = {
|
|
||||||
name = "job";
|
|
||||||
hashedPassword = "$2b$05$.sUmv2.9EWPfLwJn/oZw2e1UbR7HrpNQ2THc5jjX3ysy7CY8ZWHUC";
|
|
||||||
quota = defaultQuota;
|
|
||||||
};
|
|
||||||
"trash@${domain}" = {
|
|
||||||
name = "trash";
|
|
||||||
hashedPassword = "$2b$05$kn5ygZjN9NR3LXjnKKRw/.DXaZQNW.1XEottlCFIoKiDpIj.JGLJm";
|
|
||||||
catchAll = [ domain ];
|
|
||||||
quota = defaultQuota;
|
|
||||||
};
|
|
||||||
"noreply@${domain}" = {
|
|
||||||
name = "noreply";
|
|
||||||
hashedPassword = "$2b$05$TaKwoYmcmkAhsRRv6xG5wOkChcz50cB9BP6QPUDKNAcxMbrY6AeMK";
|
|
||||||
sendOnly = true;
|
|
||||||
quota = defaultQuota;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# monitoring = {
|
||||||
|
# enable = true;
|
||||||
|
# alertAddress = "admin@${domain}";
|
||||||
|
# };
|
||||||
};
|
};
|
||||||
|
|
||||||
enableImap = true;
|
services.roundcube = {
|
||||||
enableImapSsl = true;
|
|
||||||
enableSubmission = true;
|
|
||||||
enableSubmissionSsl = true;
|
|
||||||
|
|
||||||
virusScanning = false;
|
|
||||||
|
|
||||||
certificateScheme = "manual";
|
|
||||||
keyFile = "/acme/live/${domain}/privkey.pem";
|
|
||||||
certificateFile = "/acme/live/${domain}/cert.pem";
|
|
||||||
|
|
||||||
indexDir = "/var/lib/dovecot/indices";
|
|
||||||
mailDirectory = "/var/vmail";
|
|
||||||
sieveDirectory = "/var/sieve";
|
|
||||||
dkimKeyDirectory = "/var/dkim";
|
|
||||||
|
|
||||||
mailboxes = {
|
|
||||||
Drafts = {
|
|
||||||
auto = "subscribe";
|
|
||||||
specialUse = "Drafts";
|
|
||||||
};
|
|
||||||
Junk = {
|
|
||||||
auto = "subscribe";
|
|
||||||
specialUse = "Junk";
|
|
||||||
};
|
|
||||||
Sent = {
|
|
||||||
auto = "subscribe";
|
|
||||||
specialUse = "Sent";
|
|
||||||
};
|
|
||||||
Trash = {
|
|
||||||
auto = "no";
|
|
||||||
specialUse = "Trash";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
dmarcReporting = {
|
|
||||||
inherit domain;
|
|
||||||
enable = true;
|
enable = true;
|
||||||
organizationName = "voronind";
|
dicts = with pkgs.aspellDicts; [ en ru ];
|
||||||
# email = "noreply@${domain}";
|
hostName = cfg.domain;
|
||||||
|
extraConfig = ''
|
||||||
|
# starttls needed for authentication, so the fqdn required to match
|
||||||
|
# the certificate
|
||||||
|
# $config['smtp_server'] = "tls://${config.mailserver.fqdn}";
|
||||||
|
# $config['smtp_server'] = "tls://localhost";
|
||||||
|
$config['smtp_server'] = "localhost:25";
|
||||||
|
$config['smtp_auth_type'] = null;
|
||||||
|
$config['smtp_user'] = "";
|
||||||
|
$config['smtp_pass'] = "";
|
||||||
|
# $config['smtp_user'] = "%u";
|
||||||
|
# $config['smtp_pass'] = "%p";
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
# monitoring = {
|
services.nginx = {
|
||||||
# enable = true;
|
virtualHosts.${cfg.domain} = {
|
||||||
# alertAddress = "admin@${domain}";
|
forceSSL = false;
|
||||||
# };
|
enableACME = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.roundcube = {
|
|
||||||
enable = true;
|
|
||||||
dicts = with pkgs.aspellDicts; [ en ru ];
|
|
||||||
hostName = cfg.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
# starttls needed for authentication, so the fqdn required to match
|
|
||||||
# the certificate
|
|
||||||
# $config['smtp_server'] = "tls://${config.mailserver.fqdn}";
|
|
||||||
# $config['smtp_server'] = "tls://localhost";
|
|
||||||
$config['smtp_server'] = "localhost:25";
|
|
||||||
$config['smtp_auth_type'] = null;
|
|
||||||
$config['smtp_user'] = "";
|
|
||||||
$config['smtp_pass'] = "";
|
|
||||||
# $config['smtp_user'] = "%u";
|
|
||||||
# $config['smtp_pass'] = "%p";
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx = {
|
|
||||||
virtualHosts.${cfg.domain} = {
|
|
||||||
forceSSL = false;
|
|
||||||
enableACME = false;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,39 +2,63 @@
|
||||||
# 1. You need to change PSQL tables owner from root to onlyoffice, too. They don't do that automatically for some reason.
|
# 1. You need to change PSQL tables owner from root to onlyoffice, too. They don't do that automatically for some reason.
|
||||||
# 2. TODO: Generate JWT secret at /var/lib/onlyoffice/jwt, i.e. 9wLfMGha1YrfvWpb5hyYjZf8pvJQ3swS
|
# 2. TODO: Generate JWT secret at /var/lib/onlyoffice/jwt, i.e. 9wLfMGha1YrfvWpb5hyYjZf8pvJQ3swS
|
||||||
# See https://git.voronind.com/voronind/nixos/issues/74
|
# See https://git.voronind.com/voronind/nixos/issues/74
|
||||||
{ container, pkgs, util, lib, ... } @args: let
|
{ container, pkgs, util, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.office;
|
cfg = config.container.module.office;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.office = {
|
||||||
];
|
enable = mkEnableOption "Office web suite.";
|
||||||
|
address = mkOption {
|
||||||
containers.office = container.mkContainer cfg {
|
default = "10.1.0.21";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/onlyoffice" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
port = mkOption {
|
||||||
isReadOnly = false;
|
default = 8000;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "office.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/office";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
services.onlyoffice = let
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
dbName = "onlyoffice";
|
"data"
|
||||||
in {
|
];
|
||||||
enable = true;
|
|
||||||
hostname = cfg.domain;
|
|
||||||
|
|
||||||
postgresName = dbName;
|
containers.office = container.mkContainer cfg {
|
||||||
postgresHost = container.config.postgres.address;
|
bindMounts = {
|
||||||
postgresUser = dbName;
|
"/var/lib/onlyoffice" = {
|
||||||
postgresPasswordFile = "${pkgs.writeText "OfficeDbPassword" dbName}";
|
hostPath = "${cfg.storage}/data";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
jwtSecretFile = "/var/lib/onlyoffice/jwt";
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.onlyoffice = let
|
||||||
|
dbName = "onlyoffice";
|
||||||
|
in {
|
||||||
|
enable = true;
|
||||||
|
hostname = cfg.domain;
|
||||||
|
|
||||||
rabbitmqUrl = "amqp://guest:guest@${container.config.rabbitmq.address}:${toString container.config.rabbitmq.port}";
|
postgresName = dbName;
|
||||||
|
postgresHost = config.container.module.postgres.address;
|
||||||
|
postgresUser = dbName;
|
||||||
|
postgresPasswordFile = "${pkgs.writeText "OfficeDbPassword" dbName}";
|
||||||
|
|
||||||
examplePort = cfg.port;
|
jwtSecretFile = "/var/lib/onlyoffice/jwt";
|
||||||
enableExampleServer = true;
|
|
||||||
|
rabbitmqUrl = "amqp://guest:guest@${config.container.module.rabbitmq.address}:${toString config.container.module.rabbitmq.port}";
|
||||||
|
|
||||||
|
examplePort = cfg.port;
|
||||||
|
enableExampleServer = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,52 +1,76 @@
|
||||||
{ container, pkgs, util, lib, ... } @args: let
|
{ container, pkgs, util, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.paper;
|
cfg = config.container.module.paper;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.paper = {
|
||||||
];
|
enable = mkEnableOption "Paper scans manager.";
|
||||||
|
address = mkOption {
|
||||||
containers.paper = container.mkContainer cfg {
|
default = "10.1.0.40";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/paperless" = {
|
|
||||||
hostPath = "${cfg.storage}/data";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
};
|
||||||
"/var/lib/paperless/media" = {
|
port = mkOption {
|
||||||
hostPath = "${lib.elemAt cfg.paper 0}";
|
default = 28981;
|
||||||
isReadOnly = false;
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "paper.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/paper";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { lib, ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
environment.systemPackages = with pkgs; [ postgresql inetutils ];
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
|
"data"
|
||||||
|
];
|
||||||
|
|
||||||
services.paperless = {
|
containers.paper = container.mkContainer cfg {
|
||||||
enable = true;
|
bindMounts = {
|
||||||
dataDir = "/var/lib/paperless";
|
"/var/lib/paperless" = {
|
||||||
# address = cfg.domain;
|
hostPath = "${cfg.storage}/data";
|
||||||
address = "0.0.0.0";
|
isReadOnly = false;
|
||||||
port = cfg.port;
|
};
|
||||||
passwordFile = pkgs.writeText "PaperlessPassword" "root";
|
"/var/lib/paperless/media" = {
|
||||||
settings = {
|
hostPath = "${elemAt config.container.media.paper 0}";
|
||||||
PAPERLESS_URL = "https://${cfg.domain}";
|
isReadOnly = false;
|
||||||
PAPERLESS_ADMIN_USER = "root";
|
|
||||||
PAPERLESS_DBHOST = container.config.postgres.address;
|
|
||||||
PAPERLESS_DBENGINE = "postgresql";
|
|
||||||
PAPERLESS_DBNAME = "paperless";
|
|
||||||
PAPERLESS_DBPASS = "paperless";
|
|
||||||
PAPERLESS_DBPORT = container.config.postgres.port;
|
|
||||||
PAPERLESS_DBUSER = "paperless";
|
|
||||||
PAPERLESS_OCR_LANGUAGE = "rus";
|
|
||||||
PAPERLESS_REDIS = "redis://${container.config.redis.address}:${toString container.config.redis.port}";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# HACK: This is required for TCP postgres connection.
|
config = { lib, ... }: container.mkContainerConfig cfg {
|
||||||
systemd.services.paperless-scheduler.serviceConfig = {
|
environment.systemPackages = with pkgs; [ postgresql inetutils ];
|
||||||
PrivateNetwork = lib.mkForce false;
|
|
||||||
};
|
services.paperless = {
|
||||||
systemd.services.paperless-consumer.serviceConfig = {
|
enable = true;
|
||||||
PrivateNetwork = lib.mkForce false;
|
dataDir = "/var/lib/paperless";
|
||||||
|
# address = cfg.domain;
|
||||||
|
address = "0.0.0.0";
|
||||||
|
port = cfg.port;
|
||||||
|
passwordFile = pkgs.writeText "PaperlessPassword" "root";
|
||||||
|
settings = {
|
||||||
|
PAPERLESS_URL = "https://${cfg.domain}";
|
||||||
|
PAPERLESS_ADMIN_USER = "root";
|
||||||
|
PAPERLESS_DBHOST = config.container.module.postgres.address;
|
||||||
|
PAPERLESS_DBENGINE = "postgresql";
|
||||||
|
PAPERLESS_DBNAME = "paperless";
|
||||||
|
PAPERLESS_DBPASS = "paperless";
|
||||||
|
PAPERLESS_DBPORT = config.container.module.postgres.port;
|
||||||
|
PAPERLESS_DBUSER = "paperless";
|
||||||
|
PAPERLESS_OCR_LANGUAGE = "rus";
|
||||||
|
PAPERLESS_REDIS = "redis://${config.container.module.redis.address}:${toString config.container.module.redis.port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# HACK: This is required for TCP postgres connection.
|
||||||
|
systemd.services.paperless-scheduler.serviceConfig = {
|
||||||
|
PrivateNetwork = lib.mkForce false;
|
||||||
|
};
|
||||||
|
systemd.services.paperless-consumer.serviceConfig = {
|
||||||
|
PrivateNetwork = lib.mkForce false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,31 +1,55 @@
|
||||||
{ container, ... } @args: let
|
{ container, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.pass;
|
cfg = config.container.module.pass;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.pass = {
|
||||||
];
|
enable = mkEnableOption "Password manager";
|
||||||
|
address = mkOption {
|
||||||
containers.pass = container.mkContainer cfg {
|
default = "10.1.0.9";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/bitwarden_rs" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
port = mkOption {
|
||||||
isReadOnly = false;
|
default = 8000;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "pass.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/pass";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
services.vaultwarden = {
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
enable = true;
|
"data"
|
||||||
dbBackend = "sqlite";
|
];
|
||||||
environmentFile = "/var/lib/bitwarden_rs/Env";
|
|
||||||
config = {
|
containers.pass = container.mkContainer cfg {
|
||||||
# DATABASE_URL = "postgresql://vaultwarden:vaultwarden@${container.config.postgres.address}:${toString container.config.postgres.port}/vaultwarden";
|
bindMounts = {
|
||||||
DATA_FOLDER = "/var/lib/bitwarden_rs";
|
"/var/lib/bitwarden_rs" = {
|
||||||
DOMAIN = "http://${cfg.domain}";
|
hostPath = "${cfg.storage}/data";
|
||||||
SIGNUPS_ALLOWED = false;
|
isReadOnly = false;
|
||||||
WEB_VAULT_ENABLED = true;
|
};
|
||||||
ROCKET_ADDRESS = cfg.address;
|
};
|
||||||
ROCKET_PORT = cfg.port;
|
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.vaultwarden = {
|
||||||
|
enable = true;
|
||||||
|
dbBackend = "sqlite";
|
||||||
|
environmentFile = "/var/lib/bitwarden_rs/Env";
|
||||||
|
config = {
|
||||||
|
# DATABASE_URL = "postgresql://vaultwarden:vaultwarden@${container.config.postgres.address}:${toString container.config.postgres.port}/vaultwarden";
|
||||||
|
DATA_FOLDER = "/var/lib/bitwarden_rs";
|
||||||
|
DOMAIN = "http://${cfg.domain}";
|
||||||
|
SIGNUPS_ALLOWED = false;
|
||||||
|
WEB_VAULT_ENABLED = true;
|
||||||
|
ROCKET_ADDRESS = cfg.address;
|
||||||
|
ROCKET_PORT = cfg.port;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,100 +1,124 @@
|
||||||
{ pkgs, util, container, ... } @args: let
|
{ pkgs, util, container, lib, config, ... } @args: with lib; let
|
||||||
cfg = container.config.paste;
|
cfg = config.container.module.paste;
|
||||||
package = (pkgs.callPackage ./pastebin args);
|
package = (pkgs.callPackage ./pastebin args);
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.paste = {
|
||||||
"tmp"
|
enable = mkEnableOption "Pastebin.";
|
||||||
"nginxtmp"
|
address = mkOption {
|
||||||
"config"
|
default = "10.1.0.14";
|
||||||
];
|
type = types.str;
|
||||||
|
|
||||||
containers.paste = container.mkContainer cfg {
|
|
||||||
bindMounts = {
|
|
||||||
"/srv/data" = {
|
|
||||||
hostPath = "${cfg.storage}/data";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
};
|
||||||
"/tmp" = {
|
port = mkOption {
|
||||||
hostPath = "${cfg.storage}/tmp";
|
default = 80;
|
||||||
isReadOnly = false;
|
type = types.int;
|
||||||
};
|
};
|
||||||
"/var/lib/nginx/tmp" = {
|
domain = mkOption {
|
||||||
hostPath = "${cfg.storage}/nginxtmp";
|
default = "paste.${config.container.domain}";
|
||||||
isReadOnly = false;
|
type = types.str;
|
||||||
};
|
};
|
||||||
"/srv/config" = {
|
storage = mkOption {
|
||||||
hostPath = "${cfg.storage}/config";
|
default = "${config.container.storage}/paste";
|
||||||
isReadOnly = false;
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { config, ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
environment.systemPackages = [ package ];
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
systemd.packages = [ package ];
|
"data"
|
||||||
|
"tmp"
|
||||||
|
"nginxtmp"
|
||||||
|
"config"
|
||||||
|
];
|
||||||
|
|
||||||
users.users.paste = {
|
containers.paste = container.mkContainer cfg {
|
||||||
group = "nginx";
|
bindMounts = {
|
||||||
isSystemUser = true;
|
"/srv/data" = {
|
||||||
};
|
hostPath = "${cfg.storage}/data";
|
||||||
|
isReadOnly = false;
|
||||||
services.phpfpm.pools.paste = {
|
|
||||||
user = "paste";
|
|
||||||
group = "nginx";
|
|
||||||
|
|
||||||
phpPackage = pkgs.php;
|
|
||||||
|
|
||||||
settings = {
|
|
||||||
"pm" = "dynamic";
|
|
||||||
"php_admin_value[error_log]" = "stderr";
|
|
||||||
"php_admin_flag[log_errors]" = true;
|
|
||||||
"listen.owner" = "nginx";
|
|
||||||
"catch_workers_output" = true;
|
|
||||||
"pm.max_children" = "32";
|
|
||||||
"pm.start_servers" = "2";
|
|
||||||
"pm.min_spare_servers" = "2";
|
|
||||||
"pm.max_spare_servers" = "4";
|
|
||||||
"pm.max_requests" = "500";
|
|
||||||
};
|
};
|
||||||
|
"/tmp" = {
|
||||||
phpEnv = {
|
hostPath = "${cfg.storage}/tmp";
|
||||||
# CONFIG_PATH = "${package}/cfg";
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/var/lib/nginx/tmp" = {
|
||||||
|
hostPath = "${cfg.storage}/nginxtmp";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/srv/config" = {
|
||||||
|
hostPath = "${cfg.storage}/config";
|
||||||
|
isReadOnly = false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx = {
|
config = { config, ... }: container.mkContainerConfig cfg {
|
||||||
enable = true;
|
environment.systemPackages = [ package ];
|
||||||
virtualHosts.${cfg.domain} = container.mkServer {
|
systemd.packages = [ package ];
|
||||||
default = true;
|
|
||||||
root = "${package}";
|
|
||||||
|
|
||||||
locations = {
|
users.users.paste = {
|
||||||
"/".extraConfig = ''
|
group = "nginx";
|
||||||
rewrite ^ /index.php;
|
isSystemUser = true;
|
||||||
'';
|
};
|
||||||
|
|
||||||
"~ \\.php$".extraConfig = util.trimTabs ''
|
services.phpfpm.pools.paste = {
|
||||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
user = "paste";
|
||||||
fastcgi_pass unix:${config.services.phpfpm.pools.paste.socket};
|
group = "nginx";
|
||||||
include ${config.services.nginx.package}/conf/fastcgi.conf;
|
|
||||||
include ${config.services.nginx.package}/conf/fastcgi_params;
|
|
||||||
'';
|
|
||||||
|
|
||||||
"~ \\.(js|css|ttf|woff2?|png|jpe?g|svg)$".extraConfig = util.trimTabs ''
|
phpPackage = pkgs.php;
|
||||||
add_header Cache-Control "public, max-age=15778463";
|
|
||||||
add_header X-Content-Type-Options nosniff;
|
settings = {
|
||||||
add_header X-XSS-Protection "1; mode=block";
|
"pm" = "dynamic";
|
||||||
add_header X-Robots-Tag none;
|
"php_admin_value[error_log]" = "stderr";
|
||||||
add_header X-Download-Options noopen;
|
"php_admin_flag[log_errors]" = true;
|
||||||
add_header X-Permitted-Cross-Domain-Policies none;
|
"listen.owner" = "nginx";
|
||||||
add_header Referrer-Policy no-referrer;
|
"catch_workers_output" = true;
|
||||||
access_log off;
|
"pm.max_children" = "32";
|
||||||
'';
|
"pm.start_servers" = "2";
|
||||||
|
"pm.min_spare_servers" = "2";
|
||||||
|
"pm.max_spare_servers" = "4";
|
||||||
|
"pm.max_requests" = "500";
|
||||||
};
|
};
|
||||||
|
|
||||||
extraConfig = util.trimTabs ''
|
phpEnv = {
|
||||||
try_files $uri /index.php;
|
# CONFIG_PATH = "${package}/cfg";
|
||||||
'';
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts.${cfg.domain} = container.mkServer {
|
||||||
|
default = true;
|
||||||
|
root = "${package}";
|
||||||
|
|
||||||
|
locations = {
|
||||||
|
"/".extraConfig = ''
|
||||||
|
rewrite ^ /index.php;
|
||||||
|
'';
|
||||||
|
|
||||||
|
"~ \\.php$".extraConfig = util.trimTabs ''
|
||||||
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||||
|
fastcgi_pass unix:${config.services.phpfpm.pools.paste.socket};
|
||||||
|
include ${config.services.nginx.package}/conf/fastcgi.conf;
|
||||||
|
include ${config.services.nginx.package}/conf/fastcgi_params;
|
||||||
|
'';
|
||||||
|
|
||||||
|
"~ \\.(js|css|ttf|woff2?|png|jpe?g|svg)$".extraConfig = util.trimTabs ''
|
||||||
|
add_header Cache-Control "public, max-age=15778463";
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
add_header X-Robots-Tag none;
|
||||||
|
add_header X-Download-Options noopen;
|
||||||
|
add_header X-Permitted-Cross-Domain-Policies none;
|
||||||
|
add_header Referrer-Policy no-referrer;
|
||||||
|
access_log off;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = util.trimTabs ''
|
||||||
|
try_files $uri /index.php;
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,56 +1,76 @@
|
||||||
{ container, lib, pkgs, ... } @args: let
|
{ container, lib, pkgs, config, ... }: with lib; let
|
||||||
cfg = container.config.postgres;
|
cfg = config.container.module.postgres;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.postgres = {
|
||||||
];
|
enable = mkEnableOption "Postgresql server.";
|
||||||
|
address = mkOption {
|
||||||
containers.postgres = container.mkContainer cfg {
|
default = "10.1.0.3";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/postgresql/data" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
port = mkOption {
|
||||||
isReadOnly = false;
|
default = 5432;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/postgres";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
services.postgresql = let
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
# Populate with services here.
|
"data"
|
||||||
configurations = with container.config; {
|
];
|
||||||
gitea = git;
|
|
||||||
nextcloud = cloud;
|
containers.postgres = container.mkContainer cfg {
|
||||||
privatebin = paste;
|
bindMounts = {
|
||||||
onlyoffice = office;
|
"/var/lib/postgresql/data" = {
|
||||||
paperless = paper;
|
hostPath = "${cfg.storage}/data";
|
||||||
invidious = yt;
|
isReadOnly = false;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
access = configurations // {
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
all = { address = container.host; };
|
services.postgresql = let
|
||||||
|
# Populate with services here.
|
||||||
|
configurations = with config.container.module; {
|
||||||
|
gitea = git;
|
||||||
|
nextcloud = cloud;
|
||||||
|
privatebin = paste;
|
||||||
|
onlyoffice = office;
|
||||||
|
paperless = paper;
|
||||||
|
invidious = yt;
|
||||||
|
};
|
||||||
|
|
||||||
|
access = configurations // {
|
||||||
|
all = { address = config.container.host; };
|
||||||
|
};
|
||||||
|
|
||||||
|
authentication = builtins.foldl' (acc: item: acc + "${item}\n") "" (
|
||||||
|
mapAttrsToList (db: cfg: "host ${db} ${db} ${cfg.address}/32 trust") access
|
||||||
|
);
|
||||||
|
|
||||||
|
ensureDatabases = [ "root" ] ++ mapAttrsToList (name: _: name) configurations;
|
||||||
|
|
||||||
|
ensureUsers = map (name: {
|
||||||
|
inherit name;
|
||||||
|
ensureClauses = if name == "root" then {
|
||||||
|
superuser = true;
|
||||||
|
createrole = true;
|
||||||
|
createdb = true;
|
||||||
|
} else {};
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}) ensureDatabases;
|
||||||
|
in {
|
||||||
|
inherit authentication ensureDatabases ensureUsers;
|
||||||
|
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.postgresql_14;
|
||||||
|
dataDir = "/var/lib/postgresql/data/14";
|
||||||
|
enableTCPIP = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
authentication = builtins.foldl' (acc: item: acc + "${item}\n") "" (
|
|
||||||
lib.mapAttrsToList (db: cfg: "host ${db} ${db} ${cfg.address}/32 trust") access
|
|
||||||
);
|
|
||||||
|
|
||||||
ensureDatabases = [ "root" ] ++ lib.mapAttrsToList (name: _: name) configurations;
|
|
||||||
|
|
||||||
ensureUsers = map (name: {
|
|
||||||
inherit name;
|
|
||||||
ensureClauses = if name == "root" then {
|
|
||||||
superuser = true;
|
|
||||||
createrole = true;
|
|
||||||
createdb = true;
|
|
||||||
} else {};
|
|
||||||
ensureDBOwnership = true;
|
|
||||||
}) ensureDatabases;
|
|
||||||
in {
|
|
||||||
inherit authentication ensureDatabases ensureUsers;
|
|
||||||
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.postgresql_14;
|
|
||||||
dataDir = "/var/lib/postgresql/data/14";
|
|
||||||
enableTCPIP = true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,33 +2,57 @@
|
||||||
|
|
||||||
# ipp://192.168.2.237
|
# ipp://192.168.2.237
|
||||||
# Pantum M6500W-Series
|
# Pantum M6500W-Series
|
||||||
{ container, pkgs, ... } @args: let
|
{ container, pkgs, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.print;
|
cfg = config.container.module.print;
|
||||||
package = pkgs.callPackage ./print args;
|
package = pkgs.callPackage ./print args;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.print = {
|
||||||
];
|
enable = mkEnableOption "Printing server.";
|
||||||
|
address = mkOption {
|
||||||
containers.print = container.mkContainer cfg {
|
default = "10.1.0.46";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/cups" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
port = mkOption {
|
||||||
isReadOnly = false;
|
default = 631;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "print.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/print";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
services.printing = {
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
enable = true;
|
"data"
|
||||||
allowFrom = [ "all" ];
|
];
|
||||||
browsing = true;
|
|
||||||
defaultShared = true;
|
containers.print = container.mkContainer cfg {
|
||||||
drivers = [ package ];
|
bindMounts = {
|
||||||
listenAddresses = [ "${cfg.address}:${toString cfg.port}" ];
|
"/var/lib/cups" = {
|
||||||
startWhenNeeded = true;
|
hostPath = "${cfg.storage}/data";
|
||||||
stateless = false;
|
isReadOnly = false;
|
||||||
webInterface = true;
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.printing = {
|
||||||
|
enable = true;
|
||||||
|
allowFrom = [ "all" ];
|
||||||
|
browsing = true;
|
||||||
|
defaultShared = true;
|
||||||
|
drivers = [ package ];
|
||||||
|
listenAddresses = [ "${cfg.address}:${toString cfg.port}" ];
|
||||||
|
startWhenNeeded = true;
|
||||||
|
stateless = false;
|
||||||
|
webInterface = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,95 +9,115 @@
|
||||||
# ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
|
# ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
|
||||||
# ```
|
# ```
|
||||||
# For certbot to generate new keys: `certbot certonly --manual --manual-public-ip-logging-ok --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory -d "*.voronind.com" -d voronind.com`
|
# For certbot to generate new keys: `certbot certonly --manual --manual-public-ip-logging-ok --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory -d "*.voronind.com" -d voronind.com`
|
||||||
{ domain, util, container, pkgs, ... } @args: let
|
{ util, container, pkgs, lib, config, ... } @args: with lib; let
|
||||||
cfg = container.config.proxy;
|
cfg = config.container.module.proxy;
|
||||||
virtualHosts = util.catSet (util.ls ./proxy/host) args;
|
virtualHosts = util.catSet (util.ls ./proxy/host) args;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"challenge"
|
container.module.proxy = {
|
||||||
"letsencrypt"
|
enable = mkEnableOption "Proxy server.";
|
||||||
];
|
address = mkOption {
|
||||||
|
default = "10.1.0.2";
|
||||||
containers.proxy = container.mkContainer cfg {
|
type = types.str;
|
||||||
forwardPorts = [
|
|
||||||
# {
|
|
||||||
# containerPort = 80;
|
|
||||||
# hostPort = 80;
|
|
||||||
# protocol = "tcp";
|
|
||||||
# } {
|
|
||||||
{
|
|
||||||
containerPort = cfg.port;
|
|
||||||
hostPort = cfg.port;
|
|
||||||
protocol = "tcp";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
bindMounts = {
|
|
||||||
"/etc/letsencrypt" = {
|
|
||||||
hostPath = "${cfg.storage}/letsencrypt";
|
|
||||||
isReadOnly = true;
|
|
||||||
};
|
};
|
||||||
"/var/www/.well-known" = {
|
port = mkOption {
|
||||||
hostPath = "${cfg.storage}/challenge";
|
default = 443;
|
||||||
isReadOnly = false;
|
type = types.int;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/proxy";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
environment.systemPackages = with pkgs; [ certbot ];
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
|
"challenge"
|
||||||
|
"letsencrypt"
|
||||||
|
];
|
||||||
|
|
||||||
services.nginx = {
|
containers.proxy = container.mkContainer cfg {
|
||||||
inherit virtualHosts;
|
forwardPorts = [
|
||||||
|
# {
|
||||||
|
# containerPort = 80;
|
||||||
|
# hostPort = 80;
|
||||||
|
# protocol = "tcp";
|
||||||
|
# } {
|
||||||
|
{
|
||||||
|
containerPort = cfg.port;
|
||||||
|
hostPort = cfg.port;
|
||||||
|
protocol = "tcp";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
enable = true;
|
bindMounts = {
|
||||||
recommendedOptimisation = true;
|
"/etc/letsencrypt" = {
|
||||||
recommendedProxySettings = true;
|
hostPath = "${cfg.storage}/letsencrypt";
|
||||||
appendConfig = util.trimTabs ''
|
isReadOnly = true;
|
||||||
worker_processes 4;
|
};
|
||||||
'';
|
"/var/www/.well-known" = {
|
||||||
eventsConfig = util.trimTabs ''
|
hostPath = "${cfg.storage}/challenge";
|
||||||
worker_connections 4096;
|
isReadOnly = false;
|
||||||
'';
|
};
|
||||||
# TODO: Fix 80 redirect and 403 default.
|
};
|
||||||
appendHttpConfig = util.trimTabs ''
|
|
||||||
server {
|
|
||||||
server_name default_server;
|
|
||||||
listen 80;
|
|
||||||
|
|
||||||
location / {
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
return 301 https://$host$request_uri;
|
environment.systemPackages = with pkgs; [ certbot ];
|
||||||
|
|
||||||
|
services.nginx = {
|
||||||
|
inherit virtualHosts;
|
||||||
|
|
||||||
|
enable = true;
|
||||||
|
recommendedOptimisation = true;
|
||||||
|
recommendedProxySettings = true;
|
||||||
|
appendConfig = util.trimTabs ''
|
||||||
|
worker_processes 4;
|
||||||
|
'';
|
||||||
|
eventsConfig = util.trimTabs ''
|
||||||
|
worker_connections 4096;
|
||||||
|
'';
|
||||||
|
# TODO: Fix 80 redirect and 403 default.
|
||||||
|
appendHttpConfig = util.trimTabs ''
|
||||||
|
server {
|
||||||
|
server_name default_server;
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
map $http_accept_language $resume {
|
map $http_accept_language $resume {
|
||||||
default https://git.${domain}/voronind/resume/releases/download/latest/voronind_en.pdf;
|
default https://git.${config.container.domain}/voronind/resume/releases/download/latest/voronind_en.pdf;
|
||||||
~ru https://git.${domain}/voronind/resume/releases/download/latest/voronind_ru.pdf;
|
~ru https://git.${config.container.domain}/voronind/resume/releases/download/latest/voronind_ru.pdf;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
server_name ${domain};
|
server_name ${config.container.domain};
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
|
|
||||||
return 301 $resume;
|
return 301 $resume;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 443 ssl default_server;
|
listen 443 ssl default_server;
|
||||||
server_name _;
|
server_name _;
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
|
|
||||||
return 403;
|
return 403;
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,26 +1,46 @@
|
||||||
{ container, pkgs, util, ... } @args: let
|
{ container, pkgs, util, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.rabbitmq;
|
cfg = config.container.module.rabbitmq;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.rabbitmq = {
|
||||||
];
|
enable = mkEnableOption "Mqtt server.";
|
||||||
|
address = mkOption {
|
||||||
containers.rabbitmq = container.mkContainer cfg {
|
default = "10.1.0.28";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/rabbitmq" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
port = mkOption {
|
||||||
isReadOnly = false;
|
default = 5672;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/rabbitmq";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
services.rabbitmq = {
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
enable = true;
|
"data"
|
||||||
listenAddress = cfg.address;
|
];
|
||||||
port = cfg.port;
|
|
||||||
dataDir = "/var/lib/rabbitmq";
|
containers.rabbitmq = container.mkContainer cfg {
|
||||||
configItems = {
|
bindMounts = {
|
||||||
"loopback_users" = "none";
|
"/var/lib/rabbitmq" = {
|
||||||
|
hostPath = "${cfg.storage}/data";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.rabbitmq = {
|
||||||
|
enable = true;
|
||||||
|
listenAddress = cfg.address;
|
||||||
|
port = cfg.port;
|
||||||
|
dataDir = "/var/lib/rabbitmq";
|
||||||
|
configItems = {
|
||||||
|
"loopback_users" = "none";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,29 +1,53 @@
|
||||||
{ container, lib, pkgs, ... } @args: let
|
{ container, lib, pkgs, config, ... }: with lib; let
|
||||||
cfg = container.config.read;
|
cfg = config.container.module.read;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.read = {
|
||||||
];
|
enable = mkEnableOption "Reading server.";
|
||||||
|
address = mkOption {
|
||||||
containers.read = container.mkContainer cfg {
|
default = "10.1.0.39";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/kavita" = {
|
|
||||||
hostPath = "${cfg.storage}/data";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
};
|
||||||
}
|
port = mkOption {
|
||||||
// container.attachMedia "book" cfg.book true
|
default = 5000;
|
||||||
// container.attachMedia "manga" cfg.manga true
|
type = types.int;
|
||||||
;
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "read.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/read";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
services.kavita = {
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
enable = true;
|
"data"
|
||||||
dataDir = "/var/lib/kavita";
|
];
|
||||||
tokenKeyFile = pkgs.writeText "KavitaToken" "xY19aQOa939/Ie6GCRGbubVK8zRwrgBY/20AuyMpYshUjwK1Uyl7bw1yknVh6jJIFIfwq2vAjeotOUq7NEsf9Q==";
|
|
||||||
settings = {
|
containers.read = container.mkContainer cfg {
|
||||||
IpAddresses = cfg.address;
|
bindMounts = {
|
||||||
Port = cfg.port;
|
"/var/lib/kavita" = {
|
||||||
|
hostPath = "${cfg.storage}/data";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// container.attachMedia "book" true
|
||||||
|
// container.attachMedia "manga" true
|
||||||
|
;
|
||||||
|
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.kavita = {
|
||||||
|
enable = true;
|
||||||
|
dataDir = "/var/lib/kavita";
|
||||||
|
tokenKeyFile = pkgs.writeText "KavitaToken" "xY19aQOa939/Ie6GCRGbubVK8zRwrgBY/20AuyMpYshUjwK1Uyl7bw1yknVh6jJIFIfwq2vAjeotOUq7NEsf9Q==";
|
||||||
|
settings = {
|
||||||
|
IpAddresses = cfg.address;
|
||||||
|
Port = cfg.port;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,29 @@
|
||||||
{ container, pkgs, util, ... } @args: let
|
{ container, pkgs, util, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.redis;
|
cfg = config.container.module.redis;
|
||||||
in {
|
in {
|
||||||
containers.redis = container.mkContainer cfg {
|
options = {
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
container.module.redis = {
|
||||||
services.redis.servers.main = {
|
enable = mkEnableOption "Redis server.";
|
||||||
enable = true;
|
address = mkOption {
|
||||||
port = cfg.port;
|
default = "10.1.0.38";
|
||||||
bind = cfg.address;
|
type = types.str;
|
||||||
extraParams = [ "--protected-mode no" ];
|
};
|
||||||
|
port = mkOption {
|
||||||
|
default = 6379;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
containers.redis = container.mkContainer cfg {
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.redis.servers.main = {
|
||||||
|
enable = true;
|
||||||
|
port = cfg.port;
|
||||||
|
bind = cfg.address;
|
||||||
|
extraParams = [ "--protected-mode no" ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,16 +1,40 @@
|
||||||
{ container, pkgs, ... } @args: let
|
{ container, pkgs, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.search;
|
cfg = config.container.module.search;
|
||||||
in {
|
in {
|
||||||
containers.search = container.mkContainer cfg {
|
options = {
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
container.module.search = {
|
||||||
services.searx = {
|
enable = mkEnableOption "Search frontend.";
|
||||||
enable = true;
|
address = mkOption {
|
||||||
package = pkgs.searxng;
|
default = "10.1.0.26";
|
||||||
settings = {
|
type = types.str;
|
||||||
server = {
|
};
|
||||||
bind_address = cfg.address;
|
port = mkOption {
|
||||||
port = cfg.port;
|
default = 8080;
|
||||||
secret_key = "searxxx";
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "search.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/search";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
containers.search = container.mkContainer cfg {
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.searx = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.searxng;
|
||||||
|
settings = {
|
||||||
|
server = {
|
||||||
|
bind_address = cfg.address;
|
||||||
|
port = cfg.port;
|
||||||
|
secret_key = "searxxx";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,36 +1,60 @@
|
||||||
{ container, ... } @args: let
|
{ container, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.status;
|
cfg = config.container.module.status;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.status = {
|
||||||
];
|
enable = mkEnableOption "Status monitor.";
|
||||||
|
address = mkOption {
|
||||||
containers.status = container.mkContainer cfg {
|
default = "10.1.0.22";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/uptime-kuma" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
port = mkOption {
|
||||||
isReadOnly = false;
|
default = 3001;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "status.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/status";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { lib, ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
networking = {
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
nameservers = lib.mkForce [
|
"data"
|
||||||
container.config.dns.address
|
];
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.uptime-kuma = {
|
containers.status = container.mkContainer cfg {
|
||||||
enable = true;
|
bindMounts = {
|
||||||
settings = {
|
"/var/lib/uptime-kuma" = {
|
||||||
DATA_DIR = "/var/lib/uptime-kuma/";
|
hostPath = "${cfg.storage}/data";
|
||||||
HOST = cfg.address;
|
isReadOnly = false;
|
||||||
PORT = toString cfg.port;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.uptime-kuma = {
|
config = { lib, ... }: container.mkContainerConfig cfg {
|
||||||
serviceConfig.DynamicUser = lib.mkForce false;
|
networking = {
|
||||||
|
nameservers = mkForce [
|
||||||
|
config.container.module.dns.address
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.uptime-kuma = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
DATA_DIR = "/var/lib/uptime-kuma/";
|
||||||
|
HOST = cfg.address;
|
||||||
|
PORT = toString cfg.port;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.uptime-kuma = {
|
||||||
|
serviceConfig.DynamicUser = mkForce false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,31 +1,55 @@
|
||||||
{ container, ... } @args: let
|
{ container, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.stock;
|
cfg = config.container.module.stock;
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.stock = {
|
||||||
];
|
enable = mkEnableOption "Stock management.";
|
||||||
|
address = mkOption {
|
||||||
containers.stock = container.mkContainer cfg {
|
default = "10.1.0.45";
|
||||||
bindMounts = {
|
type = types.str;
|
||||||
"/var/lib/grocy" = {
|
};
|
||||||
hostPath = "${cfg.storage}/data";
|
port = mkOption {
|
||||||
isReadOnly = false;
|
default = 80;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "stock.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/stock";
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
services.grocy = {
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
enable = true;
|
"data"
|
||||||
dataDir = "/var/lib/grocy";
|
];
|
||||||
hostName = cfg.domain;
|
|
||||||
nginx.enableSSL = false;
|
containers.stock = container.mkContainer cfg {
|
||||||
settings = {
|
bindMounts = {
|
||||||
calendar = {
|
"/var/lib/grocy" = {
|
||||||
firstDayOfWeek = 1;
|
hostPath = "${cfg.storage}/data";
|
||||||
showWeekNumber = true;
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.grocy = {
|
||||||
|
enable = true;
|
||||||
|
dataDir = "/var/lib/grocy";
|
||||||
|
hostName = cfg.domain;
|
||||||
|
nginx.enableSSL = false;
|
||||||
|
settings = {
|
||||||
|
calendar = {
|
||||||
|
firstDayOfWeek = 1;
|
||||||
|
showWeekNumber = true;
|
||||||
|
};
|
||||||
|
culture = "en";
|
||||||
|
currency = "RUB";
|
||||||
};
|
};
|
||||||
culture = "en";
|
|
||||||
currency = "RUB";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,68 +1,90 @@
|
||||||
{ container, pkgs, ... } @args: let
|
{ container, pkgs, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.vpn;
|
cfg = config.container.module.vpn;
|
||||||
in {
|
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
wireguardPeers = let
|
||||||
"data"
|
mkPeer = name: ip: PublicKey: {
|
||||||
"data/preshared"
|
inherit PublicKey;
|
||||||
|
PresharedKeyFile = "/var/lib/wireguard/preshared/${name}";
|
||||||
|
AllowedIPs = [ "${ip}/32" ];
|
||||||
|
};
|
||||||
|
in [
|
||||||
|
(mkPeer "dashaphone" "10.1.1.3" "O/3y8+QKEY8UoLVlmbc8xdhs248L4wtQcl1MsBBfoQo=")
|
||||||
|
(mkPeer "laptop" "10.1.1.9" "xxoCNPSB86zs8L8p+wXhqaIwpNDkiZu1Yjv8sj8XhgY=")
|
||||||
|
(mkPeer "phone" "10.1.1.5" "bFmFisMqbDpIrAg3o/GiRl9XhceZEVnZtkegZDTL4yg=")
|
||||||
|
(mkPeer "tablet" "10.1.1.6" "BdslswVc9OgUpEhJd0sugDBmYw44DiS0FbUPT5EjOG0=")
|
||||||
|
(mkPeer "work" "10.1.1.2" "Pk0AASSInKO9O8RaQEmm1uNrl0cwWTJDcT8rLn7PSA0=")
|
||||||
];
|
];
|
||||||
|
in {
|
||||||
boot.kernel.sysctl = {
|
options = {
|
||||||
"net.ipv4.conf.all.src_valid_mark" = 1;
|
container.module.vpn = {
|
||||||
};
|
enable = mkEnableOption "Vpn server.";
|
||||||
|
address = mkOption {
|
||||||
containers.vpn = container.mkContainer cfg {
|
default = "10.1.0.23";
|
||||||
forwardPorts = [
|
type = types.str;
|
||||||
{
|
};
|
||||||
containerPort = cfg.port;
|
port = mkOption {
|
||||||
hostPort = cfg.port;
|
default = 51820;
|
||||||
protocol = "udp";
|
type = types.int;
|
||||||
}
|
};
|
||||||
];
|
storage = mkOption {
|
||||||
bindMounts = {
|
default = "${config.container.storage}/vpn";
|
||||||
"/var/lib/wireguard" = {
|
type = types.str;
|
||||||
hostPath = "${cfg.storage}/data";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
config = mkIf cfg.enable {
|
||||||
environment.systemPackages = with pkgs; [ wireguard-tools ];
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
networking.useNetworkd = true;
|
"data"
|
||||||
systemd.network = {
|
"data/preshared"
|
||||||
enable = true;
|
];
|
||||||
netdevs = {
|
|
||||||
"50-wg0" = {
|
boot.kernel.sysctl = {
|
||||||
netdevConfig = {
|
"net.ipv4.conf.all.src_valid_mark" = 1;
|
||||||
Kind = "wireguard";
|
};
|
||||||
MTUBytes = "1300";
|
|
||||||
Name = "wg0";
|
containers.vpn = container.mkContainer cfg {
|
||||||
};
|
forwardPorts = [
|
||||||
wireguardConfig = {
|
{
|
||||||
PrivateKeyFile = "/var/lib/wireguard/privkey";
|
containerPort = cfg.port;
|
||||||
ListenPort = cfg.port;
|
hostPort = cfg.port;
|
||||||
};
|
protocol = "udp";
|
||||||
wireguardPeers = let
|
}
|
||||||
mkPeer = name: ip: PublicKey: {
|
];
|
||||||
inherit PublicKey;
|
bindMounts = {
|
||||||
PresharedKeyFile = "/var/lib/wireguard/preshared/${name}";
|
"/var/lib/wireguard" = {
|
||||||
AllowedIPs = [ "${ip}/32" ];
|
hostPath = "${cfg.storage}/data";
|
||||||
};
|
isReadOnly = false;
|
||||||
in [
|
|
||||||
(mkPeer "dashaphone" "10.1.1.3" "O/3y8+QKEY8UoLVlmbc8xdhs248L4wtQcl1MsBBfoQo=")
|
|
||||||
(mkPeer "laptop" "10.1.1.9" "xxoCNPSB86zs8L8p+wXhqaIwpNDkiZu1Yjv8sj8XhgY=")
|
|
||||||
(mkPeer "phone" "10.1.1.5" "bFmFisMqbDpIrAg3o/GiRl9XhceZEVnZtkegZDTL4yg=")
|
|
||||||
(mkPeer "tablet" "10.1.1.6" "BdslswVc9OgUpEhJd0sugDBmYw44DiS0FbUPT5EjOG0=")
|
|
||||||
(mkPeer "work" "10.1.1.2" "Pk0AASSInKO9O8RaQEmm1uNrl0cwWTJDcT8rLn7PSA0=")
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
networks.wg0 = {
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
matchConfig.Name = "wg0";
|
environment.systemPackages = with pkgs; [ wireguard-tools ];
|
||||||
address = ["10.1.1.0/24"];
|
networking.useNetworkd = true;
|
||||||
networkConfig = {
|
systemd.network = {
|
||||||
IPForward = true;
|
enable = true;
|
||||||
IPMasquerade = "ipv4";
|
netdevs = {
|
||||||
|
"50-wg0" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Kind = "wireguard";
|
||||||
|
MTUBytes = "1300";
|
||||||
|
Name = "wg0";
|
||||||
|
};
|
||||||
|
wireguardConfig = {
|
||||||
|
PrivateKeyFile = "/var/lib/wireguard/privkey";
|
||||||
|
ListenPort = cfg.port;
|
||||||
|
};
|
||||||
|
inherit wireguardPeers;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networks.wg0 = {
|
||||||
|
matchConfig.Name = "wg0";
|
||||||
|
address = ["10.1.1.0/24"];
|
||||||
|
networkConfig = {
|
||||||
|
IPForward = true;
|
||||||
|
IPMasquerade = "ipv4";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,54 +1,81 @@
|
||||||
{ container, lib, ... } @args: let
|
{ container, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.watch;
|
cfg = config.container.module.watch;
|
||||||
memLimit = "8G";
|
|
||||||
in {
|
in {
|
||||||
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
options = {
|
||||||
"data"
|
container.module.watch = {
|
||||||
"cache"
|
enable = mkEnableOption "Media server.";
|
||||||
];
|
address = mkOption {
|
||||||
|
default = "10.1.0.11";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
port = mkOption {
|
||||||
|
default = 8096;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "watch.${config.container.domain}";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
storage = mkOption {
|
||||||
|
default = "${config.container.storage}/watch";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
memLimit = mkOption {
|
||||||
|
default = "8G";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
containers.watch = container.mkContainer cfg {
|
config = mkIf cfg.enable {
|
||||||
bindMounts = {
|
systemd.tmpfiles.rules = container.mkContainerDir cfg [
|
||||||
"/var/lib/jellyfin" = {
|
"data"
|
||||||
hostPath = "${cfg.storage}/data";
|
"cache"
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
"/var/cache/jellyfin" = {
|
|
||||||
hostPath = "${cfg.storage}/cache";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
"/dev/dri" = {
|
|
||||||
hostPath = "/dev/dri";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// container.attachMedia "anime" cfg.anime true
|
|
||||||
// container.attachMedia "download" cfg.download true
|
|
||||||
// container.attachMedia "movie" cfg.movie true
|
|
||||||
// container.attachMedia "music" cfg.music true
|
|
||||||
// container.attachMedia "photo" cfg.photo true
|
|
||||||
// container.attachMedia "porn" cfg.porn true
|
|
||||||
// container.attachMedia "show" cfg.show true
|
|
||||||
// container.attachMedia "study" cfg.study true
|
|
||||||
// container.attachMedia "work" cfg.work true
|
|
||||||
// container.attachMedia "youtube" cfg.youtube true
|
|
||||||
;
|
|
||||||
|
|
||||||
allowedDevices = [
|
|
||||||
{
|
|
||||||
modifier = "rwm";
|
|
||||||
node = "/dev/dri";
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
containers.watch = container.mkContainer cfg {
|
||||||
services.jellyfin = {
|
bindMounts = {
|
||||||
enable = true;
|
"/var/lib/jellyfin" = {
|
||||||
cacheDir = "/var/cache/jellyfin";
|
hostPath = "${cfg.storage}/data";
|
||||||
dataDir = "/var/lib/jellyfin";
|
isReadOnly = false;
|
||||||
};
|
};
|
||||||
|
"/var/cache/jellyfin" = {
|
||||||
|
hostPath = "${cfg.storage}/cache";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/dev/dri" = {
|
||||||
|
hostPath = "/dev/dri";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// container.attachMedia "anime" true
|
||||||
|
// container.attachMedia "download" true
|
||||||
|
// container.attachMedia "movie" true
|
||||||
|
// container.attachMedia "music" true
|
||||||
|
// container.attachMedia "photo" true
|
||||||
|
// container.attachMedia "porn" true
|
||||||
|
// container.attachMedia "show" true
|
||||||
|
// container.attachMedia "study" true
|
||||||
|
// container.attachMedia "work" true
|
||||||
|
// container.attachMedia "youtube" true
|
||||||
|
;
|
||||||
|
|
||||||
systemd.services.jellyfin.serviceConfig.MemoryLimit = memLimit;
|
allowedDevices = [
|
||||||
|
{
|
||||||
|
modifier = "rwm";
|
||||||
|
node = "/dev/dri";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.jellyfin = {
|
||||||
|
enable = true;
|
||||||
|
cacheDir = "/var/cache/jellyfin";
|
||||||
|
dataDir = "/var/lib/jellyfin";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.jellyfin.serviceConfig.MemoryLimit = cfg.memLimit;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,50 @@
|
||||||
{ container, pkgs, ... } @args: let
|
{ container, pkgs, lib, config, ... }: with lib; let
|
||||||
cfg = container.config.yt;
|
cfg = config.container.module.yt;
|
||||||
in {
|
in {
|
||||||
containers.yt = container.mkContainer cfg {
|
options = {
|
||||||
config = { ... }: container.mkContainerConfig cfg {
|
container.module.yt = {
|
||||||
services.invidious = {
|
enable = mkEnableOption "YouTube frontend.";
|
||||||
enable = true;
|
address = mkOption {
|
||||||
domain = cfg.domain;
|
default = "10.1.0.19";
|
||||||
port = cfg.port;
|
type = types.str;
|
||||||
nginx.enable = false;
|
};
|
||||||
database = {
|
port = mkOption {
|
||||||
port = container.config.postgres.port;
|
default = 3000;
|
||||||
host = container.config.postgres.address;
|
type = types.int;
|
||||||
createLocally = false;
|
};
|
||||||
passwordFile = "${pkgs.writeText "InvidiousDbPassword" "invidious"}";
|
domain = mkOption {
|
||||||
};
|
default = "yt.${config.container.domain}";
|
||||||
settings = {
|
type = types.str;
|
||||||
admins = [ "root" ];
|
};
|
||||||
captcha_enabled = false;
|
storage = mkOption {
|
||||||
check_tables = true;
|
default = "${config.container.storage}/yt";
|
||||||
registration_enabled = false;
|
type = types.str;
|
||||||
external_port = 443;
|
};
|
||||||
https_only = true;
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
containers.yt = container.mkContainer cfg {
|
||||||
|
config = { ... }: container.mkContainerConfig cfg {
|
||||||
|
services.invidious = {
|
||||||
|
enable = true;
|
||||||
|
domain = cfg.domain;
|
||||||
|
port = cfg.port;
|
||||||
|
nginx.enable = false;
|
||||||
|
database = {
|
||||||
|
port = config.container.module.postgres.port;
|
||||||
|
host = config.container.module.postgres.address;
|
||||||
|
createLocally = false;
|
||||||
|
passwordFile = "${pkgs.writeText "InvidiousDbPassword" "invidious"}";
|
||||||
|
};
|
||||||
|
settings = {
|
||||||
|
admins = [ "root" ];
|
||||||
|
captcha_enabled = false;
|
||||||
|
check_tables = true;
|
||||||
|
registration_enabled = false;
|
||||||
|
external_port = 443;
|
||||||
|
https_only = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,246 +1,55 @@
|
||||||
{ lib
|
{ lib, config, ... }: with lib; let
|
||||||
, const
|
cfg = config.container;
|
||||||
, host
|
in {
|
||||||
, storage
|
options = {
|
||||||
, domain
|
container = {
|
||||||
, media
|
enable = mkEnableOption "Containers!!";
|
||||||
, pkgs
|
|
||||||
, ... }: {
|
|
||||||
inherit host;
|
|
||||||
|
|
||||||
# Common configuration for all the containers.
|
autoStart = mkOption {
|
||||||
mkContainer = config: cfg: lib.recursiveUpdate {
|
default = true;
|
||||||
# Start containers with the system by default.
|
type = types.bool;
|
||||||
autoStart = true;
|
|
||||||
|
|
||||||
# IP Address of the host. This is required for container to have access to the Internet.
|
|
||||||
hostAddress = host;
|
|
||||||
|
|
||||||
# Container's IP address.
|
|
||||||
localAddress = config.address;
|
|
||||||
|
|
||||||
# Isolate container from other hosts.
|
|
||||||
privateNetwork = true;
|
|
||||||
} cfg;
|
|
||||||
|
|
||||||
# Common configuration for the system inside the container.
|
|
||||||
mkContainerConfig = config: cfg: lib.recursiveUpdate {
|
|
||||||
# HACK: Do not evaluate nixpkgs inside the container. Use host's instead.
|
|
||||||
nixpkgs.pkgs = lib.mkForce pkgs;
|
|
||||||
|
|
||||||
# Release version.
|
|
||||||
system.stateVersion = const.stateVersion;
|
|
||||||
|
|
||||||
# Allow passwordless login as root.
|
|
||||||
users.users.root.password = "";
|
|
||||||
users.mutableUsers = false;
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
# Default DNS servers.
|
|
||||||
nameservers = [
|
|
||||||
"1.1.1.1"
|
|
||||||
];
|
|
||||||
|
|
||||||
# HACK: Fix for upstream issue: https://github.com/NixOS/nixpkgs/issues/162686
|
|
||||||
useHostResolvConf = lib.mkForce false;
|
|
||||||
|
|
||||||
# Disable firewall.
|
|
||||||
firewall.enable = false;
|
|
||||||
};
|
|
||||||
} cfg;
|
|
||||||
|
|
||||||
# Create a directory on the host for container use.
|
|
||||||
mkContainerDir = cfg: dirs: map (path: "d '${cfg.storage}/${path}' 1777 root root - -") dirs;
|
|
||||||
|
|
||||||
# Common configuration for Nginx server.
|
|
||||||
mkServer = cfg: lib.recursiveUpdate {
|
|
||||||
forceSSL = false;
|
|
||||||
} cfg;
|
|
||||||
|
|
||||||
# Attach the host media directory to container.
|
|
||||||
# They will be added to /type/{0..9}
|
|
||||||
attachMedia = type: paths: ro: builtins.listToAttrs (lib.imap0 (i: path:
|
|
||||||
{
|
|
||||||
name = "/${type}/${toString i}";
|
|
||||||
value = {
|
|
||||||
hostPath = path;
|
|
||||||
isReadOnly = ro;
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
) paths);
|
|
||||||
|
|
||||||
# Range of local addresses who have access to sensitive paths like admin panels.
|
host = mkOption {
|
||||||
# Other addresses will get 403.
|
default = "0.0.0.0";
|
||||||
localAccess = "192.168.1.0/24";
|
type = types.str;
|
||||||
|
};
|
||||||
|
|
||||||
# Per-container configurations.
|
localAccess = mkOption {
|
||||||
config = {
|
default = "0.0.0.0";
|
||||||
camera = {
|
type = types.str;
|
||||||
address = "192.168.2.249";
|
};
|
||||||
domain = "camera.${domain}";
|
|
||||||
port = "554";
|
storage = mkOption {
|
||||||
|
default = "/tmp/container";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
|
||||||
|
domain = mkOption {
|
||||||
|
default = "local";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface = mkOption {
|
||||||
|
default = "lo";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
|
||||||
|
media = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrs;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
change = {
|
};
|
||||||
address = "10.1.0.41";
|
|
||||||
port = 5000;
|
config = mkIf cfg.enable {
|
||||||
domain = "change.${domain}";
|
# This is the network for all the containers.
|
||||||
storage = "${storage}/change";
|
# They are not available to the external interface by default,
|
||||||
};
|
# instead they all expose specific ports in their configuration.
|
||||||
cloud = {
|
networking.nat = {
|
||||||
address = "10.1.0.13";
|
enable = true;
|
||||||
port = 80;
|
internalInterfaces = [ "ve-+" ];
|
||||||
domain = "cloud.${domain}";
|
externalInterface = config.container.interface;
|
||||||
storage = "${storage}/cloud";
|
|
||||||
};
|
|
||||||
ddns = {
|
|
||||||
address = "10.1.0.31";
|
|
||||||
port = 53;
|
|
||||||
storage = "${storage}/ddns";
|
|
||||||
};
|
|
||||||
dns = {
|
|
||||||
address = "10.1.0.6";
|
|
||||||
};
|
|
||||||
download = {
|
|
||||||
inherit (media) download;
|
|
||||||
address = "10.1.0.12";
|
|
||||||
port = 8112;
|
|
||||||
domain = "download.${domain}";
|
|
||||||
storage = "${storage}/download";
|
|
||||||
};
|
|
||||||
git = {
|
|
||||||
address = "10.1.0.8";
|
|
||||||
port = 3000;
|
|
||||||
domain = "git.${domain}";
|
|
||||||
storage = "${storage}/git";
|
|
||||||
};
|
|
||||||
hdd = {
|
|
||||||
address = "10.1.0.10";
|
|
||||||
port = 8080;
|
|
||||||
domain = "hdd.${domain}";
|
|
||||||
storage = "${storage}/hdd";
|
|
||||||
};
|
|
||||||
home = {
|
|
||||||
address = "10.1.0.18";
|
|
||||||
port = 80;
|
|
||||||
domain = "home.${domain}";
|
|
||||||
};
|
|
||||||
iot = {
|
|
||||||
inherit (media) photo;
|
|
||||||
address = "10.1.0.27";
|
|
||||||
domain = "iot.${domain}";
|
|
||||||
port = 8123;
|
|
||||||
storage = "${storage}/iot";
|
|
||||||
};
|
|
||||||
jobber = {
|
|
||||||
address = "10.1.0.32";
|
|
||||||
storage = "${storage}/jobber";
|
|
||||||
};
|
|
||||||
mail = {
|
|
||||||
address = "10.1.0.5";
|
|
||||||
domain = "mail.${domain}";
|
|
||||||
port = 80;
|
|
||||||
storage = "${storage}/mail";
|
|
||||||
};
|
|
||||||
office = {
|
|
||||||
address = "10.1.0.21";
|
|
||||||
domain = "office.${domain}";
|
|
||||||
port = 8000;
|
|
||||||
storage = "${storage}/office";
|
|
||||||
};
|
|
||||||
paper = {
|
|
||||||
inherit (media) paper;
|
|
||||||
address = "10.1.0.40";
|
|
||||||
domain = "paper.${domain}";
|
|
||||||
port = 28981;
|
|
||||||
storage = "${storage}/paper";
|
|
||||||
};
|
|
||||||
pass = {
|
|
||||||
address = "10.1.0.9";
|
|
||||||
domain = "pass.${domain}";
|
|
||||||
port = 8000;
|
|
||||||
storage = "${storage}/pass";
|
|
||||||
};
|
|
||||||
paste = {
|
|
||||||
address = "10.1.0.14";
|
|
||||||
domain = "paste.${domain}";
|
|
||||||
port = 80;
|
|
||||||
storage = "${storage}/paste";
|
|
||||||
};
|
|
||||||
print = {
|
|
||||||
domain = "print.${domain}";
|
|
||||||
address = "10.1.0.46";
|
|
||||||
port = 631;
|
|
||||||
storage = "${storage}/print";
|
|
||||||
};
|
|
||||||
printer = {
|
|
||||||
address = "192.168.2.237";
|
|
||||||
domain = "printer.${domain}";
|
|
||||||
port = 80;
|
|
||||||
};
|
|
||||||
proxy = {
|
|
||||||
address = "10.1.0.2";
|
|
||||||
port = 443;
|
|
||||||
storage = "${storage}/proxy";
|
|
||||||
};
|
|
||||||
postgres = {
|
|
||||||
address = "10.1.0.3";
|
|
||||||
port = 5432;
|
|
||||||
storage = "${storage}/postgres";
|
|
||||||
};
|
|
||||||
rabbitmq = {
|
|
||||||
address = "10.1.0.28";
|
|
||||||
port = 5672;
|
|
||||||
storage = "${storage}/rabbitmq";
|
|
||||||
};
|
|
||||||
read = {
|
|
||||||
inherit (media) book manga;
|
|
||||||
address = "10.1.0.39";
|
|
||||||
domain = "read.${domain}";
|
|
||||||
port = 5000;
|
|
||||||
storage = "${storage}/read";
|
|
||||||
};
|
|
||||||
redis = {
|
|
||||||
address = "10.1.0.38";
|
|
||||||
port = 6379;
|
|
||||||
};
|
|
||||||
router = {
|
|
||||||
address = "192.168.1.1";
|
|
||||||
domain = "router.${domain}";
|
|
||||||
port = 80;
|
|
||||||
};
|
|
||||||
search = {
|
|
||||||
address = "10.1.0.26";
|
|
||||||
domain = "search.${domain}";
|
|
||||||
port = 8080;
|
|
||||||
};
|
|
||||||
status = {
|
|
||||||
address = "10.1.0.22";
|
|
||||||
domain = "status.${domain}";
|
|
||||||
port = 3001;
|
|
||||||
storage = "${storage}/status";
|
|
||||||
};
|
|
||||||
stock = {
|
|
||||||
address = "10.1.0.45";
|
|
||||||
domain = "stock.${domain}";
|
|
||||||
port = 80;
|
|
||||||
storage = "${storage}/stock";
|
|
||||||
};
|
|
||||||
vpn = {
|
|
||||||
address = "10.1.0.23";
|
|
||||||
port = 51820;
|
|
||||||
storage = "${storage}/vpn";
|
|
||||||
};
|
|
||||||
watch = {
|
|
||||||
inherit (media) anime download movie music photo porn show study work youtube;
|
|
||||||
address = "10.1.0.11";
|
|
||||||
domain = "watch.${domain}";
|
|
||||||
port = 8096;
|
|
||||||
storage = "${storage}/watch";
|
|
||||||
};
|
|
||||||
yt = {
|
|
||||||
address = "10.1.0.19";
|
|
||||||
domain = "yt.${domain}";
|
|
||||||
port = 3000;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ pkgs, container, ... }: let
|
{ pkgs, config, ... }: let
|
||||||
iconTheme = "fa-solid";
|
iconTheme = "fa-solid";
|
||||||
|
|
||||||
mkGroup = name: icon: items: {
|
mkGroup = name: icon: items: {
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
target = "_blank";
|
target = "_blank";
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
cfg = {
|
||||||
title = "Dashboard";
|
title = "Dashboard";
|
||||||
subtitle = "Home";
|
subtitle = "Home";
|
||||||
header = false;
|
header = false;
|
||||||
|
@ -41,33 +41,32 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
links = [
|
links = [
|
||||||
(mkLink "Status" "fa-heartbeat" "https://status.voronind.com")
|
(mkLink "Status" "fa-heartbeat" "https://${config.container.module.status.domain}")
|
||||||
];
|
];
|
||||||
|
|
||||||
services = [
|
services = [
|
||||||
(mkGroup "App" "fa-server" [
|
(mkGroup "App" "fa-server" [
|
||||||
(mkLink "Change" "fa-user-secret" "https://${container.config.change.domain}")
|
(mkLink "Change" "fa-user-secret" "https://${config.container.module.change.domain}")
|
||||||
(mkLink "Cloud" "fa-cloud" "https://${container.config.cloud.domain}")
|
(mkLink "Cloud" "fa-cloud" "https://${config.container.module.cloud.domain}")
|
||||||
(mkLink "Download" "fa-download" "https://${container.config.download.domain}")
|
(mkLink "Download" "fa-download" "https://${config.container.module.download.domain}")
|
||||||
(mkLink "Git" "fab fa-git-alt" "https://${container.config.download.domain}")
|
(mkLink "Git" "fab fa-git-alt" "https://${config.container.module.download.domain}")
|
||||||
(mkLink "Iot" "fa-home" "https://${container.config.iot.domain}")
|
(mkLink "Iot" "fa-home" "https://${config.container.module.iot.domain}")
|
||||||
(mkLink "Mail" "fa-envelope" "https://${container.config.mail.domain}")
|
(mkLink "Mail" "fa-envelope" "https://${config.container.module.mail.domain}")
|
||||||
(mkLink "Paper" "fa-paperclip" "https://${container.config.paper.domain}")
|
(mkLink "Paper" "fa-paperclip" "https://${config.container.module.paper.domain}")
|
||||||
(mkLink "Pass" "fa-key" "https://${container.config.pass.domain}")
|
(mkLink "Pass" "fa-key" "https://${config.container.module.pass.domain}")
|
||||||
(mkLink "Paste" "fa-paste" "https://${container.config.paste.domain}/s")
|
(mkLink "Paste" "fa-paste" "https://${config.container.module.paste.domain}/s")
|
||||||
(mkLink "Print" "fa-print" "https://${container.config.print.domain}")
|
(mkLink "Print" "fa-print" "https://${config.container.module.print.domain}")
|
||||||
(mkLink "Read" "fa-book" "https://${container.config.read.domain}")
|
(mkLink "Read" "fa-book" "https://${config.container.module.read.domain}")
|
||||||
(mkLink "Search" "fa-search" "https://${container.config.search.domain}")
|
(mkLink "Search" "fa-search" "https://${config.container.module.search.domain}")
|
||||||
(mkLink "Stock" "fa-boxes-stacked" "https://${container.config.stock.domain}")
|
(mkLink "Stock" "fa-boxes-stacked" "https://${config.container.module.stock.domain}")
|
||||||
(mkLink "Watch" "fa-film" "https://${container.config.watch.domain}")
|
(mkLink "Watch" "fa-film" "https://${config.container.module.watch.domain}")
|
||||||
(mkLink "YouTube" "fab fa-youtube" "https://${container.config.yt.domain}")
|
(mkLink "YouTube" "fab fa-youtube" "https://${config.container.module.yt.domain}")
|
||||||
])
|
])
|
||||||
(mkGroup "System" "fa-shield" [
|
(mkGroup "System" "fa-shield" [
|
||||||
(mkLink "Camera" "fa-camera" "https://${container.config.camera.domain}")
|
(mkLink "Camera" "fa-camera" "https://camera.${config.container.domain}")
|
||||||
# (mkLink "Hdd" "fa-hard-drive" "https://${container.config.hdd.domain}")
|
|
||||||
(mkLink "NixOS Search" "fa-snowflake" "https://search.nixos.org")
|
(mkLink "NixOS Search" "fa-snowflake" "https://search.nixos.org")
|
||||||
(mkLink "Printer" "fa-print" "https://${container.config.printer.domain}")
|
(mkLink "Printer" "fa-print" "https://printer.${config.container.domain}")
|
||||||
(mkLink "Router" "fa-route" "https://${container.config.router.domain}")
|
(mkLink "Router" "fa-route" "https://router.${config.container.domain}")
|
||||||
])
|
])
|
||||||
(mkGroup "Bookmark" "fa-bookmark" [
|
(mkGroup "Bookmark" "fa-bookmark" [
|
||||||
(mkLink "2gis" "fa-map-location-dot" "https://2gis.ru")
|
(mkLink "2gis" "fa-map-location-dot" "https://2gis.ru")
|
||||||
|
@ -96,5 +95,5 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
file = (pkgs.formats.yaml {}).generate "HomerConfig" config;
|
file = (pkgs.formats.yaml {}).generate "HomerConfig" cfg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ stdenv, pkgs, ... } @args: let
|
{ stdenv, pkgs, config, ... } @args: let
|
||||||
cfg = (import ./Config.nix args).file;
|
cfg = (import ./Config.nix args).file;
|
||||||
in stdenv.mkDerivation (finalAttrs: {
|
in stdenv.mkDerivation (finalAttrs: {
|
||||||
pname = "Homer";
|
pname = "Homer";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ util, container, ... }: {
|
{ util, config, ... }: {
|
||||||
text = util.trimTabs ''
|
text = util.trimTabs ''
|
||||||
;<?php http_response_code(403); /*
|
;<?php http_response_code(403); /*
|
||||||
; config file for PrivateBin
|
; config file for PrivateBin
|
||||||
|
@ -220,7 +220,7 @@
|
||||||
; example of DB configuration for PostgreSQL
|
; example of DB configuration for PostgreSQL
|
||||||
class = Database
|
class = Database
|
||||||
[model_options]
|
[model_options]
|
||||||
dsn = "pgsql:host=${container.config.postgres.address};dbname=privatebin"
|
dsn = "pgsql:host=${config.container.module.postgres.address};dbname=privatebin"
|
||||||
tbl = "privatebin_" ; table prefix
|
tbl = "privatebin_" ; table prefix
|
||||||
usr = "privatebin"
|
usr = "privatebin"
|
||||||
pwd = "privatebin"
|
pwd = "privatebin"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ php, pkgs, util, ... } @args: let
|
{ php, pkgs, util, config, ... } @args: let
|
||||||
cfg = pkgs.writeText "PrivateBinConfig" (import ./Config.nix args).text;
|
cfg = pkgs.writeText "PrivateBinConfig" (import ./Config.nix args).text;
|
||||||
in php.buildComposerProject (finalAttrs: {
|
in php.buildComposerProject (finalAttrs: {
|
||||||
pname = "PrivateBin";
|
pname = "PrivateBin";
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, config, lib, container, ... }: let
|
||||||
cfg = container.config.camera;
|
domain = "camera.${config.container.domain}";
|
||||||
|
address = "192.168.2.249";
|
||||||
|
port = 554;
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${domain} = container.mkServer {
|
||||||
extraConfig = util.trimTabs ''
|
extraConfig = util.trimTabs ''
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
return 301 rtsp://${cfg.address}:${cfg.port}/live/main;
|
return 301 rtsp://${address}:${toString port}/live/main;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, config, container, ... }: let
|
||||||
cfg = container.config.change;
|
cfg = config.container.module.change;
|
||||||
name = "change";
|
name = "change";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,9 +8,9 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
|
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
|
@ -18,8 +18,8 @@ in {
|
||||||
add_header Referrer-Policy 'origin';
|
add_header Referrer-Policy 'origin';
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, config, container, ... }: let
|
||||||
cfg = container.config.cloud;
|
cfg = config.container.module.cloud;
|
||||||
name = "cloud";
|
name = "cloud";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,9 +8,9 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location ~ ^/(settings/admin|settings/users|settings/apps|login|api) {
|
location ~ ^/(settings/admin|settings/users|settings/apps|login|api) {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ in {
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, config, container, ... }: let
|
||||||
cfg = container.config.download;
|
cfg = config.container.module.download;
|
||||||
name = "download";
|
name = "download";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.git;
|
cfg = config.container.module.git;
|
||||||
name = "git";
|
name = "git";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location ~ ^/(admin|api|user) {
|
location ~ ^/(admin|api|user) {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /markdown {
|
location /markdown {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
|
|
||||||
proxy_set_header Content-Type "application/json";
|
proxy_set_header Content-Type "application/json";
|
||||||
|
@ -29,15 +29,15 @@ in {
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
# allow ${container.localAccess};
|
# allow ${config.container.localAccess};
|
||||||
# allow ${container.config.status.address};
|
# allow ${config.container.module.status.address};
|
||||||
# allow ${container.config.vpn.address};
|
# allow ${config.container.module.vpn.address};
|
||||||
# deny all;
|
# deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.hdd;
|
cfg = config.container.module.hdd;
|
||||||
name = "hdd";
|
name = "hdd";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, config, container, ... }: let
|
||||||
cfg = container.config.home;
|
cfg = config.container.module.home;
|
||||||
name = "home";
|
name = "home";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.iot;
|
cfg = config.container.module.iot;
|
||||||
name = "iot";
|
name = "iot";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,9 +8,9 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
|
|
||||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
@ -22,8 +22,8 @@ in {
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.mail;
|
cfg = config.container.module.mail;
|
||||||
name = "mail";
|
name = "mail";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.office;
|
cfg = config.container.module.office;
|
||||||
name = "office";
|
name = "office";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,16 +8,16 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
# allow ${container.localAccess};
|
# allow ${config.container.localAccess};
|
||||||
# allow ${container.config.status.address};
|
# allow ${config.container.module.status.address};
|
||||||
# allow ${container.config.vpn.address};
|
# allow ${config.container.module.vpn.address};
|
||||||
# deny all;
|
# deny all;
|
||||||
add_header X-Forwarded-Proto https;
|
add_header X-Forwarded-Proto https;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.paper;
|
cfg = config.container.module.paper;
|
||||||
name = "paper";
|
name = "paper";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.pass;
|
cfg = config.container.module.pass;
|
||||||
name = "pass";
|
name = "pass";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.paste;
|
cfg = config.container.module.paste;
|
||||||
name = "paste";
|
name = "paste";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -15,8 +15,8 @@ in {
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.print;
|
cfg = config.container.module.print;
|
||||||
name = "print";
|
name = "print";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,9 +8,9 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
|
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
|
@ -20,8 +20,8 @@ in {
|
||||||
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.printer;
|
address = "192.168.2.237";
|
||||||
name = "printer";
|
domain = "printer.${config.container.domain}";
|
||||||
|
port = 80;
|
||||||
|
name = "printer";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${domain} = container.mkServer {
|
||||||
extraConfig = util.trimTabs ''
|
extraConfig = util.trimTabs ''
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${address}:${toString port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.read;
|
cfg = config.container.module.read;
|
||||||
name = "read";
|
name = "read";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.router;
|
address = "192.168.1.1";
|
||||||
name = "router";
|
domain = "router.${config.container.domain}";
|
||||||
|
port = 80;
|
||||||
|
name = "router";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${domain} = container.mkServer {
|
||||||
extraConfig = util.trimTabs ''
|
extraConfig = util.trimTabs ''
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${address}:${toString port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.search;
|
cfg = config.container.module.search;
|
||||||
name = "search";
|
name = "search";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.status;
|
cfg = config.container.module.status;
|
||||||
name = "sstatus";
|
name = "sstatus";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,21 +8,21 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location ~ ^/(dashboard|settings) {
|
location ~ ^/(dashboard|settings) {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.stock;
|
cfg = config.container.module.stock;
|
||||||
name = "stock";
|
name = "stock";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.watch;
|
cfg = config.container.module.watch;
|
||||||
name = "watch";
|
name = "watch";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,15 +8,15 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{ domain, util, container, ... }: let
|
{ util, container, config, ... }: let
|
||||||
cfg = container.config.yt;
|
cfg = config.container.module.yt;
|
||||||
name = "yt";
|
name = "yt";
|
||||||
in {
|
in {
|
||||||
${cfg.domain} = container.mkServer {
|
${cfg.domain} = container.mkServer {
|
||||||
|
@ -8,9 +8,9 @@ in {
|
||||||
set ''$${name} ${cfg.address}:${toString cfg.port};
|
set ''$${name} ${cfg.address}:${toString cfg.port};
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
allow ${container.localAccess};
|
allow ${config.container.localAccess};
|
||||||
allow ${container.config.status.address};
|
allow ${config.container.module.status.address};
|
||||||
allow ${container.config.vpn.address};
|
allow ${config.container.module.vpn.address};
|
||||||
deny all;
|
deny all;
|
||||||
|
|
||||||
proxy_pass http://''$${name}$request_uri;
|
proxy_pass http://''$${name}$request_uri;
|
||||||
|
@ -25,8 +25,8 @@ in {
|
||||||
proxy_hide_header X-Content-Type-Options;
|
proxy_hide_header X-Content-Type-Options;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/${config.container.domain}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/${config.container.domain}/privkey.pem;
|
||||||
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
|
||||||
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
|
||||||
'';
|
'';
|
||||||
|
|
255
flake.nix
255
flake.nix
|
@ -137,182 +137,85 @@
|
||||||
url = "https://git.voronind.com/voronind/nixos.git";
|
url = "https://git.voronind.com/voronind/nixos.git";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Common modules used across all the hosts.
|
nixosConfigurations = let
|
||||||
nixosModules.common = let
|
# List all files in a dir.
|
||||||
# This function allows me to get the list of all the files from the directories I need.
|
|
||||||
# It differs from the util.ls function because it also filters out all the directories.
|
|
||||||
lsFiles = path: map (f: "${path}/${f}") (
|
lsFiles = path: map (f: "${path}/${f}") (
|
||||||
builtins.filter (i: builtins.readFileType "${path}/${i}" == "regular") (
|
builtins.filter (i: builtins.readFileType "${path}/${i}" == "regular") (
|
||||||
builtins.attrNames (builtins.readDir path)
|
builtins.attrNames (builtins.readDir path)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
in {
|
|
||||||
# Here I import everything from those directories.
|
|
||||||
imports = (lsFiles ./module/common) ++ (lsFiles ./overlay) ++ [
|
|
||||||
./part/Setting.nix
|
|
||||||
./user/Root.nix
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Function to create a host. It does basic setup, like adding common modules.
|
# Function to create a host. It does basic setup, like adding common modules.
|
||||||
mkHost = { system, hostname, modules } @args: nixpkgs.lib.nixosSystem {
|
mkHost = { system, hostname, modules } @args: nixpkgs.lib.nixosSystem {
|
||||||
# `Inherit` is just an alias for `system = system;`, which means that
|
# `Inherit` is just an alias for `system = system;`, which means that
|
||||||
# keep the `system` argument as a property in a resulting set.
|
# keep the `system` argument as a property in a resulting set.
|
||||||
inherit system;
|
inherit system;
|
||||||
|
|
||||||
# List of modules to use by defualt for all the hosts.
|
# List of modules to use by defualt for all the hosts.
|
||||||
modules = [
|
modules = modules ++ [
|
||||||
# There I put host-specific configurations.
|
# There I put host-specific configurations.
|
||||||
./host/${hostname}
|
./host/${hostname}
|
||||||
|
|
||||||
# Make a device hostname match the one from this config.
|
# Make a device hostname match the one from this config.
|
||||||
{ networking.hostName = hostname; }
|
{ networking.hostName = hostname; }
|
||||||
|
|
||||||
# Specify current release version.
|
# Specify current release version.
|
||||||
{ system.stateVersion = self.const.stateVersion; }
|
{ system.stateVersion = self.const.stateVersion; }
|
||||||
|
|
||||||
# Add common modules.
|
# Add modules.
|
||||||
inputs.self.nixosModules.common
|
{ imports =
|
||||||
|
(lsFiles ./container) ++
|
||||||
|
(lsFiles ./module) ++
|
||||||
|
(lsFiles ./module/common) ++
|
||||||
|
(lsFiles ./module/desktop) ++
|
||||||
|
(lsFiles ./overlay) ++
|
||||||
|
(lsFiles ./user);
|
||||||
|
}
|
||||||
|
|
||||||
# Add Home Manager module.
|
# Add Home Manager module.
|
||||||
home-manager.nixosModules.home-manager
|
home-manager.nixosModules.home-manager
|
||||||
|
|
||||||
# Add Stylix module.
|
# Add Stylix module.
|
||||||
stylix.nixosModules.stylix
|
stylix.nixosModules.stylix
|
||||||
]
|
];
|
||||||
# Also add host-specific modules from mkHost args.
|
|
||||||
++ modules;
|
|
||||||
|
|
||||||
# SpecialArgs allows you to pass objects down to other NixOS modules.
|
# SpecialArgs allows you to pass objects down to other NixOS modules.
|
||||||
specialArgs = let
|
specialArgs = let
|
||||||
pkgs = nixpkgs.legacyPackages.${system}.pkgs;
|
pkgs = nixpkgs.legacyPackages.${system}.pkgs;
|
||||||
lib = nixpkgs.lib;
|
lib = nixpkgs.lib;
|
||||||
config = self.nixosConfigurations.${hostname}.config;
|
config = self.nixosConfigurations.${hostname}.config;
|
||||||
|
|
||||||
pkgsJobber = nixpkgsJobber.legacyPackages.${system}.pkgs;
|
pkgsJobber = nixpkgsJobber.legacyPackages.${system}.pkgs;
|
||||||
pkgsStable = nixpkgsJobber.legacyPackages.${system}.pkgs;
|
pkgsStable = nixpkgsJobber.legacyPackages.${system}.pkgs;
|
||||||
pkgsMaster = nixpkgsJobber.legacyPackages.${system}.pkgs;
|
pkgsMaster = nixpkgsJobber.legacyPackages.${system}.pkgs;
|
||||||
in {
|
|
||||||
const = self.const; # Constant values.
|
|
||||||
flake = self; # This Flake itself.
|
|
||||||
inputs = inputs; # Our dependencies.
|
|
||||||
secret = import ./part/Secret.nix {}; # Secrets (public keys).
|
|
||||||
style = import ./part/Style.nix { inherit config; }; # Style abstraction.
|
|
||||||
util = import ./part/Util.nix { inherit pkgs lib; }; # Util functions.
|
|
||||||
wallpaper = import ./part/Wallpaper.nix { inherit pkgs; }; # Wallpaper.
|
|
||||||
|
|
||||||
# Stable and Master pkgs.
|
secret = import ./secret {}; # Secrets (public keys).
|
||||||
inherit pkgsStable pkgsMaster;
|
container = import ./lib/Container.nix { inherit lib pkgs config; inherit (self) const; }; # Container utils.
|
||||||
|
util = import ./lib/Util.nix { inherit pkgs lib; }; # Util functions.
|
||||||
|
in {
|
||||||
|
flake = self;
|
||||||
|
|
||||||
# Stuff for Jobber container, skip this part.
|
inherit secret container util inputs;
|
||||||
inherit poetry2nixJobber pkgsJobber;
|
inherit (self) const;
|
||||||
|
|
||||||
|
# Stable and Master pkgs.
|
||||||
|
inherit pkgsStable pkgsMaster;
|
||||||
|
|
||||||
|
# Stuff for Jobber container, skip this part.
|
||||||
|
inherit poetry2nixJobber pkgsJobber;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
# Bellow is the list of all the hosts I currently use.
|
mkSystem = hostname: system: modules: {
|
||||||
# They call the `mkHost` function that I defined above
|
"${hostname}" = mkHost {
|
||||||
# with their specific parameters.
|
inherit hostname system modules;
|
||||||
# You might be interested in `live` and `nixOnDroidConfiguration`
|
};
|
||||||
# for Live ISO and Android configurations respectively.
|
};
|
||||||
nixosConfigurations.basic = self.mkHost {
|
|
||||||
hostname = "basic"; # Hostname to use.
|
|
||||||
system = "x86_64-linux"; # System architecture.
|
|
||||||
|
|
||||||
# Host-specific modules.
|
liveModules = [
|
||||||
modules = [
|
|
||||||
# Force LTS kernel.
|
|
||||||
({ pkgs, ... }: { boot.kernelPackages = nixpkgs.lib.mkForce pkgs.linuxPackages; })
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosConfigurations.dasha = self.mkHost {
|
|
||||||
hostname = "dasha";
|
|
||||||
system = "x86_64-linux";
|
|
||||||
modules = [
|
|
||||||
./module/AmdGpu.nix
|
|
||||||
./module/CapsToggle.nix
|
|
||||||
# ./module/Gnome.nix
|
|
||||||
./module/IntelCpu.nix
|
|
||||||
./module/PowersaveIntel.nix
|
|
||||||
./module/Print.nix
|
|
||||||
./module/RemoteBuild.nix
|
|
||||||
./module/StrongSwan.nix
|
|
||||||
./module/Sway.nix
|
|
||||||
./module/Tablet.nix
|
|
||||||
./user/Dasha.nix
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosConfigurations.desktop = self.mkHost {
|
|
||||||
hostname = "desktop";
|
|
||||||
system = "x86_64-linux";
|
|
||||||
modules = [
|
|
||||||
./module/AmdCompute.nix
|
|
||||||
./module/AmdCpu.nix
|
|
||||||
./module/AmdGpu.nix
|
|
||||||
./module/Docker.nix
|
|
||||||
./module/Ollama.nix
|
|
||||||
./module/PowersaveAmd.nix
|
|
||||||
./module/Print.nix
|
|
||||||
./module/RemoteBuild.nix
|
|
||||||
./module/Sway.nix
|
|
||||||
./module/VirtManager.nix
|
|
||||||
./user/Voronind.nix
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosConfigurations.fsight = self.mkHost {
|
|
||||||
hostname = "fsight";
|
|
||||||
system = "x86_64-linux";
|
|
||||||
modules = [
|
|
||||||
./module/Docker.nix
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosConfigurations.home = self.mkHost {
|
|
||||||
hostname = "home";
|
|
||||||
system = "x86_64-linux";
|
|
||||||
modules = [
|
|
||||||
./module/AmdCpu.nix
|
|
||||||
./module/AmdGpu.nix
|
|
||||||
./module/Ftpd.nix
|
|
||||||
./module/RemoteBuilder.nix
|
|
||||||
./module/Sway.nix
|
|
||||||
./user/Voronind.nix
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosConfigurations.laptop = self.mkHost {
|
|
||||||
hostname = "laptop";
|
|
||||||
system = "x86_64-linux";
|
|
||||||
modules = [
|
|
||||||
./module/AmdCpu.nix
|
|
||||||
./module/AmdGpu.nix
|
|
||||||
./module/CapsToggle.nix
|
|
||||||
./module/Gnome.nix
|
|
||||||
./module/PowersaveAmd.nix
|
|
||||||
./module/Print.nix
|
|
||||||
./module/RemoteBuild.nix
|
|
||||||
./module/StrongSwan.nix
|
|
||||||
./module/Tablet.nix
|
|
||||||
./user/Dasha.nix
|
|
||||||
./user/Voronind.nix
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Live ISO configuration.
|
|
||||||
nixosConfigurations.live = self.mkHost {
|
|
||||||
hostname = "live";
|
|
||||||
system = "x86_64-linux";
|
|
||||||
modules = [
|
|
||||||
# Those are basic modules for Live ISO image.
|
|
||||||
# You can discover other possible base images here:
|
|
||||||
# https://github.com/NixOS/nixpkgs/tree/master/nixos/modules/installer/cd-dvd
|
|
||||||
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
|
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
|
||||||
"${nixpkgs}/nixos/modules/installer/cd-dvd/channel.nix"
|
"${nixpkgs}/nixos/modules/installer/cd-dvd/channel.nix"
|
||||||
|
|
||||||
# This is required for Live ISO in my case because I use NetworkManager,
|
|
||||||
# but base Live images require this.
|
|
||||||
{ networking.wireless.enable = nixpkgs.lib.mkForce false; }
|
{ networking.wireless.enable = nixpkgs.lib.mkForce false; }
|
||||||
|
|
||||||
# Override my settings to allow SSH logins using root password.
|
# Override my settings to allow SSH logins using root password.
|
||||||
|
@ -320,27 +223,29 @@
|
||||||
{ services.openssh.settings.PermitRootLogin = nixpkgs.lib.mkForce "yes"; }
|
{ services.openssh.settings.PermitRootLogin = nixpkgs.lib.mkForce "yes"; }
|
||||||
|
|
||||||
# Disable auto-updates as they are not possible for Live ISO.
|
# Disable auto-updates as they are not possible for Live ISO.
|
||||||
{ systemd.services.autoupdate.enable = nixpkgs.lib.mkForce false; }
|
{ module.common.autoupdate.enable = false; }
|
||||||
{ systemd.timers.autoupdate.enable = nixpkgs.lib.mkForce false; }
|
|
||||||
|
|
||||||
# Base Live images also require the LTS kernel.
|
# Base Live images also require the LTS kernel.
|
||||||
({ pkgs, ... }: { boot.kernelPackages = nixpkgs.lib.mkForce pkgs.linuxPackages; })
|
{ module.common.kernel.latest = false; }
|
||||||
];
|
];
|
||||||
};
|
|
||||||
|
|
||||||
nixosConfigurations.work = self.mkHost {
|
x86System = hostname: mkSystem hostname "x86_64-linux" [];
|
||||||
hostname = "work";
|
|
||||||
system = "x86_64-linux";
|
x86LiveSystem = hostname: mkSystem hostname "x86_64-linux" liveModules;
|
||||||
modules = [
|
in
|
||||||
./module/IntelCpu.nix
|
# Bellow is the list of all the hosts I currently use.
|
||||||
./module/PowerlimitThinkpad.nix
|
# They call the `mkSystem` function that I defined above
|
||||||
./module/PowersaveIntel.nix
|
# with their specific parameters.
|
||||||
./module/Print.nix
|
# You might be interested in `live` and `nixOnDroidConfiguration`
|
||||||
./module/RemoteBuild.nix
|
# for Live ISO and Android configurations respectively.
|
||||||
./module/Sway.nix
|
(x86System "dasha") //
|
||||||
./user/Voronind.nix
|
(x86System "desktop") //
|
||||||
];
|
(x86System "fsight") //
|
||||||
};
|
(x86System "home") //
|
||||||
|
(x86System "laptop") //
|
||||||
|
(x86System "work") //
|
||||||
|
(x86LiveSystem "live")
|
||||||
|
;
|
||||||
|
|
||||||
# Android.
|
# Android.
|
||||||
nixOnDroidConfigurations.default = nix-on-droid.lib.nixOnDroidConfiguration {
|
nixOnDroidConfigurations.default = nix-on-droid.lib.nixOnDroidConfiguration {
|
||||||
|
@ -348,9 +253,6 @@
|
||||||
# Android release version.
|
# Android release version.
|
||||||
{ system.stateVersion = inputs.self.const.droidStateVersion; }
|
{ system.stateVersion = inputs.self.const.droidStateVersion; }
|
||||||
|
|
||||||
# Common settings.
|
|
||||||
./part/Setting.nix
|
|
||||||
|
|
||||||
# I put all my Android configuration there.
|
# I put all my Android configuration there.
|
||||||
./android
|
./android
|
||||||
];
|
];
|
||||||
|
@ -364,9 +266,8 @@
|
||||||
const = self.const; # Constant values.
|
const = self.const; # Constant values.
|
||||||
flake = self; # This Flake itself.
|
flake = self; # This Flake itself.
|
||||||
inputs = inputs; # Our dependencies.
|
inputs = inputs; # Our dependencies.
|
||||||
secret = import ./part/Secret.nix {}; # Secrets (public keys).
|
secret = import ./lib/Secret.nix {}; # Secrets (public keys).
|
||||||
style = import ./part/Style.nix { config = import ./part/style/Gruvbox.nix {}; }; # Style abstraction. Stylix is not available for Android so I provide static Gruvbox style.
|
util = import ./lib/Util.nix { inherit pkgs lib; }; # Util functions.
|
||||||
util = import ./part/Util.nix { inherit pkgs lib; }; # Util functions.
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
# Basic host is a dummy and has no specific configuration.
|
|
||||||
# I don't really need it, this is just a failsafe that I can definitely install and run.
|
|
||||||
{ ... }: {
|
|
||||||
imports = [ ];
|
|
||||||
}
|
|
|
@ -3,7 +3,15 @@
|
||||||
./Filesystem.nix
|
./Filesystem.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# Disable keyd.
|
user.dasha.enable = true;
|
||||||
# services.keyd.enable = lib.mkForce false;
|
|
||||||
# systemd.services.keyd-application-mapper.enable = lib.mkForce false;
|
module = {
|
||||||
|
amd.gpu.enable = true;
|
||||||
|
builder.client.enable = true;
|
||||||
|
desktop.sway.enable = true;
|
||||||
|
intel.cpu.enable = true;
|
||||||
|
print.enable = true;
|
||||||
|
strongswan.enable = true;
|
||||||
|
tablet.enable = true;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,29 @@
|
||||||
./Filesystem.nix
|
./Filesystem.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# Disable docker service.
|
user.voronind.enable = true;
|
||||||
systemd.services.docker-prune.enable = lib.mkForce false;
|
|
||||||
systemd.services.docker.enable = lib.mkForce false;
|
module = {
|
||||||
systemd.sockets.docker.enable = lib.mkForce false;
|
builder.client.enable = true;
|
||||||
|
desktop.sway.enable = true;
|
||||||
|
print.enable = true;
|
||||||
|
virtmanager.enable = true;
|
||||||
|
amd = {
|
||||||
|
compute.enable = true;
|
||||||
|
cpu.enable = true;
|
||||||
|
gpu.enable = true;
|
||||||
|
};
|
||||||
|
docker = {
|
||||||
|
enable = true;
|
||||||
|
autostart = false;
|
||||||
|
rootless = false;
|
||||||
|
};
|
||||||
|
ollama = {
|
||||||
|
enable = true;
|
||||||
|
models = [
|
||||||
|
"llama3"
|
||||||
|
"llama3:70b"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,6 @@
|
||||||
./Grub.nix
|
./Grub.nix
|
||||||
./Root.nix
|
./Root.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
module.docker.enable = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,40 @@
|
||||||
{ pkgs
|
{ ... }: {
|
||||||
, const
|
container = {
|
||||||
, lib
|
enable = true;
|
||||||
, config
|
|
||||||
, util
|
|
||||||
, poetry2nixJobber
|
|
||||||
, pkgsJobber
|
|
||||||
, pkgsMaster
|
|
||||||
, pkgsStable
|
|
||||||
, ... }: let
|
|
||||||
args = let
|
|
||||||
# Path where all the container data will be stored.
|
|
||||||
storage = "/storage/hot/container";
|
|
||||||
|
|
||||||
# Domain used to host stuff. All the services will be like `service.${domain}`.
|
module = {
|
||||||
domain = "voronind.com";
|
change.enable = true;
|
||||||
|
cloud.enable = true;
|
||||||
|
ddns.enable = true;
|
||||||
|
dns.enable = true;
|
||||||
|
download.enable = true;
|
||||||
|
git.enable = true;
|
||||||
|
# ISSUE: hdd.enable = true;
|
||||||
|
home.enable = true;
|
||||||
|
iot.enable = true;
|
||||||
|
jobber.enable = true;
|
||||||
|
mail.enable = true;
|
||||||
|
# ISSUE: office.enable = true;
|
||||||
|
paper.enable = true;
|
||||||
|
pass.enable = true;
|
||||||
|
paste.enable = true;
|
||||||
|
postgres.enable = true;
|
||||||
|
proxy.enable = true;
|
||||||
|
rabbitmq.enable = true;
|
||||||
|
read.enable = true;
|
||||||
|
redis.enable = true;
|
||||||
|
search.enable = true;
|
||||||
|
status.enable = true;
|
||||||
|
stock.enable = true;
|
||||||
|
vpn.enable = true;
|
||||||
|
watch.enable = true;
|
||||||
|
yt.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
# External IP address of the host, where all the services will listen to.
|
storage = "/storage/hot/container";
|
||||||
host = "192.168.1.2";
|
domain = "voronind.com";
|
||||||
|
host = "192.168.1.2";
|
||||||
# External interface where all the services will listen on.
|
interface = "enp7s0";
|
||||||
externalInterface = "enp7s0";
|
|
||||||
|
|
||||||
# Paths to media content. Later they can be plugged to the containers using the `attachMedia "photo"` function.
|
|
||||||
media = {
|
media = {
|
||||||
anime = [ "/storage/cold_1/media/anime" "/storage/cold_2/media/anime" ];
|
anime = [ "/storage/cold_1/media/anime" "/storage/cold_2/media/anime" ];
|
||||||
book = [ "/storage/hot/media/book" ];
|
book = [ "/storage/hot/media/book" ];
|
||||||
|
@ -31,59 +44,11 @@
|
||||||
music = [ "/storage/cold_2/media/music" ];
|
music = [ "/storage/cold_2/media/music" ];
|
||||||
paper = [ "/storage/hot/media/paper" ];
|
paper = [ "/storage/hot/media/paper" ];
|
||||||
porn = [ "/storage/cold_2/media/porn" ];
|
porn = [ "/storage/cold_2/media/porn" ];
|
||||||
photo = [ "${storage}/cloud/data/data/cakee/files/media/photo" "/storage/cold_1/backup/tmp/photo" ];
|
photo = [ "/storage/hot/container/cloud/data/data/cakee/files/media/photo" "/storage/cold_1/backup/tmp/photo" ];
|
||||||
show = [ "/storage/cold_1/media/show" "/storage/cold_2/media/show" ];
|
show = [ "/storage/cold_1/media/show" "/storage/cold_2/media/show" ];
|
||||||
study = [ "/storage/cold_1/media/study" "/storage/cold_2/media/study" ];
|
study = [ "/storage/cold_1/media/study" "/storage/cold_2/media/study" ];
|
||||||
work = [ "/storage/cold_2/media/work" ];
|
work = [ "/storage/cold_2/media/work" ];
|
||||||
youtube = [ "/storage/cold_1/media/youtube" "/storage/cold_2/media/youtube" ];
|
youtube = [ "/storage/cold_1/media/youtube" "/storage/cold_2/media/youtube" ];
|
||||||
};
|
};
|
||||||
in {
|
|
||||||
# Pass all the arguments further.
|
|
||||||
inherit storage domain host pkgs const lib config util media externalInterface;
|
|
||||||
inherit poetry2nixJobber pkgsJobber;
|
|
||||||
inherit pkgsMaster pkgsStable;
|
|
||||||
|
|
||||||
# Pass the global container configuration.
|
|
||||||
container = import ../../container args;
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
# List of containers enabled on this host.
|
|
||||||
imports = [
|
|
||||||
(import ../../container/Change.nix args)
|
|
||||||
(import ../../container/Cloud.nix args)
|
|
||||||
(import ../../container/Ddns.nix args)
|
|
||||||
(import ../../container/Dns.nix args)
|
|
||||||
(import ../../container/Download.nix args)
|
|
||||||
(import ../../container/Git.nix args)
|
|
||||||
# (import ../../container/Hdd.nix args)
|
|
||||||
(import ../../container/Home.nix args)
|
|
||||||
(import ../../container/Iot.nix args)
|
|
||||||
(import ../../container/Jobber.nix args)
|
|
||||||
(import ../../container/Mail.nix args)
|
|
||||||
(import ../../container/Office.nix args)
|
|
||||||
(import ../../container/Paper.nix args)
|
|
||||||
(import ../../container/Pass.nix args)
|
|
||||||
(import ../../container/Paste.nix args)
|
|
||||||
(import ../../container/Postgres.nix args)
|
|
||||||
(import ../../container/Print.nix args)
|
|
||||||
(import ../../container/Proxy.nix args)
|
|
||||||
(import ../../container/Rabbitmq.nix args)
|
|
||||||
(import ../../container/Read.nix args)
|
|
||||||
(import ../../container/Redis.nix args)
|
|
||||||
(import ../../container/Search.nix args)
|
|
||||||
(import ../../container/Status.nix args)
|
|
||||||
(import ../../container/Stock.nix args)
|
|
||||||
(import ../../container/Vpn.nix args)
|
|
||||||
(import ../../container/Watch.nix args)
|
|
||||||
(import ../../container/Yt.nix args)
|
|
||||||
];
|
|
||||||
|
|
||||||
# This is the network for all the containers.
|
|
||||||
# They are not available to the external interface by default,
|
|
||||||
# instead they all expose specific ports in their configuration.
|
|
||||||
networking.nat = {
|
|
||||||
enable = true;
|
|
||||||
internalInterfaces = [ "ve-+" ];
|
|
||||||
inherit (args) externalInterface;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ lib, ... }: {
|
{ ... }: {
|
||||||
imports = [
|
imports = [
|
||||||
./Backup.nix
|
./Backup.nix
|
||||||
./Container.nix
|
./Container.nix
|
||||||
|
@ -7,7 +7,21 @@
|
||||||
./Photoprocess.nix
|
./Photoprocess.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
user.voronind.enable = true;
|
||||||
|
|
||||||
|
module = {
|
||||||
|
builder.server.enable = true;
|
||||||
|
desktop.sway.enable = true;
|
||||||
|
ftpd = {
|
||||||
|
enable = true;
|
||||||
|
storage = "/storage/hot/ftp";
|
||||||
|
};
|
||||||
|
amd = {
|
||||||
|
cpu.enable = true;
|
||||||
|
gpu.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# Disable auto-switch.
|
# Disable auto-switch.
|
||||||
systemd.services.autoupdate.enable = lib.mkForce false;
|
module.common.autoupdate.enable = false;
|
||||||
systemd.timers.autoupdate.enable = lib.mkForce false;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,21 @@
|
||||||
imports = [
|
imports = [
|
||||||
./Filesystem.nix
|
./Filesystem.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
user = {
|
||||||
|
dasha.enable = true;
|
||||||
|
voronind.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
builder.client.enable = true;
|
||||||
|
print.enable = true;
|
||||||
|
strongswan.enable = true;
|
||||||
|
tablet.enable = true;
|
||||||
|
amd = {
|
||||||
|
compute.enable = true;
|
||||||
|
cpu.enable = true;
|
||||||
|
gpu.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
{ ... }: {
|
{ ... }: { }
|
||||||
imports = [ ];
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,4 +5,14 @@
|
||||||
|
|
||||||
# Keyd Print to Macro remap.
|
# Keyd Print to Macro remap.
|
||||||
services.keyd.keyboards.default.settings.main.print = "layer(layer_macro)";
|
services.keyd.keyboards.default.settings.main.print = "layer(layer_macro)";
|
||||||
|
|
||||||
|
user.voronind.enable = true;
|
||||||
|
|
||||||
|
module = {
|
||||||
|
builder.client.enable = true;
|
||||||
|
desktop.sway.enable = true;
|
||||||
|
intel.cpu.enable = true;
|
||||||
|
powerlimit.thinkpad.enable = true;
|
||||||
|
print.enable = true;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
63
lib/Container.nix
Normal file
63
lib/Container.nix
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
{ lib, pkgs, const, config, ... }: {
|
||||||
|
mkContainer = cfg: extra: lib.recursiveUpdate {
|
||||||
|
# Start containers with the system by default.
|
||||||
|
autoStart = config.container.autoStart;
|
||||||
|
|
||||||
|
# IP Address of the host. This is required for container to have access to the Internet.
|
||||||
|
hostAddress = config.container.host;
|
||||||
|
|
||||||
|
# Container's IP address.
|
||||||
|
localAddress = cfg.address;
|
||||||
|
|
||||||
|
# Isolate container from other hosts.
|
||||||
|
privateNetwork = true;
|
||||||
|
} extra;
|
||||||
|
|
||||||
|
# Common configuration for the system inside the container.
|
||||||
|
mkContainerConfig = cfg: extra: lib.recursiveUpdate {
|
||||||
|
# HACK: Do not evaluate nixpkgs inside the container. Use host's instead.
|
||||||
|
nixpkgs.pkgs = lib.mkForce pkgs;
|
||||||
|
|
||||||
|
# Release version.
|
||||||
|
system.stateVersion = const.stateVersion;
|
||||||
|
|
||||||
|
# Allow passwordless login as root.
|
||||||
|
users = {
|
||||||
|
users.root.password = "";
|
||||||
|
mutableUsers = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
# Default DNS servers.
|
||||||
|
nameservers = [
|
||||||
|
"1.1.1.1"
|
||||||
|
];
|
||||||
|
|
||||||
|
# HACK: Fix for upstream issue: https://github.com/NixOS/nixpkgs/issues/162686
|
||||||
|
useHostResolvConf = lib.mkForce false;
|
||||||
|
|
||||||
|
# Disable firewall.
|
||||||
|
firewall.enable = false;
|
||||||
|
};
|
||||||
|
} extra;
|
||||||
|
|
||||||
|
# Create a directory on the host for container use.
|
||||||
|
mkContainerDir = cfg: dirs: map (path: "d '${cfg.storage}/${path}' 1777 root root - -") dirs;
|
||||||
|
|
||||||
|
# Common configuration for Nginx server.
|
||||||
|
mkServer = cfg: lib.recursiveUpdate {
|
||||||
|
forceSSL = false;
|
||||||
|
} cfg;
|
||||||
|
|
||||||
|
# Attach the host media directory to container.
|
||||||
|
# They will be added to /type/{0..9}
|
||||||
|
attachMedia = type: ro: builtins.listToAttrs (lib.imap0 (i: path:
|
||||||
|
{
|
||||||
|
name = "/${type}/${toString i}";
|
||||||
|
value = {
|
||||||
|
hostPath = path;
|
||||||
|
isReadOnly = ro;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) config.container.media.${type});
|
||||||
|
}
|
|
@ -30,4 +30,6 @@
|
||||||
stopIfChanged = false;
|
stopIfChanged = false;
|
||||||
unitConfig.X-StopOnRemoval = false;
|
unitConfig.X-StopOnRemoval = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,10 +1,17 @@
|
||||||
# AMD Rocm support (for Blender).
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
{ nixpkgs, pkgs, ... }: {
|
cfg = config.module.amd.compute;
|
||||||
nixpkgs.config.rocmSupport = true;
|
in {
|
||||||
systemd.tmpfiles.rules = [
|
options = {
|
||||||
"L+ /opt/rocm/hip - - - - ${pkgs.rocmPackages.clr}"
|
module.amd.compute.enable = mkEnableOption "Enable AMD Rocm support i.e. for Blender.";
|
||||||
];
|
};
|
||||||
hardware.opengl.extraPackages = with pkgs; [
|
|
||||||
rocmPackages.clr.icd
|
config = mkIf cfg.enable {
|
||||||
];
|
nixpkgs.config.rocmSupport = true;
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"L+ /opt/rocm/hip - - - - ${pkgs.rocmPackages.clr}"
|
||||||
|
];
|
||||||
|
hardware.opengl.extraPackages = with pkgs; [
|
||||||
|
rocmPackages.clr.icd
|
||||||
|
];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,27 @@
|
||||||
# AMD CPU specific configuration.
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
{ lib, config, ... }: {
|
cfg = config.module.amd.cpu;
|
||||||
boot.kernelModules = [ "kvm-amd" ];
|
|
||||||
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
controlFile = "/sys/devices/system/cpu/cpufreq/boost";
|
||||||
|
enableCmd = "0";
|
||||||
|
disableCmd = "1";
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
module.amd.cpu = {
|
||||||
|
enable = mkEnableOption "Enable AMD Cpu support.";
|
||||||
|
powersave.enable = mkEnableOption "Enable AMD Cpu powersave." // { default = true; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable (mkMerge [
|
||||||
|
{
|
||||||
|
boot.kernelModules = [ "kvm-amd" ];
|
||||||
|
hardware.cpu.amd.updateMicrocode = mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
}
|
||||||
|
(mkIf cfg.powersave.enable {
|
||||||
|
module.powersave = {
|
||||||
|
enable = true;
|
||||||
|
cpu.boost = { inherit controlFile enableCmd disableCmd; };
|
||||||
|
};
|
||||||
|
})
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
# AMD GPU specific configuration.
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
# No, I do not own any Nvidia/Intel GPUs, so I have no configuration for them.
|
cfg = config.module.amd.gpu;
|
||||||
{ nixpkgs, pkgs, ... }: {
|
in {
|
||||||
boot.initrd.kernelModules = [ "amdgpu" ];
|
options = {
|
||||||
services.xserver.videoDrivers = [ "amdgpu" ];
|
module.amd.gpu.enable = mkEnableOption "Enable AMD Gpu support.";
|
||||||
hardware.opengl.driSupport = true;
|
};
|
||||||
hardware.opengl.driSupport32Bit = true;
|
|
||||||
environment.variables.AMD_VULKAN_ICD = "RADV";
|
|
||||||
|
|
||||||
# AMDVLK was broken for me (huge stuttering). So keep it disabled, at least for now.
|
config = mkIf cfg.enable {
|
||||||
# hardware.opengl.extraPackages = with pkgs; [
|
boot.initrd.kernelModules = [ "amdgpu" ];
|
||||||
# amdvlk
|
services.xserver.videoDrivers = [ "amdgpu" ];
|
||||||
# ];
|
hardware.opengl.driSupport = true;
|
||||||
# hardware.opengl.extraPackages32 = with pkgs; [
|
hardware.opengl.driSupport32Bit = true;
|
||||||
# driversi686Linux.amdvlk
|
environment.variables.AMD_VULKAN_ICD = "RADV";
|
||||||
# ];
|
|
||||||
|
# AMDVLK was broken for me (huge stuttering). So keep it disabled, at least for now.
|
||||||
|
# hardware.opengl.extraPackages = with pkgs; [
|
||||||
|
# amdvlk
|
||||||
|
# ];
|
||||||
|
# hardware.opengl.extraPackages32 = with pkgs; [
|
||||||
|
# driversi686Linux.amdvlk
|
||||||
|
# ];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
# Toggle language with CapsLock. My wife prefers this.
|
|
||||||
{ lib, ... }: {
|
|
||||||
services.xserver.xkb = {
|
|
||||||
options = lib.mkForce "grp:caps_toggle";
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,3 +1,41 @@
|
||||||
{ ... }: {
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
virtualisation.docker.enable = true;
|
cfg = config.module.docker;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
module.docker = {
|
||||||
|
enable = mkEnableOption "Enable Cocker";
|
||||||
|
rootless = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
autostart = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
virtualisation.docker.enable = true;
|
||||||
|
|
||||||
|
virtualisation.docker.rootless = mkIf cfg.rootless {
|
||||||
|
enable = true;
|
||||||
|
setSocketVariable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.docker-prune.enable = mkForce cfg.autostart;
|
||||||
|
systemd.services.docker.enable = mkForce cfg.autostart;
|
||||||
|
systemd.sockets.docker.enable = mkForce cfg.autostart;
|
||||||
|
};
|
||||||
|
|
||||||
|
# NOTE: mkMerge example.
|
||||||
|
# config = mkIf cfg.enable (mkMerge [
|
||||||
|
# { virtualisation.docker.enable = true; }
|
||||||
|
# (mkIf cfg.rootless {
|
||||||
|
# virtualisation.docker.rootless = {
|
||||||
|
# enable = true;
|
||||||
|
# setSocketVariable = true;
|
||||||
|
# };
|
||||||
|
# })
|
||||||
|
# ]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
{ ... }: {
|
|
||||||
virtualisation.docker.enable = true;
|
|
||||||
virtualisation.docker.rootless = {
|
|
||||||
enable = true;
|
|
||||||
setSocketVariable = true;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,17 +1,31 @@
|
||||||
{ ... }: {
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
services.vsftpd = {
|
cfg = config.module.ftpd;
|
||||||
enable = true;
|
in {
|
||||||
anonymousUser = true;
|
options = {
|
||||||
anonymousUserNoPassword = true;
|
module.ftpd = {
|
||||||
anonymousUploadEnable = true;
|
enable = mkEnableOption "Enable FTP server";
|
||||||
anonymousMkdirEnable = true;
|
storage = mkOption {
|
||||||
anonymousUmask = "000";
|
default = null;
|
||||||
anonymousUserHome = "/storage/hot/ftp";
|
type = types.str;
|
||||||
allowWriteableChroot = true;
|
};
|
||||||
writeEnable = true;
|
};
|
||||||
localUsers = false;
|
};
|
||||||
extraConfig = ''
|
|
||||||
anon_other_write_enable=YES
|
config = mkIf cfg.enable {
|
||||||
'';
|
services.vsftpd = {
|
||||||
|
enable = true;
|
||||||
|
anonymousUser = true;
|
||||||
|
anonymousUserNoPassword = true;
|
||||||
|
anonymousUploadEnable = true;
|
||||||
|
anonymousMkdirEnable = true;
|
||||||
|
anonymousUmask = "000";
|
||||||
|
anonymousUserHome = cfg.storage;
|
||||||
|
allowWriteableChroot = true;
|
||||||
|
writeEnable = true;
|
||||||
|
localUsers = false;
|
||||||
|
extraConfig = ''
|
||||||
|
anon_other_write_enable=YES
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
{ pkgs, lib, ... }: {
|
|
||||||
imports = [
|
|
||||||
./desktop/App.nix
|
|
||||||
./desktop/Dconf.nix
|
|
||||||
./desktop/DisplayManager.nix
|
|
||||||
./desktop/Sound.nix
|
|
||||||
./desktop/Wayland.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
services.xserver.displayManager.gdm.enable = true;
|
|
||||||
services.xserver.desktopManager.gnome.enable = true;
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
gnome.gnome-tweaks # Gnome "hidden" settings.
|
|
||||||
openssl # It was needed for something, can't remember.
|
|
||||||
];
|
|
||||||
|
|
||||||
# Disable some Gnome apps.
|
|
||||||
services.gnome.gnome-keyring.enable = lib.mkForce false;
|
|
||||||
environment.gnome.excludePackages = with pkgs.gnome; [
|
|
||||||
# baobab # Disk usage analyzer.
|
|
||||||
# cheese # Photo booth.
|
|
||||||
# epiphany # Web browser.
|
|
||||||
# simple-scan # Document scanner.
|
|
||||||
# totem # Video player.
|
|
||||||
# yelp # Help viewer.
|
|
||||||
# file-roller # Archive manager.
|
|
||||||
# geary # Email client.
|
|
||||||
# seahorse # Password manager.
|
|
||||||
|
|
||||||
# gnome-calculator
|
|
||||||
# gnome-calendar
|
|
||||||
# gnome-characters
|
|
||||||
# gnome-clocks
|
|
||||||
# gnome-contacts
|
|
||||||
# gnome-font-viewer
|
|
||||||
# gnome-keyring
|
|
||||||
# gnome-logs
|
|
||||||
# gnome-maps
|
|
||||||
# gnome-music
|
|
||||||
# gnome-shell-extensions
|
|
||||||
gnome-software
|
|
||||||
# gnome-system-monitor
|
|
||||||
# gnome-weather
|
|
||||||
# gnome-disk-utility
|
|
||||||
# pkgs.gnome-text-editor
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -1,4 +1,27 @@
|
||||||
# Intel CPU specific configuration.
|
# Intel CPU specific configuration.
|
||||||
{ ... }: {
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
boot.kernelModules = [ "kvm-intel" ];
|
cfg = config.module.intel.cpu;
|
||||||
|
|
||||||
|
controlFile = "/sys/devices/system/cpu/intel_pstate/no_turbo";
|
||||||
|
enableCmd = "1";
|
||||||
|
disableCmd = "0";
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
module.intel.cpu = {
|
||||||
|
enable = mkEnableOption "Support for Shintel CPUs";
|
||||||
|
powersave.enable = mkEnableOption "Enable Shintel Cpu powersave." // { default = true; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable (mkMerge [
|
||||||
|
{
|
||||||
|
boot.kernelModules = [ "kvm-intel" ];
|
||||||
|
}
|
||||||
|
(mkIf cfg.powersave.enable {
|
||||||
|
module.powersave = {
|
||||||
|
enable = true;
|
||||||
|
cpu.boost = { inherit controlFile enableCmd disableCmd; };
|
||||||
|
};
|
||||||
|
})
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,54 @@
|
||||||
# https://github.com/ollama/ollama
|
# https://github.com/ollama/ollama
|
||||||
{ pkgsStable, lib, config, ... }: let
|
{ pkgsStable, lib, config, ... }: with lib; let
|
||||||
pkgs = pkgsStable;
|
pkgs = pkgsStable;
|
||||||
|
cfg = config.module.ollama;
|
||||||
in {
|
in {
|
||||||
environment = {
|
options = {
|
||||||
# Add Ollama CLI app.
|
module.ollama = {
|
||||||
systemPackages = with pkgs; [ ollama ];
|
enable = mkEnableOption "Local LLM server";
|
||||||
|
primaryModel = mkOption {
|
||||||
# Specify default model.
|
default = "llama3";
|
||||||
variables.OLLAMA_MODEL = config.setting.ollama.primaryModel;
|
type = types.str;
|
||||||
|
};
|
||||||
|
models = mkOption {
|
||||||
|
default = [ cfg.primaryModel ];
|
||||||
|
type = types.listOf types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Enable Ollama server.
|
config = mkIf cfg.enable {
|
||||||
systemd.services.ollama = {
|
environment = {
|
||||||
description = "Ollama LLM server.";
|
# Add Ollama CLI app.
|
||||||
wantedBy = [ "multi-user.target" ];
|
systemPackages = with pkgs; [ ollama ];
|
||||||
wants = [ "NetworkManager-wait-online.service" ];
|
|
||||||
after = [ "NetworkManager-wait-online.service" ];
|
|
||||||
serviceConfig.Type = "simple";
|
|
||||||
script = ''
|
|
||||||
HOME=/root ${lib.getExe pkgs.ollama} serve
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Download Ollama models.
|
# Specify default model.
|
||||||
systemd.services.ollamamodel = {
|
variables.OLLAMA_MODEL = cfg.primaryModel;
|
||||||
description = "Ollama LLM model.";
|
};
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
wants = [ "ollama.service" ];
|
# Enable Ollama server.
|
||||||
after = [ "ollama.service" ];
|
systemd.services.ollama = {
|
||||||
serviceConfig.Type = "simple";
|
description = "Ollama LLM server.";
|
||||||
script = ''
|
wantedBy = [ "multi-user.target" ];
|
||||||
sleep 5
|
wants = [ "NetworkManager-wait-online.service" ];
|
||||||
${lib.getExe pkgs.ollama} pull ${config.setting.ollama.primaryModel}
|
after = [ "NetworkManager-wait-online.service" ];
|
||||||
'';
|
serviceConfig.Type = "simple";
|
||||||
|
script = ''
|
||||||
|
HOME=/root ${getExe pkgs.ollama} serve
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Download Ollama models.
|
||||||
|
systemd.services.ollamamodel = {
|
||||||
|
description = "Ollama LLM model.";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
wants = [ "ollama.service" ];
|
||||||
|
after = [ "ollama.service" ];
|
||||||
|
serviceConfig.Type = "simple";
|
||||||
|
script = ''
|
||||||
|
sleep 5
|
||||||
|
${getExe pkgs.ollama} pull ${concatStringsSep " " cfg.models}
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
24
module/Podman.nix
Normal file
24
module/Podman.nix
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{ lib, config, ... }: with lib; let
|
||||||
|
cfg = config.module.podman;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
module.podman = {
|
||||||
|
enable = mkEnableOption "OCI Podman.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
virtualisation = {
|
||||||
|
podman = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
# Free the 53 port ffs.
|
||||||
|
defaultNetwork.settings.dns_enabled = false;
|
||||||
|
|
||||||
|
# Do not interfere with Docker so we can have both installed at the same time.
|
||||||
|
# Podman can't replace Docker anyway.
|
||||||
|
dockerCompat = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,22 +1,79 @@
|
||||||
# ThinkPad charge limits.
|
# ThinkPad charge limits.
|
||||||
{ pkgs, lib, ... } @args: let
|
{ pkgs, lib, config, ... } @args: with lib; let
|
||||||
|
cfg = config.module.powerlimit.thinkpad;
|
||||||
|
|
||||||
controlFileMin = "/sys/class/power_supply/BAT0/charge_control_start_threshold";
|
controlFileMin = "/sys/class/power_supply/BAT0/charge_control_start_threshold";
|
||||||
controlFileMax = "/sys/class/power_supply/BAT0/charge_control_end_threshold";
|
controlFileMax = "/sys/class/power_supply/BAT0/charge_control_end_threshold";
|
||||||
|
|
||||||
onMin = "40";
|
script = pkgs.writeShellScriptBin "powerlimit" ''
|
||||||
onMax = "80";
|
function toggle() {
|
||||||
offMin = "90";
|
if status; then
|
||||||
offMax = "95";
|
echo ${toString cfg.offMax} > ${controlFileMax}
|
||||||
|
echo ${toString cfg.offMin} > ${controlFileMin}
|
||||||
|
else
|
||||||
|
echo ${toString cfg.onMin} > ${controlFileMin}
|
||||||
|
echo ${toString cfg.onMax} > ${controlFileMax}
|
||||||
|
fi
|
||||||
|
|
||||||
script = pkgs.writeShellScriptBin "powerlimit" (import ./powerlimit/Script.nix {
|
true
|
||||||
inherit controlFileMax controlFileMin onMin onMax offMin offMax;
|
}
|
||||||
}).script;
|
|
||||||
|
function waybar() {
|
||||||
|
status || echo -n ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function status() {
|
||||||
|
local current=$(cat ${controlFileMax})
|
||||||
|
local enabled="${toString cfg.onMax}"
|
||||||
|
|
||||||
|
[[ "''${current}" = "''${enabled}" ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
''${@}
|
||||||
|
'';
|
||||||
in {
|
in {
|
||||||
imports = [
|
options = {
|
||||||
(import ./powerlimit ({
|
module.powerlimit.thinkpad = {
|
||||||
inherit controlFileMax controlFileMin onMin onMax offMin offMax;
|
enable = mkEnableOption "Powerlimit Service";
|
||||||
} // args))
|
onMin = mkOption {
|
||||||
];
|
default = 40;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
onMax = mkOption {
|
||||||
|
default = 80;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
offMin = mkOption {
|
||||||
|
default = 90;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
offMax = mkOption {
|
||||||
|
default = 95;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
environment.systemPackages = [ script ];
|
config = mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [ script ];
|
||||||
|
systemd = {
|
||||||
|
services.powerlimit = {
|
||||||
|
description = "Limit battery charge.";
|
||||||
|
enable = true;
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
RemainAfterExit = "yes";
|
||||||
|
ExecStart = "${getExe pkgs.bash} -c 'echo ${toString cfg.onMin} > ${controlFileMin}; echo ${toString cfg.onMax} > ${controlFileMax};'";
|
||||||
|
ExecStop = "${getExe pkgs.bash} -c 'echo ${toString cfg.offMax} > ${controlFileMax}; echo ${toString cfg.offMin} > ${controlFileMin};'";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# HACK: Allow user access.
|
||||||
|
tmpfiles.rules = [
|
||||||
|
"z ${controlFileMax} 0777 - - - -"
|
||||||
|
"z ${controlFileMin} 0777 - - - -"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
73
module/Powersave.nix
Normal file
73
module/Powersave.nix
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
{ lib, config, pkgs, ... }: with lib; let
|
||||||
|
cfg = config.module.powersave;
|
||||||
|
|
||||||
|
script = pkgs.writeShellScriptBin "powersave" ''
|
||||||
|
function toggle() {
|
||||||
|
if status; then
|
||||||
|
echo ${cfg.cpu.boost.disableCmd} > ${cfg.cpu.boost.controlFile}
|
||||||
|
else
|
||||||
|
echo ${cfg.cpu.boost.enableCmd} > ${cfg.cpu.boost.controlFile}
|
||||||
|
fi
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
function waybar() {
|
||||||
|
status || echo -n ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function status() {
|
||||||
|
local current=$(cat ${cfg.cpu.boost.controlFile})
|
||||||
|
local enabled="${cfg.cpu.boost.enableCmd}"
|
||||||
|
|
||||||
|
[[ "''${current}" = "''${enabled}" ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
''${@}
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
module.powersave = {
|
||||||
|
enable = mkEnableOption "Powersave";
|
||||||
|
cpu.boost = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
disableCmd = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
enableCmd = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
controlFile = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [ script ];
|
||||||
|
systemd = {
|
||||||
|
services.powersave-cpu = {
|
||||||
|
description = "Disable CPU Boost";
|
||||||
|
enable = true;
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
RemainAfterExit = "yes";
|
||||||
|
ExecStart = "${getExe pkgs.bash} -c 'echo ${cfg.cpu.boost.enableCmd} > ${cfg.cpu.boost.controlFile}'";
|
||||||
|
ExecStop = "${getExe pkgs.bash} -c 'echo ${cfg.cpu.boost.disableCmd} > ${cfg.cpu.boost.controlFile}'";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# HACK: Allow user access.
|
||||||
|
tmpfiles.rules = [ "z ${cfg.cpu.boost.controlFile} 0777 - - - -" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
# AMD CPU boost control.
|
|
||||||
{ pkgs, ... } @args: let
|
|
||||||
controlFile = "/sys/devices/system/cpu/cpufreq/boost";
|
|
||||||
enable = "0";
|
|
||||||
disable = "1";
|
|
||||||
|
|
||||||
script = pkgs.writeShellScriptBin "powersave" (import ./powersave/Script.nix {
|
|
||||||
inherit controlFile enable disable;
|
|
||||||
}).script;
|
|
||||||
in {
|
|
||||||
# Requirements:
|
|
||||||
# CPPC (Collaborative Power Control) - Disabled.
|
|
||||||
# PSS (Cool and Quiet) - Enabled.
|
|
||||||
imports = [
|
|
||||||
(import ./powersave ({
|
|
||||||
inherit controlFile enable disable;
|
|
||||||
} // args))
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.systemPackages = [ script ];
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Intel CPU boost control.
|
|
||||||
{ pkgs, ... } @args: let
|
|
||||||
controlFile = "/sys/devices/system/cpu/intel_pstate/no_turbo";
|
|
||||||
enable = "1";
|
|
||||||
disable = "0";
|
|
||||||
|
|
||||||
script = pkgs.writeShellScriptBin "powersave" (import ./powersave/Script.nix {
|
|
||||||
inherit controlFile enable disable;
|
|
||||||
}).script;
|
|
||||||
in {
|
|
||||||
imports = [
|
|
||||||
(import ./powersave ({
|
|
||||||
inherit controlFile enable disable;
|
|
||||||
} // args))
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.systemPackages = [ script ];
|
|
||||||
}
|
|
|
@ -1,9 +1,17 @@
|
||||||
{ ... }: {
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
services.printing = {
|
cfg = config.module.print;
|
||||||
enable = true;
|
in {
|
||||||
clientConf = ''
|
options = {
|
||||||
DigestOptions DenyMD5
|
module.print.enable = mkEnableOption "Add support for printers.";
|
||||||
ServerName 192.168.1.2
|
};
|
||||||
'';
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
services.printing = {
|
||||||
|
enable = true;
|
||||||
|
clientConf = ''
|
||||||
|
DigestOptions DenyMD5
|
||||||
|
ServerName 192.168.1.2
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,79 @@
|
||||||
# Module that enables remote builds. This is a client configuration.
|
# Module that enables remote builds. This is a client configuration.
|
||||||
{ lib, secret, ... }: {
|
{ pkgs, lib, config, secret, ... }: with lib; let
|
||||||
# NOTE: Requires host private key to be present in secret.ssh.builderKeys.
|
cfg = config.module.builder;
|
||||||
nix.buildMachines = [{
|
|
||||||
hostName = "nixbuilder";
|
serverKeyPath = "/root/.nixbuilder";
|
||||||
protocol = "ssh-ng";
|
in {
|
||||||
systems = [
|
options = {
|
||||||
"x86_64-linux"
|
module.builder = {
|
||||||
"i686-linux"
|
server.enable = mkEnableOption "This is a builder server.";
|
||||||
"aarch64-linux"
|
client.enable = mkEnableOption "This is a builder client.";
|
||||||
];
|
};
|
||||||
maxJobs = 1;
|
|
||||||
speedFactor = 2;
|
|
||||||
mandatoryFeatures = [ ];
|
|
||||||
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
|
|
||||||
}];
|
|
||||||
nix.distributedBuilds = true;
|
|
||||||
nix.settings = let
|
|
||||||
substituters = [ "ssh-ng://nixbuilder" ];
|
|
||||||
in {
|
|
||||||
substituters = lib.mkForce substituters;
|
|
||||||
trusted-substituters = substituters;
|
|
||||||
builders-use-substitutes = true;
|
|
||||||
max-jobs = 0;
|
|
||||||
trusted-public-keys = [ secret.ssh.builderKey ];
|
|
||||||
# require-sigs = false;
|
|
||||||
# substitute = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config = mkMerge [
|
||||||
|
(mkIf cfg.server.enable {
|
||||||
|
# Service that generates new key on boot if not present.
|
||||||
|
# Don't forget to add new key to secret.ssh.buildKeys.
|
||||||
|
systemd.services.generate-nix-cache-key = {
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig.Type = "oneshot";
|
||||||
|
path = [ pkgs.nix ];
|
||||||
|
script = ''
|
||||||
|
[[ -f "${serverKeyPath}/private-key" ]] && exit
|
||||||
|
mkdir ${serverKeyPath} || true
|
||||||
|
nix-store --generate-binary-cache-key "nixbuilder-1" "${serverKeyPath}/private-key" "${serverKeyPath}/public-key"
|
||||||
|
nix store sign --all -k "${serverKeyPath}/private-key"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Add `nixbuilder` restricted user.
|
||||||
|
users.groups.nixbuilder = {};
|
||||||
|
users.users.nixbuilder = {
|
||||||
|
openssh.authorizedKeys.keys = secret.ssh.buildKeys;
|
||||||
|
description = "Nix Remote Builder";
|
||||||
|
isNormalUser = true;
|
||||||
|
createHome = lib.mkForce false;
|
||||||
|
uid = 1234;
|
||||||
|
home = "/";
|
||||||
|
group = "nixbuilder";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Sign store automatically.
|
||||||
|
# Sign existing store with: nix store sign --all -k /path/to/secret-key-file
|
||||||
|
nix.settings = {
|
||||||
|
trusted-users = [ "nixbuilder" ];
|
||||||
|
secret-key-files = [ "${serverKeyPath}/private-key" ];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
(mkIf cfg.client.enable {
|
||||||
|
# NOTE: Requires host private key to be present in secret.ssh.builderKeys.
|
||||||
|
nix.buildMachines = [{
|
||||||
|
hostName = "nixbuilder";
|
||||||
|
protocol = "ssh-ng";
|
||||||
|
systems = [
|
||||||
|
"x86_64-linux"
|
||||||
|
"i686-linux"
|
||||||
|
"aarch64-linux"
|
||||||
|
];
|
||||||
|
maxJobs = 1;
|
||||||
|
speedFactor = 2;
|
||||||
|
mandatoryFeatures = [ ];
|
||||||
|
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
|
||||||
|
}];
|
||||||
|
nix.distributedBuilds = true;
|
||||||
|
nix.settings = let
|
||||||
|
substituters = [ "ssh-ng://nixbuilder" ];
|
||||||
|
in {
|
||||||
|
substituters = mkForce substituters;
|
||||||
|
trusted-substituters = substituters;
|
||||||
|
builders-use-substitutes = true;
|
||||||
|
max-jobs = 0;
|
||||||
|
trusted-public-keys = [ secret.ssh.builderKey ];
|
||||||
|
# require-sigs = false;
|
||||||
|
# substitute = false;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
# Module that enables remote builds. This is a server configuration.
|
|
||||||
{ pkgs, secret, lib, ... }: let
|
|
||||||
keyPath = "/root/.nixbuilder";
|
|
||||||
in {
|
|
||||||
# Service that generates new key on boot if not present.
|
|
||||||
# Don't forget to add new key to secret.ssh.buildKeys.
|
|
||||||
systemd.services.generate-nix-cache-key = {
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
path = [ pkgs.nix ];
|
|
||||||
script = ''
|
|
||||||
[[ -f "${keyPath}/private-key" ]] && exit
|
|
||||||
mkdir ${keyPath} || true
|
|
||||||
nix-store --generate-binary-cache-key "nixbuilder-1" "${keyPath}/private-key" "${keyPath}/public-key"
|
|
||||||
nix store sign --all -k "${keyPath}/private-key"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Add `nixbuilder` restricted user.
|
|
||||||
users.groups.nixbuilder = {};
|
|
||||||
users.users.nixbuilder = {
|
|
||||||
openssh.authorizedKeys.keys = secret.ssh.buildKeys;
|
|
||||||
description = "Nix Remote Builder";
|
|
||||||
isNormalUser = true;
|
|
||||||
createHome = lib.mkForce false;
|
|
||||||
uid = 1234;
|
|
||||||
home = "/";
|
|
||||||
group = "nixbuilder";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Sign store automatically.
|
|
||||||
# Sign existing store with: nix store sign --all -k /path/to/secret-key-file
|
|
||||||
nix.settings = {
|
|
||||||
trusted-users = [ "nixbuilder" ];
|
|
||||||
secret-key-files = [ "${keyPath}/private-key" ];
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -5,6 +5,8 @@
|
||||||
,lib
|
,lib
|
||||||
, ... }: {
|
, ... }: {
|
||||||
options.setting = with lib; {
|
options.setting = with lib; {
|
||||||
|
# Ollama settings.
|
||||||
|
# I use the best light model by default.
|
||||||
ollama = mkOption {
|
ollama = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
type = types.submodule {
|
type = types.submodule {
|
||||||
|
@ -18,6 +20,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Default browser settings.
|
||||||
browser = mkOption {
|
browser = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
type = types.submodule {
|
type = types.submodule {
|
||||||
|
@ -30,6 +33,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Terminal settings.
|
||||||
terminal = mkOption {
|
terminal = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
type = types.submodule {
|
type = types.submodule {
|
||||||
|
@ -42,16 +46,19 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Whether to use Dpi-aware setting in supported apps.
|
||||||
dpiAware = mkOption {
|
dpiAware = mkOption {
|
||||||
default = false;
|
default = false;
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# The key used for system-related shortcuts.
|
||||||
sysctrl = mkOption {
|
sysctrl = mkOption {
|
||||||
default = "print";
|
default = "print";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Keyboard options.
|
||||||
keyboard = mkOption {
|
keyboard = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
type = types.submodule {
|
type = types.submodule {
|
||||||
|
@ -68,6 +75,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Settings related to different refreshes, like top apps.
|
||||||
refresh = mkOption {
|
refresh = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
type = types.submodule {
|
type = types.submodule {
|
||||||
|
@ -80,6 +88,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Configure steps for different actions.
|
||||||
step = mkOption {
|
step = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
type = types.submodule {
|
type = types.submodule {
|
||||||
|
@ -100,6 +109,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Specify timeouts.
|
||||||
timeout = mkOption {
|
timeout = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
type = types.submodule {
|
type = types.submodule {
|
|
@ -1,21 +1,29 @@
|
||||||
{ pkgs, ... }: {
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
environment.systemPackages = with pkgs; [
|
cfg = config.module.strongswan;
|
||||||
networkmanager-l2tp
|
in {
|
||||||
gnome.networkmanager-l2tp
|
options = {
|
||||||
# networkmanager_strongswan
|
module.strongswan.enable = mkEnableOption "StrongSwan Vpn support.";
|
||||||
# strongswan
|
};
|
||||||
# strongswanNM
|
|
||||||
];
|
config = mkIf cfg.enable {
|
||||||
networking.networkmanager.enableStrongSwan = true;
|
environment.systemPackages = with pkgs; [
|
||||||
services.xl2tpd.enable = true;
|
networkmanager-l2tp
|
||||||
services.strongswan = {
|
gnome.networkmanager-l2tp
|
||||||
enable = true;
|
# networkmanager_strongswan
|
||||||
secrets = [
|
# strongswan
|
||||||
"ipsec.d/ipsec.nm-l2tp.secrets"
|
# strongswanNM
|
||||||
];
|
];
|
||||||
|
networking.networkmanager.enableStrongSwan = true;
|
||||||
|
services.xl2tpd.enable = true;
|
||||||
|
services.strongswan = {
|
||||||
|
enable = true;
|
||||||
|
secrets = [
|
||||||
|
"ipsec.d/ipsec.nm-l2tp.secrets"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
# NOTE: Try this if VPN ever breaks.
|
||||||
|
# systemd.tmpfiles.rules = [
|
||||||
|
# "L /etc/ipsec.secrets - - - - /etc/ipsec.d/ipsec.nm-l2tp.secrets"
|
||||||
|
# ];
|
||||||
};
|
};
|
||||||
# NOTE: Try this if VPN ever breaks.
|
|
||||||
# systemd.tmpfiles.rules = [
|
|
||||||
# "L /etc/ipsec.secrets - - - - /etc/ipsec.d/ipsec.nm-l2tp.secrets"
|
|
||||||
# ];
|
|
||||||
}
|
}
|
||||||
|
|
91
module/Style.nix
Normal file
91
module/Style.nix
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
|
cfg = config.module.style;
|
||||||
|
in {
|
||||||
|
options = let
|
||||||
|
mkTypeOption = default: type: mkOption { inherit default type; };
|
||||||
|
mkStrOption = default: mkTypeOption default types.str;
|
||||||
|
mkIntOption = default: mkTypeOption default types.int;
|
||||||
|
mkFloatOption = default: mkTypeOption default types.float;
|
||||||
|
in {
|
||||||
|
module.style = {
|
||||||
|
color = {
|
||||||
|
bg = {
|
||||||
|
dark = mkStrOption config.lib.stylix.colors.base00;
|
||||||
|
light = mkStrOption config.lib.stylix.colors.base07;
|
||||||
|
regular = mkStrOption config.lib.stylix.colors.base01;
|
||||||
|
};
|
||||||
|
fg = {
|
||||||
|
dark = mkStrOption config.lib.stylix.colors.base04;
|
||||||
|
light = mkStrOption config.lib.stylix.colors.base06;
|
||||||
|
regular = mkStrOption config.lib.stylix.colors.base05;
|
||||||
|
};
|
||||||
|
accent = mkStrOption config.lib.stylix.colors.base0A;
|
||||||
|
heading = mkStrOption config.lib.stylix.colors.base0D;
|
||||||
|
hl = mkStrOption config.lib.stylix.colors.base03;
|
||||||
|
keyword = mkStrOption config.lib.stylix.colors.base0E;
|
||||||
|
link = mkStrOption config.lib.stylix.colors.base09;
|
||||||
|
misc = mkStrOption config.lib.stylix.colors.base0F;
|
||||||
|
negative = mkStrOption config.lib.stylix.colors.base08;
|
||||||
|
neutral = mkStrOption config.lib.stylix.colors.base0C;
|
||||||
|
positive = mkStrOption config.lib.stylix.colors.base0B;
|
||||||
|
selection = mkStrOption config.lib.stylix.colors.base02;
|
||||||
|
transparent = mkStrOption "ffffff00";
|
||||||
|
|
||||||
|
accent-b = mkStrOption config.lib.stylix.colors.base0A-rgb-b;
|
||||||
|
accent-g = mkStrOption config.lib.stylix.colors.base0A-rgb-g;
|
||||||
|
accent-r = mkStrOption config.lib.stylix.colors.base0A-rgb-r;
|
||||||
|
|
||||||
|
negative-b = mkStrOption config.lib.stylix.colors.base08-rgb-b;
|
||||||
|
negative-g = mkStrOption config.lib.stylix.colors.base08-rgb-g;
|
||||||
|
negative-r = mkStrOption config.lib.stylix.colors.base08-rgb-r;
|
||||||
|
|
||||||
|
neutral-b = mkStrOption config.lib.stylix.colors.base0C-rgb-b;
|
||||||
|
neutral-g = mkStrOption config.lib.stylix.colors.base0C-rgb-g;
|
||||||
|
neutral-r = mkStrOption config.lib.stylix.colors.base0C-rgb-r;
|
||||||
|
|
||||||
|
positive-b = mkStrOption config.lib.stylix.colors.base0B-rgb-b;
|
||||||
|
positive-g = mkStrOption config.lib.stylix.colors.base0B-rgb-g;
|
||||||
|
positive-r = mkStrOption config.lib.stylix.colors.base0B-rgb-r;
|
||||||
|
|
||||||
|
bg-b = mkStrOption config.lib.stylix.colors.base00-rgb-b;
|
||||||
|
bg-g = mkStrOption config.lib.stylix.colors.base00-rgb-g;
|
||||||
|
bg-r = mkStrOption config.lib.stylix.colors.base00-rgb-r;
|
||||||
|
|
||||||
|
fg-b = mkStrOption config.lib.stylix.colors.base06-rgb-b;
|
||||||
|
fg-g = mkStrOption config.lib.stylix.colors.base06-rgb-g;
|
||||||
|
fg-r = mkStrOption config.lib.stylix.colors.base06-rgb-r;
|
||||||
|
|
||||||
|
border = mkStrOption config.lib.stylix.colors.base01;
|
||||||
|
border-b = mkStrOption config.lib.stylix.colors.base01-rgb-b;
|
||||||
|
border-g = mkStrOption config.lib.stylix.colors.base01-rgb-g;
|
||||||
|
border-r = mkStrOption config.lib.stylix.colors.base01-rgb-r;
|
||||||
|
};
|
||||||
|
|
||||||
|
font = {
|
||||||
|
emoji.name = mkStrOption config.stylix.fonts.emoji.name;
|
||||||
|
monospace.name = mkStrOption config.stylix.fonts.monospace.name;
|
||||||
|
sansSerif.name = mkStrOption config.stylix.fonts.sansSerif.name;
|
||||||
|
serif.name = mkStrOption config.stylix.fonts.serif.name;
|
||||||
|
size = {
|
||||||
|
terminal = mkIntOption config.stylix.fonts.sizes.terminal;
|
||||||
|
popup = mkIntOption config.stylix.fonts.sizes.popups;
|
||||||
|
application = mkIntOption config.stylix.fonts.sizes.applications;
|
||||||
|
desktop = mkIntOption config.stylix.fonts.sizes.desktop;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
opacity = {
|
||||||
|
application = mkFloatOption config.stylix.opacity.applications;
|
||||||
|
desktop = mkFloatOption config.stylix.opacity.desktop;
|
||||||
|
popup = mkFloatOption config.stylix.opacity.popups;
|
||||||
|
terminal = mkFloatOption config.stylix.opacity.terminal;
|
||||||
|
hex = mkStrOption "D9";
|
||||||
|
};
|
||||||
|
|
||||||
|
window = {
|
||||||
|
gap = mkIntOption 8;
|
||||||
|
border = mkIntOption 4;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
{ pkgs, lib, ... } @args: let
|
|
||||||
sway = import ./desktop/sway args;
|
|
||||||
config = pkgs.writeText "swayConfig" sway.config;
|
|
||||||
script = pkgs.writeShellScriptBin "swayscript" sway.script;
|
|
||||||
in {
|
|
||||||
imports = [
|
|
||||||
./desktop/App.nix
|
|
||||||
./desktop/Bluetooth.nix
|
|
||||||
./desktop/Brightness.nix
|
|
||||||
./desktop/Dconf.nix
|
|
||||||
./desktop/Portal.nix
|
|
||||||
./desktop/Realtime.nix
|
|
||||||
./desktop/Sound.nix
|
|
||||||
./desktop/Waybar.nix
|
|
||||||
./desktop/Wayland.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
services.gnome.gnome-keyring.enable = lib.mkForce false;
|
|
||||||
environment = {
|
|
||||||
systemPackages = with pkgs; [
|
|
||||||
fuzzel # Application launcher.
|
|
||||||
grim slurp # Screenshot.
|
|
||||||
mako # Notification system.
|
|
||||||
networkmanagerapplet # Internet configuration.
|
|
||||||
pamixer pavucontrol pulseaudio # Audio.
|
|
||||||
playerctl # Multimedia controls.
|
|
||||||
script # My custom Sway shell scripts.
|
|
||||||
];
|
|
||||||
|
|
||||||
variables.XDG_CURRENT_DESKTOP = "sway";
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.sway = {
|
|
||||||
enable = true;
|
|
||||||
wrapperFeatures = {
|
|
||||||
base = true;
|
|
||||||
gtk = true;
|
|
||||||
};
|
|
||||||
extraOptions = [
|
|
||||||
"--config=${config}"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,6 +1,14 @@
|
||||||
{ pkgs, ... }: {
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
hardware.opentabletdriver.enable = true;
|
cfg = config.module.tablet;
|
||||||
environment.systemPackages = with pkgs; [
|
in {
|
||||||
krita
|
options = {
|
||||||
];
|
module.tablet.enable = mkEnableOption "Support for tables.";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
hardware.opentabletdriver.enable = true;
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
krita
|
||||||
|
];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
{ pkgs, ... }: {
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
virtualisation.libvirtd.enable = true;
|
cfg = config.module.virtmanager;
|
||||||
programs.virt-manager.enable = true;
|
in {
|
||||||
|
options = {
|
||||||
|
module.virtmanager.enable = mkEnableOption "VM support.";
|
||||||
|
};
|
||||||
|
|
||||||
# HACK: Fixes bug: https://www.reddit.com/r/NixOS/comments/1afbjiu/i_get_a_nonetype_error_when_trying_to_launch_a_vm/
|
config = mkIf cfg.enable {
|
||||||
# May also need to run: `gsettings set org.gnome.desktop.interface cursor-theme "Adwaita"`
|
virtualisation.libvirtd.enable = true;
|
||||||
environment.systemPackages = with pkgs; [
|
programs.virt-manager.enable = true;
|
||||||
# glib
|
|
||||||
gnome3.adwaita-icon-theme # default gnome cursors,
|
# HACK: Fixes bug: https://www.reddit.com/r/NixOS/comments/1afbjiu/i_get_a_nonetype_error_when_trying_to_launch_a_vm/
|
||||||
];
|
# May also need to run: `gsettings set org.gnome.desktop.interface cursor-theme "Adwaita"`
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
# glib
|
||||||
|
gnome3.adwaita-icon-theme # default gnome cursors,
|
||||||
|
];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,17 @@
|
||||||
# I want to pull all the Apk files in their current state
|
# I want to pull all the Apk files in their current state
|
||||||
# so that I always have an access to clients that match
|
# so that I always have an access to clients that match
|
||||||
# my service versions.
|
# my service versions.
|
||||||
{ pkgs, ... } @args: let
|
{ pkgs, lib, config, ... } @args: with lib; let
|
||||||
|
cfg = config.module.common.apks;
|
||||||
package = (pkgs.callPackage ./apks args);
|
package = (pkgs.callPackage ./apks args);
|
||||||
in {
|
in {
|
||||||
environment.etc.apks.source = package;
|
options = {
|
||||||
|
module.common.apks = {
|
||||||
|
enable = mkEnableOption "Android Apps Apk" // { default = true; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment.etc.apks.source = package;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,41 +2,51 @@
|
||||||
# This is a systemd service that pulls updates every hour.
|
# This is a systemd service that pulls updates every hour.
|
||||||
# Unlike system.autoUpgrade, this script also verifies my git signature
|
# Unlike system.autoUpgrade, this script also verifies my git signature
|
||||||
# to prevent unathorized changes to hosts.
|
# to prevent unathorized changes to hosts.
|
||||||
{ const, pkgs, lib, secret, util, ... }: {
|
{ const, pkgs, lib, util, config, ... }: with lib; let
|
||||||
systemd.services.autoupdate = util.mkStaticSystemdService {
|
cfg = config.module.common.autoupdate;
|
||||||
enable = true;
|
in {
|
||||||
description = "Signed system auto-update.";
|
options = {
|
||||||
serviceConfig.Type = "oneshot";
|
module.common.autoupdate = {
|
||||||
path = with pkgs; [
|
enable = mkEnableOption "System auto-updates." // { default = true; };
|
||||||
bash
|
};
|
||||||
git
|
|
||||||
gnumake
|
|
||||||
nixos-rebuild
|
|
||||||
openssh
|
|
||||||
];
|
|
||||||
script = ''
|
|
||||||
pushd /tmp
|
|
||||||
rm -rf ./nixos
|
|
||||||
${lib.getExe pkgs.git} clone --depth=1 --single-branch --branch=main ${const.url} ./nixos
|
|
||||||
pushd ./nixos
|
|
||||||
${lib.getExe pkgs.git} verify-commit HEAD || {
|
|
||||||
echo "Verification failed."
|
|
||||||
exit 1
|
|
||||||
};
|
|
||||||
${lib.getExe pkgs.gnumake} switch
|
|
||||||
'';
|
|
||||||
after = [ "network-online.target" ];
|
|
||||||
wants = [ "network-online.target" ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.timers.autoupdate = {
|
config = mkIf cfg.enable {
|
||||||
enable = true;
|
systemd.services.autoupdate = util.mkStaticSystemdService {
|
||||||
timerConfig = {
|
enable = true;
|
||||||
OnCalendar = "hourly";
|
description = "Signed system auto-update.";
|
||||||
Persistent = true;
|
serviceConfig.Type = "oneshot";
|
||||||
Unit = "autoupdate.service";
|
path = with pkgs; [
|
||||||
# RandomizedDelaySec = 60;
|
bash
|
||||||
|
git
|
||||||
|
gnumake
|
||||||
|
nixos-rebuild
|
||||||
|
openssh
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
pushd /tmp
|
||||||
|
rm -rf ./nixos
|
||||||
|
${getExe pkgs.git} clone --depth=1 --single-branch --branch=main ${const.url} ./nixos
|
||||||
|
pushd ./nixos
|
||||||
|
${getExe pkgs.git} verify-commit HEAD || {
|
||||||
|
echo "Verification failed."
|
||||||
|
exit 1
|
||||||
|
};
|
||||||
|
${getExe pkgs.gnumake} switch
|
||||||
|
'';
|
||||||
|
after = [ "network-online.target" ];
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.timers.autoupdate = {
|
||||||
|
enable = true;
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = "hourly";
|
||||||
|
Persistent = true;
|
||||||
|
Unit = "autoupdate.service";
|
||||||
|
# RandomizedDelaySec = 60;
|
||||||
|
};
|
||||||
|
wantedBy = [ "timers.target" ];
|
||||||
};
|
};
|
||||||
wantedBy = [ "timers.target" ];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ lib, style, util, pkgs, ... } @args: let
|
{ lib, util, pkgs, ... } @args: let
|
||||||
bash = import ./bash args;
|
bash = import ./bash args;
|
||||||
in {
|
in {
|
||||||
# Add my bash configuration to all *interactive* shells.
|
# Add my bash configuration to all *interactive* shells.
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
{ pkgs, ... }: {
|
{ pkgs, lib, config, ... }: with lib; let
|
||||||
# Distrobox works best with Podman, so enable it here.
|
cfg = config.module.common.distrobox;
|
||||||
imports = [ ./Podman.nix ];
|
in {
|
||||||
|
options = {
|
||||||
|
module.common.distrobox = {
|
||||||
|
enable = mkEnableOption "Distrobox." // { default = true; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
config = mkIf cfg.enable {
|
||||||
distrobox
|
# Distrobox works best with Podman, so enable it here.
|
||||||
];
|
module.podman.enable = true;
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [ distrobox ];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
# /etc overlay.
|
# /etc overlay.
|
||||||
|
# ISSUE: Should be fixed when you read this. Try it!
|
||||||
# boot.initrd.systemd.enable = true;
|
# boot.initrd.systemd.enable = true;
|
||||||
# systemd.sysusers.enable = true;
|
# systemd.sysusers.enable = true;
|
||||||
# system.etc.overlay = {
|
# system.etc.overlay = {
|
||||||
|
|
|
@ -1,59 +1,76 @@
|
||||||
{ pkgs, ... }: {
|
{ pkgs, config, lib, ... }: with lib; let
|
||||||
# Use latest kernel.
|
cfg = config.module.common.kernel;
|
||||||
boot.kernelPackages = pkgs.linuxPackages_latest;
|
in {
|
||||||
|
options = {
|
||||||
boot.kernel.sysctl = {
|
module.common.kernel = {
|
||||||
# # Spoof protection.
|
latest = mkOption {
|
||||||
# "net.ipv4.conf.default.rp_filter" = 1;
|
default = true;
|
||||||
# "net.ipv4.conf.all.rp_filter" = 1;
|
type = types.bool;
|
||||||
|
};
|
||||||
# # Packet forwarding.
|
};
|
||||||
# "net.ipv4.ip_forward" = 0;
|
|
||||||
# "net.ipv6.conf.all.forwarding" = 1;
|
|
||||||
|
|
||||||
# # MITM protection.
|
|
||||||
# "net.ipv4.conf.all.accept_redirects" = 0;
|
|
||||||
# "net.ipv6.conf.all.accept_redirects" = 0;
|
|
||||||
|
|
||||||
# # Do not send ICMP redirects (we are not a router).
|
|
||||||
# "net.ipv4.conf.all.send_redirects" = 0;
|
|
||||||
|
|
||||||
# # Do not accept IP source route packets (we are not a router).
|
|
||||||
# "net.ipv4.conf.all.accept_source_route" = 0;
|
|
||||||
# "net.ipv6.conf.all.accept_source_route" = 0;
|
|
||||||
|
|
||||||
# Allow sysrq.
|
|
||||||
"kernel.sysrq" = 1;
|
|
||||||
|
|
||||||
# # Protect filesystem links.
|
|
||||||
# "fs.protected_hardlinks" = 0;
|
|
||||||
# "fs.protected_symlinks" = 0;
|
|
||||||
|
|
||||||
# # Specify ttl.
|
|
||||||
# "net.ipv4.ip_default_ttl" = 65;
|
|
||||||
|
|
||||||
# # Lynis config.
|
|
||||||
# "kernel.core_uses_pid" = 1;
|
|
||||||
# "kernel.kptr_restrict" = 2;
|
|
||||||
|
|
||||||
# # IP hardening.
|
|
||||||
# "net.ipv4.conf.all.log_martians" = 1;
|
|
||||||
# "net.ipv4.conf.default.accept_redirects" = 0;
|
|
||||||
# "net.ipv4.conf.default.accept_source_route" = 0;
|
|
||||||
# "net.ipv4.conf.default.log_martians" = 0;
|
|
||||||
# "net.ipv4.tcp_timestamps" = 0;
|
|
||||||
# "net.ipv6.conf.default.accept_redirects" = 0;
|
|
||||||
|
|
||||||
# Increase file watchers.
|
|
||||||
"fs.inotify.max_user_instances" = 9999999;
|
|
||||||
"fs.inotify.max_user_watches" = 9999999;
|
|
||||||
"fs.inotify.max_user_event" = 9999999;
|
|
||||||
# "fs.file-max" = 999999;
|
|
||||||
|
|
||||||
# # Disable ipv6.
|
|
||||||
# "net.ipv6.conf.all.disable_ipv6" = 1;
|
|
||||||
# "net.ipv6.conf.default.disable_ipv6" = 1;
|
|
||||||
# "net.ipv6.conf.lo.disable_ipv6" = 1;
|
|
||||||
# "net.ipv6.conf.eth0.disable_ipv6" = 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config = mkMerge [
|
||||||
|
(mkIf cfg.latest {
|
||||||
|
# Use latest kernel.
|
||||||
|
boot.kernelPackages = pkgs.linuxPackages_latest;
|
||||||
|
})
|
||||||
|
|
||||||
|
{
|
||||||
|
boot.kernel.sysctl = {
|
||||||
|
# # Spoof protection.
|
||||||
|
# "net.ipv4.conf.default.rp_filter" = 1;
|
||||||
|
# "net.ipv4.conf.all.rp_filter" = 1;
|
||||||
|
|
||||||
|
# # Packet forwarding.
|
||||||
|
# "net.ipv4.ip_forward" = 0;
|
||||||
|
# "net.ipv6.conf.all.forwarding" = 1;
|
||||||
|
|
||||||
|
# # MITM protection.
|
||||||
|
# "net.ipv4.conf.all.accept_redirects" = 0;
|
||||||
|
# "net.ipv6.conf.all.accept_redirects" = 0;
|
||||||
|
|
||||||
|
# # Do not send ICMP redirects (we are not a router).
|
||||||
|
# "net.ipv4.conf.all.send_redirects" = 0;
|
||||||
|
|
||||||
|
# # Do not accept IP source route packets (we are not a router).
|
||||||
|
# "net.ipv4.conf.all.accept_source_route" = 0;
|
||||||
|
# "net.ipv6.conf.all.accept_source_route" = 0;
|
||||||
|
|
||||||
|
# Allow sysrq.
|
||||||
|
"kernel.sysrq" = 1;
|
||||||
|
|
||||||
|
# # Protect filesystem links.
|
||||||
|
# "fs.protected_hardlinks" = 0;
|
||||||
|
# "fs.protected_symlinks" = 0;
|
||||||
|
|
||||||
|
# # Specify ttl.
|
||||||
|
# "net.ipv4.ip_default_ttl" = 65;
|
||||||
|
|
||||||
|
# # Lynis config.
|
||||||
|
# "kernel.core_uses_pid" = 1;
|
||||||
|
# "kernel.kptr_restrict" = 2;
|
||||||
|
|
||||||
|
# # IP hardening.
|
||||||
|
# "net.ipv4.conf.all.log_martians" = 1;
|
||||||
|
# "net.ipv4.conf.default.accept_redirects" = 0;
|
||||||
|
# "net.ipv4.conf.default.accept_source_route" = 0;
|
||||||
|
# "net.ipv4.conf.default.log_martians" = 0;
|
||||||
|
# "net.ipv4.tcp_timestamps" = 0;
|
||||||
|
# "net.ipv6.conf.default.accept_redirects" = 0;
|
||||||
|
|
||||||
|
# Increase file watchers.
|
||||||
|
"fs.inotify.max_user_instances" = 9999999;
|
||||||
|
"fs.inotify.max_user_watches" = 9999999;
|
||||||
|
"fs.inotify.max_user_event" = 9999999;
|
||||||
|
# "fs.file-max" = 999999;
|
||||||
|
|
||||||
|
# # Disable ipv6.
|
||||||
|
# "net.ipv6.conf.all.disable_ipv6" = 1;
|
||||||
|
# "net.ipv6.conf.default.disable_ipv6" = 1;
|
||||||
|
# "net.ipv6.conf.lo.disable_ipv6" = 1;
|
||||||
|
# "net.ipv6.conf.eth0.disable_ipv6" = 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,88 +1,98 @@
|
||||||
{ pkgs, config, ... }: {
|
{ pkgs, config, lib, ... }: with lib; let
|
||||||
environment.systemPackages = with pkgs; [ keyd ];
|
cfg = config.module.common.keyd;
|
||||||
|
in {
|
||||||
services.keyd = {
|
options = {
|
||||||
enable = true;
|
module.common.keyd = {
|
||||||
keyboards.default = {
|
enable = mkEnableOption "Keyboard remaps." // { default = true; };
|
||||||
ids = [ "*" ];
|
|
||||||
settings = {
|
|
||||||
main = {
|
|
||||||
backspace = "delete"; # Delete key on backspace.
|
|
||||||
capslock = "overload(control, esc)"; # Ctrl/esc combo.
|
|
||||||
compose = "layer(layer_number)"; # Number input layer.
|
|
||||||
esc = "${config.setting.sysctrl}"; # System controls.
|
|
||||||
leftcontrol = "overload(layer_alternative, leftcontrol)"; # Alternative layer for home, end etc.
|
|
||||||
rightcontrol = "layer(layer_control)"; # Media and other controls.
|
|
||||||
rightshift = "backspace"; # Backspace.
|
|
||||||
};
|
|
||||||
|
|
||||||
# Alternative navigation.
|
|
||||||
layer_alternative = {
|
|
||||||
w = "pageup";
|
|
||||||
a = "home";
|
|
||||||
s = "pagedown";
|
|
||||||
d = "end";
|
|
||||||
x = "cut";
|
|
||||||
c = "copy";
|
|
||||||
v = "paste";
|
|
||||||
h = "left";
|
|
||||||
j = "down";
|
|
||||||
k = "up";
|
|
||||||
l = "right";
|
|
||||||
esc = "esc";
|
|
||||||
rightcontrol = "leftcontrol";
|
|
||||||
capslock = "capslock";
|
|
||||||
# space = "macro2(1, 100, macro(space))"; # NOTE: Possible bhop example. Use in per-application, not here.
|
|
||||||
};
|
|
||||||
|
|
||||||
# Media controls.
|
|
||||||
layer_control = {
|
|
||||||
space = "playpause";
|
|
||||||
a = "back";
|
|
||||||
c = "ejectcd";
|
|
||||||
d = "forward";
|
|
||||||
e = "nextsong";
|
|
||||||
q = "previoussong";
|
|
||||||
s = "volumedown";
|
|
||||||
w = "volumeup";
|
|
||||||
x = "stopcd";
|
|
||||||
z = "mute";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Number inputs.
|
|
||||||
layer_number = {
|
|
||||||
q = "1";
|
|
||||||
w = "2";
|
|
||||||
e = "3";
|
|
||||||
a = "4";
|
|
||||||
s = "5";
|
|
||||||
d = "6";
|
|
||||||
z = "7";
|
|
||||||
x = "8";
|
|
||||||
c = "9";
|
|
||||||
space = "0";
|
|
||||||
"1" = "f13";
|
|
||||||
"2" = "f14";
|
|
||||||
"3" = "f15";
|
|
||||||
"4" = "f16";
|
|
||||||
"5" = "f17";
|
|
||||||
"6" = "f18";
|
|
||||||
"7" = "f19";
|
|
||||||
"8" = "f20";
|
|
||||||
"9" = "f21";
|
|
||||||
"0" = "f22";
|
|
||||||
"-" = "f23";
|
|
||||||
"=" = "f24";
|
|
||||||
enter = "kpenter";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# HACK: Workaround for https://github.com/NixOS/nixpkgs/issues/290161
|
config = mkIf cfg.enable {
|
||||||
users.groups.keyd = {};
|
environment.systemPackages = with pkgs; [ keyd ];
|
||||||
systemd.services.keyd.serviceConfig.CapabilityBoundingSet = [ "CAP_SETGID" ];
|
|
||||||
|
|
||||||
# Debug toggle just in case I need it again.
|
services.keyd = {
|
||||||
# systemd.services.keyd.environment.KEYD_DEBUG = "1";
|
enable = true;
|
||||||
|
keyboards.default = {
|
||||||
|
ids = [ "*" ];
|
||||||
|
settings = {
|
||||||
|
main = {
|
||||||
|
backspace = "delete"; # Delete key on backspace.
|
||||||
|
capslock = "overload(control, esc)"; # Ctrl/esc combo.
|
||||||
|
compose = "layer(layer_number)"; # Number input layer.
|
||||||
|
esc = "${config.setting.sysctrl}"; # System controls.
|
||||||
|
leftcontrol = "overload(layer_alternative, leftcontrol)"; # Alternative layer for home, end etc.
|
||||||
|
rightcontrol = "layer(layer_control)"; # Media and other controls.
|
||||||
|
rightshift = "backspace"; # Backspace.
|
||||||
|
};
|
||||||
|
|
||||||
|
# Alternative navigation.
|
||||||
|
layer_alternative = {
|
||||||
|
w = "pageup";
|
||||||
|
a = "home";
|
||||||
|
s = "pagedown";
|
||||||
|
d = "end";
|
||||||
|
x = "cut";
|
||||||
|
c = "copy";
|
||||||
|
v = "paste";
|
||||||
|
h = "left";
|
||||||
|
j = "down";
|
||||||
|
k = "up";
|
||||||
|
l = "right";
|
||||||
|
esc = "esc";
|
||||||
|
rightcontrol = "leftcontrol";
|
||||||
|
capslock = "capslock";
|
||||||
|
# space = "macro2(1, 100, macro(space))"; # NOTE: Possible bhop example. Use in per-application, not here.
|
||||||
|
};
|
||||||
|
|
||||||
|
# Media controls.
|
||||||
|
layer_control = {
|
||||||
|
space = "playpause";
|
||||||
|
a = "back";
|
||||||
|
c = "ejectcd";
|
||||||
|
d = "forward";
|
||||||
|
e = "nextsong";
|
||||||
|
q = "previoussong";
|
||||||
|
s = "volumedown";
|
||||||
|
w = "volumeup";
|
||||||
|
x = "stopcd";
|
||||||
|
z = "mute";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Number inputs.
|
||||||
|
layer_number = {
|
||||||
|
q = "1";
|
||||||
|
w = "2";
|
||||||
|
e = "3";
|
||||||
|
a = "4";
|
||||||
|
s = "5";
|
||||||
|
d = "6";
|
||||||
|
z = "7";
|
||||||
|
x = "8";
|
||||||
|
c = "9";
|
||||||
|
space = "0";
|
||||||
|
"1" = "f13";
|
||||||
|
"2" = "f14";
|
||||||
|
"3" = "f15";
|
||||||
|
"4" = "f16";
|
||||||
|
"5" = "f17";
|
||||||
|
"6" = "f18";
|
||||||
|
"7" = "f19";
|
||||||
|
"8" = "f20";
|
||||||
|
"9" = "f21";
|
||||||
|
"0" = "f22";
|
||||||
|
"-" = "f23";
|
||||||
|
"=" = "f24";
|
||||||
|
enter = "kpenter";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# HACK: Workaround for https://github.com/NixOS/nixpkgs/issues/290161
|
||||||
|
users.groups.keyd = {};
|
||||||
|
systemd.services.keyd.serviceConfig.CapabilityBoundingSet = [ "CAP_SETGID" ];
|
||||||
|
|
||||||
|
# Debug toggle just in case I need it again.
|
||||||
|
# systemd.services.keyd.environment.KEYD_DEBUG = "1";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue