From 70c2ada986bd9d5514d335ff0437349d85211f79 Mon Sep 17 00:00:00 2001 From: Lars Nolden Date: Mon, 29 Jun 2026 17:22:43 +0200 Subject: [PATCH] add secrets and age pubkeys to sops --- .sops.yaml | 8 ++-- nix/secrets/secrets.yaml | 76 ++++++++++++++++++++++++++++++++ nix/secrets/secrets.yaml.example | 3 ++ 3 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 nix/secrets/secrets.yaml diff --git a/.sops.yaml b/.sops.yaml index e8415d8..85df367 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -10,12 +10,12 @@ keys: # ---- developers (laptops, hardware keys) ---- - - &dev_lars age1TODO_lars_personal_age_pubkey_replace_me_before_first_real_secret + - &dev_lars age1cx8ul285kjkzmnhw6skdstnzrxnnme4xkflknzn7yhv52fgxqevqkd66cn # ---- hosts (derived from each host's ssh_host_ed25519_key.pub via ssh-to-age) ---- - - &host_db age1TODO_db_host_age_pubkey_replace_me - - &host_app age1TODO_app_host_age_pubkey_replace_me - - &host_ingest age1TODO_mqtt_ingest_host_age_pubkey_replace_me + - &host_db age1wpl3vz60tlt880p5fmfedr8c59dm4kf0czsacv0w5my706twuf5q9p0x43 + - &host_app age1g57pznep69nlyv3sltz6k0sml47v68m03gh68jkqwcq4jdx68vtsvnefq0 + - &host_ingest age190gu75rf3ra89mhk27xe3tv87tad087altqhugjlhkerqwe2jfqsnu738d creation_rules: # Supabase compose stack → app-host only. diff --git a/nix/secrets/secrets.yaml b/nix/secrets/secrets.yaml new file mode 100644 index 0000000..d1a5fa2 --- /dev/null +++ b/nix/secrets/secrets.yaml @@ -0,0 +1,76 @@ +# Template for nix/secrets/secrets.yaml — the sops-encrypted store. +# +# To bootstrap: +# 1. cp nix/secrets/secrets.yaml.example nix/secrets/secrets.yaml +# 2. Replace the placeholder values below with real ones. +# (See nix/secrets/README.md for how to generate JWT_SECRET / ANON_KEY / +# SERVICE_ROLE_KEY etc.) +# 3. sops -e -i nix/secrets/secrets.yaml +# (requires sops + age + the recipients in .sops.yaml to be real keys) +# +# Once encrypted, edit in place with: sops nix/secrets/secrets.yaml +# +# Local dev does NOT need this file at all — process-compose.nix bakes in +# dev defaults and the NixOS modules fall back to a writeText env file when +# nix/secrets/secrets.yaml is absent. This file is only consumed at activation +# time on real hosts. +# Supabase compose stack (consumed on app-host by gebos-supabase.service) +supabase_postgres_password: ENC[AES256_GCM,data:jXXxqvd15zPe5gDwnrFohsl8qrPny0IFV8UE2oyN9hGOWQ7KheltWm2r0IOL,iv:ZYBfmtduP2rSTezFwwv/NAavaF6/fvXBrdrF0MM0jY4=,tag:TiodVCwbCXDGafeaOsLURg==,type:str] +supabase_jwt_secret: ENC[AES256_GCM,data:j17p4R3JiLWlO4C8iYE2SXthzqB4kGbkypFMPTI30J2bI9c=,iv:AAamwue0Vs1Ns7OlujNtjU5IY43Z1NVJxJW5S9ftGbk=,tag:LWX3h0QMRBNNzUPWLxe3HQ==,type:str] +supabase_anon_key: ENC[AES256_GCM,data:zpeMG5L5GHlhGrHETnSY3cG+0rgC52HmSTDfdr0Il6cuEb0/KiUA9iyQOybT7Oo=,iv:NIMbKi14WlrTkLUt0ybBOFCklpBZ8TdFq+LkvqeElqA=,tag:rOQ1ETG13pt00kkCQQRJbQ==,type:str] +supabase_service_role_key: ENC[AES256_GCM,data:MDacdgnZhC3mx/YUoQT8j2LGHyCYGmW2TMBdcSp91WmoWh4/WuYy5BtpBfgDLC1S+6taTPmfjA==,iv:a7mSPzr/JYs6036NGlI75NqFm0Y1WMTJJGp8YX1PIOs=,tag:Q3ygfgexT6Ju9GHIf+jHjw==,type:str] +supabase_dashboard_password: ENC[AES256_GCM,data:i9Pl87BtOICcKwJxDp9QH1CtPaUbTb3IObrdPg/xcsqSMim9+RyO+g==,iv:qDQH1//2ZKNXAgAmFir2TG6auUEh6AFE00a/gP/1+Aw=,tag:llYW7o9XK5vmAIs45QQJpQ==,type:str] +# Ingester (consumed on mqtt-ingest by gebos-ingester.service) +ingester_postgres_password: ENC[AES256_GCM,data:Aq5gMK4RaYloOoYURXaGbb3jVVfSl8ZiXaabKkcrs+/iaHm1KBWtrw==,iv:07b7SF8khDBXVTVZGoqEuDsD+k9sOsvnunJAtKpfchg=,tag:DnFLwyB5Mt3NRo/Jklcntg==,type:str] +# Postgres bootstrap (consumed on db-host by a one-shot ALTER ROLE unit) +postgres_admin_password: ENC[AES256_GCM,data:Ien5PaD37D7c6EAq3dgh5+cpDANIA7j+V2SLiUJeIUXpqi1EjtvjTIm4,iv:PZa0Of3c2ozZ/ZE57sw6TMV7ze19A3eHKYcf6hc0kKo=,tag:YDVbdMr7gRmbp1ma2VWrmw==,type:str] +# HiveMQ file-RBAC broker users (consumed on mqtt-ingest by gebos-hivemq). +# PLAIN passwords (password-type defaults to PLAIN; the whole file is sops- +# encrypted). The ingester will authenticate as `ingester`; `admin` is for ops. +hivemq_ingester_password: ENC[AES256_GCM,data:0Kfqp5V03fyZU6ulSlCmIbV5x0Wrot8wRxtut8rxFzxsygprLkEV462R+g==,iv:6Lb7PhmJoa2JbS1g/VaPCq3HOXBpX3/8eaww/A6EJqY=,tag:Ny4pygCw3wfWObccWfOBxQ==,type:str] +hivemq_admin_password: ENC[AES256_GCM,data:I9g7/PcZb9TMf81SKNppMDf/8Je/9V+TSG932KGi+BXZjU7IsocM8HuY,iv:AlyAI44Ryl60W3HFxExC3i92WqMKA1myW+sLsBD50mo=,tag:JYO7YtDTouCZ5frTlDofBw==,type:str] +# Shared device login (Option A) — must match mqtt_user/mqtt_password on the +# senders. Per-device users (Option B) are a TODO in gebos-secrets.nix. +hivemq_device_password: ENC[AES256_GCM,data:27kqmePshQ==,iv:5m2e7Hc583jvsSjiKbl63cY9cTFs0aAY/L6jV5Vh9MU=,tag:nGhgrVpNU8Z2Z7cHTbBSSQ==,type:str] +sops: + age: + - enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRL1VHOWVreFdsQ0JWK3o0 + aFZYd0JITHU0RHg2a09DeVdFRXFiUC95OHlFCnZzaDVGeFdJa2l6S1Zxbng1K2tr + ZkEzQzdHeXRWWi9OUTdDYXJBeTZUTWcKLS0tIDBKdEZTSlZFeFRFSGtXclV0MkxR + RVFNbnQxbDdGSnpNendBbmJnditLMDAKNrn1/8gIngi0pM+DEf6ov/SGNQrXnFby + 1a2iAqBP+EDG0z52dcZns53Mj6XDgeh5Z2W5hDpITxDNhSVXEKmdHQ== + -----END AGE ENCRYPTED FILE----- + recipient: age1cx8ul285kjkzmnhw6skdstnzrxnnme4xkflknzn7yhv52fgxqevqkd66cn + - enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1Z3JpRnZIUG90b0xkdnU0 + aHpBQm5BMjF1YVNhOHVQcXJEWnhxbU5FQUM0Cml3SUJvWjAydWFwcGVHQlo0SjhU + bzM4N3J0YjdBWURJbER5OENsR3VMYWsKLS0tIElQWTZqL1lscUZoOXArR014ZDVJ + Z0JidnBZSWt0QmdBb1l0MlUxSngyUjQK6EuSmh77Gcc9aow16fgeZV+/GlJw1Zaz + aH3GqG7lw6hvn0HWSqJj8shTROqj+sWi1fUCIgMo1kcTBhKQC+ErEQ== + -----END AGE ENCRYPTED FILE----- + recipient: age1wpl3vz60tlt880p5fmfedr8c59dm4kf0czsacv0w5my706twuf5q9p0x43 + - enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjZEw0UC82azY2c3NBVk42 + M1RORGszMDVWbG5UVkRZOFVEL05hcVpzSlVvCklhOThsMDRGelBtTlFSZ3hWT01G + ZkErVTdhT2t2dFpzOHI2Z1p3a2c0NTgKLS0tIFNpNE53VEVPczVSRTJNWlEyMU5X + RFp0VzZaeG5hcTNmZ21GTENBM09zZTQK1QswQul0EbX1UnuF1iL4WXXZN3nOSBjp + inIv5inJhjcZ+Vo82NDeQcWnk+5Ns43sKqQjHf0XpfgyzRyjV6SHmw== + -----END AGE ENCRYPTED FILE----- + recipient: age1g57pznep69nlyv3sltz6k0sml47v68m03gh68jkqwcq4jdx68vtsvnefq0 + - enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTRE4wSUxMMjA2cUNEQXFL + ZE9ha2dsL0tKK2tTTTJpd25EUUFlQnJiQ1RBCjNTcUk2cGxvUWF5b2MrVi81bVZr + dDBoSFhRdDR0UnZsMWdRYnJhNGtMYjQKLS0tIFBiM3pweFgzRWNCSHozV01XbCs3 + elhHMFE0dnZHU2pFaEJ2ekJ0U2FhQTAKNZGdxEMPf7pG11zS233wFYfDKySMqL/m + 7syeofAs00911pOubBhRa1G6zvwblevDnZuAqhHBTiKfKtGrpCG4Jg== + -----END AGE ENCRYPTED FILE----- + recipient: age190gu75rf3ra89mhk27xe3tv87tad087altqhugjlhkerqwe2jfqsnu738d + encrypted_regex: ^(supabase_|ingester_|postgres_admin_|hivemq_) + lastmodified: "2026-06-29T15:20:36Z" + mac: ENC[AES256_GCM,data:ds4eFZC9fjU+0NjvpaRKWq8HSbslFSPVGLlPtVGlvLm1kpZ8OtC6D6H4VtZZdIKvie/SahcA/3oMGMC66UDADrem7OGKWX5UFRrtuwrctenxteu6Q16sNqlmYBUSkd1YNAH3K4m4TR1DyvMNVC6hTbpCP2hVv7k9fy0o5UZT7bQ=,iv:vRBvBsypuurce0yq3Nu4zvqpzL7+84O3SkbOPoHllt8=,tag:ANZ7TYppVgX36SU1WvLlow==,type:str] + version: 3.13.1 diff --git a/nix/secrets/secrets.yaml.example b/nix/secrets/secrets.yaml.example index 4df2543..ce53b68 100644 --- a/nix/secrets/secrets.yaml.example +++ b/nix/secrets/secrets.yaml.example @@ -33,3 +33,6 @@ postgres_admin_password: "replace-me-openssl-rand-hex-32" # encrypted). The ingester will authenticate as `ingester`; `admin` is for ops. hivemq_ingester_password: "replace-me-openssl-rand-hex-32" hivemq_admin_password: "replace-me-openssl-rand-hex-32" +# Shared device login (Option A) — must match mqtt_user/mqtt_password on the +# senders. Per-device users (Option B) are a TODO in gebos-secrets.nix. +hivemq_device_password: "replace-me-to-match-the-sender-mqtt_password"