From 6c2551349ec9c31b9518d10d0743b2a8befc8571 Mon Sep 17 00:00:00 2001 From: Philip Peterson <1326208+philip-peterson@users.noreply.github.com> Date: Fri, 15 Nov 2024 22:00:01 -0900 Subject: [PATCH] Publish quine-core --- .gitignore | 2 + nixos/.github/workflows/build.yml | 15 ++ nixos/.gitignore | 3 + nixos/README.md | 10 + nixos/apply.sh | 6 + nixos/clean.sh | 8 + nixos/cloned_repos/default.nix | 71 +++++ nixos/disk-config.nix | 55 ++++ nixos/firewall.nix | 3 + nixos/flake.lock | 227 ++++++++++++++++ nixos/flake.nix | 110 ++++++++ nixos/format.sh | 5 + nixos/globals.json | 2 + nixos/hetzner.nix | 42 +++ nixos/invoke-ddns/default.nix | 68 +++++ nixos/invoke-ddns/invoke_ddns/__init__.py | 2 + .../invoke_ddns/command/__init__.py | 2 + nixos/invoke-ddns/setup.py | 20 ++ .../keys/authorized_keys/macbookpro-intel.pub | 1 + nixos/keys/authorized_keys/macbookpro.pub | 1 + nixos/keys/authorized_keys/monolith.pub | 1 + nixos/keys/known_hosts/one.nix | 1 + nixos/keys/known_hosts/three.nix | 2 + nixos/keys/known_hosts/two.nix | 2 + nixos/keys/mainframe.pub | 1 + nixos/linux.nix | 186 +++++++++++++ nixos/nfsn_ddns-0.2.0-py3-none-any.whl | Bin 0 -> 18620 bytes nixos/nginx.nix | 144 ++++++++++ nixos/pullomatic/default.nix | 41 +++ nixos/refresh.sh | 5 + nixos/secrets/README.md | 5 + nixos/secrets/default.nix | 8 + nixos/secrets/nearlyfreespeech.age | 9 + nixos/system/home/ironmagma.nix | 15 ++ nixos/system/home/root.nix | 17 ++ nixos/system/home/shared.nix | 252 ++++++++++++++++++ nixos/system/users.nix | 74 +++++ terraform/.terraform.lock.hcl | 46 ++++ terraform/foo.tf | 45 ++++ terraform/terraform.tfstate | 75 ++++++ terraform/terraform.tfstate.backup | 56 ++++ 41 files changed, 1638 insertions(+) create mode 100644 .gitignore create mode 100644 nixos/.github/workflows/build.yml create mode 100644 nixos/.gitignore create mode 100644 nixos/README.md create mode 100755 nixos/apply.sh create mode 100755 nixos/clean.sh create mode 100644 nixos/cloned_repos/default.nix create mode 100644 nixos/disk-config.nix create mode 100644 nixos/firewall.nix create mode 100644 nixos/flake.lock create mode 100644 nixos/flake.nix create mode 100755 nixos/format.sh create mode 100644 nixos/globals.json create mode 100644 nixos/hetzner.nix create mode 100644 nixos/invoke-ddns/default.nix create mode 100644 nixos/invoke-ddns/invoke_ddns/__init__.py create mode 100644 nixos/invoke-ddns/invoke_ddns/command/__init__.py create mode 100644 nixos/invoke-ddns/setup.py create mode 100644 nixos/keys/authorized_keys/macbookpro-intel.pub create mode 100644 nixos/keys/authorized_keys/macbookpro.pub create mode 100644 nixos/keys/authorized_keys/monolith.pub create mode 100644 nixos/keys/known_hosts/one.nix create mode 100644 nixos/keys/known_hosts/three.nix create mode 100644 nixos/keys/known_hosts/two.nix create mode 100644 nixos/keys/mainframe.pub create mode 100644 nixos/linux.nix create mode 100644 nixos/nfsn_ddns-0.2.0-py3-none-any.whl create mode 100644 nixos/nginx.nix create mode 100644 nixos/pullomatic/default.nix create mode 100755 nixos/refresh.sh create mode 100644 nixos/secrets/README.md create mode 100644 nixos/secrets/default.nix create mode 100644 nixos/secrets/nearlyfreespeech.age create mode 100644 nixos/system/home/ironmagma.nix create mode 100644 nixos/system/home/root.nix create mode 100644 nixos/system/home/shared.nix create mode 100644 nixos/system/users.nix create mode 100644 terraform/.terraform.lock.hcl create mode 100644 terraform/foo.tf create mode 100644 terraform/terraform.tfstate create mode 100644 terraform/terraform.tfstate.backup diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4913cd5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +terraform/.terraform diff --git a/nixos/.github/workflows/build.yml b/nixos/.github/workflows/build.yml new file mode 100644 index 0000000..181c1c6 --- /dev/null +++ b/nixos/.github/workflows/build.yml @@ -0,0 +1,15 @@ +name: 'build' + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: DeterminateSystems/nix-installer-action@main + - uses: DeterminateSystems/magic-nix-cache-action@main + - run: ssh-keygen -t rsa -N '' -f ./id_rsa && git add id_rsa.pub + - run: nix build .#nixosConfigurations.nixos.config.system.build.toplevel diff --git a/nixos/.gitignore b/nixos/.gitignore new file mode 100644 index 0000000..d9b63dc --- /dev/null +++ b/nixos/.gitignore @@ -0,0 +1,3 @@ +.idea +result +secrets.json diff --git a/nixos/README.md b/nixos/README.md new file mode 100644 index 0000000..3dd24b6 --- /dev/null +++ b/nixos/README.md @@ -0,0 +1,10 @@ +How to install: + +nix --extra-experimental-features flakes --extra-experimental-features nix-command run --debug github:numtide/nixos-anywhere --verbose -- --flake .#nixos root@yourhost.com + +You will need to maually make these: +``` +/root/.ssh/id_rsa +/root/.ssh/id_rsa.pub +/root/.ssh/id_rsa.pem +``` diff --git a/nixos/apply.sh b/nixos/apply.sh new file mode 100755 index 0000000..50a7953 --- /dev/null +++ b/nixos/apply.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -e + +git pull origin main +nixos-rebuild switch --flake .#nixos --verbose --show-trace diff --git a/nixos/clean.sh b/nixos/clean.sh new file mode 100755 index 0000000..e93313d --- /dev/null +++ b/nixos/clean.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +nix-store --gc +nix-collect-garbage -d +rm -rf ~/.cache/nix +rm -rf /nix/var/nix/gcroots/* diff --git a/nixos/cloned_repos/default.nix b/nixos/cloned_repos/default.nix new file mode 100644 index 0000000..f597719 --- /dev/null +++ b/nixos/cloned_repos/default.nix @@ -0,0 +1,71 @@ +{ + pullomatic, + pkgs, + lib, + ... +}: let + domainToPath = domain: lib.concatStringsSep "_" domain; + domainToRepoName = domain: lib.concatStringsSep "-" domain; + + makeConfigFile = domain: remoteUrl: branch: { + name = domainToRepoName domain; + text = '' + path: /etc/pullomatic/${domainToPath domain} + remote_url: ${remoteUrl} + remote_branch: ${branch} + interval: + interval: 10m + credentials: + private_key: /root/.ssh/id_rsa.pem + private_key_path: true + ''; + }; + + configFiles = [ + (makeConfigFile + ["com" "philippeterson"] + "git@github.com:philip-peterson/philippeterson.com.git" + "master") + (makeConfigFile + ["com" "quinefoundation" "blog"] + "git@github.com:philip-peterson/blog.git" + "master") + (makeConfigFile + ["atcsim"] + "git@github.com:philip-peterson/ATC-Sim.git" + "master") + ]; + + configDir = + pkgs.runCommand "config-dir" { + buildInputs = [pkgs.coreutils]; + } '' + mkdir -p $out + + # Loop over the config files and write each one to $out + ${lib.concatStringsSep "\n" (map (cf: '' + echo "${cf.text}" > $out/${cf.name} + chmod 0644 $out/${cf.name} + '') + configFiles)} + + chmod -R 0750 $out + ''; +in { + systemd.services.pullomatic = { + description = "Pull repositories with polling from a daemon"; + serviceConfig = { + ExecStart = "${pullomatic} -c ${configDir}"; + Restart = "always"; + RestartSec = "0"; + User = "root"; + Group = "root"; + }; + }; + + systemd.tmpfiles.rules = [ + "d /etc/pullomatic - root repo-data - -" + "Z /etc/pullomatic - root repo-data - -" + "Z /etc/pullomatic/* - root repo-data - -" + ]; +} diff --git a/nixos/disk-config.nix b/nixos/disk-config.nix new file mode 100644 index 0000000..c72a8d4 --- /dev/null +++ b/nixos/disk-config.nix @@ -0,0 +1,55 @@ +# Example to create a bios compatible gpt partition +{lib, ...}: { + disko.devices = { + disk.disk1 = { + device = lib.mkDefault "/dev/sda"; + type = "disk"; + content = { + type = "gpt"; + partitions = { + boot = { + name = "boot"; + size = "1M"; + type = "EF02"; + }; + esp = { + name = "ESP"; + size = "500M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + root = { + name = "root"; + size = "100%"; + content = { + type = "lvm_pv"; + vg = "pool"; + }; + }; + }; + }; + }; + lvm_vg = { + pool = { + type = "lvm_vg"; + lvs = { + root = { + size = "100%FREE"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/"; + mountOptions = [ + "defaults" + ]; + }; + }; + }; + }; + }; + }; +} diff --git a/nixos/firewall.nix b/nixos/firewall.nix new file mode 100644 index 0000000..845d4cb --- /dev/null +++ b/nixos/firewall.nix @@ -0,0 +1,3 @@ +{pkgs, ...}: { + networking.firewall.allowedTCPPorts = [80 22 443]; +} diff --git a/nixos/flake.lock b/nixos/flake.lock new file mode 100644 index 0000000..dec861d --- /dev/null +++ b/nixos/flake.lock @@ -0,0 +1,227 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1723293904, + "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", + "owner": "ryantm", + "repo": "agenix", + "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1700795494, + "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1707385478, + "narHash": "sha256-xwKXoBeiwfp+jqQxt3O0mUxrBXsNfdBn15teMMWbw0U=", + "owner": "nix-community", + "repo": "disko", + "rev": "15b52c3c8a718253e66f1b92f595dc47873fdfea", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703113217, + "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1706981411, + "narHash": "sha256-cLbLPTL1CDmETVh4p0nQtvoF+FSEjsnJTFpTxhXywhQ=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "652fda4ca6dafeb090943422c34ae9145787af37", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-23.11", + "repo": "home-manager", + "type": "github" + } + }, + "nix-index-database": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1707016097, + "narHash": "sha256-V4lHr6hFQ3rK650dh64Xffxsf4kse9vUYWsM+ldjkco=", + "owner": "Mic92", + "repo": "nix-index-database", + "rev": "3e3dad2808379c522138e2e8b0eb73500721a237", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "nix-index-database", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1707347730, + "narHash": "sha256-0etC/exQIaqC9vliKhc3eZE2Mm2wgLa0tj93ZF/egvM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "6832d0d99649db3d65a0e15fa51471537b2c56a6", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1707268954, + "narHash": "sha256-2en1kvde3cJVc3ZnTy8QeD2oKcseLFjYPLKhIGDanQ0=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "f8e2ebd66d097614d51a56a755450d4ae1632df1", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nur": { + "locked": { + "lastModified": 1707488227, + "narHash": "sha256-CJavI6VIk12u8mntxepDDinX2TX5et1I2phRm9mObtI=", + "owner": "nix-community", + "repo": "NUR", + "rev": "7401f12518027ed8ea1d8f7634a446ac3269c3c4", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "disko": "disko", + "home-manager": "home-manager_2", + "nix-index-database": "nix-index-database", + "nixpkgs": "nixpkgs", + "nixpkgs-unstable": "nixpkgs-unstable", + "nur": "nur", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1723515680, + "narHash": "sha256-nHdKymsHCVIh0Wdm4MvSgxcTTg34FJIYHRQkQYaSuvk=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "4ee3d9e9569f70d7bb40f28804d6fe950c81eab3", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "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" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/nixos/flake.nix b/nixos/flake.nix new file mode 100644 index 0000000..d5b38e4 --- /dev/null +++ b/nixos/flake.nix @@ -0,0 +1,110 @@ +{ + description = "NixOS configuration"; + + # 24.05 + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11"; + inputs.nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + + inputs.agenix.url = "github:ryantm/agenix"; + inputs.agenix.inputs.nixpkgs.follows = "nixpkgs"; + + inputs.rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + inputs.home-manager.url = "github:nix-community/home-manager/release-23.11"; + inputs.home-manager.inputs.nixpkgs.follows = "nixpkgs"; + + inputs.nur.url = "github:nix-community/NUR"; + + inputs.nix-index-database.url = "github:Mic92/nix-index-database"; + inputs.nix-index-database.inputs.nixpkgs.follows = "nixpkgs"; + + inputs.disko.url = "github:nix-community/disko"; + inputs.disko.inputs.nixpkgs.follows = "nixpkgs"; + + outputs = inputs: + with inputs; let + system = "x86_64-linux"; + globals = builtins.fromJSON (builtins.readFile "${self}/globals.json"); + + config = { + allowUnfree = true; + permittedInsecurePackages = [ + # FIXME:: add any insecure packages you absolutely need here + ]; + }; + + overlays = [ + nur.overlay + (_final: prev: { + # this allows us to reference pkgs.unstable + unstable = import nixpkgs-unstable { + inherit (prev) system; + inherit config; + }; + }) + (import rust-overlay) + ]; + + nixpkgsWithOverlays = with inputs; rec { + inherit overlays config; + }; + + pkgs = nixpkgsWithOverlays; + lib = pkgs.lib; + + configurationDefaults = args: { + nixpkgs = nixpkgsWithOverlays; + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.backupFileExtension = "hm-backup"; + home-manager.extraSpecialArgs = args; + }; + + argDefaults = { + inherit + globals + inputs + self + nix-index-database + ; + channels = { + inherit nixpkgs nixpkgs-unstable; + }; + }; + + mkNixosConfiguration = { + hostname, + username, + args ? {}, + modules, + }: let + specialArgs = argDefaults // {inherit hostname username;} // args; + in + nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = + [ + (configurationDefaults specialArgs) + home-manager.nixosModules.home-manager + ] + ++ modules; + }; + in { + nixosConfigurations.nixos = mkNixosConfiguration { + hostname = "pw-mainframe"; + username = "ironmagma"; + args = { + nixPkgs = import nixpkgs {inherit system overlays;}; + }; + modules = [ + disko.nixosModules.disko + agenix.nixosModules.age + ./hetzner.nix + ./linux.nix + ]; + }; + }; +} diff --git a/nixos/format.sh b/nixos/format.sh new file mode 100755 index 0000000..1a6c017 --- /dev/null +++ b/nixos/format.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -e + +nix-shell -p alejandra.out --run 'alejandra .' diff --git a/nixos/globals.json b/nixos/globals.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/nixos/globals.json @@ -0,0 +1,2 @@ +{ +} diff --git a/nixos/hetzner.nix b/nixos/hetzner.nix new file mode 100644 index 0000000..82fab44 --- /dev/null +++ b/nixos/hetzner.nix @@ -0,0 +1,42 @@ +{modulesPath, ...}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + (modulesPath + "/profiles/qemu-guest.nix") + ./disk-config.nix + ]; + + # Fixes iotop + boot.kernel.sysctl = {"kernel.task_delayacct" = 1;}; + + boot.loader.grub = { + # no need to set devices, disko will add all devices that have a EF02 partition to the list already + # devices = [ ]; + efiSupport = true; + efiInstallAsRemovable = true; + }; + + services.openssh = { + enable = true; + settings.PasswordAuthentication = false; + extraConfig = '' + PrintLastLog no + ''; + hostKeys = [ + { + bits = 4096; + path = "/etc/ssh/ssh_host_rsa_key"; + type = "rsa"; + } + { + path = "/etc/ssh/ssh_host_ed25519_key"; + type = "ed25519"; + } + + # For secrets + { + path = "/root/.ssh/id_rsa_nix"; + type = "ed25519"; + } + ]; + }; +} diff --git a/nixos/invoke-ddns/default.nix b/nixos/invoke-ddns/default.nix new file mode 100644 index 0000000..d3ee9bf --- /dev/null +++ b/nixos/invoke-ddns/default.nix @@ -0,0 +1,68 @@ +{pkgs ? import {}, ...}: let + # Fetch the tarball + nfsn_ddns_tarball = pkgs.fetchurl { + url = "https://files.pythonhosted.org/packages/76/15/607b52a0bfda95fd8157c1c4b3b3631aa535206b2bd8fb43f57961460402/nfsn_ddns-0.2.0.tar.gz"; + sha256 = "sha256-ijD3hrdoYNt/MHy4C6zIqgU5sj+kGg+ma8TswO5qOEk="; + }; + + # Extract the tarball + extracted_nfsn_ddns = pkgs.stdenv.mkDerivation { + name = "nfsn-ddns-extracted"; + + src = nfsn_ddns_tarball; + + buildInputs = [pkgs.gnugrep pkgs.gnumake pkgs.gzip]; # Ensure tools are available for extraction if needed + + phases = ["unpackPhase" "installPhase"]; + + unpackPhase = '' + mkdir -p $out + tar -xzf $src -C $out + ''; + + installPhase = '' + echo "Extracted files available in $out" + ''; + + meta = with pkgs.lib; { + description = "Extracted files from nfsn_ddns tarball"; + license = licenses.unlicense; + maintainers = []; + }; + }; +in + pkgs.python3Packages.buildPythonApplication rec { + pname = "invoke-ddns"; + version = "0.0.1"; + + src = ./.; + + format = "setuptools"; + + dontUseCmakeConfigure = true; + + buildInputs = with pkgs.python3Packages; [ + setuptools + extracted_nfsn_ddns + ]; + + propagatedBuildInputs = with pkgs.python3Packages; [ + tornado + requests + python-daemon + pip + pykka + pytest + ]; + + # no tests implemented + #doCheck = false; + #pythonImportsCheck = [ "mopidy_jellyfin" ]; + + meta = with pkgs.lib; { + homepage = "https://github.com/philip-peterson/invoke-ddns"; + description = "Invoke DDNS for fun and profit"; + license = licenses.unlicense; + maintainers = ["Philip Peterson"]; + }; + } diff --git a/nixos/invoke-ddns/invoke_ddns/__init__.py b/nixos/invoke-ddns/invoke_ddns/__init__.py new file mode 100644 index 0000000..ee1b4af --- /dev/null +++ b/nixos/invoke-ddns/invoke_ddns/__init__.py @@ -0,0 +1,2 @@ +if __name__ == '__main__': + pass diff --git a/nixos/invoke-ddns/invoke_ddns/command/__init__.py b/nixos/invoke-ddns/invoke_ddns/command/__init__.py new file mode 100644 index 0000000..4f023ea --- /dev/null +++ b/nixos/invoke-ddns/invoke_ddns/command/__init__.py @@ -0,0 +1,2 @@ +def main(): + pass \ No newline at end of file diff --git a/nixos/invoke-ddns/setup.py b/nixos/invoke-ddns/setup.py new file mode 100644 index 0000000..9fe0192 --- /dev/null +++ b/nixos/invoke-ddns/setup.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +from distutils.core import setup + +setup(name='InvokeDdns', + version='1.0', + description='Checks with NearlyFreeSpeech that the dynamic dns entries are right', + author='Philip Peterson', + author_email='peterson@sent.com', + url='https://github.com/philip-peterson/invoke-ddns', + packages=['invoke_ddns', 'invoke_ddns.command'], + install_requires=[ + 'tornado>=4.4' + ], + entry_points={ + 'console_scripts': [ + 'invoke-ddns = invoke_ddns.command:main', + ], + }, + ) diff --git a/nixos/keys/authorized_keys/macbookpro-intel.pub b/nixos/keys/authorized_keys/macbookpro-intel.pub new file mode 100644 index 0000000..4ffe400 --- /dev/null +++ b/nixos/keys/authorized_keys/macbookpro-intel.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDtibpc9Zz03PvrNLfgAz4UQ58UYrxw+8AZbzuSO8Gpvu4Eu0X3dJkD90tnK2XxsqKLUqN9pvoveA/29ul0DoAe9XHUXZJw//htwkUttVae2Uu7I+YnIqre1y3I0YQt+B1FzkYEaZ6KOTAqLGlRB27nzVagoCfZ0IW1cHf4NIL91hmZBNFHMNZoDP41p0zPOvJcw8SDTYv3h6K/sY60b1QB7yu5xIfFihzvTG7M6TBluLTNtdOK/qj79dEVbHr6etCjj0CChPozxq+CaCT/Mp2V6fpNxFADWsh7oLFG/gsDFYLJAn02NwQOT+yjWqWWa3qS73HzL2MaOzwDwwwV+4PK+/dIiU8Jw21guevWrZVGvmoZb4IC/I4DrlGZBpfBz/e0Kznkf8+pRx10SGjepXQVYCIUce6ptYm2X+oPuriUjTQKa3a4bvDFSMzgK6nt5CJzZI+tk9uTpxYH2gX4D06M7cylYgywJNSIyGE8+yJ8XpWgyAoM6tf9BIppJbLJQKsbO+IuElSjQWj5pcw/KIwYAFW5mQLjnjRmQg5HX8gkT6PD9jen26JJahYcfZnvlVwl1GkU52hCGP5LhdG2dgbZHG9Jibd+aVm5IfhnaB0/jWjV0+IuB1Wns3Etkbp098rXmiG6TLfI1XdH7+xbPw4+vSvBtlzTfRUfTTaY57VR4Q== ironmagma@Philips-MBP diff --git a/nixos/keys/authorized_keys/macbookpro.pub b/nixos/keys/authorized_keys/macbookpro.pub new file mode 100644 index 0000000..d91c113 --- /dev/null +++ b/nixos/keys/authorized_keys/macbookpro.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDOqjSTQAQ2H4RD7oHWXjc6M4TcLniAsieo1hk7jl/VHxl6fVKxab5rtWpbDBN9SqNmoTHlWRSd+kCIVdg8a0Psy0NISTfSUniWh9qIJrjXTpWfJ9PkXIlVrleEz9Szn0GY5NyYUcNiZSencMszrOkJC8DcKIW8qp+17VeYpnS/hbwjIjdhgaFA8DjrHRgXuf88XBbi+XDB+Rw0vLLL1qsdT0NPe3uE1ixYCIUlVu3imMq431xJ/x3MLJoLJm3KSjO8NKWbw4PetxOd4LDhJbHkDpdA0P+D2ZewPIGYA45Z+pxZqvfrKIBnB4RIW5tCMGMeZHWS74vhXODPzf67TkScCGt/FU92yZHRpBNYwZ+dS+8YWMmo3t2/YWpPxLFXkAx6t78TdVGhhFrjWdxPB9hTdfdX1Sh51mbp9WVLYgqT+M/YROesrSwm7TKMgMLemA77ISf0LqWrGBo6fHRGmIfwe/fI9hSAObdHkARwPHD2GhZl+SxW7D9CV8jhV6KKbc0= ironmagma@Philips-MacBook-Pro.local diff --git a/nixos/keys/authorized_keys/monolith.pub b/nixos/keys/authorized_keys/monolith.pub new file mode 100644 index 0000000..3cba45d --- /dev/null +++ b/nixos/keys/authorized_keys/monolith.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC534fjfQ8PFUuyqp/3jH+tE2hq5EbbR8QcJ5ZYdm5H28d0+npxE4RnxqA82q/ZHiZT1nG5BIlRitPoIE74LFruLPBzZVfpOQxqczCAM2gsKGOY8Ug30Jl3OazsEyXYcZPdYdl/KhdrzPuJArRA7rdiI3krgVRnyG/bmU9/uQJ5fhowMJ8owYLdP4SXxh0O/vTauyNTxvddQAtGd+1DmcrFjFFNc8FeEhItMu2I9E1nIMS+lVSXOLZr1kXJa4kAhjUrWziI4nfzHESkV0hjF+DOQB/6bMFD04vkhCdK3wXKbEFkKzSBBtHQavpD7givk8mKWncdNR0bH+mB6WgiPbDAG83Q6ycAk3gX/AQAG/k/ZWo5x0u6MCN2op++JQLghdsg7T6iTJ+vTwqtEXiaWzckpEs+NR6GML8o/HCRZTTam8RIBgW5oUoqa52aDUS0WNpAGEfiUnmoKmAbxhsjtTVNPU0pWAKmon9mEmw83CzqogxAkOIgrWM58QGaGsuNgqU= root@monolith diff --git a/nixos/keys/known_hosts/one.nix b/nixos/keys/known_hosts/one.nix new file mode 100644 index 0000000..9d9f7fc --- /dev/null +++ b/nixos/keys/known_hosts/one.nix @@ -0,0 +1 @@ +"github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl" \ No newline at end of file diff --git a/nixos/keys/known_hosts/three.nix b/nixos/keys/known_hosts/three.nix new file mode 100644 index 0000000..7f953b3 --- /dev/null +++ b/nixos/keys/known_hosts/three.nix @@ -0,0 +1,2 @@ + +"github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=" \ No newline at end of file diff --git a/nixos/keys/known_hosts/two.nix b/nixos/keys/known_hosts/two.nix new file mode 100644 index 0000000..6ca2226 --- /dev/null +++ b/nixos/keys/known_hosts/two.nix @@ -0,0 +1,2 @@ + +"github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=" \ No newline at end of file diff --git a/nixos/keys/mainframe.pub b/nixos/keys/mainframe.pub new file mode 100644 index 0000000..9b4035e --- /dev/null +++ b/nixos/keys/mainframe.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB5cEJLzQH5v3r4DrwZxwXOGQWaRVlyJGciXkOz6KiKI root@pw-mainframe \ No newline at end of file diff --git a/nixos/linux.nix b/nixos/linux.nix new file mode 100644 index 0000000..2d8794c --- /dev/null +++ b/nixos/linux.nix @@ -0,0 +1,186 @@ +{ + config, + username, + hostname, + pkgs, + lib, + nix-index-database, + inputs, + specialArgs, + ... +}: let + ddnsPkg = import ./invoke-ddns {inherit pkgs;}; + + startSeq = builtins.fromJSON ''"\u001b[7m"''; # Start inverted color + endSeq = builtins.fromJSON ''"\u001b[27m"''; # End inverted color + motd = "${startSeq} Welcome to the Peterson Mainframe! Look, touch, but DO NOT LICK. ${endSeq}"; + + nixPkgs = specialArgs.nixPkgs; + ourRustVersion = pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.complete); + + ourRustPlatform = nixPkgs.makeRustPlatform { + rustc = ourRustVersion; + cargo = ourRustVersion; + }; + + pullomaticPkg = import ./pullomatic { + inherit lib pkgs; + rustPlatform = ourRustPlatform; + specialArgs = {}; + }; + + pullomatic = "${pullomaticPkg}/bin/pullomatic"; +in { + imports = [ + (import ./cloned_repos {inherit pkgs pullomatic lib;}) + (import ./nginx.nix {inherit pkgs lib config;}) + (import ./firewall.nix {inherit pkgs;}) + (import ./system/users.nix {inherit pkgs config lib nix-index-database;}) + ]; + + time.timeZone = "America/Anchorage"; + + age.secrets.nearlyfreespeech.file = ./secrets/nearlyfreespeech.age; + age.secrets.nearlyfreespeech.owner = "root"; + + environment.systemPackages = [ + ddnsPkg + pullomaticPkg + pkgs.vim + pkgs.php + pkgs.rustc + pkgs.cargo + pkgs.util-linux + pkgs.iotop + pkgs.rust-bin.stable.latest.default + ]; + + swapDevices = [ + { + device = "/swapfile"; + size = 1 * 1024; # 1GB + } + ]; + + systemd.tmpfiles.rules = [ + "d /home/ironmagma/.config 0755 ${username} users" + "d /root/.config 0755 ${username} users" + ]; + + networking.hostName = "${hostname}"; + + # FIXME: change your shell here if you don't want zsh + programs.zsh.enable = true; + environment.pathsToLink = ["/share/zsh"]; + environment.shells = [pkgs.zsh]; + + environment.enableAllTerminfo = true; + + security.sudo.wheelNeedsPassword = false; + + users.motd = motd; + + system.stateVersion = "22.05"; + + virtualisation.docker = { + enable = true; + enableOnBoot = true; + autoPrune.enable = true; + }; + + virtualisation.oci-containers = { + backend = "docker"; + + containers = { + "hello" = { + autoStart = true; + image = "nginxdemos/hello"; + #user = "root:jellyfin"; + volumes = [ + ]; + ports = ["8081:80"]; + }; + + "navidrome" = { + autoStart = true; + environment = { + "TZ" = "America/Anchorage"; + "PUID" = "1000"; + "PGID" = "100"; + + "ND_SCANSCHEDULE" = "1h"; + "ND_LOGLEVEL" = "info"; + "ND_SESSIONTIMEOUT" = "24h"; + "ND_BASEURL" = ""; + }; + ports = ["4533:4533"]; + volumes = [ + "/var/navidrome/data:/data" + "/var/navidrome/music:/music:ro" + ]; + image = "deluan/navidrome"; + }; + + "webdav" = { + autoStart = true; + image = "dgraziotin/nginx-webdav-nononsense"; + #user = "root:jellyfin"; + volumes = [ + "/mnt/webdav/data:/data" + "/mnt/webdav/config:/config" + ]; + environment = { + "WEBDAV_USERNAME" = "foo"; + # TODO + "WEBDAV_PASSWORD" = "bar"; + "TZ" = "America/Anchorage"; + + "PUID" = "60"; # nginx user + "PGID" = "60"; # nginx group + }; + ports = ["8082:80"]; + }; + }; + }; + + nix = { + settings = { + trusted-users = [username]; + + accept-flake-config = true; + auto-optimise-store = true; + }; + + registry = { + nixpkgs = { + flake = inputs.nixpkgs; + }; + }; + + nixPath = [ + "nixpkgs=${inputs.nixpkgs.outPath}" + "nixos-config=/etc/nixos/configuration.nix" + "/nix/var/nix/profiles/per-user/root/channels" + ]; + + package = pkgs.nixFlakes; + extraOptions = ''experimental-features = nix-command flakes''; + + gc = { + automatic = true; + options = "--delete-older-than 7d"; + }; + }; + + # HTTPS + + security.acme = { + acceptTerms = true; + defaults.email = "peterson@sent.com"; + certs."philippeterson.com" = { + dnsProvider = "nearlyfreespeech"; + environmentFile = config.age.secrets."nearlyfreespeech".path; + webroot = null; + }; + }; +} diff --git a/nixos/nfsn_ddns-0.2.0-py3-none-any.whl b/nixos/nfsn_ddns-0.2.0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..f8072584942d91876dfa51ead54fda2358256137 GIT binary patch literal 18620 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 n$ME@I^dpYTiH!UGAtM<{Tnq z5(oi{qJivwLeA=Ebh8%3BE731(CN{j%{TobY=hdw5n9W({+tbiDi4G_)renF!!3@) z9JgTeCmffbp6F0X1S!pn-vNiGpQe5L7q3C$L_lUDEh+ABU>efTUB^n6R)E>=-?q zFFp)FZ&%F@FmXN>9-Z|tde$5hpMZv20)*4iyWth2@B1^I-~<@OdxC57HP@UMrs`X5tReg?(=Xp)h&qrIDs zt&N$rqXUhjt7C-B^bFK`2X!FR;g76sN3ha?0R|G7@X{Uaiv5U z0{vG9ah-9LNBR##^Zmon{Lc@zG&3-=b}(|Fl@b>emQfT=QqZx zD7!A{+sq>2jTAVkcG{1zIrcDpLzOWAuMU~Z3D!chx%#sWLtFbiU?;V+Dh*bL%Ll3`N9OauS*xF!6$*fjPOZ1K@O)jTk#7HL zw$*@jGVtZD1MH|BVpkcs!$P+5oR-1gKli}LsCQNC+@-|euPps0z_4Hro9E0BVD!`? zY&CnN4gbjH;21Qp<@k|dZ)wn`SXA$^#E-0&+UE()A}XfbwA46BeNa9shZSoy+)}i} zR8zGVL22fCM}Ztj)#BTdBx1m4maD9c5J2CaTtv(SDVK)oByz|A2a(PxNAQASFHFk zo~4aJ;n4#Lnz>N;@6bS(_+?C0e#T?nv$i@zi-=k!iU@wJMGJ|!jZlHKR23^aJuu4O z^n$iZMZIELCg}kQ~K@Ykt*y2MJ<3#h6n?)x(UCx&k;gc0m({Z&Ha8#J+9&*);6VmC*Muj+JdSR*E!+JA(S`4tDr6%1-$Qrb=L)A> zG5b*hGzdPEm37hr*~{58tS!aK(k*AhY*Rqd$AC?7-?d*z$=c4crXwEP+)ZC?L66aM zOPk#e!dFLJIK}G~!s(~$TOA5qJ8elSk%A5JBp#8BEEI_bcV*PxZ`iUCJkHBW*HJ|> z=w<^_ULS>zz`1HN8iJs`zULW%ZUHaIu=6ceS5f3uPQ(7MeYTWJ! z#fe09d*kJ2(CXr^&XmUB#Iz1FmL!i*+gGA`akD&jd|YUaDo0Csqjn>#L!thS@#dbw zt=j4iYqy%h73n(*__s73j3%HGjlQ=UB1fH||7&X>r3EUv#d+pROpA}q-EJ3Wc<=m$ zm%`RPQP=L@S)WyOZPQ^hub^vgUEUc5b$28D{k*!KFD<>2?D*F!>uK`ycCE`IhsEYD zS2fkUW^m|+$-L!X&iWnIo}YFjLeO6$?8$Y{#|^i>`bt*wPTa#IKkdfd*egW^y5O6T@x!eEV{>0{HE(rUHuW)`Dag7d=%3=CHhcCY`wbhwAtPV z+pOknp4RD?`zVO#@H#nB-hDUpKZGh8UEqk{HJ^`1B$ji^{Vz9;{%hXF3ZA=z+`YkRKp}uE*+jRSDm*zb6O1bmfch;22 z|6ZMYvMj7+rQ17$?oiK@m&~(z+pkahE_;air_{5DGHkI4-XEj6zIE~P;4A(6fi);2lL#~JGeCeD3k;Stf+(yf zf}k6Lej*6O0N`TwMpHB+;73`Y8-ac*2f~OiP$OWcVZhHNK{o>Z2n~c0U5v;(x8vh+ zx&nQ>H^K--;Itve=5KTtpzl>hXkQFmynxUS-?@rz0Qz1UgaIzVNf(3x(495t+R--= zAhdS@Pj^9Rhi@rBHvoO*7{Y*Sz~&Xg0LVHrblvDHH4wU&s37ZxuG>J@jy^++(EeHj zSvzdL7F|F36cs|hmJYIh*n}0je)O3LxPHcFJtX}&=Oxh1LvNfS%sXI%&pdEb72PoO zW+lR~U|W2Kp*J$o%|&lDBFsI5*Ie{AB)Ylibv44=bq@I43#qvSyjg*}$w2FU1R0h9 K+p|nAARYiPGvhD- literal 0 HcmV?d00001 diff --git a/nixos/nginx.nix b/nixos/nginx.nix new file mode 100644 index 0000000..e5ec4a0 --- /dev/null +++ b/nixos/nginx.nix @@ -0,0 +1,144 @@ +{ + lib, + pkgs, + config, + ... +}: { + services.nginx = { + enable = true; + + virtualHosts = { + "_default" = { + listen = [ + { addr = "0.0.0.0"; port = 80; } + { addr = "[::]"; port = 80; } + ]; + serverName = "_"; + extraConfig = '' + deny all; + return 444; + ''; + }; + + "philippeterson.com" = { + enableACME = true; # Enable Let's Encrypt certificate for HTTPS + forceSSL = false; # Redirect HTTP to HTTPS? + addSSL = true; + + root = "/etc/pullomatic/com_philippeterson"; + + locations."~ /.git(/.*)$ " = { + extraConfig = '' + deny all; + return 404; + ''; + }; + + locations."~ ^/games/atcsim(/[^/\\s]*)*$" = { + extraConfig = '' + index index.html index.htm; + rewrite ^/games/atcsim/?$ "/index.html" break; + rewrite ^/games/atcsim(?(/[^/\\s]*)*)$ "$query" break; + root /etc/pullomatic/atcsim; + ''; + }; + + locations."~ ^/echo(?((/[^/\\s]*)*))$" = { + extraConfig = '' + add_header Content-Type text/plain; + return 200 "$query"; + ''; + }; + + locations."/" = { + extraConfig = '' + try_files $uri $uri.php $uri/ =404; + index index.php index.html index.htm; + rewrite ^/contact$ /contact.php last; + rewrite ^/resume$ /resume.php last; + ''; + }; + + locations."~ \.php$" = { + extraConfig = '' + include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:${config.services.phpfpm.pools.main.socket}; + ''; + }; + }; + "blog.quinefoundation.com" = { + enableACME = true; + forceSSL = false; + addSSL = true; + + root = "/etc/pullomatic/com_quinefoundation_blog/markdown-blog"; + + locations."~ /.git(/.*)$ " = { + extraConfig = '' + deny all; + return 404; + ''; + }; + + locations."~ ^/static(/.*)?$" = { + extraConfig = '' + autoindex on; + root /etc/pullomatic/com_quinefoundation_blog/static; + rewrite ^/static(?(/[^/\\s]*)*)$ "$query" break; + ''; + }; + + locations."/" = { + extraConfig = '' + rewrite ^/?$ /blog-posts-list.php last; + rewrite ^/post/?$ /blog-posts-list.php last; + rewrite ^/about/?$ /about.php last; + rewrite ^/credits/?$ /credits.php last; + rewrite ^/post/([-a-zA-Z0-9]*)$ /blog-page.php?page=$1.md last; + rewrite ^/rss.xml$ /rss.php last; + try_files $uri $uri/ =404; + index index.php index.html index.htm; + ''; + }; + + locations."~ \.php$" = { + extraConfig = '' + include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:${config.services.phpfpm.pools.main.socket}; + ''; + }; + }; + }; + + # Optionally configure additional options + recommendedGzipSettings = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + }; + + services.phpfpm.pools = { + main = { + phpEnv."PATH" = lib.makeBinPath [pkgs.php]; + user = "nginx"; + group = "nginx"; + settings = { + # listen = /run/phpfpm.sock + # "listen.mode = 0660 + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "pm" = "dynamic"; + "pm.max_children" = 75; + "pm.start_servers" = 10; + "pm.min_spare_servers" = 5; + "pm.max_spare_servers" = 20; + "pm.max_requests" = 500; + + "php_admin_value[error_log]" = "stderr"; + "php_admin_flag[log_errors]" = true; + "catch_workers_output" = true; + }; + }; + }; +} diff --git a/nixos/pullomatic/default.nix b/nixos/pullomatic/default.nix new file mode 100644 index 0000000..9d60225 --- /dev/null +++ b/nixos/pullomatic/default.nix @@ -0,0 +1,41 @@ +{ + lib, + pkgs, + rustPlatform, + specialArgs, +}: +rustPlatform.buildRustPackage rec { + pname = "pullomatic"; + version = "1.0.0"; + + src = pkgs.fetchFromGitHub { + owner = "philip-peterson"; + repo = pname; + rev = "master"; + hash = "sha256-VVIhbbdHBBeodODWQq40q91uqtTrUHsCyPgTZ5VtrRc="; + }; + + cargoBuildFlags = ["--bin" "pullomatic"]; + + cargoHash = "sha256-oo0M4AlraRw2LRYzvhlbjgvSolZcuRz+2WruesEWltk="; + + nativeBuildInputs = with pkgs; [ + pkg-config + ]; + + buildInputs = with pkgs; [ + openssl + ]; + + meta = { + description = "A tool for automating GitHub pulls"; + homepage = "https://github.com/philip-peterson/pullomatic"; + license = lib.licenses.unlicense; + maintainers = [ + { + name = "Philip Peterson"; + email = "peterson@sent.com"; + } + ]; + }; +} diff --git a/nixos/refresh.sh b/nixos/refresh.sh new file mode 100755 index 0000000..4a29207 --- /dev/null +++ b/nixos/refresh.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -e + +./apply.sh diff --git a/nixos/secrets/README.md b/nixos/secrets/README.md new file mode 100644 index 0000000..9e6dbc6 --- /dev/null +++ b/nixos/secrets/README.md @@ -0,0 +1,5 @@ +To decrypt these files, you would need the Quine Foundation server's private key, +which is of course not public information. However, you could also generate your own +secrets using `age` which is an open source project used to power this server. +These would use your own private key, and therefore the encrypted versions would of +course differ from what's public in this repository. \ No newline at end of file diff --git a/nixos/secrets/default.nix b/nixos/secrets/default.nix new file mode 100644 index 0000000..819eae3 --- /dev/null +++ b/nixos/secrets/default.nix @@ -0,0 +1,8 @@ +{}: let + mainframePublicKey = builtins.toString "../keys/mainframe.pub"; +in { + # This .age file should contain the following environment variables: + # NEARLYFREESPEECH_API_KEY + # NEARLYFREESPEECH_LOGIN + "./nearlyfreespeech.age".publicKeys = [mainframePublicKey]; +} diff --git a/nixos/secrets/nearlyfreespeech.age b/nixos/secrets/nearlyfreespeech.age new file mode 100644 index 0000000..d0c4ab0 --- /dev/null +++ b/nixos/secrets/nearlyfreespeech.age @@ -0,0 +1,9 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE5GRC92ZyBteHlN +bTNkUUxaY2NwRFdSR1E4VWhkbW8yV2VrT2dJbGRFMjJoUkJHNGc0CkI0Z25jMDJK +ck1TOWM0eHFZSzJETU1sekxFVGFDOWdDWGlicVlwdGY4T2cKLS0tIEZBSnJyQVN5 +Nk1WZjM2aVdDdkNtamdBOExUSWNobEJzdFRnQ1JsbjZyNUEKpQAGd4xnEZd2JHFN +grhQ/kLePUz7W0i8epk+bu2aJiSs7sSznRI0gTf6zTwpUk1p0zOtJaK7uopPC+go +I9FPCx+rXzbmwrMcVUuzZLa8M1gikABswKSxKB/kHqH7KzrVGscQ4xz1gN+hdOS8 +5xoP +-----END AGE ENCRYPTED FILE----- diff --git a/nixos/system/home/ironmagma.nix b/nixos/system/home/ironmagma.nix new file mode 100644 index 0000000..c919235 --- /dev/null +++ b/nixos/system/home/ironmagma.nix @@ -0,0 +1,15 @@ +{ + config, + pkgs, + username, + nix-index-database, + lib, + ... +}: let + shared = import ./shared.nix { + inherit config pkgs username nix-index-database lib; + homeDirectory = "/home/ironmagma"; + }; +in { + imports = [shared]; +} diff --git a/nixos/system/home/root.nix b/nixos/system/home/root.nix new file mode 100644 index 0000000..a6fea46 --- /dev/null +++ b/nixos/system/home/root.nix @@ -0,0 +1,17 @@ +{ + config, + pkgs, + username, + nix-index-database, + lib, + ... +}: let + shared = import ./shared.nix { + inherit config pkgs username nix-index-database lib; + homeDirectory = "/root"; + }; +in { + imports = [shared]; + + home.sessionVariables.EDITOR = "vim"; +} diff --git a/nixos/system/home/shared.nix b/nixos/system/home/shared.nix new file mode 100644 index 0000000..e79560a --- /dev/null +++ b/nixos/system/home/shared.nix @@ -0,0 +1,252 @@ +{ + config, + pkgs, + username, + nix-index-database, + lib, + homeDirectory, + ... +}: let + unstable-packages = with pkgs.unstable; [ + coreutils + curl + findutils + git + git-crypt + jq + killall + tmux + unzip + vim + wget + zip + ]; + + stable-packages = with pkgs; [ + rustup + go + nodejs + python3 + alejandra # nix formatter + ]; + + dir = builtins.toString ../../keys/known_hosts; + files = builtins.attrNames (builtins.readDir dir); + pubKeys = map (file: import (dir + "/" + file)) files; + joinedString = lib.concatStringsSep " " pubKeys; +in { + imports = [ + nix-index-database.hmModules.nix-index + ]; + + home = { + stateVersion = "22.11"; + username = lib.mkDefault "${username}"; + homeDirectory = homeDirectory; + + sessionVariables.EDITOR = "vim"; + sessionVariables.SHELL = "/etc/profiles/per-user/${username}/bin/zsh"; + + packages = lib.mkDefault ( + stable-packages + ++ unstable-packages + ); + + file.".ssh/known_hosts".text = joinedString; + }; + + programs = { + home-manager.enable = true; + nix-index.enable = true; + nix-index.enableZshIntegration = true; + nix-index-database.comma.enable = true; + + # FIXME: disable this if you don't want to use the starship prompt + starship.enable = true; + starship.settings = { + aws.disabled = true; + gcloud.disabled = true; + kubernetes.disabled = false; + git_branch.style = "242"; + directory.style = "blue"; + directory.truncate_to_repo = false; + directory.truncation_length = 8; + python.disabled = true; + ruby.disabled = true; + hostname.ssh_only = false; + hostname.style = "bold green"; + }; + + # FIXME: disable whatever you don't want + fzf.enable = true; + fzf.enableZshIntegration = true; + lsd.enable = true; + lsd.enableAliases = true; + zoxide.enable = true; + zoxide.enableZshIntegration = true; + broot.enable = true; + broot.enableZshIntegration = true; + + direnv.enable = true; + direnv.enableZshIntegration = true; + direnv.nix-direnv.enable = true; + + git = { + enable = true; + package = pkgs.unstable.git; + delta.enable = true; + delta.options = { + line-numbers = true; + side-by-side = true; + navigate = true; + }; + userEmail = "1326208+philip-peterson@users.noreply.github.com"; + userName = "philip-peterson"; + extraConfig = { + push = { + default = "current"; + autoSetupRemote = true; + }; + merge = { + conflictstyle = "diff3"; + }; + diff = { + colorMoved = "default"; + }; + safe = { + directory = "/var/petersweb-infra"; + }; + }; + }; + + zsh = { + enable = true; + autocd = true; + enableAutosuggestions = true; + enableCompletion = true; + defaultKeymap = "emacs"; + history.size = 10000; + history.save = 10000; + history.expireDuplicatesFirst = true; + history.ignoreDups = true; + history.ignoreSpace = true; + historySubstringSearch.enable = true; + + plugins = [ + { + name = "fast-syntax-highlighting"; + src = "${pkgs.zsh-fast-syntax-highlighting}/share/zsh/site-functions"; + } + { + name = "zsh-nix-shell"; + file = "nix-shell.plugin.zsh"; + src = pkgs.fetchFromGitHub { + owner = "chisui"; + repo = "zsh-nix-shell"; + rev = "v0.5.0"; + sha256 = "0za4aiwwrlawnia4f29msk822rj9bgcygw6a8a6iikiwzjjz0g91"; + }; + } + ]; + + shellAliases = { + "u" = "cd .."; + "uu" = "cd ../.."; + "uuu" = "cd ../../.."; + "uuuu" = "cd ../../../.."; + gs = "git status"; + gc = "nix-collect-garbage --delete-old"; + refresh = "source ~/.zshrc"; + show_path = "echo $PATH | tr ':' '\n'"; + + gst = "git status"; + gco = "git checkout"; + }; + + envExtra = '' + export PATH=$PATH:$HOME/.local/bin + ''; + + initExtra = '' + bindkey '^p' history-search-backward + bindkey '^n' history-search-forward + bindkey '^e' end-of-line + bindkey '^w' forward-word + bindkey "^[[3~" delete-char + bindkey ";5C" forward-word + bindkey ";5D" backward-word + + zstyle ':completion:*:*:*:*:*' menu select + + # Complete . and .. special directories + zstyle ':completion:*' special-dirs true + + zstyle ':completion:*' list-colors "" + zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#) ([0-9a-z-]#)*=01;34=0=01' + + # disable named-directories autocompletion + zstyle ':completion:*:cd:*' tag-order local-directories directory-stack path-directories + + # Use caching so that commands like apt and dpkg complete are useable + zstyle ':completion:*' use-cache on + zstyle ':completion:*' cache-path "$XDG_CACHE_HOME/zsh/.zcompcache" + + # Don't complete uninteresting users + zstyle ':completion:*:*:*:users' ignored-patterns \ + adm amanda apache at avahi avahi-autoipd beaglidx bin cacti canna \ + clamav daemon dbus distcache dnsmasq dovecot fax ftp games gdm \ + gkrellmd gopher hacluster haldaemon halt hsqldb ident junkbust kdm \ + ldap lp mail mailman mailnull man messagebus mldonkey mysql nagios \ + named netdump news nfsnobody nobody nscd ntp nut nx obsrun openvpn \ + operator pcap polkitd postfix postgres privoxy pulse pvm quagga radvd \ + rpc rpcuser rpm rtkit scard shutdown squid sshd statd svn sync tftp \ + usbmux uucp vcsa wwwrun xfs '_*' + # ... unless we really want to. + zstyle '*' single-ignored complete + + # https://thevaluable.dev/zsh-completion-guide-examples/ + zstyle ':completion:*' completer _extensions _complete _approximate + zstyle ':completion:*:descriptions' format '%F{green}-- %d --%f' + zstyle ':completion:*' group-name "" + zstyle ':completion:*:*:-command-:*:*' group-order alias builtins functions commands + zstyle ':completion:*' squeeze-slashes true + zstyle ':completion:*' matcher-list "" 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*' + + # mkcd is equivalent to takedir + function mkcd takedir() { + mkdir -p $@ && cd ''${@:$#} + } + + function takeurl() { + local data thedir + data="$(mktemp)" + curl -L "$1" > "$data" + tar xf "$data" + thedir="$(tar tf "$data" | head -n 1)" + rm "$data" + cd "$thedir" + } + + function takegit() { + git clone "$1" + cd "$(basename ''${1%%.git})" + } + + function take() { + if [[ $1 =~ ^(https?|ftp).*\.(tar\.(gz|bz2|xz)|tgz)$ ]]; then + takeurl "$1" + elif [[ $1 =~ ^([A-Za-z0-9]\+@|https?|git|ssh|ftps?|rsync).*\.git/?$ ]]; then + takegit "$1" + else + takedir "$@" + fi + } + + WORDCHARS='*?[]~=&;!#$%^(){}<>' + + # fixes duplication of commands when using tab-completion + export LANG=C.UTF-8 + ''; + }; + }; +} diff --git a/nixos/system/users.nix b/nixos/system/users.nix new file mode 100644 index 0000000..462ea73 --- /dev/null +++ b/nixos/system/users.nix @@ -0,0 +1,74 @@ +{ + pkgs, + config, + nix-index-database, + lib, + ... +}: let + makeUser = { + username, + home, + extraGroups, + authorizedKeys, + homeConfig ? null, + isNormalUser ? true, + }: { + extraGroups = extraGroups ++ [username]; + + home-manager.users.${username} = homeConfig; + + users.users.${username} = { + isNormalUser = isNormalUser; + shell = pkgs.zsh; + openssh.authorizedKeys.keys = authorizedKeys; + home = home; + }; + + users.groups.${username} = { + name = "${username}"; + members = ["${username}"]; + }; + }; + + dir = builtins.toString ../keys/authorized_keys; + files = builtins.attrNames (builtins.readDir dir); + authorizedKeys = map (file: builtins.readFile "${dir}/${file}") files; + + rootUser = makeUser { + isNormalUser = false; + username = "root"; + home = "/root"; + extraGroups = []; + authorizedKeys = authorizedKeys; + homeConfig = import ./home/root.nix { + username = "root"; + inherit config pkgs nix-index-database lib; + }; + }; + + ironmagmaUser = makeUser { + username = "ironmagma"; + home = "/home/ironmagma"; + extraGroups = [ + "wheel" + "docker" + ]; + authorizedKeys = [ + (builtins.readFile ../keys/authorized_keys/macbookpro.pub) + (builtins.readFile ../keys/authorized_keys/macbookpro-intel.pub) + (builtins.readFile ../keys/authorized_keys/monolith.pub) + ]; + homeConfig = import ./home/ironmagma.nix { + username = "ironmagma"; + inherit config pkgs nix-index-database lib; + }; + }; +in { + users.groups.repo-data = { + name = "repo-data"; + members = ["nginx"]; + }; + + users.users = rootUser.users.users // ironmagmaUser.users.users // {}; + home-manager.users = rootUser.home-manager.users // ironmagmaUser.home-manager.users; +} diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl new file mode 100644 index 0000000..91519f4 --- /dev/null +++ b/terraform/.terraform.lock.hcl @@ -0,0 +1,46 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.2" + constraints = "3.2.2" + hashes = [ + "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", + "h1:vWAsYRd7MjYr3adj8BVKRohVfHpWQdvkIwUQ2Jf5FVM=", + "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", + "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", + "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", + "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", + "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", + "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", + "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", + "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", + "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", + "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", + ] +} + +provider "registry.terraform.io/hetznercloud/hcloud" { + version = "1.47.0" + constraints = "~> 1.45" + hashes = [ + "h1:B7iDacnh16TWyenN4+eledjmuZ89vYkdg5yFjlRNT7M=", + "h1:KQbtq1sXF4deoc0DKgjyyJMdIuHfhfhAPkVV0DlTMRI=", + "zh:0759f0c23d0e59baab3382320eef4eb314e0c5967b6ef67ff07135da07a97b34", + "zh:0e9ca84c4059d6d7e2c9f13d3c2b1cd91f7d9a47bedcb4b80c7c77d536eff887", + "zh:17a033ac4650a39ddacf3265a449edabaea528f81542c4e63e254272d5aac340", + "zh:2997c76a500e42b7519b24fa1f8646d9baab70c68277f80394560d3e1fd06e6d", + "zh:37f3fe7bb34cac63c69123e43e5426bab75816b3665dbe7125276a8d2ee6b2d8", + "zh:45d4b04dc470f24ad96c1c0b6636ea5422c659004f3e472c863bc50130fabf25", + "zh:46df99d972a78af6875565e53a73df66d870c474a20cd90e9e0a3092aa25197f", + "zh:4b5bb8d49366ad895c6c767efe16a1b8143802414abfe3fdb1184cbbecf424eb", + "zh:55c6199eb401c4b0a6c948ceac8b50f352e252e1c985903ed173bf26ad0f109e", + "zh:7b6efe897bffa37248064155a699e67953350b5b9a5476456c0160ce59254557", + "zh:7bc004bcb649ce1ec70e2cf848392e10a1edbcbf11b3292a4cc5c5d49bd769e4", + "zh:e1b17b7595f158fbb3021afa8869b541b5c10bdd2d8d2b2b3eaa82200b104ddd", + "zh:f741ca40e8e99a3e4114ad108ea2b5a5bccbedb008326c7f647f250580e69c0e", + "zh:fae9c7f8d08a447bb0972529f6db06999c35391046320206041a988aeca6b54c", + ] +} diff --git a/terraform/foo.tf b/terraform/foo.tf new file mode 100644 index 0000000..7f43304 --- /dev/null +++ b/terraform/foo.tf @@ -0,0 +1,45 @@ +locals { + public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDOqjSTQAQ2H4RD7oHWXjc6M4TcLniAsieo1hk7jl/VHxl6fVKxab5rtWpbDBN9SqNmoTHlWRSd+kCIVdg8a0Psy0NISTfSUniWh9qIJrjXTpWfJ9PkXIlVrleEz9Szn0GY5NyYUcNiZSencMszrOkJC8DcKIW8qp+17VeYpnS/hbwjIjdhgaFA8DjrHRgXuf88XBbi+XDB+Rw0vLLL1qsdT0NPe3uE1ixYCIUlVu3imMq431xJ/x3MLJoLJm3KSjO8NKWbw4PetxOd4LDhJbHkDpdA0P+D2ZewPIGYA45Z+pxZqvfrKIBnB4RIW5tCMGMeZHWS74vhXODPzf67TkScCGt/FU92yZHRpBNYwZ+dS+8YWMmo3t2/YWpPxLFXkAx6t78TdVGhhFrjWdxPB9hTdfdX1Sh51mbp9WVLYgqT+M/YROesrSwm7TKMgMLemA77ISf0LqWrGBo6fHRGmIfwe/fI9hSAObdHkARwPHD2GhZl+SxW7D9CV8jhV6KKbc0= ironmagma@Philips-MacBook-Pro.local" +} + +terraform { + required_providers { + hcloud = { + source = "hetznercloud/hcloud" + version = "~> 1.45" + } + + null = { + source = "hashicorp/null" + version = "3.2.2" + } + } +} + +resource "hcloud_ssh_key" "default" { + name = "Philip Macbook Pro M2" + public_key = local.public_key +} + +# Set the variable value in *.tfvars file +# or using the -var="hcloud_token=..." CLI option +# variable "hcloud_token" { +# sensitive = true +# } + +# Configure the Hetzner Cloud Provider +provider "hcloud" { + token = "hmUptEnfNpDdYVAeLOvmv14fZn9YV9wYuDhU4t0Mso26K2JLNbuJ2CvtCI3mLJyp" +} + +# Create a server +resource "hcloud_server" "web" { + name = "syncthing" + image = "fedora-40" + server_type = "cx32" + + ssh_keys = [ + "Philip Macbook Pro M2" + ] +} + diff --git a/terraform/terraform.tfstate b/terraform/terraform.tfstate new file mode 100644 index 0000000..0cd3f83 --- /dev/null +++ b/terraform/terraform.tfstate @@ -0,0 +1,75 @@ +{ + "version": 4, + "terraform_version": "1.5.7", + "serial": 28, + "lineage": "0a446551-97f6-5e1f-fd21-d1a5bd66b38f", + "outputs": {}, + "resources": [ + { + "mode": "managed", + "type": "hcloud_server", + "name": "web", + "provider": "provider[\"registry.terraform.io/hetznercloud/hcloud\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "allow_deprecated_images": false, + "backup_window": "", + "backups": false, + "datacenter": "hel1-dc2", + "delete_protection": false, + "firewall_ids": [], + "id": "51104554", + "ignore_remote_firewall_ids": false, + "image": "fedora-40", + "ipv4_address": "135.181.83.225", + "ipv6_address": "2a01:4f9:c010:8efd::1", + "ipv6_network": "2a01:4f9:c010:8efd::/64", + "iso": null, + "keep_disk": false, + "labels": {}, + "location": "hel1", + "name": "syncthing", + "network": [], + "placement_group_id": 0, + "primary_disk_size": 80, + "public_net": [], + "rebuild_protection": false, + "rescue": null, + "server_type": "cx32", + "shutdown_before_deletion": false, + "ssh_keys": [ + "Philip Macbook Pro M2" + ], + "status": "running", + "timeouts": null, + "user_data": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo1NDAwMDAwMDAwMDAwfX0=" + } + ] + }, + { + "mode": "managed", + "type": "hcloud_ssh_key", + "name": "default", + "provider": "provider[\"registry.terraform.io/hetznercloud/hcloud\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fingerprint": "eb:d4:34:7f:69:a7:82:3c:4c:f6:54:d3:4a:f3:73:cd", + "id": "22314214", + "labels": {}, + "name": "Philip Macbook Pro M2", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDOqjSTQAQ2H4RD7oHWXjc6M4TcLniAsieo1hk7jl/VHxl6fVKxab5rtWpbDBN9SqNmoTHlWRSd+kCIVdg8a0Psy0NISTfSUniWh9qIJrjXTpWfJ9PkXIlVrleEz9Szn0GY5NyYUcNiZSencMszrOkJC8DcKIW8qp+17VeYpnS/hbwjIjdhgaFA8DjrHRgXuf88XBbi+XDB+Rw0vLLL1qsdT0NPe3uE1ixYCIUlVu3imMq431xJ/x3MLJoLJm3KSjO8NKWbw4PetxOd4LDhJbHkDpdA0P+D2ZewPIGYA45Z+pxZqvfrKIBnB4RIW5tCMGMeZHWS74vhXODPzf67TkScCGt/FU92yZHRpBNYwZ+dS+8YWMmo3t2/YWpPxLFXkAx6t78TdVGhhFrjWdxPB9hTdfdX1Sh51mbp9WVLYgqT+M/YROesrSwm7TKMgMLemA77ISf0LqWrGBo6fHRGmIfwe/fI9hSAObdHkARwPHD2GhZl+SxW7D9CV8jhV6KKbc0= ironmagma@Philips-MacBook-Pro.local" + }, + "sensitive_attributes": [] + } + ] + } + ], + "check_results": null +} diff --git a/terraform/terraform.tfstate.backup b/terraform/terraform.tfstate.backup new file mode 100644 index 0000000..b415c17 --- /dev/null +++ b/terraform/terraform.tfstate.backup @@ -0,0 +1,56 @@ +{ + "version": 4, + "terraform_version": "1.5.7", + "serial": 26, + "lineage": "0a446551-97f6-5e1f-fd21-d1a5bd66b38f", + "outputs": {}, + "resources": [ + { + "mode": "managed", + "type": "hcloud_server", + "name": "web", + "provider": "provider[\"registry.terraform.io/hetznercloud/hcloud\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "allow_deprecated_images": false, + "backup_window": "", + "backups": false, + "datacenter": "hel1-dc2", + "delete_protection": false, + "firewall_ids": [], + "id": "51104554", + "ignore_remote_firewall_ids": false, + "image": "fedora-40", + "ipv4_address": "135.181.83.225", + "ipv6_address": "2a01:4f9:c010:8efd::1", + "ipv6_network": "2a01:4f9:c010:8efd::/64", + "iso": null, + "keep_disk": false, + "labels": {}, + "location": "hel1", + "name": "syncthing", + "network": [], + "placement_group_id": 0, + "primary_disk_size": 80, + "public_net": [], + "rebuild_protection": false, + "rescue": null, + "server_type": "cx32", + "shutdown_before_deletion": false, + "ssh_keys": [ + "Philip Macbook Pro M2" + ], + "status": "running", + "timeouts": null, + "user_data": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo1NDAwMDAwMDAwMDAwfX0=" + } + ] + } + ], + "check_results": null +}