Huge containers update

This commit is contained in:
Dmitry Voronin 2024-06-09 23:35:53 +03:00
parent 620da6ccc1
commit 5456ec4824
Signed by: voronind
SSH key fingerprint: SHA256:3kBb4iV2ahufEBNq+vFbUe4QYfHt98DHQjN7QaptY9k
71 changed files with 2743 additions and 105 deletions

View file

@ -92,7 +92,7 @@ Tmux:<br>
<details> <details>
<summary>Media Controls</summary> <summary>Media Controls</summary>
<img src="https://i.imgur.com/p9trGMi.png" /> <img src="https://i.imgur.com/FRZ7G2N.png" />
</details> </details>
<details> <details>

View file

@ -17,20 +17,23 @@ in {
environment.systemPackages = [ pkgs.postgresql ]; environment.systemPackages = [ pkgs.postgresql ];
services.nextcloud = { services.nextcloud = {
enable = true; enable = true;
package = pkgs.nextcloud29; # package = pkgs.nextcloud29;
hostName = cfg.domain; hostName = cfg.domain;
# phpOptions = {
# memory_limit = lib.mkForce "20G";
# };
config = { config = {
adminuser = "root"; adminuser = "root";
adminpassFile = "${pkgs.writeText "NextcloudPassword" "root"}"; adminpassFile = "${pkgs.writeText "NextcloudPassword" "root"}";
dbhost = container.config.postgres.address; dbhost = container.config.postgres.address;
dbname = "nextcloud"; dbname = "nextcloud";
# dbpassFile = "${pkgs.writeText "NextcloudDbPassword" "nextcloud"}"; dbpassFile = "${pkgs.writeText "NextcloudDbPassword" "nextcloud"}";
dbtype = "pgsql"; dbtype = "pgsql";
dbuser = "nextcloud"; dbuser = "nextcloud";
}; };
extraApps = { extraApps = {
inherit (config.services.nextcloud.package.packages.apps) contacts calendar; inherit (config.services.nextcloud.package.packages.apps) contacts calendar onlyoffice;
}; };
extraAppsEnable = true; extraAppsEnable = true;
settings = { settings = {

36
container/Ddns.nix Normal file
View file

@ -0,0 +1,36 @@
{ container, domain, ... } @args: let
cfg = container.config.ddns;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.ddns = container.mkContainer cfg {
bindMounts = {
"/data" = {
hostPath = "${cfg.storage}/data";
isReadOnly = true;
};
};
config = { ... }: container.mkContainerConfig cfg {
services.cloudflare-dyndns = {
enable = true;
apiTokenFile = "/data/token";
deleteMissing = true;
ipv4 = true;
ipv6 = false;
proxied = false;
domains = [ domain ] ++ map (sub: "${sub}.${domain}") [
"cloud"
"git"
"mail"
"office"
"paste"
"play"
"vpn"
];
};
};
};
}

115
container/Dns.nix Normal file
View file

@ -0,0 +1,115 @@
{ container, ... } @args: let
cfg = container.config.dns;
in {
containers.dns = container.mkContainer cfg {
forwardPorts = [
{
containerPort = 53;
hostPort = 53;
protocol = "udp";
} {
containerPort = 53;
hostPort = 53;
protocol = "tcp";
}
];
config = { pkgs, lib, ... }: container.mkContainerConfig cfg {
environment.systemPackages = [
pkgs.cloudflared
];
systemd.services.cloudflared = {
description = "Cloudflare DoH server.";
enable = true;
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
ExecStart = "${lib.getExe pkgs.cloudflared} proxy-dns --port 5054";
};
};
services.blocky = {
enable = true;
settings = {
upstream = {
default = [
"0.0.0.0:5054"
"0.0.0.0:5054"
];
};
blocking = {
blackLists = {
suspicious = [
"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 = {
"voronind.com" = "192.168.1.2";
};
};
port = "53";
httpPort = "80";
};
};
};
};
}

32
container/Download.nix Normal file
View file

@ -0,0 +1,32 @@
{ container, lib, ... } @args: let
cfg = container.config.download;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.download = container.mkContainer cfg {
bindMounts = {
"/var/lib/deluge" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
} // builtins.listToAttrs (lib.imap0 (i: path:
{
name = "/download/${toString i}";
value = {
hostPath = path;
isReadOnly = false;
};
}
) cfg.download);
config = { ... }: container.mkContainerConfig cfg {
services.deluge = {
enable = true;
dataDir = "/var/lib/deluge";
web.enable = true;
};
};
};
}

74
container/Git.nix Normal file
View file

@ -0,0 +1,74 @@
{ container, ... } @args: let
cfg = container.config.git;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.git = container.mkContainer cfg {
bindMounts = {
"/var/lib/gitea" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
};
config = { pkgs, ... }: container.mkContainerConfig cfg {
environment.systemPackages = with pkgs; [ gitea ];
services.gitea = {
enable = true;
stateDir = "/var/lib/gitea";
database = let
postgre = container.config.postgres;
in {
type = "postgres";
host = postgre.address;
port = postgre.port;
user = "gitea";
createDatabase = false;
};
settings = let
gcArgs = "--aggressive --no-cruft --prune=now";
gcTimeout = 600;
in {
"service".DISABLE_REGISTRATION = false;
"log".LEVEL = "Error";
"server" = {
DISABLE_SSH = true;
DOMAIN = cfg.domain;
HTTP_ADDR = cfg.address;
# ROOT_URL = 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;
};
"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;
};
};
};
};
}

46
container/Hdd.nix Normal file
View file

@ -0,0 +1,46 @@
# ISSUE: Broken, can't read/write sda device.
{ container, ... } @args: let
cfg = container.config.hdd;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.hdd = container.mkContainer cfg {
# bindMounts = let
# attachDrive = hostPath: {
# inherit hostPath;
# isReadOnly = false;
# };
# in {
# "/opt/scrutiny" = {
# hostPath = "${cfg.storage}/data";
# isReadOnly = false;
# };
# "/dev/sda" = attachDrive "/dev/sda";
# };
# allowedDevices = [
# {
# modifier = "rwm";
# node = "/dev/sda";
# }
# ];
# additionalCapabilities = [ "CAP_SYS_ADMIN" ];
config = { pkgs, ... }: container.mkContainerConfig cfg {
environment.systemPackages = with pkgs; [ smartmontools ];
services.scrutiny = {
enable = true;
settings.web = {
listen = {
host = cfg.address;
port = cfg.port;
};
};
};
};
};
}

25
container/Home.nix Normal file
View file

@ -0,0 +1,25 @@
{ container, pkgs, util, ... } @args: let
cfg = container.config.home;
package = (pkgs.callpackage ./homer args);
in {
containers.home = container.mkContainer cfg {
config = { ... }: container.mkContainerConfig cfg {
environment.systempackages = [ package ];
systemd.packages = [ package ];
services.nginx = {
enable = true;
virtualhosts.${cfg.domain} = container.mkserver {
default = true;
root = "${package}";
locations = {
"/".extraconfig = ''
try_files $uri $uri/index.html;
'';
};
};
};
};
};
}

62
container/Iot.nix Normal file
View file

@ -0,0 +1,62 @@
{ container, ... } @args: let
cfg = container.config.iot;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.iot = container.mkContainer cfg {
bindMounts = {
"/var/lib/hass" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
# "/photo" = {
# hostPath = "${cfg.photos}";
# isReadOnly = true;
# };
# "/dev/ttyACM0" = {
# hostPath = "/dev/ttyACM0";
# isReadOnly = false;
# };
# "/dev/serial/by-id" = {
# hostPath = "/dev/serial/by-id";
# isReadOnly = false;
# };
};
config = { pkgs, ... }: container.mkContainerConfig cfg {
services.home-assistant = {
# NOTE: Missing: hacs. Inside hacs: `card-mod`, `Clock Weather Card`, `WallPanel` and `Yandex.Station`.
enable = true;
extraComponents = [
"caldav"
"met"
"sun"
"systemmonitor"
"zha"
];
extraPackages = python3Packages: with python3Packages; [
aiodhcpwatcher
aiodiscover
async-upnp-client
ha-av
ha-ffmpeg
hassil
home-assistant-intents
mutagen
numpy
pynacl
pyturbojpeg
zeroconf
];
configDir = "/var/lib/hass";
# lovelaceConfig = {
# title = "Home IoT control center.";
# };
# NOTE: Using imperative config because of secrets.
config = null;
};
};
};
}

