From e60ecf1f919cf849ecc83568cd3e724701b173ff Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Mon, 5 Aug 2024 19:31:01 +0200 Subject: [PATCH] hugo-chat works --- newinfra/nix/apps/hugo-chat/default.nix | 74 ++++++------------ newinfra/nix/hive.nix | 3 +- newinfra/nix/modules/ingress/Caddyfile | 5 -- newinfra/nix/modules/podman/default.nix | 8 ++ .../nix/secrets/docker_registry_password.age | 9 +-- newinfra/nix/secrets/hugochat_db_password.age | 8 +- newinfra/nix/secrets/minio_env_file.age | Bin 397 -> 397 bytes newinfra/nix/secrets/wg_private_vps1.age | Bin 257 -> 257 bytes newinfra/nix/secrets/wg_private_vps3.age | Bin 257 -> 257 bytes newinfra/nix/secrets/wg_private_vps4.age | Bin 256 -> 256 bytes newinfra/nix/secrets/wg_private_vps5.age | Bin 256 -> 256 bytes newinfra/nix/secrets/widetom_bot_token.age | Bin 272 -> 272 bytes newinfra/nix/secrets/widetom_config_toml.age | Bin 4006 -> 4006 bytes .../secrets-git-crypt/hugochat_db_password | Bin 85 -> 149 bytes 14 files changed, 43 insertions(+), 64 deletions(-) create mode 100644 newinfra/nix/modules/podman/default.nix diff --git a/newinfra/nix/apps/hugo-chat/default.nix b/newinfra/nix/apps/hugo-chat/default.nix index d76beb3..43107af 100644 --- a/newinfra/nix/apps/hugo-chat/default.nix +++ b/newinfra/nix/apps/hugo-chat/default.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ config, lib, pkgs, ... }: let dockerLogin = { registry = "docker.noratrieb.dev"; @@ -10,68 +10,46 @@ in age.secrets.hugochat_db_password.file = ../../secrets/hugochat_db_password.age; virtualisation.oci-containers.containers = { - /* - hugo_chat_client: - container_name: hugo-chat-client - image: "docker.noratrieb.dev/hugo-chat-client:63bd1922" - restart: always - ports: - - "5002:80" - */ hugo-chat-client = { - image = "docker.noratrieb.dev/hugo-chat-client:63bd1922"; + image = "docker.noratrieb.dev/hugo-chat-client:89ce0b07"; login = dockerLogin; ports = [ "127.0.0.1:5002:80" ]; }; - /* - hugo_chat_server: - container_name: hugo-chat-server - image: "docker.noratrieb.dev/hugo-chat-server:63bd1922" - ports: - - "5001:8080" - environment: - SPRING_DATASOURCE_URL: "jdbc:postgresql://hugo-chat-db:5432/hugochat" - SPRING_DATASOURCE_PASSWORD: "${HUGO_CHAT_DB_PASSWORD}" - networks: - - hugo-chat - */ - # disabled since the DB connection doesn't work yet. - #hugo-chat-server = { - # image = "docker.noratrieb.dev/hugo-chat-server:63bd1922"; - # ports = [ "5001:80" ]; - # environment = { - # SPRING_DATASOURCE_URL = "jdbc:postgresql://vps1.local:5003/hugochat"; - # }; - # environmentFiles = [ config.age.secrets.hugochat_db_password.path ]; - # login = dockerLogin; - #}; - /* - hugo_chat_db: - container_name: hugo-chat-db - image: "postgres:latest" - restart: always - volumes: - - "/apps/hugo-chat/data:/var/lib/postgresql/data" - environment: - POSTGRES_PASSWORD: "${HUGO_CHAT_DB_PASSWORD}" - PGDATA: "/var/lib/postgresql/data/pgdata" - networks: - - hugo-chat - */ + hugo-chat-server = { + image = "docker.noratrieb.dev/hugo-chat-server:89ce0b07"; + ports = [ "127.0.0.1:5001:8080" ]; + environment = { + SPRING_DATASOURCE_URL = "jdbc:postgresql://hugo-chat-db:5432/postgres"; + }; + environmentFiles = [ config.age.secrets.hugochat_db_password.path ]; + extraOptions = [ "--network=hugo-chat" ]; + + dependsOn = [ "hugo-chat-db" ]; + login = dockerLogin; + }; + hugo-chat-db = { image = "postgres:16"; - ports = [ "127.0.0.1:5003:80" ]; volumes = [ "/var/lib/hugo-chat/data:/var/lib/postgresql/data" ]; environment = { - POSTGRES_PASSWORD = "\${HUGO_CHAT_DB_PASSWORD}"; PGDATA = "/var/lib/postgresql/data/pgdata"; }; + extraOptions = [ "--network=hugo-chat" ]; environmentFiles = [ config.age.secrets.hugochat_db_password.path ]; }; }; - + # https://www.reddit.com/r/NixOS/comments/13e5w6b/does_anyone_have_a_working_nixos_ocicontainers/ + systemd.services.init-hugo-chat-podman-network = { + description = "Create the network bridge for hugo-chat."; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig.Type = "oneshot"; + script = '' + ${lib.getExe pkgs.podman} network create hugo-chat || true + ''; + }; system.activationScripts.makeHugoChatDir = lib.stringAfter [ "var" ] '' mkdir -p /var/lib/hugo-chat/data ''; diff --git a/newinfra/nix/hive.nix b/newinfra/nix/hive.nix index b6ce4b2..ac7c1ea 100644 --- a/newinfra/nix/hive.nix +++ b/newinfra/nix/hive.nix @@ -140,13 +140,12 @@ ./modules/contabo ./modules/wg-mesh ./modules/ingress + ./modules/podman ./apps/widetom ./apps/hugo-chat ./apps/uptime ]; - age.secrets.docker_registry_password.file = ./secrets/docker_registry_password.age; - deployment.tags = [ "ingress" "eu" "apps" "wg" ]; system.stateVersion = "23.11"; }; diff --git a/newinfra/nix/modules/ingress/Caddyfile b/newinfra/nix/modules/ingress/Caddyfile index 1a5c396..d259690 100644 --- a/newinfra/nix/modules/ingress/Caddyfile +++ b/newinfra/nix/modules/ingress/Caddyfile @@ -43,11 +43,6 @@ api.hugo-chat.noratrieb.dev { reverse_proxy * localhost:5001 } -# TODO: -# Set up a domain called gh-pages.noratrieb.dev that's a CNAME for noratrieb.github.io -# such that all one-off repos use that domain, making links redirectable in the future. -# i've posted a bunch of nilstrieb.github.io links that are now dead - ################################################################ # deadname redirects nilstrieb.dev { diff --git a/newinfra/nix/modules/podman/default.nix b/newinfra/nix/modules/podman/default.nix new file mode 100644 index 0000000..8d97937 --- /dev/null +++ b/newinfra/nix/modules/podman/default.nix @@ -0,0 +1,8 @@ +{ ... }: { + virtualisation.podman = { + enable = true; + }; + # https://github.com/NixOS/nixpkgs/issues/226365 + networking.firewall.interfaces."podman+".allowedUDPPorts = [ 53 5353 ]; + age.secrets.docker_registry_password.file = ../../secrets/docker_registry_password.age; +} diff --git a/newinfra/nix/secrets/docker_registry_password.age b/newinfra/nix/secrets/docker_registry_password.age index 98217bb..2e36b9f 100644 --- a/newinfra/nix/secrets/docker_registry_password.age +++ b/newinfra/nix/secrets/docker_registry_password.age @@ -1,6 +1,5 @@ age-encryption.org/v1 --> ssh-ed25519 qM6TYg 6TlkoQ0YMB4Cg0VqY8ec1RgRpfiRLh2YQpoc4D49uRg -BbqDPWQGmGrcDSdNNajm0GJJRlPiazgeF2/MRsyDZkw ---- OUif9tz9JRMMZEA1LTwPipE/Hezj5nVaN/qgiwoi3ws -"՝7l10I?Cjg3L -O8kI+h< \ No newline at end of file +-> ssh-ed25519 qM6TYg lW7MJ/iW+nvXMk984BZjeEojIbqDojP1y6w0sRkQpzM +5t7qrvWDhmIfs0F2Av1kkq0zB9LMiHG1uM9G73KjgY8 +--- BrrUNOV8vvacVsORvb5tnuoZENT8dvSv9ZQPKDY2cbA +YE@u6ZX_BSnj0i97hCySlH{ i \ No newline at end of file diff --git a/newinfra/nix/secrets/hugochat_db_password.age b/newinfra/nix/secrets/hugochat_db_password.age index 855e776..f819d6b 100644 --- a/newinfra/nix/secrets/hugochat_db_password.age +++ b/newinfra/nix/secrets/hugochat_db_password.age @@ -1,5 +1,5 @@ age-encryption.org/v1 --> ssh-ed25519 qM6TYg AP0dV7U8/42OGcDtBv5eq3jSLdmXP3fMfTnd9o86EVM -e5ftZHvKL6uqhInQgFSclzvnExxwYnFu0/ANTpa9bBI ---- Zyyydt+U1p6UR2BP+s3ynm2Q2MmzWWUSrhlBn5kZdCI -W{e8,?nr4KX{'2٭h 9<fP,U_NgTD4Z$Kz & \ No newline at end of file +-> ssh-ed25519 qM6TYg KvzMXsvYp7qnuTxYxqtYLxGqYDXomluSaUFb8zjngn4 +HNM0YiyvFfr7nEcoIP/w7KRgfL+7bgF0PPkxPqhNoJA +--- 1fPbYebzO+9VHQsSr/wIshnrqXCvO5AL0roNBbR64DE +^nj$w{x`0-68Yr >ͿT#$\ܖno%;pԄeƌNYn`޶i#gíL41*Hb¥UE6j%a)szFyJc02CkK2?M$v!8 \ No newline at end of file diff --git a/newinfra/nix/secrets/minio_env_file.age b/newinfra/nix/secrets/minio_env_file.age index 0eca6a282db3b7987f745c0aafc114abfeee789b..0998fdbf5adf1ead27fb1d18126890aca2fb8eca 100644 GIT binary patch delta 362 zcmeBW?q!~!Q(xxl@8j>~k?d%ilU8h+8I)9+Uf`FO=aiOX9$A=a;ulhxnGxk~=9HOk z!DXNwp`DW+R2=3Q9Oh#bWR??dX>5?^Y!u*Q;S*pP9&8wHVC|K%V$)#(jP+Xj$ zo0?)|YHDby5K-mm92KZgVOE}==$x5m6qQtx<&|OXQSTRAmX&L0R2ftiUQ*;{p5j~X zR1shjyvN6 zrK_u}kmFHY8Cq75W$s#OWbS2ATI?CNU60`DH)xc2T0*TU>lgL9uUXCM5t#l13Zb)@7qU4>s>OM*{p>^*(t z%MSL95i1pPK6Xy}ugUt%*yMRIzx=D3MGTUx|3VH`2wp1=Tlu7?;QzKd?^d;Q-q#Bb LI==a|yWEn~=lO9o&nWUfSon)eKR$-c2?pGCF z&J~dB6P8$6V&r9EkXn^jkse}X6p0FkbXc*)ZRT$uE6j)`Jq;KjIZ0-|g|E&@<(wUC=@^ug5mXRSR9+VB>{uCP7#ikWs%;pa;+j>=^=_S| zwN84XO!8vezAft-s+{}#zH-L1Y4Nprn%lo(VsNiNn#UdZNA2qGx1wR@bBcd|I#s#i z(q4w{4fhH{e8k_zzHGQu@Nv}vrOoe~`HmI$u(U`=D=cU5OkC6{=%jcqjqk^?5chMh K&T}UvD+2)kpoK;N diff --git a/newinfra/nix/secrets/wg_private_vps1.age b/newinfra/nix/secrets/wg_private_vps1.age index 44caeedeec1ba510578efdf48f70fad48b23141f..3e85a7a0612605f4a2fbb0ee58742acc0277c6ef 100644 GIT binary patch delta 221 zcmZoSAQ%m6GCQ9#xvW@(ZW6`B!VT4<8upORsiSCr*x5mZ@dkXv3-8CK|1;aOo88OkO5=EC#+vc$;@%5dS6KGxZBh~AYeJZi7Lv+8>}V(09+DNDgXcg delta 221 zcmZoY8t4o|KhQ z&gGn!98l)xk!G4|8s+O773JX(7+&t-xuDEyW@&C6 Y%bNf9kX5)ihn{t`Z~XJtjej=)0R4_q0RR91 diff --git a/newinfra/nix/secrets/wg_private_vps3.age b/newinfra/nix/secrets/wg_private_vps3.age index 01e7b936c000c97c8847ab5a991dfcdc2046cf9d..e6f2fc7e9c89e975831be1a8fa466618136c78d9 100644 GIT binary patch delta 221 zcmZo&xyP>D?)|mUAvAufV<2bGXQuaRMPXd7$IeZ*eQIhbwO74`GsEvWYu);7 X^H0n*ew+0$wT9Hl6_}f25ak(EROspK>XjLk7oKbB=^vDu@0^xe%%!WVtKeOiY8Y9bV&ZC4Y93w`mExJ{73po}lIdZZW#Lk3p6BMs zm0?nlT9oITqn%fo5n*ns@1L3LlM$}%7;NN~ZB%S#T zZ+_1e6W;X0^wMXZtIPexGJKW0T>XsB96ae&eJDFhxZUr`){MDTg-&Y^&3U^*{f6^* WVGA~s*VgX>;>@=`J1WGisto{CR8pA$ delta 219 zcmZo*YG9h6TVIxx72#W2oEGKgk>wQZ?HN^Iu5FZSVw9bl;bfF&X68|lmtt&T>S2`3 zm7i_ymzwVCnC+2lP*o9b;uesaW?5Y57w#J3SQhGPl4IuX73G@bQ*4mVrK_u}kZtao z?OPV^9hszWsU1)jn33skU}jkCWMN(!6&zkwRag)a6_T7|7MxfZ%60XKPQsLnEmO4p z*<$)1^eky%kaWy6IeYNwTjf(GS9erJ8ZS$jscjb!Q0B(>VA^5>zP-z3=d{?m=^L%) W%bzL5F1|ux_TnE6w+uC2?E(OxNKeH8 diff --git a/newinfra/nix/secrets/wg_private_vps5.age b/newinfra/nix/secrets/wg_private_vps5.age index 8c2310321b6a1de22b952998651dece64188d0ff..9fdef5abe7b84f35a64f381ecf622ea44d9f84d9 100644 GIT binary patch delta 220 zcmZo*YG9h6Qy-aQm|2l)UK*HDYMfVDl^>jI=vd~JVwO~_U7F=+9Fh_lnrNO^;$&1| zz~$pv;A7&F?igj6SXt_9VXSR#98qZ!S?XAxmTGL0Y>*uknVz3z=4Bjgz@@9Js}O1A zWMblxniy%KpX^>%ROW6L5MfqnY~pS1s9$X6?(LUj5n7d5}?o51Y|(`#k{Lj!;_w delta 220 zcmZo*YG9h6Q=gU;>R#bvQDPPrnH}RT-69oL}tdn4In5pJ)+fROxCGP?Q~DtnZiT>#y(creEfpQ{{sUR9u{xZRryh=^2t&P!JiC5^CU|?3qzo;K_BbQvTC^wR1JW zo*R=SzJGno%M&p(g6Cz?+oIDkp^l*+G>&>tk0_Qpr^#`)x@DL2Iw8}CmG4hYs^;%s Xe2`7)uk!xyYBCp1+P_t;)?@$xp~zEN diff --git a/newinfra/nix/secrets/widetom_bot_token.age b/newinfra/nix/secrets/widetom_bot_token.age index 774c72a6cba8d5a557491a7df159021d9ba221c0..811d2e44414deb21deaaee9659b33ee64365e8a2 100644 GIT binary patch delta 236 zcmbQhG=XV?PJMYrVo+&rMscEcU{G*Xd1-iwS6+crerSNFlb26qafGE)sFO#iTcod} z0atQfu$QrCx`$DDWpRbMNoqt^q>p!aZgzfYsF#6nv7>*vx0!!Iaj<(pF_*5cu0nZa zc~-V-T6U0ysin4lVS#07UaC`NiJ6B*n!Z_5ka=N}f2y~kYlO2=wkwzHT8k~J)qF`? z!}YuspWNcP)|~!*UBl!6<(Ur`F-aZF&0J|9Ruv=@S1t8=&FioEawoDUPm{EXv+-U50CbyLq5uE@ delta 236 zcmbQhG=XV?PJOs>a(QuZx}#&JnZ8A)SE`|7Nr0D=U$B`^d09b4sbiG3i%WoElD?5) zHkVtDuSJoYsY#@JXoX3cc2q%DzIR1>X+@TQPL`#ydil_xyS}FEhPF8(urvWx0KM$e<**^^x~YB?;fFTH0R$pO{&r diff --git a/newinfra/nix/secrets/widetom_config_toml.age b/newinfra/nix/secrets/widetom_config_toml.age index 1ef149df4620a606e3ae5d33ab677a2130e43556..adf61a3b263fe6329762e94629e51a7888ce1db6 100644 GIT binary patch delta 4000 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 E07d|;5&!@I delta 4000 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