From b7716061e4adb4a8dc7c4e3f16b249db8b699283 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Fri, 8 May 2026 10:56:08 +0300 Subject: [PATCH 1/2] add tide and sops-nix flake inputs --- flake.lock | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++- flake.nix | 17 ++++++++++++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/flake.lock b/flake.lock index 4719a70..7bd0259 100644 --- a/flake.lock +++ b/flake.lock @@ -39,7 +39,80 @@ "root": { "inputs": { "home-manager": "home-manager", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "sops-nix": "sops-nix", + "tide": "tide" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1777944972, + "narHash": "sha256-VfGRo1qTBKOe3s2gOv8LSoA6Fk19PvBlwQ1ECN0Evn8=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "c591bf665727040c6cc5cb409079acb22dcce33c", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "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" + } + }, + "tide": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "utils": "utils" + }, + "locked": { + "lastModified": 1778226636, + "narHash": "sha256-YaOeH7HHvThS+qB7AU35iJgE9PnYuooHIu0oEdh2md4=", + "path": "/home/yisroel/Projects/TIDE", + "type": "path" + }, + "original": { + "path": "/home/yisroel/Projects/TIDE", + "type": "path" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index f90fcd3..992c9f9 100644 --- a/flake.nix +++ b/flake.nix @@ -8,9 +8,19 @@ url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; + sops-nix = { + url = "github:Mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + tide = { + # Local path while iterating; switch to + # git+https://git.yisroelbaum.com/yisroelbaum/TIDE once pushed. + url = "path:/home/yisroel/Projects/TIDE"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; - outputs = { self, nixpkgs, home-manager, ... }: + outputs = { self, nixpkgs, home-manager, sops-nix, tide, ... }: let system = "x86_64-linux"; domainName = "yisroelbaum.com"; @@ -18,7 +28,10 @@ nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { modules = [ ./configuration.nix + ./tide.nix home-manager.nixosModules.home-manager + sops-nix.nixosModules.sops + tide.nixosModules.tide { home-manager.useGlobalPkgs = true; home-manager.useUserPackages = true; @@ -32,6 +45,8 @@ in pkgs.mkShell { buildInputs = with pkgs; [ nixos-rebuild + sops + age ]; }; }; From d195c6b37ca1e3d238f60e2df1255dbe08cc441b Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Fri, 8 May 2026 10:56:13 +0300 Subject: [PATCH 2/2] wire tide service into nixos config Imports the tide nixos module from the TIDE flake and configures it for tide.yisroelbaum.com (frontend) and apitide.yisroelbaum.com (backend), reusing the existing wildcard ACME cert. Secrets are pulled from sops-encrypted secrets/tide.yaml; replace the placeholder with real encrypted content before deploy. --- secrets/README.md | 23 +++++++++++++++++++++++ secrets/tide.yaml | 3 +++ secrets/tide.yaml.example | 20 ++++++++++++++++++++ tide.nix | 29 +++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 secrets/README.md create mode 100644 secrets/tide.yaml create mode 100644 secrets/tide.yaml.example create mode 100644 tide.nix diff --git a/secrets/README.md b/secrets/README.md new file mode 100644 index 0000000..d923746 --- /dev/null +++ b/secrets/README.md @@ -0,0 +1,23 @@ +# Secrets + +Encrypted with [sops](https://github.com/getsops/sops) using the +host's age key. + +## First-time setup on the server + +1. Generate an age key for the host: + ``` + sudo mkdir -p /var/lib/sops-nix + sudo age-keygen -o /var/lib/sops-nix/key.txt + sudo chmod 600 /var/lib/sops-nix/key.txt + ``` +2. Read the public key: + ``` + sudo grep "public key" /var/lib/sops-nix/key.txt + ``` +3. On a workstation, put that public key into `.sops.yaml` at + the repo root and encrypt `tide.yaml.example` into + `tide.yaml`. + +`tide.yaml` is encrypted and committed. `tide.yaml.example` is +the plaintext template. diff --git a/secrets/tide.yaml b/secrets/tide.yaml new file mode 100644 index 0000000..fea1aa9 --- /dev/null +++ b/secrets/tide.yaml @@ -0,0 +1,3 @@ +# PLACEHOLDER - replace with sops-encrypted content before deploy. +# See secrets/README.md and secrets/tide.yaml.example. +tide-env: "" diff --git a/secrets/tide.yaml.example b/secrets/tide.yaml.example new file mode 100644 index 0000000..40dfc8a --- /dev/null +++ b/secrets/tide.yaml.example @@ -0,0 +1,20 @@ +# Encrypt this with sops to produce ./tide.yaml: +# +# sops --encrypt --age $(cat ~/.config/sops/age/keys.txt | grep public | cut -d: -f2 | tr -d ' ') \ +# secrets/tide.yaml.example > secrets/tide.yaml +# +# Or set up .sops.yaml with the host's age public key and run +# `sops secrets/tide.yaml`. +# +# Generate APP_KEY with: +# php -r "echo 'base64:'.base64_encode(random_bytes(32)).PHP_EOL;" + +tide-env: | + APP_KEY=base64:REPLACE_ME + DB_PASSWORD=REPLACE_ME + MAIL_HOST=127.0.0.1 + MAIL_PORT=1025 + MAIL_USERNAME= + MAIL_PASSWORD= + MAIL_FROM_ADDRESS=noreply@tide.yisroelbaum.com + MAIL_FROM_NAME=TIDE diff --git a/tide.nix b/tide.nix new file mode 100644 index 0000000..fac2eba --- /dev/null +++ b/tide.nix @@ -0,0 +1,29 @@ +{ + domainName, + ... +}: +{ + services.tide = { + enable = true; + domain = "tide.${domainName}"; + apiDomain = "apitide.${domainName}"; + secretsFile = "/run/secrets/tide-env"; + # Reuse the wildcard cert already issued for *.${domainName} + # in configuration.nix instead of requesting a new one per + # subdomain. + nginx.useACMEHost = domainName; + }; + + # Don't fail evaluation when secrets/tide.yaml is missing (e.g. + # before the operator has encrypted it on a fresh checkout). + # sops-install-secrets will still error at activation time if + # the file is absent, which is the right place for that failure. + sops.validateSopsFiles = false; + + sops.secrets."tide-env" = { + sopsFile = ./secrets/tide.yaml; + # phpfpm reads this via EnvironmentFile, which runs as root + # before dropping to the tide user, so root readable is enough. + mode = "0400"; + }; +}