50
container/Jobber.nix Normal file
View file

@ -0,0 +1,50 @@
{ container, pkgsJobber, poetry2nixJobber, lib, ... } @args: let
cfg = container.config.jobber;
script = import ./jobber { poetry2nix = poetry2nixJobber; pkgs = pkgsJobber; };
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.jobber = container.mkContainer cfg {
bindMounts = {
"/data" = {
hostPath = "${cfg.storage}/data";
isReadOnly = true;
};
};
enableTun = true;
config = { lib, ... }: let
packages = [ script ] ++ (with pkgsJobber; [
firefox
geckodriver
openvpn
python311
]);
in container.mkContainerConfig cfg {
networking = lib.mkForce {
nameservers = [
"10.9.0.5"
];
};
systemd.services.jobber = {
description = "My job is pushing the button.";
enable = true;
wantedBy = [ "multi-user.target" ];
path = packages;
environment = {
PYTHONUNBUFFERED = "1";
PYTHONDONTWRITEBYTECODE = "1";
};
serviceConfig = {
Type = "simple";
ExecStart = "${script}/bin/jobber -u";
Restart = "on-failure";
};
};
};
};
}

175
container/Mail.nix Normal file
View file

@ -0,0 +1,175 @@
# Guide: https://nixos-mailserver.readthedocs.io/en/latest/setup-guide.html
{ container, domain, pkgs, util, const, ... } @args: let
cfg = container.config.mail;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
"data/indices"
"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";
}
];
bindMounts = {
"/var/lib/dovecot/indices" = {
hostPath = "${cfg.storage}/data/indices";
isReadOnly = false;
};
"/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 = "${container.config.proxy.storage}/letsencrypt";
isReadOnly = false;
};
};
config = { pkgs, config, ... }: container.mkContainerConfig cfg {
imports = [
(builtins.fetchTarball {
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-${const.stateVersion}/nixos-mailserver-nixos-${const.stateVersion}.tar.gz";
sha256 = "sha256:0clvw4622mqzk1aqw1qn6shl9pai097q62mq1ibzscnjayhp278b";
})
];
mailserver = {
enable = true;
fqdn = cfg.domain;
domains = [ 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;
};
};
enableImap = true;
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;
organizationName = "voronind";
# email = "noreply@${domain}";
};
# monitoring = {
# enable = true;
# alertAddress = "admin@${domain}";
# };
};
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_user'] = "%u";
$config['smtp_pass'] = "%p";
'';
};
services.nginx = {
virtualHosts.${cfg.domain} = {
forceSSL = false;
enableACME = false;
};
};
};
};
}

22
container/Office.nix Normal file
View file

@ -0,0 +1,22 @@
{ container, pkgs, util, ... } @args: let
cfg = container.config.office;
in {
containers.office = container.mkContainer cfg {
config = { ... }: container.mkContainerConfig cfg {
services.onlyoffice = let
dbName = "onlyoffice";
in {
enable = true;
hostname = cfg.domain;
postgresName = dbName;
postgresHost = container.config.postgres.address;
postgresUser = dbName;
postgresPasswordFile = "${pkgs.writeText "OfficeDbPassword" dbName}";
examplePort = cfg.port;
enableExampleServer = true;
};
};
};
}

46
container/Paper.nix Normal file
View file

@ -0,0 +1,46 @@
{ container, pkgs, util, ... } @args: let
cfg = container.config.paper;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.paper = container.mkContainer cfg {
bindMounts = {
"/var/lib/paperless" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
};
config = { lib, ... }: container.mkContainerConfig cfg {
services.paperless = {
enable = true;
dataDir = "/var/lib/paperless";
# address = cfg.domain;
address = "0.0.0.0";
port = cfg.port;
passwordFile = pkgs.writeText "PaperlessPassword" "root";
settings = {
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.
systemd.services.paperless-scheduler.serviceConfig = {
PrivateNetwork = lib.mkForce false;
};
systemd.services.paperless-consumer.serviceConfig = {
PrivateNetwork = lib.mkForce false;
};
};
};
}

33
container/Pass.nix Normal file
View file

@ -0,0 +1,33 @@
{ container, ... } @args: let
cfg = container.config.pass;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.pass = container.mkContainer cfg {
bindMounts = {
"/var/lib/bitwarden_rs" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
};
config = { ... }: container.mkContainerConfig cfg {
services.vaultwarden = {
enable = true;
dbBackend = "postgresql";
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;
};
};
};
};
}

100
container/Photoprocess.nix Normal file
View file

@ -0,0 +1,100 @@
# Takes pictures from first photo dir, processes and stores to the second one.
{ container, util, ... } @args: let
cfg = container.config.photoprocess;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.photoprocess = container.mkContainer cfg {
bindMounts = {
"/data" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
"/in" = {
# hostPath = "${container.config.cloud.storage}/data/data/"
hostPath = builtins.elemAt cfg.photo 0;
isReadOnly = false;
};
"/out" = {
hostPath = builtins.elemAt cfg.photo 1;
isReadOnly = false;
};
};
config = { pkgs, lib, ... }: container.mkContainerConfig cfg {
systemd.services.photosprocess = let
script = pkgs.writeText "PhotoprocessScript" (util.trimTabs ''
source /data/Notify.sh
cd /in
# Convert png to jpg.
for img in $(ls *.png) $(ls *.PNG); do
filename=''${img%.*}
convert "$filename.png" "$filename.jpg"
done
rm *.png *.PNG
# Rename bad extensions.
for img in $(ls *.jpeg) $(ls *.JPG) $(ls *.JPEG); do
filename=''${img%.*}
mv "$img" "$filename.jpg"
done
# Compress jpg.
mogrify -resize 2073600@ *.jpg
jpegoptim --size=1000k *.jpg
# Rename to hash.
for file in *; do
if [[ -f "$file" ]]; then
extension="''${file##*.}"
if [ -f "$file" ] && [ "$extension" != "$file" ]; then
new_name="''${file%$extension}"
else
new_name="$file"
extension=""
fi
new_name=$(sha1sum "$file" | cut -d\ -f1)
if [[ "$extension" != "" ]]; then
new_name="''${new_name,,}.$extension"
else
new_name="''${new_name,,}"
fi
mv "$file" "$new_name"
fi
done
# Move to images.
total_photos=$(ls | wc -l)
mv *.jpg /out
notify_silent "Photos processed: $total_photos"
'');
in util.mkStaticSystemdService {
enable = true;
description = "Process uploaded photos.";
serviceConfig = {
Type = "oneshot";
ExecStart = "-${lib.getExe pkgs.bashInteractive} ${script}";
Restart = "on-failure";
};
path = with pkgs; [
curl
imagemagick
jpegoptim
];
};
systemd.timers.photosprocess = {
timerConfig = {
OnCalendar = "daily";
Persistent = true;
Unit = "photosprocess.service";
};
wantedBy = [ "timers.target" ];
};
};
};
}

View file

@ -1,4 +1,4 @@
{ container, ... } @args: let { container, lib, ... } @args: let
cfg = container.config.postgres; cfg = container.config.postgres;
in { in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [ systemd.tmpfiles.rules = container.mkContainerDir cfg [
@ -15,25 +15,43 @@ in {
config = { pkgs, ... }: container.mkContainerConfig cfg { config = { pkgs, ... }: container.mkContainerConfig cfg {
services.postgresql = let services.postgresql = let
databases = [ # Populate with services here.
"privatebin" configurations = with container.config; {
"nextcloud" gitea = git;
]; nextcloud = cloud;
privatebin = paste;
onlyoffice = office;
paperless = paper;
vaultwarden = pass;
invidious = yt;
};
access = configurations // {
all = { address = container.host; };
};
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 { in {
inherit authentication ensureDatabases ensureUsers;
enable = true; enable = true;
package = pkgs.postgresql_14; package = pkgs.postgresql_14;
dataDir = "/var/lib/postgresql/data/14"; dataDir = "/var/lib/postgresql/data/14";
enableTCPIP = true; enableTCPIP = true;
authentication = ''
host all all ${container.host}/32 trust
host privatebin privatebin ${container.config.paste.address}/32 trust
host nextcloud nextcloud ${container.config.cloud.address}/32 trust
'';
ensureDatabases = databases;
ensureUsers = map (name: {
inherit name;
ensureDBOwnership = true;
}) databases;
}; };
}; };
}; };

36
container/Print.nix Normal file
View file

@ -0,0 +1,36 @@
# NOTE: Login to contaier, run passwd and use that root/pw combo for administration. `AllowFrom = all` doesn't seem to work.
# ipp://192.168.2.237
# Pantum M6500W-Series
{ container, pkgs, ... } @args: let
cfg = container.config.print;
package = pkgs.callPackage ./print args;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.print = container.mkContainer cfg {
bindMounts = {
"/var/lib/cups" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
};
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;
};
};
};
}

