From 355e35b9f6cda972b995b581f80a7117b86b04f3 Mon Sep 17 00:00:00 2001 From: naturallaw77 Date: Thu, 1 Jun 2023 05:47:05 -0700 Subject: [PATCH] initial add --- For_NEW_Sovran_Pros_Upload/flake.nix | 14 + For_NEW_Sovran_Pros_Upload/sp | 197 ++++++++++++ README.md | 30 +- flake.lock | 122 ++++++++ flake.nix | 28 ++ modules/bitcoinecosystem.nix | 76 +++++ modules/configuration.nix | 434 +++++++++++++++++++++++++++ modules/coturn.nix | 51 ++++ modules/modules.nix | 13 + modules/personalization.nix | 17 ++ modules/synapse.nix | 75 +++++ modules/vaultwarden.nix | 21 ++ sovran_systems.png | Bin 0 -> 23137 bytes 13 files changed, 1076 insertions(+), 2 deletions(-) create mode 100644 For_NEW_Sovran_Pros_Upload/flake.nix create mode 100644 For_NEW_Sovran_Pros_Upload/sp create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 modules/bitcoinecosystem.nix create mode 100644 modules/configuration.nix create mode 100644 modules/coturn.nix create mode 100644 modules/modules.nix create mode 100644 modules/personalization.nix create mode 100644 modules/synapse.nix create mode 100644 modules/vaultwarden.nix create mode 100644 sovran_systems.png diff --git a/For_NEW_Sovran_Pros_Upload/flake.nix b/For_NEW_Sovran_Pros_Upload/flake.nix new file mode 100644 index 0000000..7d9c4e8 --- /dev/null +++ b/For_NEW_Sovran_Pros_Upload/flake.nix @@ -0,0 +1,14 @@ +{ + description = "The Ultimate Sovran Pro Configuration from Sovran Systems"; + + inputs = { + Sovran_Systems.url = "git+https://git.sovransystems.com/Sovran_Systems/Sovran_Pro"; + }; + + outputs = { self, Sovran_Systems, ... }@inputs: { + nixosConfigurations."nixos" = Sovran_Systems.inputs.nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ Sovran_Systems.nixosModules.Sovran_Pro ]; + }; + }; +} \ No newline at end of file diff --git a/For_NEW_Sovran_Pros_Upload/sp b/For_NEW_Sovran_Pros_Upload/sp new file mode 100644 index 0000000..701e52e --- /dev/null +++ b/For_NEW_Sovran_Pros_Upload/sp @@ -0,0 +1,197 @@ +#!/usr/bin/env bash + +GREEN="\e[32m" +LIGHTBLUE="\e[94m" +ENDCOLOR="\e[0m" + +# + +pushd /etc/nixos/ + +sudo wget https://git.sovransystems.com/Sovran_Systems/Sovran_Pro/raw/branch/main/For_NEW_Sovran_Pros_Upload/flake.nix + +sudo chown root:root /etc/nixos/ -R + +sudo chmod 770 /etc/nixos/ -R + +popd + +# + +sudo rsync -av -e "ssh -i /root/sovransystems" root@192.168.1.32:/home/ /home + +sudo rsync -av -e "ssh -i /root/sovransystems" root@192.168.1.32:/var/lib/www/ /var/lib/www + +sudo rsync -av -e "ssh -i /root/sovransystems" root@192.168.1.32:/var/lib/domains/ /var/lib/domains + +sudo rsync -av -e "ssh -i /root/sovransystems" root@192.168.1.32:/var/lib/nextcloudaddition/ /var/lib/nextcloudaddition + +sudo rsync -av -e "ssh -i /root/sovransystems" root@192.168.1.32:/var/lib/njalla/ /var/lib/njalla + +sudo rsync -av -e "ssh -i /root/sovransystems" root@192.168.1.32:/var/lib/external_ip/ /var/lib/external_ip + +sudo rsync -av -e "ssh -i /root/sovransystems" root@192.168.1.32:/var/lib/secrets/ /var/lib/secrets + +# + +nixos-rebuild switch --flake '/etc/nixos/#' --impure --update-input Sovran_Systems --commit-lock-file + +# + +sudo chown root:root /var/lib/secrets/main -R + +sudo chown matrix-synapse:matrix-synapse /var/lib/secrets/matrix_reg_secret -R + +sudo chown matrix-synapse:matrix-synapse /var/lib/secrets/matrixdb -R + +sudo chown postgres:postgres /var/lib/secrets/nextclouddb -R + +sudo chown turnserver:turnserver /var/lib/secrets/turn -R + +sudo chown mysql:mysql /var/lib/secrets/wordpressdb -R + +sudo chmod 770 /var/lib/secrets/ -R + +# + +sudo echo -e "${GREEN}What is your New Matrix (Element Chat) domain name?${ENDCOLOR}" +read +sudo echo -n $REPLY > /var/lib/domains/matrix + +sudo echo -e "${GREEN}What is your New Wordpress domain name?${ENDCOLOR}" +read +sudo echo -n $REPLY > /var/lib/domains/wordpress + +sudo echo -e "${GREEN}What is your New Nextcloud domain name?${ENDCOLOR}" +read +sudo echo -n $REPLY > /var/lib/domains/nextcloud + +sudo echo -e "${GREEN}What is your New BTCPayserver domain name?${ENDCOLOR}" +read +sudo echo -n $REPLY > /var/lib/domains/btcpayserver + +sudo echo -e "${GREEN}What is your New Vaultwarden domain name?${ENDCOLOR}" +read +sudo echo -n $REPLY > /var/lib/domains/vaultwarden + +sudo echo -e "${GREEN}What is the email you would like to use to manage the SSL certificates for your domains?${ENDCOLOR}" +read +sudo echo -n $REPLY > /var/lib/domains/sslemail + + +sudo chown caddy:php /var/lib/domains -R + +sudo chmod 770 /var/lib/domains -R + +# + +set -x + + +sudo rm -rf /home/free/.config/BraveSoftware + +sudo rm -rf /home/free/.local/share/fish/fish_history + +# + +sudo rm -rf /var/lib/www/wordpress/wp-config.php + +sudo rm -rf /var/lib/www/nextcloud/config/config.php + +sudo touch /var/lib/www/nextcloud/config/CAN_INSTALL + +sudo sed -i '$e cat /var/lib/nextcloudaddition/nextcloudaddition' /var/lib/www/nextcloud/config/config.php + + +sudo chown caddy:php /var/lib/www -R + +sudo chmod 770 /var/lib/www -R + +# + +sudo mkdir /var/lib/nextcloud + +sudo chown caddy:php /var/lib/nextcloud -R + +sudo chmod 770 /var/lib/nextcloud -R + +# + +sudo mkdir /var/lib/coturn + +sudo chown turnserver:turnserver /var/lib/coturn -R + +sudo chmod 770 /var/lib/coturn -R + +# + +sudo touch /var/lib/vaultwarden.env + +sudo chown vaultwarden:vaultwarden /var/lib/vaultwarden.env + +sudo chmod 770 /var/lib/vaultwarden.env + +# + +sudo echo -n $(pwgen -s 17 -1) > /var/lib/secrets/nextclouddb +sudo echo -n $(pwgen -s 17 -1) > /var/lib/secrets/wordpressdb +sudo echo -n $(pwgen -s 17 -1) > /var/lib/secrets/matrixdb +sudo echo -n $(pwgen -s 17 -1) > /var/lib/secrets/turn +sudo echo -n $(pwgen -s 17 -1) > /var/lib/secrets/matrix_reg_secret +sudo echo -n $(pwgen -s 17 -1) > /var/lib/secrets/main +sudo echo -n ADMIN_TOKEN=$(openssl rand -base64 48 +) > /var/lib/vaultwarden.env + +# + +sudo echo "root:$(cat /var/lib/secrets/main)" | chpasswd -c SHA512 + +# + +flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo +flatpak update + +# + +sudo echo "free:a" | chpasswd -c SHA512 + +# + +sudo rm -rf /root/sp + +sudo rm -rf /root/Step_2_psp + +sudo rm -rf /root/.ssh + +sudo rm -rf /home/free/.ssh + +sudo rm -rf /root/sovransystems + + +sudo chown bitcoin:bitcoin /run/media/Second_Drive/BTCEcoandBackup/Bitcoin_Node -R + +sudo chmod 770 /run/media/Second_Drive/BTCEcoandBackup/Bitcoin_Node -R + +sudo chown electrs:electrs /run/media/Second_Drive/BTCEcoandBackup/Electrs_Data -R + +sudo chmod 770 /run/media/Second_Drive/BTCEcoandBackup/Electrs_Data -R + +nixos-rebuild switch --flake '/etc/nixos/#' --impure --update-input Sovran_Systems --commit-lock-file + + +# + +set +x + +sudo echo -e "${GREEN}These four passwords are generated for convenience to use for the Web front end setup UI accounts for Nextcloud, Wordpress, VaultWarden, and BTCPayserver (if you want to use them).${ENDCOLOR} \n" + +sudo echo -e "$(pwgen -s 17 -1) \n" +sudo echo -e "$(pwgen -s 17 -1) \n" +sudo echo -e "$(pwgen -s 17 -1) \n" +sudo echo -e "$(pwgen -s 17 -1) \n" + +# + +sudo echo -e "${LIGHTBLUE}One last thing, you need to put the Njalla DDNS info from Njalla into njalla.sh.${ENDCOLOR} \n" + +sudo echo -e "${GREEN}All Finished! Please Reboot then Enjoy your New Sovran Pro!${ENDCOLOR} \n" \ No newline at end of file diff --git a/README.md b/README.md index b8fcfa8..62621c7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,29 @@ -# Sovran_SystemsOS +
+
-The Official Repository of Sovran_SystemsOS. \ No newline at end of file +
drawing
+ +
+
+
+# Complete Configuration for Sovran_SystemsOS and the Sovran Pro +________________________________________________________ + +A Nix Flake Implementation + +Thanks to all the NixOS creators and developers for creating what is the future of computing. + +https://www.sovransystems.com + +Connect on Matrix here: https://matrix.to/#/#sovran-systems:anarchyislove.xyz + +_________________________________________________________ +GNU GPL 3.0+ + +All Open Source Software Used Falls Under Its Specific Open Source License. + +Created, Handcrafted, and Headquartered in Southern California – 2022-2023 🏖️. + +This Gitea is Proudly Powered by a Sovran Pro 💚. + +All Is Love. Fear Is Illusion. All Beings Are Free. Truth Can Never Be Destroyed. \ No newline at end of file diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..8a39b31 --- /dev/null +++ b/flake.lock @@ -0,0 +1,122 @@ +{ + "nodes": { + "extra-container": { + "inputs": { + "flake-utils": [ + "nix-bitcoin", + "flake-utils" + ], + "nixpkgs": [ + "nix-bitcoin", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1678566036, + "narHash": "sha256-dq+gCYplCTkbHOH1ERCzuTnwY/RvwMyw/kijPy7C3vE=", + "owner": "erikarvstedt", + "repo": "extra-container", + "rev": "a4fe3227bf63bf8479938e1457ebe1c04fe51ef5", + "type": "github" + }, + "original": { + "owner": "erikarvstedt", + "repo": "extra-container", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nix-bitcoin": { + "inputs": { + "extra-container": "extra-container", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "nixpkgs-unstable": "nixpkgs-unstable" + }, + "locked": { + "lastModified": 1679384842, + "narHash": "sha256-SMJW+QZt3iRuoezjE12sopBsdLHDihXe/RerLfRpqoI=", + "owner": "fort-nix", + "repo": "nix-bitcoin", + "rev": "481050bdf75106bff652016bfe5c39736bdd03ef", + "type": "github" + }, + "original": { + "owner": "fort-nix", + "ref": "release", + "repo": "nix-bitcoin", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1679139072, + "narHash": "sha256-Gtw2Yj8DfETie3u7iHv1y5Wt+plGRmp6nTQ0EEfaPho=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "08ef7dc8334521605a5c8b7086cc248e74ee338b", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1679198465, + "narHash": "sha256-VfXpHpniNWgg7pBzxb20pRX7kqn80LApPDQYTReiFCw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5a05160f7671434e1c833b1b01284b876e04eca4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1681217261, + "narHash": "sha256-RbxCHWN3Vhyv/WEsXcJlDwF7bpvZ9NxDjfSouQxXEKo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3fb8eedc450286d5092e4953118212fa21091b3b", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nix-bitcoin": "nix-bitcoin", + "nixpkgs": "nixpkgs_2" + } + } + }, + "root": "root", + "version": 7 +} \ No newline at end of file diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..243b4e3 --- /dev/null +++ b/flake.nix @@ -0,0 +1,28 @@ +{ + description = "The Ultimate Sovran Pro Configuration from Sovran Systems"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + nix-bitcoin.url = "github:fort-nix/nix-bitcoin/release"; + }; + + outputs = { self, nixpkgs, nix-bitcoin, ... }: + { + + nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { + system ="x86_64-linux"; + }; + + nixosModules.Sovran_Pro = { pkgs, ... }: { + + imports = [ + + ./modules/modules.nix + + nix-bitcoin.nixosModules.default + + ]; + }; + }; +} \ No newline at end of file diff --git a/modules/bitcoinecosystem.nix b/modules/bitcoinecosystem.nix new file mode 100644 index 0000000..0f8e45d --- /dev/null +++ b/modules/bitcoinecosystem.nix @@ -0,0 +1,76 @@ +{ config, pkgs, lib, ... }: + +{ + nix-bitcoin.generateSecrets = true; + + services.bitcoind = { + enable = true; + dataDir = "/run/media/Second_Drive/BTCEcoandBackup/Bitcoin_Node"; + txindex = true; + tor.proxy = true; + disablewallet = true; + extraConfig = '' + peerbloomfilters=1 + server=1 + ''; + }; + + nix-bitcoin.onionServices.bitcoind.enable = true; + nix-bitcoin.onionServices.electrs.enable = true; + + services.lnd = { + enable = true; + }; + + services.lightning-loop = { + enable = true; + }; + + services.lightning-pool = { + enable = true; + }; + + services.rtl = { + enable = true; + port = 3050; + nightTheme = true; + nodes = { + lnd = { + enable = true; + loop = true; + }; + reverseOrder = true; + }; + }; + + nix-bitcoin.onionServices.lnd.public = true; + services.lnd.lndconnect = { + enable = true; + onion = true; + }; + services.charge-lnd.enable = true; + + services.btcpayserver.lightningBackend = "lnd"; + + + services.electrs = { + enable = true; + tor.enforce = true; + dataDir = "/run/media/Second_Drive/BTCEcoandBackup/Electrs_Data"; + }; + + + services.btcpayserver = { + enable = true; + }; + + + nix-bitcoin.nodeinfo.enable = true; + + + nix-bitcoin.operator = { + enable = true; + name = "free"; + }; + +} diff --git a/modules/configuration.nix b/modules/configuration.nix new file mode 100644 index 0000000..bf43b2e --- /dev/null +++ b/modules/configuration.nix @@ -0,0 +1,434 @@ +{ config, pkgs, lib, ... }: + + +let + personalization = import ./personalization.nix; + + + custom-php = pkgs.php81.buildEnv { + extensions = { enabled, all }: enabled ++ (with all; [ apcu imagick memcached ]); + extraConfig = '' + display_errors = On + display_startup_errors = On + max_execution_time = 6000 + max_input_time = 3000 + memory_limit = 8G; + opcache.enable=1; + opcache.memory_consumption=512; + opcache_revalidate_freq = 240; + opcache.max_accelerated_files=4000; + auto_prepend_file = '/var/lib/www/wordpress/wordfence-waf.php' + post_max_size = 2048M + upload_max_filesize = 2048M + opcache.interned_strings_buffer = 32 + apc.enable_cli=1 + ''; + }; +in +{ + # Bootloader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + boot.loader.efi.efiSysMountPoint = "/boot/efi"; + boot.kernelPackages = pkgs.linuxPackages_latest; + + # Enable Automount without Fail for Internal Drive. + fileSystems."/run/media/Second_Drive" = { + device = "LABEL=BTCEcoandBackup"; + fsType = "ext4"; + options = [ "nofail" ]; + }; + + nix = { + package = pkgs.nixUnstable; + extraOptions = '' + experimental-features = nix-command flakes + ''; + }; + + networking.hostName = "nixos"; # Define your hostname. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + + # Enable networking + networking.networkmanager.enable = true; + + # Set your time zone. + time.timeZone = "America/Los_Angeles"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + # Enable the X11 windowing system. + services.xserver.enable = true; + + # Enable the GNOME Desktop Environment. + services.xserver.displayManager.gdm.enable = true; + services.xserver.desktopManager.gnome.enable = true; + + # Configure keymap in X11 + services.xserver = { + layout = "us"; + xkbVariant = ""; + }; + + # Enable CUPS to print documents. + services.printing.enable = true; + + # Systemd Settings + systemd.enableEmergencyMode = false; + + # Enable sound with pipewire. + sound.enable = true; + hardware.pulseaudio.enable = false; + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + }; + + users.users = { + free = { + isNormalUser = true; + description = "free"; + extraGroups = [ "networkmanager" ]; + }; + + +####### PHP user for PHPFPM ####### + php = { + isSystemUser = true; + createHome = false; + uid = 7777; + }; + }; + + users.users.php.group = "php"; + users.groups.php = {}; + + + + # Enable automatic login for the user. + services.xserver.displayManager.autoLogin.enable = true; + services.xserver.displayManager.autoLogin.user = "free"; + + # Workaround for GNOME autologin: https://github.com/NixOS/nixpkgs/issues/103746#issuecomment-945091229 + systemd.services."getty@tty1".enable = true; + systemd.services."autovt@tty1".enable = true; + + # Allow Flatpak + services.flatpak.enable = true; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + git + wget + librewolf + fish + htop + gnomeExtensions.dash-to-dock-for-cosmic + gnomeExtensions.vitals + gnomeExtensions.pop-shell + gnomeExtensions.transparent-top-bar + gnomeExtensions.just-perfection + gnomeExtensions.appindicator + gnomeExtensions.systemd-manager + gnome.gnome-tweaks + papirus-icon-theme + ranger + gnome.gnome-tweaks + sparrow + bisq-desktop + neofetch + gnome.gedit + matrix-synapse + openssl + pwgen + aspell + aspellDicts.en + lm_sensors + hunspell + hunspellDicts.en_US + custom-php + matrix-synapse-tools.synadm + brave + ncdu_2 + bitwarden + gparted + pv + unzip + parted + screen + gnome.zenity + + ]; + + nixpkgs.config.permittedInsecurePackages = [ + "nodejs-16.20.0" + "nodejs-slim-16.20.0" + ]; + + + programs.bash.promptInit = "fish"; + programs.fish = { + enable = true; + promptInit = "neofetch"; + }; + + +####### PHPFMP ####### + services.phpfpm.pools = { + mypool = { + user = "caddy"; + group = "php"; + phpPackage = custom-php; + settings = { + "pm" = "dynamic"; + "pm.max_children" = 75; + "pm.start_servers" = 10; + "pm.min_spare_servers" = 5; + "pm.max_spare_servers" = 20; + "pm.max_requests" = 500; + "clear_env" = "no"; + }; + }; + }; + + + +####### CADDY ####### + services.caddy = { + enable = true; + package = pkgs.caddy; + user = "caddy"; + group = "root"; + email = "${personalization.caddy_email_for_zerossl}"; + acmeCA = "https://acme.zerossl.com/v2/DV90"; + virtualHosts = { + "${personalization.wordpress_url}" = { + extraConfig = '' + encode gzip zstd + root * /var/lib/www/wordpress + php_fastcgi unix//run/phpfpm/mypool.sock + file_server browse + ''; + }; + + "www.${personalization.wordpress_url}" = { + extraConfig = '' + encode gzip zstd + root * /var/lib/www/wordpress + php_fastcgi unix//run/phpfpm/mypool.sock + file_server browse + ''; + }; + + "${personalization.nextcloud_url}" = { + extraConfig = '' + encode gzip zstd + root * /var/lib/www/nextcloud + php_fastcgi unix//run/phpfpm/mypool.sock + file_server + redir /.well-known/carddav /remote.php/carddav 301 + redir /.well-known/caldav /remote.php/caldav 301 + header { + Strict-Transport-Security max-age=31536000; + } + ''; + }; + + "${personalization.matrix_url}" = { + extraConfig = '' + reverse_proxy /_matrix/* http://localhost:8008 + reverse_proxy /_synapse/client/* http://localhost:8008 + ''; + }; + + "${personalization.matrix_url}:8448" = { + extraConfig = '' + reverse_proxy http://localhost:8008 + ''; + }; + + "${personalization.btcpayserver_url}" = { + extraConfig = '' + reverse_proxy http://localhost:23000 + encode gzip zstd + ''; + }; + + "https://${personalization.vaultwarden_url}" = { + extraConfig = '' + reverse_proxy http://localhost:8777 + encode gzip zstd + ''; + }; + + ":3051" = { + extraConfig = '' + reverse_proxy :3050 + encode gzip zstd + tls internal + ''; + }; + }; + }; + + +###### CREATE DATABASE (WORDPRESS, MATRIX_SYNAPSE, AND NEXTCLOUD) ####### + services.postgresql = { + enable = true; + package = pkgs.postgresql_14; + }; + + services.postgresql.authentication = lib.mkForce '' + # Generated file; do not edit! + # TYPE DATABASE USER ADDRESS METHOD + local all all trust + host all all 127.0.0.1/32 trust + host all all ::1/128 trust + ''; + + + services.mysql = { + enable = true; + package = pkgs.mariadb_1011; + }; + + services.postgresql.initialScript = pkgs.writeText "begin-init.sql" '' + CREATE ROLE "ncusr" WITH LOGIN PASSWORD '${personalization.nextclouddb_pass}'; + CREATE DATABASE "nextclouddb" WITH OWNER "ncusr" + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C"; + + + CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD '${personalization.matrix-synapsedb_pass}'; + CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C"; + + '' + ; + + services.mysql.initialScript = pkgs.writeText "wordpress-init.sql" '' + CREATE DATABASE wordpressdb; + GRANT ALL ON *.* TO 'wpusr'@'localhost' IDENTIFIED BY '${personalization.wordpressdb_pass}'; + FLUSH PRIVILEGES; + '' + ; + + + +####### KEEP AWAKE for DISPLAY and HEADLESS ####### + services.xserver.displayManager.gdm.autoSuspend = false; + + + +####### BACKUP TO INTERNAL DRIVE ####### + services.rsnapshot = { + enable = true; + extraConfig = '' +snapshot_root /run/media/Second_Drive/BTCEcoandBackup/NixOS_Snapshot_Backup +retain hourly 12 +retain daily 12 +backup /home/ localhost/ +backup /var/lib/ localhost/ +backup /etc/nixos/ localhost/ +backup /etc/nix-bitcoin-secrets/ localhost/ + ''; + cronIntervals = { + daily = "50 21 * * *"; + hourly = "0 * * * *"; + }; + }; + + + +####### CRON ####### + services.cron = { + enable = true; + systemCronJobs = [ + "*/5 * * * * caddy /run/current-system/sw/bin/php -f /var/lib/www/nextcloud/cron.php" + "15 * * * * root /var/lib/njalla/njalla.sh" + "0 */2 * * * root /var/lib/external_ip/external_ip.sh" + ]; + }; + + +####### TOR ####### + services.tor = { + enable = true; + client.enable = true; + torsocks.enable = true; + }; + services.privoxy.enableTor = true; + + + + +####### Enable the OpenSSH daemon ####### + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; + PermitRootLogin = "yes"; + }; + }; + + +#######FailtoBan####### + services.fail2ban = { + enable = true; + ignoreIP = [ + "127.0.0.0/8" + "10.0.0.0/8" + "172.16.0.0/12" + "192.168.0.0/16" + "8.8.8.8" + ]; + }; + + +####### Open ports in the firewall ####### + networking.firewall.allowedTCPPorts = [ 80 443 5349 8448 3050 3051 ]; + networking.firewall.allowedUDPPorts = [ 80 443 5349 8448 3050 3051 ]; + networking.firewall.allowedUDPPortRanges = [ + { from=49152; to=65535; } # TURN relay + ]; + + # Or disable the firewall altogether. + networking.firewall.enable = true; + + + + +####### AUTO UPDATE ####### +# system.autoUpgrade = { +# enable = true; +# flags = [ "--impure" "--update-input" "Sovran_Systems" "--commit-lock-file" ]; +# flake = "/etc/nixos"; +# persistent = true; +# allowReboot = true; +# rebootWindow = { lower = "02:00"; upper = "05:00"; }; +# }; + + + +####### AUTO COLLECT GARABAGE ####### + nix.gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 7d"; + }; + + system.stateVersion = "22.05"; + +} diff --git a/modules/coturn.nix b/modules/coturn.nix new file mode 100644 index 0000000..d6de653 --- /dev/null +++ b/modules/coturn.nix @@ -0,0 +1,51 @@ +{config, pkgs, lib, ...}: + +let + personalization = import ./personalization.nix; + in +{ + systemd.services.sslcoturn = { + script = '' + cp -n /var/lib/caddy/.local/share/caddy/certificates/acme.zerossl.com-v2-dv90/${personalization.matrix_url}/${personalization.matrix_url}.crt /var/lib/coturn/${personalization.matrix_url}.crt.pem + + cp -n /var/lib/caddy/.local/share/caddy/certificates/acme.zerossl.com-v2-dv90/${personalization.matrix_url}/${personalization.matrix_url}.key /var/lib/coturn/${personalization.matrix_url}.key.pem + + chown turnserver:turnserver /var/lib/coturn -R + + chmod 770 /var/lib/coturn -R + + systemctl restart coturn + ''; + + unitConfig = { + Type = "simple"; + After = "NetworkManager.service"; + Requires = "network-online.target"; + }; + + serviceConfig = { + RemainAfterExit = "yes"; + Type = "oneshot"; + }; + + wantedBy = [ "multi-user.target" ]; + }; + + + services.coturn = { + enable = true; + use-auth-secret = true; + static-auth-secret = "${personalization.turn_shared}"; + realm = personalization.matrix_url; + cert = "/var/lib/coturn/${personalization.matrix_url}.crt.pem"; + pkey = "/var/lib/coturn/${personalization.matrix_url}.key.pem"; + min-port = 49152; + max-port = 65535; + no-cli = true; + #listening-ips = [ "127.0.0.1" ]; + extraConfig = '' + verbose + external-ip=${personalization.external_ip_secret} + ''; + }; +} diff --git a/modules/modules.nix b/modules/modules.nix new file mode 100644 index 0000000..518304e --- /dev/null +++ b/modules/modules.nix @@ -0,0 +1,13 @@ +{ config, pkgs, lib, ... }: + +{ + + imports = [ + ./configuration.nix + ./synapse.nix + ./coturn.nix + ./bitcoinecosystem.nix + ./vaultwarden.nix + /etc/nixos/hardware-configuration.nix + ]; +} \ No newline at end of file diff --git a/modules/personalization.nix b/modules/personalization.nix new file mode 100644 index 0000000..3310da5 --- /dev/null +++ b/modules/personalization.nix @@ -0,0 +1,17 @@ +{ + +matrix_url = builtins.readFile /var/lib/domains/matrix; +wordpress_url = builtins.readFile /var/lib/domains/wordpress; +nextcloud_url = builtins.readFile /var/lib/domains/nextcloud; +btcpayserver_url = builtins.readFile /var/lib/domains/btcpayserver; +caddy_email_for_zerossl = builtins.readFile /var/lib/domains/sslemail; +vaultwarden_url = builtins.readFile /var/lib/domains/vaultwarden; + +wordpressdb_pass = builtins.readFile /var/lib/secrets/wordpressdb; +matrix-synapsedb_pass = builtins.readFile /var/lib/secrets/matrixdb; +nextclouddb_pass = builtins.readFile /var/lib/secrets/nextclouddb; +turn_shared = builtins.readFile /var/lib/secrets/turn; +matrix_reg_secret = builtins.readFile /var/lib/secrets/matrix_reg_secret; +external_ip_secret = builtins.readFile /var/lib/secrets/external_ip; + +} diff --git a/modules/synapse.nix b/modules/synapse.nix new file mode 100644 index 0000000..76839ae --- /dev/null +++ b/modules/synapse.nix @@ -0,0 +1,75 @@ +{ config, pkgs, lib, ... }: + + +####### CREATE NEW USER (ADMIN OR NOT) VIA TERMINAL ####### + +# (Run as root in terminal) matrix-synapse-register_new_matrix_user # + +####### ####### + +let + personalization = import ./personalization.nix; +in +{ + services.matrix-synapse = { + enable = true; + settings = { + include_content = false; + group_unread_count_by_room = false; + encryption_enabled_by_default_for_room_type = "invite"; + allow_profile_lookup_over_federation = false; + allow_device_name_lookup_over_federation = false; + server_name = personalization.matrix_url; + url_preview_enabled = true; + max_upload_size = "1024M"; + url_preview_ip_range_blacklist = [ + "10.0.0.0/8" + "100.64.0.0/10" + "169.254.0.0/16" + "172.16.0.0/12" + "192.0.0.0/24" + "192.0.2.0/24" + "192.168.0.0/16" + "192.88.99.0/24" + "198.18.0.0/15" + "198.51.100.0/24" + "2001:db8::/32" + "203.0.113.0/24" + "224.0.0.0/4" + "::1/128" + "fc00::/7" + "fe80::/10" + "fec0::/10" + "ff00::/8" + ]; + url_preview_ip_ranger_whitelist = [ "127.0.0.1" ]; + turn_shared_secret = "${personalization.turn_shared}"; + turn_uris = [ + "turn:${personalization.matrix_url}:5349?transport=udp" + "turn:${personalization.matrix_url}:5349?transport=tcp" + "turns:${personalization.matrix_url}:5349?transport=udp" + "turns:${personalization.matrix_url}:5349?transport=tcp" + ]; + presence.enabled = true; + enable_registration = false; + registration_shared_secret = "${personalization.matrix_reg_secret}"; + listeners = [ + { + port = 8008; + bind_addresses = [ "::1" ]; + type = "http"; + tls = false; + x_forwarded = true; + resources = [ { + names = [ "client" ]; + compress = true; + } + { + names = [ "federation" ]; + compress = false; + } ]; + } + ]; + }; + }; +} diff --git a/modules/vaultwarden.nix b/modules/vaultwarden.nix new file mode 100644 index 0000000..46b0678 --- /dev/null +++ b/modules/vaultwarden.nix @@ -0,0 +1,21 @@ +{ config, pkgs, lib, ... }: + +let + personalization = import ./personalization.nix; +in +{ + + services.vaultwarden = { + enable = true; + config = { + + DOMAIN = "https://${personalization.vaultwarden_url}"; + SIGNUPS_ALLOWED = false; + ROCKET_ADDRESS = "127.0.0.1"; + ROCKET_PORT = 8777; + ROCKET_LOG = "critical"; + }; + dbBackend = "sqlite"; + environmentFile = "/var/lib/vaultwarden.env"; + }; +} \ No newline at end of file diff --git a/sovran_systems.png b/sovran_systems.png new file mode 100644 index 0000000000000000000000000000000000000000..618f61e62581d9214459805f1f7a35bc1f977514 GIT binary patch literal 23137 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 fJOLdWH~T;H$3@y3f-EETKz&e8S3j3^P6