From 4f86c92941e829be838db37082b7fee86c9e10a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Yule=20B=C3=A4dorf?= Date: Thu, 22 Feb 2024 19:20:24 +0100 Subject: [PATCH] obs-portal: init obs-portal on nachtigall This follows the official installation instructions at https://github.com/openbikesensor/portal/blob/main/docs/production-deployment.md Unfortunately, the postgres database needs to have postgis enabled, so we'll have to start a second instance. To stay close to the official deployment instructions, this is running in docker. The secrets were taken from the old installation instance. During initial installation, we'll need to import data from the old instance into this one, which might take a while. --- hosts/nachtigall/apps/obs-portal.nix | 140 +++++++++++++++++++++++++++ hosts/nachtigall/default.nix | 1 + secrets/obs-portal-database-env.age | 27 ++++++ secrets/obs-portal-env.age | Bin 0 -> 1593 bytes secrets/secrets.nix | 4 + 5 files changed, 172 insertions(+) create mode 100644 hosts/nachtigall/apps/obs-portal.nix create mode 100644 secrets/obs-portal-database-env.age create mode 100644 secrets/obs-portal-env.age diff --git a/hosts/nachtigall/apps/obs-portal.nix b/hosts/nachtigall/apps/obs-portal.nix new file mode 100644 index 00000000..0fd680dc --- /dev/null +++ b/hosts/nachtigall/apps/obs-portal.nix @@ -0,0 +1,140 @@ +{ config +, lib +, pkgs +, self +, flake +, ... +}: let + configPy = pkgs.writeText "obs-portal-config.py" '' +DEBUG = False +VERBOSE = DEBUG +AUTO_RESTART = DEBUG +LEAN_MODE = False +FRONTEND_URL = None +FRONTEND_HTTPS = True +FRONTEND_DIR = "../frontend/build/" +FRONTEND_CONFIG = { + "imprintUrl": "https://pub.solar/about", + "privacyPolicyUrl": "https://pub.solar/privacy", + "mapHome": {"zoom": 12, "latitude": 50.93, "longitude": 6.97}, + "banner": { + "text": "This is an installation serving the Cologne/Bonn region run for Team OBSKöln by pub.solar n.e.V.", + "style": "info" + }, +} +TILES_FILE = None +ADDITIONAL_CORS_ORIGINS = None + ''; + + env = { + OBS_KEYCLOAK_URI = "auth.pub.solar"; + OBS_PORTAL_URI = "obs-portal.pub.solar"; + + OBS_POSTGRES_MAX_OVERFLOW = "20"; + OBS_POSTGRES_POOL_SIZE = "40"; + + OBS_HOST = "0.0.0.0"; + OBS_PORT = "3000"; + OBS_KEYCLOAK_URL = "https://auth.pub.solar/realms/pub.solar/"; + OBS_KEYCLOAK_CLIENT_ID = "openbikesensor-portal"; + OBS_DEDICATED_WORKER = "True"; + OBS_DATA_DIR = "/data"; + OBS_PROXIES_COUNT = "1"; + }; +in { + age.secrets.obs-portal-env = { + file = "${flake.self}/secrets/obs-portal-env.age"; + mode = "600"; + }; + + age.secrets.obs-portal-database-env = { + file = "${flake.self}/secrets/obs-portal-database-env.age"; + mode = "600"; + }; + + systemd.services."docker-network-obs-portal" = + let + docker = config.virtualisation.oci-containers.backend; + dockerBin = "${pkgs.${docker}}/bin/${docker}"; + in + { + serviceConfig.Type = "oneshot"; + before = [ "docker-obs-portal.service" ]; + script = '' + ${dockerBin} network inspect obs-portal-net >/dev/null 2>&1 || ${dockerBin} network create obs-portal-net --subnet 172.20.0.0/24 + ''; + }; + + services.nginx.virtualHosts."obs-portal.pub.solar" = { + enableACME = true; + forceSSL = true; + + locations."/" = { + proxyWebsockets = true; + extraConfig = '' + proxy_pass http://127.0.0.1:3001; + proxy_set_header Host $host; + ''; + }; + }; + + virtualisation = { + oci-containers = { + backend = "docker"; + + containers."obs-portal" = { + image = "git.pub.solar/pub-solar/obs-portal:latest"; + autoStart = true; + ports = [ "localhost:3001:${env.OBS_PORT}" ]; + + environment = env; + environmentFiles = [ config.age.secrets.obs-portal-env.path ]; + + volumes = [ + "${configPy}:/opt/obs/api/config.py" + "/var/lib/obs-portal${env.OBS_DATA_DIR}:${env.OBS_DATA_DIR}" + "/var/lib/obs-portal/tiles/:/tiles" + "/var/lib/obs-portal/pbf/:/pbf" + ]; + + extraOptions = [ + "--network=obs-portal-net" + ]; + }; + + containers."obs-portal-worker" = { + image = "git.pub.solar/pub-solar/obs-portal:latest"; + autoStart = true; + + cmd = [ "python" "tools/process_track.py" ]; + + environment = env; + environmentFiles = [ config.age.secrets.obs-portal-env.path ]; + + volumes = [ + "${configPy}:/opt/obs/api/config.py" + "/var/lib/obs-portal${env.OBS_DATA_DIR}:${env.OBS_DATA_DIR}" + ]; + + extraOptions = [ + "--network=obs-portal-net" + ]; + }; + + containers."obs-portal-db" = { + image = "openmaptiles/postgis:7.0"; + autoStart = true; + + environmentFiles = [ config.age.secrets.obs-portal-database-env.path ]; + + volumes = [ + "/var/lib/postgres-obs-portal/data:/var/lib/postgresql/data" + ]; + + extraOptions = [ + "--network=obs-portal-net" + ]; + }; + }; + }; +} diff --git a/hosts/nachtigall/default.nix b/hosts/nachtigall/default.nix index 69428bf9..8e1455e0 100644 --- a/hosts/nachtigall/default.nix +++ b/hosts/nachtigall/default.nix @@ -32,6 +32,7 @@ ./apps/promtail.nix ./apps/searx.nix ./apps/tmate.nix + ./apps/obs-portal.nix ./apps/matrix/irc.nix ./apps/matrix/mautrix-telegram.nix diff --git a/secrets/obs-portal-database-env.age b/secrets/obs-portal-database-env.age new file mode 100644 index 00000000..0286690a --- /dev/null +++ b/secrets/obs-portal-database-env.age @@ -0,0 +1,27 @@ +age-encryption.org/v1 +-> ssh-ed25519 iDKjwg hAoEiOaK1U0HImALePEYHiE6xebOOqtVujaBWgNBZF8 +ecf/ykqYPihRJxI/Y7Oh6QhWSyncwevlzEZoRqm3aGM +-> ssh-ed25519 uYcDNw NcIttsTn6wPCmoOYGtZ66IYhthjLDI3sYFe4pbW6cB4 +9hv4dEYoXXWSZ2pG1hy68vmTf++v+g3q7wVhT6cAog0 +-> ssh-rsa kFDS0A +KoW3J2Tw90chM6Oy17umOQN0WFI4je7CBk3IgdImsd4Mz5q17/nXlhVlFFhx4ZEk +Or9LaqytVk1NA6J4+suMRlx4Pd6oberXu1KBkFQMr1B3LKhNOaOZ+W1mrbQLGG9U +YUTyOpkHxVkw0IOsvxB/0reMCHtjKHo661zFjim1YFmEk0WRt4hU1XqsMNiE4wbc +GF0t9EWMN2pU2p7DpX/DzVTqu8yk8SQhCZc9kfzWcuawwf0rcjwUJ/Rk1MH5tMpK +odRXXl1slPPwQinE+KJqeyrfuRDHqwqmxnOfOWG6KQwWkVSE1btiHEvfuuLOjSjl +3wO+veRC9hW5sSCPANoFbuSQ1dprmoyaZnOyeRTbgw91ks/ogLBezF/KSkaMQeHx +XRnfcceBmeeqHl9L3Z+3EmBjwIqu2Og0pvhDU8G/ZeA0cHS/22QYGzeD/gOqaEW7 +d1VyA6LZd8PxIjoBamdipIpY0TqZ8+cA/yaUKNnYXXRSlKQ5ggPxh7ZXfvRbGg+m +WbNiHxBPcTK7/Bpzes4LJVcx0Ar4XeDxVQe1MITLpFWh+FDEQZEA3630JngZ153J +vBvw+VFedPSr6Ov+/33/J3LKC0XRatGnc++AWfo4rWPLCE6qovEDyY+wmct8gv0j +rMEK7OaNfyy+Z21mjrkwcEUbyoGt9ksEplaRblE0Lsk +-> ssh-ed25519 YFSOsg LmLRtBYMSzjid3VkUgAQvDOS9r0imWSKE7fm0t/x41Y +0mae0vsNmaS5aVOKezXit7KV44JKLpU+GWpuA++dCVo +-> ssh-ed25519 iHV63A Tc2z2JciftAikoj4Hv9IBgkcYWAcyGuPJTNA3Yw2K1w +cO5o/pbaZAtTvXUskOah9vWP/Tuvyi3QDM7g4AQ+b8s +-> ssh-ed25519 BVsyTA mk6n6ytaI4V9JVoUZFtwfFOgaLYc6gvVOcSZXQj/FVI +etqbUCqe0eY81qaVco7pMJjhfM+sA/bXLMW0bEsCLxI +--- CmNq6ZPxFoFTsySVfr7BTHV0tm9cbRYGG6IR7DNgbEY +!烈} +SꝟSlDs;!jrZR"#~!6AwEn ?kAcx~GV&M, +aU \ No newline at end of file diff --git a/secrets/obs-portal-env.age b/secrets/obs-portal-env.age new file mode 100644 index 0000000000000000000000000000000000000000..c23caae3a44fbe3881f2be79fd1d187f2743fbd9 GIT binary patch literal 1593 zcmZXU+3Vy60f5yOx&-=AM6`-_kX5kZXOfvoG7(zLB$H#3nH-Z$Cec!JOpeKYPXQ+o#vjZqXKMiDI>`e00-iG(%7b zi3SDbbXdDKu@WH*q*zy!d6QPv_9$lP4NL;b3O_-q=Te>vPd7|`*r5h_z$Ju|b$hSY z5ySc@R}prk;}wnb6?Qad1vyP%c#u{~1}Mg2Ty3$%nqq|#+>L`?(pCk&UKgiHq;wb` zd3|6qkQ4}W-sRTbDqMKzQAAe@&u4H4h~=5&U?*4(29H3h^5{!U8RGmQ*EVo-+|5(+ zK+2&D5(F9&^nw8kI>>9TDj72mnG~Suw95)p$e^)n&GZ(^TM(tWAZ>7M;VZqEHOi#7 z(s44b_ho8Ta5=b%qNGO`Q8xnw;D_Bj9^;v=orWr1!sBAKYoK^ZSv@Mkkv--_9fTv= z3yq`ULpe=2g#;rKYC07NWeKp()Yz<9UuBQu*52=pdE_w8f`Sx=l8hJ)hiqS;q)CYH z`Axbp^j#Q{X3EXP*p`X81P~f;sDqx!o*gq9!)fqwU=2|sU~dk3tmMy4d$*JeD0f*z z(Ye_emiVTlv!v)r4Cw&T534mL7)rlf!crSaSxU(V2t4%5!QXg`Dzv4-| zmilTbhhXc4GS35WH`Cc>9N?YZ!@(5XkgUNbq&n>8F6;|5yN$`#n6X%rD-7v%Ilgw& zwq+Q4(Y9+6269J|;<^--Ii;(;sHNsMz}!rCXs2}Ph?|BU+0dv_B=Aj-Z#HT&8>tRP zvM=+ymA20u_*krX#7gB;I%ZRIsvGSFGn;O;%H?>a4wKXpmJbldO-c$wEQRL#R(81ooWH4*TfHYN$@2y0@j~W|t_k5&qv1=G%JE$PrG+9=pLH zN&%CYVdqA=)lCQVGOBDA?mWO)yyi(zn*=71oxG?MoWqz7+apm&_(`xLMVW<}<5^m; zOVmXdvD0RfEr7GLv(dB`IRt{O!<^+hZcKH4l)4Itlr3AHT-9{3gtOLL(9>$*u5;)! zx9>(5-t*Yguc2>0_Nw{7>^uMb?eA;hzU?z#IR5g(pZrwt=%w@Yja#44z{lfjfBxOu z1o&L=LzM^A=DQcZ6lo zxmSPs#4W#i?Jae5ukhAq?t1pu@caL8>9~9O^XLEZy+^-xzH$A=Ef?;5absM4F*>Wy{op^}T%P~zZ=SpGkofE;F8=G*2QTr? g>GEIReE9W`=KA^NQToVj=$Br2