View file

@ -8,6 +8,18 @@ in {
]; ];
containers.proxy = container.mkContainer cfg { containers.proxy = container.mkContainer cfg {
forwardPorts = [
{
containerPort = 80;
hostPort = 80;
protocol = "tcp";
} {
containerPort = 443;
hostPort = 443;
protocol = "tcp";
}
];
bindMounts = { bindMounts = {
"/etc/letsencrypt" = { "/etc/letsencrypt" = {
hostPath = "${cfg.storage}/letsencrypt"; hostPath = "${cfg.storage}/letsencrypt";
@ -34,6 +46,7 @@ in {
eventsConfig = util.trimTabs '' eventsConfig = util.trimTabs ''
worker_connections 4096; worker_connections 4096;
''; '';
# TODO: Fix 80 redirect and 403 default.
appendHttpConfig = util.trimTabs '' appendHttpConfig = util.trimTabs ''
server { server {
server_name default_server; server_name default_server;

25
container/Rabbitmq.nix Normal file
View file

@ -0,0 +1,25 @@
{ container, pkgs, util, ... } @args: let
cfg = container.config.rabbitmq;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.rabbitmq = container.mkContainer cfg {
bindMounts = {
"/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";
};
};
};
}

36
container/Read.nix Normal file
View file

@ -0,0 +1,36 @@
{ container, lib, ... } @args: let
cfg = container.config.read;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.read = container.mkContainer cfg {
bindMounts = {
"/var/lib/kavita" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
} // builtins.listToAttrs (lib.imap0 (i: path:
{
name = "/book/${toString i}";
value = {
hostPath = path;
isReadOnly = true;
};
}
) cfg.book);
config = { pkgs, ... }: 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;
};
};
};
};
}

15
container/Redis.nix Normal file
View file

@ -0,0 +1,15 @@
{ container, pkgs, util, ... } @args: let
cfg = container.config.redis;
in {
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" ];
};
};
};
}

19
container/Search.nix Normal file
View file

@ -0,0 +1,19 @@
{ container, ... } @args: let
cfg = container.config.search;
in {
containers.search = container.mkContainer cfg {
config = { pkgs, ... }: container.mkContainerConfig cfg {
services.searx = {
enable = true;
package = pkgs.searxng;
settings = {
server = {
bind_address = cfg.address;
port = cfg.port;
secret_key = "searxxx";
};
};
};
};
};
}

32
container/Status.nix Normal file
View file

@ -0,0 +1,32 @@
{ container, ... } @args: let
cfg = container.config.status;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.status = container.mkContainer cfg {
bindMounts = {
"/var/lib/uptime-kuma" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
};
config = { lib, ... }: container.mkContainerConfig cfg {
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 = lib.mkForce false;
};
};
};
}

33
container/Stock.nix Normal file
View file

@ -0,0 +1,33 @@
{ container, ... } @args: let
cfg = container.config.stock;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
];
containers.stock = container.mkContainer cfg {
bindMounts = {
"/var/lib/grocy" = {
hostPath = "${cfg.storage}/data";
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";
};
};
};
};
}

65
container/Vpn.nix Normal file
View file

@ -0,0 +1,65 @@
{ container, ... } @args: let
cfg = container.config.vpn;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
"data/preshared"
];
boot.kernel.sysctl = {
"net.ipv4.conf.all.src_valid_mark" = 1;
};
containers.vpn = container.mkContainer cfg {
bindMounts = {
"/var/lib/wireguard" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
};
config = { pkgs, ... }: container.mkContainerConfig cfg {
environment.systemPackages = with pkgs; [ wireguard-tools ];
networking.useNetworkd = true;
systemd.network = {
enable = true;
netdevs = {
"50-wg0" = {
netdevConfig = {
Kind = "wireguard";
MTUBytes = "1300";
Name = "wg0";
};
wireguardConfig = {
PrivateKeyFile = "/var/lib/wireguard/privkey";
ListenPort = cfg.port;
};
wireguardPeers = let
mkPeer = name: ip: PublicKey: {
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=")
];
};
};
networks.wg0 = {
matchConfig.Name = "wg0";
address = ["10.1.1.0/24"];
networkConfig = {
IPForward = true;
IPMasquerade = "ipv4";
};
};
};
};
};
}

29
container/Watch.nix Normal file
View file

@ -0,0 +1,29 @@
{ container, ... } @args: let
cfg = container.config.watch;
in {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
"cache"
];
containers.watch = container.mkContainer cfg {
bindMounts = {
"/var/lib/jellyfin" = {
hostPath = "${cfg.storage}/data";
isReadOnly = false;
};
"/var/cache/jellyfin" = {
hostPath = "${cfg.storage}/cache";
isReadOnly = false;
};
};
config = { ... }: container.mkContainerConfig cfg {
services.jellyfin = {
enable = true;
cacheDir = "/var/cache/jellyfin";
dataDir = "/var/lib/jellyfin";
};
};
};
}

26
container/Yt.nix Normal file
View file

@ -0,0 +1,26 @@
{ container, ... } @args: let
cfg = container.config.yt;
in {
containers.yt = container.mkContainer cfg {
config = { pkgs, ... }: container.mkContainerConfig cfg {
services.invidious = {
enable = true;
domain = cfg.domain;
port = cfg.port;
nginx.enable = false;
database = {
port = container.config.postgres.port;
host = container.config.postgres.address;
createLocally = false;
passwordFile = "${pkgs.writeText "InvidiousDbPassword" "invidious"}";
};
settings = {
admins = [ "root" ];
captcha_enabled = false;
check_tables = true;
registration_enabled = false;
};
};
};
};
}

View file

@ -3,6 +3,7 @@
, host , host
, storage , storage
, domain , domain
, media
, ... }: { , ... }: {
inherit host; inherit host;
@ -16,6 +17,8 @@
mkContainerConfig = config: cfg: lib.recursiveUpdate cfg { mkContainerConfig = config: cfg: lib.recursiveUpdate cfg {
system.stateVersion = const.stateVersion; system.stateVersion = const.stateVersion;
nixpkgs.config.allowUnfree = true;
users.users.root.password = ""; users.users.root.password = "";
users.mutableUsers = false; users.mutableUsers = false;
@ -34,29 +37,170 @@
forceSSL = false; forceSSL = false;
}; };
localAccess = "192.168.1.0/24";
config = { config = {
change = { change = {
address = "10.1.0.41"; address = "10.1.0.41";
port = 5000;
domain = "change.${domain}"; domain = "change.${domain}";
storage = "${storage}/change"; storage = "${storage}/change";
}; };
cloud = { cloud = {
address = "10.1.0.13"; address = "10.1.0.13";
port = 80;
domain = "cloud.${domain}"; domain = "cloud.${domain}";
storage = "${storage}/cloud"; storage = "${storage}/cloud";
}; };
ddns = {
address = "10.1.0.31";
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;
};
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 = { paste = {
address = "10.1.0.14"; address = "10.1.0.14";
domain = "paste.${domain}"; domain = "paste.${domain}";
port = 80;
storage = "${storage}/paste"; storage = "${storage}/paste";
}; };
photoprocess = {
inherit (media) photo;
address = "10.1.0.4";
storage = "${storage}/photoprocess";
};
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 = { proxy = {
address = "10.1.0.2"; address = "10.1.0.2";
storage = "${storage}/proxy"; storage = "${storage}/proxy";
}; };
postgres = { postgres = {
address = "10.1.0.3"; address = "10.1.0.3";
port = 5432;
storage = "${storage}/postgres"; storage = "${storage}/postgres";
}; };
rabbitmq = {
address = "10.1.0.28";
port = 5672;
storage = "${storage}/rabbitmq";
};
read = {
inherit (media) book;
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 = {
address = "10.1.0.11";
domain = "watch.${domain}";
port = 8096;
storage = "${storage}/watch";
};
yt = {
address = "10.1.0.19";
domain = "yt.${domain}";
port = 3000;
};
}; };
} }

100
container/homer/Config.nix Normal file
View file

@ -0,0 +1,100 @@
{ lib, container, ... }: let
iconTheme = "fa-solid";
mkGroup = name: icon: items: {
inherit name items;
icon = "${iconTheme} ${icon}";
};
mkLink = name: icon: url: {
inherit name url;
icon = "${iconTheme} ${icon}";
target = "_blank";
};
config = {
title = "Dashboard";
subtitle = "Home";
header = false;
footer = false;
connectivityCheck = false;
theme = "default";
colors = let
colors = {
background = "#1b1b1b";
card-background = "#2b2b2b";
card-shadow = "#2b2b2b";
highlight-hover = "#003006";
highlight-primary = "#004016";
highlight-secondary = "#004016";
link = "#666666";
link-hover = "#ffdd57";
text = "#eaeaea";
text-header = "#ffffff";
text-subtitle = "#f5f5f5";
text-title = "#fafafa";
};
in {
light = colors;
dark = colors;
};
links = [
(mkLink "Status" "fa-heartbeat" "https://status.voronind.com")
];
services = [
(mkGroup "App" "fa-server" [
(mkLink "Change" "fa-user-secret" "https://${container.config.change.domain}")
(mkLink "Cloud" "fa-cloud" "https://${container.config.cloud.domain}")
(mkLink "Download" "fa-download" "https://${container.config.download.domain}")
(mkLink "Git" "fab fa-git-alt" "https://${container.config.download.domain}")
# (mkLink "Iot" "fa-home" "https://${container.config.iot.domain}")
# (mkLink "Mail" "fa-envelope" "https://${container.config.mail.domain}")
# (mkLink "Paper" "fa-paperclip" "https://${container.config.paper.domain}")
# (mkLink "Pass" "fa-key" "https://${container.config.pass.domain}")
# (mkLink "Paste" "fa-paste" "https://${container.config.paste.domain}")
# (mkLink "Print" "fa-print" "https://${container.config.print.domain}")
# (mkLink "Read" "fa-book" "https://${container.config.read.domain}")
# (mkLink "Search" "fa-search" "https://${container.config.search.domain}")
# (mkLink "Stock" "fa-boxes-stacked" "https://${container.config.stock.domain}")
# (mkLink "Tool" "fa-toolbox" "https://${container.config.tool.domain}")
# (mkLink "Watch" "fa-film" "https://${container.config.watch.domain}")
# (mkLink "YouTube" "fab fa-youtube" "https://${container.config.yt.domain}")
])
(mkGroup "System" "fa-shield" [
(mkLink "Hdd" "fa-hard-drive" "https://${container.config.hdd.domain}")
(mkLink "NixOS Search" "fa-snowflake" "https://search.nixos.org")
(mkLink "Printer" "fa-print" "https://${container.config.printer.domain}")
(mkLink "Router" "fa-route" "https://${container.config.router.domain}")
])
(mkGroup "Bookmark" "fa-bookmark" [
(mkLink "2gis" "fa-map-location-dot" "https://2gis.ru")
(mkLink "FontAwesome" "fa-font-awesome" "https://fontawesome.com/search?o=r&m=free")
(mkLink "MonkeyType" "fa-keyboard" "https://monkeytype.com")
(mkLink "NerdFonts" "fa-font" "https://www.nerdfonts.com/cheat-sheet")
(mkLink "Reddit" "fab fa-reddit" "https://reddit.com")
(mkLink "Zigbee" "fa-satellite-dish" "https://zigbee.blakadder.com")
])
(mkGroup "Work" "fa-briefcase" [
(mkLink "Vm Manager" "fa-server" "https://fs-vcsa.fs.fsight.world/ui")
])
(mkGroup "Pirate" "fa-skull-crossbones" [
(mkLink "1337x" "fa-skull-crossbones" "https://1337x.to")
(mkLink "Cs.rin.ru" "fa-skull-crossbones" "https://cs.rin.ru/forum/index.php")
(mkLink "DigitalCore" "fa-skull-crossbones" "https://digitalcore.club")
(mkLink "FitGirl" "fa-skull-crossbones" "https://digitalcore.club")
(mkLink "Hf" "fa-skull-crossbones" "https://happyfappy.org")
(mkLink "Lst" "fa-skull-crossbones" "https://lst.gg")
(mkLink "NnmClub" "fa-skull-crossbones" "https://nnmclub.to")
(mkLink "Rutor" "fa-skull-crossbones" "https://nnmclub.to")
(mkLink "Rutracker" "fa-skull-crossbones" "https://rutracker.org")
(mkLink "Tapochek.net" "fa-skull-crossbones" "https://tapochek.net/index.php")
])
];
};
in {
text = lib.generators.toYAML {} config;
}

View file

@ -0,0 +1,26 @@
{ stdenv, pkgs, ... } @args: let
cfg = pkgs.writeText "HomerConfig" (import ./Config.nix args).text;
in stdenv.mkDerivation (finalAttrs: {
pname = "Homerr";
version = "24.05.1";
src = pkgs.fetchurl {
url = "https://github.com/bastienwirtz/homer/releases/download/v${finalAttrs.version}/homer.zip";
sha256 = "sha256-Ji/7BSKCnnhj4NIdGngTHcGRRbx9UWrx48bBsKkEj34=";
};
nativeBuildInputs = with pkgs; [ unzip ];
dontUnpack = true;
installPhase = ''
runHook preInstall
mkdir -p $out/assets
pushd $out
unzip $src
cp ${cfg} $out/assets/config.yml
runHook postInstall
'';
})

View file

@ -0,0 +1,4 @@
{ poetry2nix, pkgs, ... }: let
inherit (poetry2nix.lib.mkPoetry2Nix { inherit pkgs; }) mkPoetryApplication;
in
mkPoetryApplication { projectDir = ./project; }

View file

View file

@ -0,0 +1,143 @@
#!/usr/bin/env python3 -u
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
import subprocess
import datetime
import time
import random
import os
import sys
# sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
print('starting jobber..')
# config.
DELAY_CYCLE = 300 # Check time every in seconds.
DELAY_SUCCESS = 3600 # Delay after successful in/out in seconds.
DELAY_CAP = 120 # Delay between users in seconds.
DELAY_VPN = 30 # Delay waiting for VPN connection in seconds.
DELAY_ERROR = 30 # Delay in case of errors in seconds.
DELAY_CLICK = 30 # Delay after button click.
SHIFT_START = 9 # Work starts at hour.
SHIFT_END = 18 # Work ends at hour.
TRIES_MAX = 5 # Maximum tries to press button before give up.
URL_SCHEME = "https://"
URL = "portal.fsight.ru/"
# DRIVER = "/data/geckodriver"
DRIVER = "geckodriver"
USERS = "/data/users.txt"
OVPN = "/data/fsight.ovpn"
BUTTON = "//*[contains(@id, '_InOutButton')]"
TEXT_HERE = "Пришёл"
TEXT_GONE = "Ушёл"
VPN = None
def toggle_vpn(state):
print("toggle_vpn(state = {})".format(state))
try:
if state:
print('waiting for VPN for {}s'.format(DELAY_VPN))
global VPN
VPN = subprocess.Popen(['openvpn', OVPN])
time.sleep(DELAY_VPN)
else:
VPN.kill()
except: pass
def toggle_button(cred, at_work):
tag = 'toggle(cred = {}, at_work = {})'.format(cred.strip('\n'), at_work)
print(tag)
# start Firefox
options = Options()
options.set_preference("browser.tabs.remote.force-enable", True)
options.set_preference("network.negotiate-auth.trusted-uris", URL_SCHEME + URL)
options.set_preference("network.negotiate-auth.delegation-uris", URL_SCHEME + URL)
options.set_preference("network.automatic-ntlm-auth.trusted-uris", URL_SCHEME + URL)
options.headless = True
firefox_capabilities = DesiredCapabilities.FIREFOX
firefox_capabilities['marionette'] = True
driver = webdriver.Firefox(options=options, executable_path=DRIVER, service_log_path=None, capabilities=firefox_capabilities)
# load page and click button
tries = 0
button = None
while button is None and tries <= TRIES_MAX:
toggle_vpn(True)
# try:
driver.get(URL_SCHEME + cred + "@" + URL)
# button = driver.find_element_by_xpath(BUTTON)
button = driver.find_element(by=By.XPATH, value=BUTTON)
# except: print()
if button is None:
print('{} : button not found, trying again after {}s'.format(tag, DELAY_VPN))
toggle_vpn(False)
tries += 1
time.sleep(DELAY_ERROR)
if (tries <= TRIES_MAX):
# time.sleep(DELAY_CLICK)
text = button.get_attribute('value')
if (text == TEXT_HERE and at_work) or (text == TEXT_GONE and not at_work):
print('{} : clicking button'.format(tag))
# button.submit()
# driver.execute_script('arguments[0].click();', button)
button.click()
time.sleep(DELAY_CLICK)
# stop firefox
driver.quit()
# kill vpn
toggle_vpn(False)
def main():
while True:
try:
# load users
users = open(USERS, 'r').readlines()
for user in users:
if user.startswith('#'):
users.remove(user)
print('loaded {} users'.format(len(users)))
# loop forever
while True:
print('time is {}h'.format(datetime.datetime.now().hour))
# check for day start
if datetime.datetime.now().hour == SHIFT_START and datetime.datetime.now().isoweekday() < 6:
print('starting work day..')
for user in users:
toggle_button(user, True)
time.sleep(random.random() * DELAY_CAP)
time.sleep(DELAY_SUCCESS)
continue
# check for day end
if datetime.datetime.now().hour == SHIFT_END and datetime.datetime.now().isoweekday() < 6:
print('ending work day..')
for user in users:
toggle_button(user, False)
time.sleep(random.random() * DELAY_CAP)
time.sleep(DELAY_SUCCESS)
continue
# loop delay
print('not the right time, waiting {}s'.format(DELAY_CYCLE))
time.sleep(DELAY_CYCLE)
except:
time.sleep(DELAY_ERROR)
pass

264
container/jobber/project/poetry.lock generated Normal file
View file

@ -0,0 +1,264 @@
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
[[package]]
name = "attrs"
version = "23.2.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.7"
files = [
{file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"},
{file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
]
[package.extras]
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
dev = ["attrs[tests]", "pre-commit"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
tests = ["attrs[tests-no-zope]", "zope-interface"]
tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"]
tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"]
[[package]]
name = "certifi"
version = "2024.6.2"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"},
{file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"},
]
[[package]]
name = "cffi"
version = "1.16.0"
description = "Foreign Function Interface for Python calling C code."
optional = false
python-versions = ">=3.8"
files = [
{file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"},
{file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"},
{file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"},
{file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"},
{file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"},
{file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"},
{file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"},
{file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"},
{file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"},
{file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"},
{file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"},
{file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"},
{file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"},
{file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"},
{file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"},
{file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"},
{file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"},
{file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"},
{file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"},
{file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"},
{file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"},
{file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"},
{file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"},
{file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"},
{file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"},
{file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"},
{file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"},
{file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"},
{file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"},
{file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"},
{file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"},
{file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"},
{file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"},
{file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"},
{file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"},
{file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"},
{file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"},
{file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"},
{file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"},
{file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"},
{file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"},
{file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"},
{file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"},
{file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"},
{file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"},
{file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"},
{file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"},
{file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"},
{file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"},
{file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"},
{file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"},
{file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"},
]
[package.dependencies]
pycparser = "*"
[[package]]
name = "h11"
version = "0.14.0"
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
optional = false
python-versions = ">=3.7"
files = [
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
]
[[package]]
name = "idna"
version = "3.7"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.5"
files = [
{file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
{file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
]
[[package]]
name = "outcome"
version = "1.3.0.post0"
description = "Capture the outcome of Python function calls."
optional = false
python-versions = ">=3.7"
files = [
{file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"},
{file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"},
]
[package.dependencies]
attrs = ">=19.2.0"
[[package]]
name = "pycparser"
version = "2.22"
description = "C parser in Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"},
{file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
]
[[package]]
name = "pysocks"
version = "1.7.1"
description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information."
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
{file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"},
{file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"},
{file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"},
]
[[package]]
name = "selenium"
version = "4.4.3"
description = ""
optional = false
python-versions = "~=3.7"
files = [
{file = "selenium-4.4.3-py3-none-any.whl", hash = "sha256:ca6ed4a58a426bb40bf5aa2b027ce211cc5200f1acdcdfb8258b32b24624150c"},
]
[package.dependencies]
certifi = ">=2021.10.8"
trio = ">=0.17,<1.0"
trio-websocket = ">=0.9,<1.0"
urllib3 = {version = ">=1.26,<2.0", extras = ["socks"]}
[[package]]
name = "sniffio"
version = "1.3.1"
description = "Sniff out which async library your code is running under"
optional = false
python-versions = ">=3.7"
files = [
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
]
[[package]]
name = "sortedcontainers"
version = "2.4.0"
description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
optional = false
python-versions = "*"
files = [
{file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"},
{file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"},
]
[[package]]
name = "trio"
version = "0.25.1"
description = "A friendly Python library for async concurrency and I/O"
optional = false
python-versions = ">=3.8"
files = [
{file = "trio-0.25.1-py3-none-any.whl", hash = "sha256:e42617ba091e7b2e50c899052e83a3c403101841de925187f61e7b7eaebdf3fb"},
{file = "trio-0.25.1.tar.gz", hash = "sha256:9f5314f014ea3af489e77b001861c535005c3858d38ec46b6b071ebfa339d7fb"},
]
[package.dependencies]
attrs = ">=23.2.0"
cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
idna = "*"
outcome = "*"
sniffio = ">=1.3.0"
sortedcontainers = "*"
[[package]]
name = "trio-websocket"
version = "0.11.1"
description = "WebSocket library for Trio"
optional = false
python-versions = ">=3.7"
files = [
{file = "trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f"},
{file = "trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"},
]
[package.dependencies]
trio = ">=0.11"
wsproto = ">=0.14"
[[package]]
name = "urllib3"
version = "1.26.18"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
{file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"},
{file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"},
]
[package.dependencies]
PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
[package.extras]
brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "wsproto"
version = "1.2.0"
description = "WebSockets state-machine based protocol implementation"
optional = false
python-versions = ">=3.7.0"
files = [
{file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"},
{file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"},
]
[package.dependencies]
h11 = ">=0.9.0,<1"
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
content-hash = "dd717145958cead19a77bd40d475c6b019b20388561b403f475cfb767b7a05c6"

View file

@ -0,0 +1,17 @@
[tool.poetry]
name = "jobber"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.11"
selenium = "4.4.3"
[tool.poetry.scripts]
jobber = "jobber:main"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

View file

@ -1,4 +1,4 @@
{ util, ... }: { { util, container, ... }: {
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=10.1.0.3;dbname=privatebin" dsn = "pgsql:host=${container.config.postgres.address};dbname=privatebin"
tbl = "privatebin_" ; table prefix tbl = "privatebin_" ; table prefix
usr = "privatebin" usr = "privatebin"
pwd = "privatebin" pwd = "privatebin"

View file

@ -0,0 +1,36 @@
# https://github.com/NixOS/nixpkgs/blob/nixos-24.05/pkgs/misc/drivers/pantum-driver/default.nix
{ stdenv, fetchurl, pkgs, ... }: let
in stdenv.mkDerivation rec {
pname = "pantum-driver";
version = "1.1.106";
src = fetchurl {
url = "https://cloud.voronind.com/s/k6Ea6QsrsKcAeNg/download/Pantum%20Ubuntu%20Driver%20V1_1_106.zip";
# hash = "sha256-vyhQIdiF7CgRg1wPN94Ex8yfLLam6pf5KRGqSCVlQ34=";
hash = "sha256-IflzEM2kqqMqOQWZ5Eu906dEa85h+NFRmoR7y7WPX7Q=";
};
buildInputs = with pkgs; [ libusb1 libjpeg8 cups ];
nativeBuildInputs = with pkgs; [ unzip dpkg autoPatchelfHook ];
dontUnpack = true;
installPhase = ''
unzip $src
pushd Pantum\ Ubuntu\ Driver\ V1.1.106/
dpkg-deb -x ./Resources/pantum_${version}-1_amd64.deb .
mkdir -p $out $out/lib
cp -r etc $out/
cp -r usr/lib/cups $out/lib/
cp -r usr/local/lib/* $out/lib/
cp -r usr/share $out/
cp Resources/locale/en_US.UTF-8/* $out/share/doc/pantum/
'';
# + ''
# cp -r opt/pantum/* $out/
# ln -s $out/lib/libqpdf.so* $out/lib/libqpdf.so
# ln -s $out/lib/libqpdf.so $out/lib/libqpdf.so.21
# '';
}

View file

@ -1,16 +1,17 @@
{ domain, util, container, ... }: let { domain, util, container, ... }: let
cfg = container.config.change; cfg = container.config.change;
name = "change";
in { in {
${cfg.domain} = container.mkServer { ${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs '' extraConfig = util.trimTabs ''
listen 443 ssl; listen 443 ssl;
set $change ${cfg.address}:5000; set ''$${name} ${cfg.address}:${toString cfg.port};
location / { location / {
allow 192.168.1.0/24; allow ${container.localAccess};
allow 10.1.0.1; allow ${container.config.vpn.address};
deny all; deny all;
proxy_pass http://$change$request_uri; proxy_pass http://''$${name}$request_uri;
} }
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem; ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;

View file

@ -1,19 +1,21 @@
{ domain, util, container, ... }: let { domain, util, container, ... }: let
cfg = container.config.cloud; cfg = container.config.cloud;
name = "cloud";
in { in {
${cfg.domain} = container.mkServer { ${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs '' extraConfig = util.trimTabs ''
listen 443 ssl; listen 443 ssl;
set $cloud ${cfg.address}:80; 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 192.168.1.0/24; allow ${container.localAccess};
allow 10.1.0.1; allow ${container.config.vpn.address};
deny all; deny all;
proxy_pass http://$cloud$request_uri; proxy_pass http://''$${name}$request_uri;
} }
location / { location / {
proxy_pass http://$cloud$request_uri; proxy_pass http://''$${name}$request_uri;
} }
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem; ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.download;
name = "download";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,44 @@
{ domain, util, container, ... }: let
cfg = container.config.git;
name = "git";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location ~ ^/(admin|api|user) {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
location /markdown {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_set_header Content-Type "application/json";
proxy_set_header Authorization "Basic dm9yb25pbmQ6QUxwWHZoRlRNYmpIazY3OVBkZDhCTjZNS0hyWjZ4aGU=";
proxy_pass_header Content-Type;
proxy_pass_header Authorization;
proxy_pass http://''$${name}/api/v1/markdown/raw;
}
location / {
# allow ${container.localAccess};
# allow ${container.config.vpn.address};
# deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.hdd;
name = "hdd";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.home;
name = "home";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,30 @@
{ domain, util, container, ... }: let
cfg = container.config.iot;
name = "iot";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.mail;
name = "mail";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.office;
name = "office";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.paper;
name = "paper";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.pass;
name = "pass";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -1,16 +1,18 @@
{ domain, util, container, ... }: let { domain, util, container, ... }: let
cfg = container.config.paste; cfg = container.config.paste;
name = "paste";
in { in {
${cfg.domain} = container.mkServer { ${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs '' extraConfig = util.trimTabs ''
listen 443 ssl; listen 443 ssl;
set $paste ${cfg.address}:80; set ''$${name} ${cfg.address}:${toString cfg.port};
location = / { location = / {
return 403; return 403;
} }
location / { location / {
proxy_pass http://$paste$request_uri; proxy_pass http://''$${name}$request_uri;
} }
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem; ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;

View file

@ -0,0 +1,28 @@
{ domain, util, container, ... }: let
cfg = container.config.print;
name = "print";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
proxy_set_header Host "127.0.0.1";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.printer;
name = "printer";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.read;
name = "read";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,24 @@
{ domain, util, container, ... }: let
cfg = container.config.router;
name = "router";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.search;
name = "search";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,30 @@
{ domain, util, container, ... }: let
cfg = container.config.status;
name = "sstatus";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location ~ ^/(dashboard|settings) {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.stock;
name = "stock";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.watch;
name = "watch";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -0,0 +1,23 @@
{ domain, util, container, ... }: let
cfg = container.config.yt;
name = "yt";
in {
${cfg.domain} = container.mkServer {
extraConfig = util.trimTabs ''
listen 443 ssl;
set ''$${name} ${cfg.address}:${toString cfg.port};
location / {
allow ${container.localAccess};
allow ${container.config.vpn.address};
deny all;
proxy_pass http://''$${name}$request_uri;
}
ssl_certificate /etc/letsencrypt/live/${domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${domain}/privkey.pem;
include /etc/letsencrypt/conf/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/conf/ssl-dhparams.pem;
'';
};
}

View file

@ -130,6 +130,24 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"fromYaml": { "fromYaml": {
"flake": false, "flake": false,
"locked": { "locked": {
@ -227,6 +245,27 @@
"type": "github" "type": "github"
} }
}, },
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"poetry2nixJobber",
"nixpkgs"
]
},
"locked": {
"lastModified": 1703863825,
"narHash": "sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "5163432afc817cf8bd1f031418d1869e4c9d5547",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nix-on-droid": { "nix-on-droid": {
"inputs": { "inputs": {
"home-manager": [ "home-manager": [
@ -286,7 +325,39 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgsJobber": {
"locked": {
"lastModified": 1717786204,
"narHash": "sha256-4q0s6m0GUcN7q+Y2DqD27iLvbcd1G50T2lv08kKxkSI=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "051f920625ab5aabe37c920346e3e69d7d34400e",
"type": "github"
},
"original": {
"owner": "nixos",
"repo": "nixpkgs",
"rev": "051f920625ab5aabe37c920346e3e69d7d34400e",
"type": "github"
}
},
"nixpkgs_2": { "nixpkgs_2": {
"locked": {
"lastModified": 1717298511,
"narHash": "sha256-9sXuJn/nL+9ImeYtlspTvjt83z1wIgU+9AwfNbnq+tI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6634a0509e9e81e980b129435fbbec518ab246d0",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable-small",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1714912032, "lastModified": 1714912032,
"narHash": "sha256-clkcOIkg8G4xuJh+1onLG4HPMpbtzdLv4rHxFzgsH9c=", "narHash": "sha256-clkcOIkg8G4xuJh+1onLG4HPMpbtzdLv4rHxFzgsH9c=",
@ -670,11 +741,35 @@
"type": "github" "type": "github"
} }
}, },
"poetry2nixJobber": {
"inputs": {
"flake-utils": "flake-utils",
"nix-github-actions": "nix-github-actions",
"nixpkgs": "nixpkgs_2",
"systems": "systems_2",
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1717965289,
"narHash": "sha256-62VsS1MvwcsyYWnxxOD9rX5yqDUvMXH7qE3Kj8HECYE=",
"owner": "nix-community",
"repo": "poetry2nix",
"rev": "304f8235fb0729fd48567af34fcd1b58d18f9b95",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "poetry2nix",
"rev": "304f8235fb0729fd48567af34fcd1b58d18f9b95",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"home-manager": "home-manager", "home-manager": "home-manager",
"nix-on-droid": "nix-on-droid", "nix-on-droid": "nix-on-droid",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nixpkgsJobber": "nixpkgsJobber",
"nvimAlign": "nvimAlign", "nvimAlign": "nvimAlign",
"nvimAutoclose": "nvimAutoclose", "nvimAutoclose": "nvimAutoclose",
"nvimBufferline": "nvimBufferline", "nvimBufferline": "nvimBufferline",
@ -695,6 +790,7 @@
"nvimTreesitter": "nvimTreesitter", "nvimTreesitter": "nvimTreesitter",
"nvimTrouble": "nvimTrouble", "nvimTrouble": "nvimTrouble",
"nvimWhichKey": "nvimWhichKey", "nvimWhichKey": "nvimWhichKey",
"poetry2nixJobber": "poetry2nixJobber",
"stylix": "stylix" "stylix": "stylix"
} }
}, },
@ -710,7 +806,7 @@
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"gnome-shell": "gnome-shell", "gnome-shell": "gnome-shell",
"home-manager": "home-manager_2", "home-manager": "home-manager_2",
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_3"
}, },
"locked": { "locked": {
"lastModified": 1717866166, "lastModified": 1717866166,
@ -725,6 +821,56 @@
"repo": "stylix", "repo": "stylix",
"type": "github" "type": "github"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"id": "systems",
"type": "indirect"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"poetry2nixJobber",
"nixpkgs"
]
},
"locked": {
"lastModified": 1717278143,
"narHash": "sha256-u10aDdYrpiGOLoxzY/mJ9llST9yO8Q7K/UlROoNxzDw=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "3eb96ca1ae9edf792a8e0963cc92fddfa5a87706",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -25,6 +25,11 @@
# Manual: https://danth.github.io/stylix # Manual: https://danth.github.io/stylix
stylix.url = "github:danth/stylix"; stylix.url = "github:danth/stylix";
# I use this for a single container called jobber.
# You likely won't need this one, so just skip it for now.
poetry2nixJobber.url = "github:nix-community/poetry2nix/304f8235fb0729fd48567af34fcd1b58d18f9b95";
nixpkgsJobber.url = "github:nixos/nixpkgs/051f920625ab5aabe37c920346e3e69d7d34400e";
# Nix on Android (inside Termux). It has no NixOS modules, but still allows the use of Nixpkgs arm packages with Home-Manager configurations. # Nix on Android (inside Termux). It has no NixOS modules, but still allows the use of Nixpkgs arm packages with Home-Manager configurations.
# Homepage: https://github.com/nix-community/nix-on-droid # Homepage: https://github.com/nix-community/nix-on-droid
# Manual: https://github.com/nix-community/nix-on-droid/blob/master/README.md # Manual: https://github.com/nix-community/nix-on-droid/blob/master/README.md
@ -121,7 +126,7 @@
# Here you see a set of inputs we defined above, like nixpkgs, home-manager and so on. # Here you see a set of inputs we defined above, like nixpkgs, home-manager and so on.
# `...` at the end of a set means "ignore other arguments provided to this function". # `...` at the end of a set means "ignore other arguments provided to this function".
# @inputs means aliasing all the inputs to the `inputs` name, so we can pass them all at once later. # @inputs means aliasing all the inputs to the `inputs` name, so we can pass them all at once later.
outputs = { self, nixpkgs, nix-on-droid, home-manager, stylix, ... } @inputs: { outputs = { self, nixpkgs, nix-on-droid, home-manager, stylix, poetry2nixJobber, nixpkgsJobber, ... } @inputs: {
# Constant values. # Constant values.
const = { const = {
droidStateVersion = "22.11"; droidStateVersion = "22.11";
@ -178,6 +183,8 @@
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;
in { in {
const = self.const; # Constant values. const = self.const; # Constant values.
flake = self; # This Flake itself. flake = self; # This Flake itself.
@ -188,6 +195,9 @@
style = import ./part/Style.nix { inherit config; }; # Style abstraction. style = import ./part/Style.nix { inherit config; }; # Style abstraction.
util = import ./part/Util.nix { inherit pkgs lib; }; # Util functions. util = import ./part/Util.nix { inherit pkgs lib; }; # Util functions.
wallpaper = import ./part/Wallpaper.nix { inherit pkgs; }; # Wallpaper. wallpaper = import ./part/Wallpaper.nix { inherit pkgs; }; # Wallpaper.
# Stuff for Jobber container, skip this part.
inherit poetry2nixJobber pkgsJobber;
}; };
}; };

View file

@ -1,33 +1,108 @@
{ pkgs, const, lib, config, util, ... }: let { pkgs
, const
, lib
, config
, util
, poetry2nixJobber
, pkgsJobber
, ... }: let
externalInterface = "enp4s0";
args = let args = let
storage = "/storage/hot/container"; storage = "/storage/hot/container";
domain = "local"; domain = "local";
host = "192.168.1.3"; host = "192.168.1.3";
media = {
download = [ "/tmp/download" ];
photo = [ "/tmp/in" "/tmp/out" ];
book = [ "/tmp/book_1" "/tmp/book_2" ];
};
in { in {
inherit storage domain host pkgs const lib config util; inherit storage domain host pkgs const lib config util media;
inherit poetry2nixJobber pkgsJobber;
container = import ../../container args; container = import ../../container args;
}; };
in { in {
imports = [
# (import ../../container/Proxy.nix args)
];
networking.nat = { networking.nat = {
enable = true; enable = true;
internalInterfaces = [ "ve-+" ]; internalInterfaces = [ "ve-+" ];
externalInterface = "enp4s0"; inherit externalInterface;
forwardPorts = with args.container.config; [
# Dns Server.
{
destination = "${dns.address}:53";
proto = "udp";
sourcePort = 53;
} {
destination = "${dns.address}:53";
proto = "tcp";
sourcePort = 53;
}
# Reverse proxy.
{
destination = "${proxy.address}:80";
proto = "tcp";
sourcePort = 80;
} {
destination = "${proxy.address}:443";
proto = "tcp";
sourcePort = 443;
}
# Cups.
{
destination = "${print.address}:${toString print.port}";
proto = "tcp";
sourcePort = 631;
} {
destination = "${print.address}:6566";
proto = "tcp";
sourcePort = 6566;
}
# Wireguard.
{
destination = "${vpn.address}:${toString vpn.port}";
proto = "udp";
sourcePort = 51820;
}
# Deluge.
{
destination = "${download.address}:${toString download.port}";
proto = "tcp";
sourcePort = 8112;
} {
destination = "${download.address}:54630-54631";
proto = "udp";
sourcePort = "54630:54631";
} {
destination = "${download.address}:54630-54631";
proto = "tcp";
sourcePort = "54630:54631";
}
# Mail.
{
destination = "${mail.address}:25";
proto = "tcp";
sourcePort = 25;
} {
destination = "${mail.address}:465";
proto = "tcp";
sourcePort = 465;
} {
destination = "${mail.address}:993";
proto = "tcp";
sourcePort = 993;
}
];
}; };
# TODO: Remove this.
networking.extraHosts = ''
10.1.0.2 change.local
10.1.0.2 cloud.local
10.1.0.2 paste.local
10.1.0.2 local
'';
imports = [
(import ../../container/Change.nix args)
(import ../../container/Cloud.nix args)
(import ../../container/Paste.nix args)
(import ../../container/Postgres.nix args)
(import ../../container/Proxy.nix args)
];
} }

View file

@ -1,25 +0,0 @@
{ pkgs, const, lib, config, util, ... }: let
args = let
storage = "/tmp/container";
domain = "local";
host = "192.168.0.174";
in {
inherit storage domain host pkgs const lib config util;
};
in {
networking.nat = {
enable = true;
internalInterfaces = [ "ve-+" ];
externalInterface = "enp4s0";
};
# NOTE: Remove this.
networking.extraHosts = ''
10.1.0.2 paste.local
'';
imports = [
(import ../../container/Paste.nix args)
(import ../../container/Proxy.nix args)
];
}

View file

@ -1,6 +1,5 @@
{ lib, ... }: { { lib, ... }: {
imports = [ imports = [
./Container.nix
./Fprint.nix ./Fprint.nix
]; ];

View file

@ -2,7 +2,7 @@
list = with pkgs; [ list = with pkgs; [
android-tools android-tools
binwalk binwalk
coreutils diffutils findutils utillinux coreutils dnsutils diffutils findutils utillinux
curl curl
ffmpeg ffmpeg
file file

8
module/common/Apks.nix Normal file
View file

@ -0,0 +1,8 @@
# I want to pull all the Apk files in their current state
# so that I always have an access to clients that match
# my service versions.
{ pkgs, ... } @args: let
package = (pkgs.callPackage ./apks args);
in {
environment.etc.apks.source = package;
}

View file

@ -2,14 +2,14 @@
# Use latest kernel. # Use latest kernel.
boot.kernelPackages = pkgs.linuxPackages_latest; boot.kernelPackages = pkgs.linuxPackages_latest;
boot.kernel.sysctl = { # boot.kernel.sysctl = {
# # Spoof protection. # # Spoof protection.
# "net.ipv4.conf.default.rp_filter" = 1; # "net.ipv4.conf.default.rp_filter" = 1;
# "net.ipv4.conf.all.rp_filter" = 1; # "net.ipv4.conf.all.rp_filter" = 1;
# # Packet forwarding. # # Packet forwarding.
# "net.ipv4.ip_forward" = 1; # "net.ipv4.ip_forward" = 0;
# # "net.ipv6.conf.all.forwarding" = 1; # "net.ipv6.conf.all.forwarding" = 1;
# # MITM protection. # # MITM protection.
# "net.ipv4.conf.all.accept_redirects" = 0; # "net.ipv4.conf.all.accept_redirects" = 0;
@ -22,19 +22,19 @@
# "net.ipv4.conf.all.accept_source_route" = 0; # "net.ipv4.conf.all.accept_source_route" = 0;
# "net.ipv6.conf.all.accept_source_route" = 0; # "net.ipv6.conf.all.accept_source_route" = 0;
# Allow sysrq. # # Allow sysrq.
"kernel.sysrq" = 1; # "kernel.sysrq" = 1;
# Protect filesystem links. # # Protect filesystem links.
# "fs.protected_hardlinks" = 0; # "fs.protected_hardlinks" = 0;
# "fs.protected_symlinks" = 0; # "fs.protected_symlinks" = 0;
# Specify ttl. # # Specify ttl.
"net.ipv4.ip_default_ttl" = 65; # "net.ipv4.ip_default_ttl" = 65;
# Lynis config. # # Lynis config.
"kernel.core_uses_pid" = 1; # "kernel.core_uses_pid" = 1;
"kernel.kptr_restrict" = 2; # "kernel.kptr_restrict" = 2;
# # IP hardening. # # IP hardening.
# "net.ipv4.conf.all.log_martians" = 1; # "net.ipv4.conf.all.log_martians" = 1;
@ -44,15 +44,15 @@
# "net.ipv4.tcp_timestamps" = 0; # "net.ipv4.tcp_timestamps" = 0;
# "net.ipv6.conf.default.accept_redirects" = 0; # "net.ipv6.conf.default.accept_redirects" = 0;
# Increase file watchers. # # Increase file watchers.
"fs.inotify.max_user_instances" = 999999; # "fs.inotify.max_user_instances" = 999999;
"fs.inotify.max_user_watches" = 999999; # "fs.inotify.max_user_watches" = 999999;
"fs.inotify.max_user_event" = 999999; # "fs.inotify.max_user_event" = 999999;
# # Disable ipv6. # # Disable ipv6.
# "net.ipv6.conf.all.disable_ipv6" = 1; # "net.ipv6.conf.all.disable_ipv6" = 1;
# "net.ipv6.conf.default.disable_ipv6" = 1; # "net.ipv6.conf.default.disable_ipv6" = 1;
# "net.ipv6.conf.lo.disable_ipv6" = 1; # "net.ipv6.conf.lo.disable_ipv6" = 1;
# "net.ipv6.conf.eth0.disable_ipv6" = 1; # "net.ipv6.conf.eth0.disable_ipv6" = 1;
}; # };
} }

View file

@ -38,12 +38,13 @@
# Media controls. # Media controls.
layer_control = { layer_control = {
space = "playpause"; space = "playpause";
w = "volumeup";
s = "volumedown";
d = "forward";
a = "back"; a = "back";
c = "ejectcd";
d = "forward";
e = "nextsong"; e = "nextsong";
q = "previoussong"; q = "previoussong";
s = "volumedown";
w = "volumeup";
x = "stopcd"; x = "stopcd";
z = "mute"; z = "mute";
}; };

View file

@ -3,10 +3,11 @@
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
binwalk # Can analyze files for other files inside them. binwalk # Can analyze files for other files inside them.
btop htop # System monitors. btop htop # System monitors.
coreutils usbutils # Common utilities. coreutils # Common utilities.
cryptsetup # Filesystem encryption (LUKS). cryptsetup # Filesystem encryption (LUKS).
curl # CLI http client. curl # CLI http client.
ddrescue testdisk # Apps to recover data from drives. ddrescue testdisk # Apps to recover data from drives.
dnsutils # Dns utilities like host.
fastfetch # Systeminfo summary. fastfetch # Systeminfo summary.
ffmpeg # Video/audio converter. ffmpeg # Video/audio converter.
file # Get general info about a file. file # Get general info about a file.
@ -30,8 +31,10 @@
smartmontools # S.M.A.R.T. tools. smartmontools # S.M.A.R.T. tools.
sqlite # Serverless file-based database engine. sqlite # Serverless file-based database engine.
tree # Show directory stricture as a tree. tree # Show directory stricture as a tree.
usbutils # Usb utilities like udiskctl.
ventoy # Boot multiple ISO/images from a single USB stick. ventoy # Boot multiple ISO/images from a single USB stick.
wget # CLI http download tool. wget # CLI http download tool.
wireguard-tools # Tools to work with Wireguard.
zip unzip # Zip archive/unarchive tools. zip unzip # Zip archive/unarchive tools.
universal-android-debloater # Debloat Android devices. universal-android-debloater # Debloat Android devices.

View file

@ -4,6 +4,8 @@ in {
environment.etc.wallpaper.source = wallpaper.path; environment.etc.wallpaper.source = wallpaper.path;
stylix = { stylix = {
# NOTE: Enable this later...
# enable = true;
image = wallpaper.path; image = wallpaper.path;
autoEnable = true; autoEnable = true;
polarity = "dark"; polarity = "dark";

View file

@ -0,0 +1,58 @@
{ lib, stdenv, fetchurl, ... }: let
apks = {
# https://github.com/bitwarden/mobile/releases
Bitwarden = fetchurl {
url = "https://github.com/bitwarden/mobile/releases/download/v2024.5.1/com.x8bit.bitwarden-fdroid.apk";
sha256 = "sha256-n4c5xEYvgd8Uhkqh3zSSyVA13ia+yqqGWA/DCATgOmU=";
};
# https://github.com/bitfireAT/davx5-ose/releases
Davx5 = fetchurl {
url = "https://github.com/bitfireAT/davx5-ose/releases/download/v4.4.0.1-ose/davx5-ose-4.4.0.1-ose-release.apk";
sha256 = "sha256-CBGWVBrxmxUSQ0Q7OEX8W6ZBfEW9AXQ90QyKfA+cENw=";
};
# https://github.com/patzly/grocy-android/releases
Grocy = fetchurl {
url = "https://github.com/patzly/grocy-android/releases/download/v3.5.2/Grocy-Android-v3.5.2.apk";
sha256 = "sha256-HyKoSl5po1Pl5keknlArruKXQHiSkNYfqKPMeBtvAN4=";
};
# https://github.com/jellyfin/jellyfin-android/releases
Jellyfin = fetchurl {
url = "https://github.com/jellyfin/jellyfin-android/releases/download/v2.6.1/jellyfin-android-v2.6.1-libre-release.apk";
sha256 = "sha256-Jyd/qM2vvtU7uogVla7ldpFqn2yRmq3ZKW/yHKpUafg=";
};
# https://github.com/nextcloud/android/releases
NextCloud = fetchurl {
url = "https://github.com/nextcloud/android/releases/download/stable-3.29.0/nextcloud-30290090.apk";
sha256 = "sha256-ArsGpXX7ClkBdOBJwQrxPVTr7fNNjZjTflvlAd5insw=";
};
# https://f-droid.org/packages/com.termux.nix
NixOnDroid = fetchurl {
url = "https://f-droid.org/repo/com.termux.nix_188035.apk";
sha256 = "sha256-sAuJejlDO5JY8+k1uql8ANug1l324lpxLg4w276pbEw=";
};
# https://github.com/ONLYOFFICE/documents-app-android/releases
OnlyOffice = fetchurl {
url = "https://github.com/ONLYOFFICE/documents-app-android/releases/download/v8.0.1-533/onlyoffice-manager-8.0.1-533.apk";
sha256 = "sha256-M2x5Vgaxcwuzc1QsIwhuIK9w7ANLcT3oOOJniWjCh3E=";
};
# https://download.wireguard.com/android-client
Wireguard = fetchurl {
url = "https://download.wireguard.com/android-client/com.wireguard.android-1.0.20231018.apk";
sha256 = "sha256-2NiCqtIO68j7X1FSc/c6xzTNaXUPRfbs2qt7/PVchP4=";
};
};
in stdenv.mkDerivation {
name = "apks";
dontUnpack = true;
installPhase = "mkdir $out\n" + builtins.foldl' (acc: apk: acc + "${apk}\n") "" (
lib.mapAttrsToList (name: path: "cp ${path} $out/${name}.apk") apks
);
}

View file

@ -14,5 +14,6 @@ in {
bindsym XF86AudioPrev exec 'playerctl previous' bindsym XF86AudioPrev exec 'playerctl previous'
bindsym XF86Forward exec 'playerctl position ${step_music}+' bindsym XF86Forward exec 'playerctl position ${step_music}+'
bindsym XF86Back exec 'playerctl position ${step_music}-' bindsym XF86Back exec 'playerctl position ${step_music}-'
bindsym XF86Eject exec 'swayscript sound_output_cycle'
''; '';
} }