about summary refs log tree commit diff
path: root/nix
diff options
context:
space:
mode:
Diffstat (limited to 'nix')
-rw-r--r--nix/hosts/corrino/configuration.nix4
-rw-r--r--nix/hosts/corrino/ports.nix1
-rw-r--r--nix/hosts/corrino/secrets/goapp_oidc_secret.age7
-rw-r--r--nix/hosts/corrino/secrets/goapp_oidc_session_key.age8
-rw-r--r--nix/hosts/corrino/vm.nix15
-rw-r--r--nix/hosts/corrino/www/goapp.emile.space.nix89
-rw-r--r--nix/hosts/corrino/www/templates/goapp/default.nix30
-rw-r--r--nix/lib/flake-helper.nix15
-rw-r--r--nix/modules/goapp-frontend/default.nix134
-rw-r--r--nix/modules/x86_64-linux.nix3
-rw-r--r--nix/pkgs/overlay.nix9
-rw-r--r--nix/pkgs/x86_64-linux.nix2
-rw-r--r--nix/templates/goapp/flake.nix16
-rw-r--r--nix/templates/goapp/frontend/default.nix15
-rw-r--r--nix/templates/goapp/frontend/go.mod8
-rw-r--r--nix/templates/goapp/frontend/go.sum7
-rwxr-xr-xnix/templates/goapp/frontend/run.sh4
-rw-r--r--nix/templates/goapp/frontend/server.log2
-rw-r--r--nix/templates/goapp/frontend/src/handlers.go66
-rw-r--r--nix/templates/goapp/frontend/src/init.go25
-rw-r--r--nix/templates/goapp/frontend/src/main.go9
-rw-r--r--nix/templates/goapp/frontend/src/types.go27
-rw-r--r--nix/templates/goapp/frontend/templates/index.html2
23 files changed, 394 insertions, 104 deletions
diff --git a/nix/hosts/corrino/configuration.nix b/nix/hosts/corrino/configuration.nix
index d453b34..52e9ecf 100644
--- a/nix/hosts/corrino/configuration.nix
+++ b/nix/hosts/corrino/configuration.nix
@@ -27,6 +27,8 @@ in
     ./www/git
     ./www/nix-cache
 
+    ./www/goapp.emile.space.nix
+
     # screego
 
     # web
@@ -42,7 +44,7 @@ in
 
     ./www/photo
 
-    # ./www/tickets.emile.space.nix
+    ./www/tickets.emile.space.nix
     # ./www/talks.emile.space.nix
     # ./www/stream.emile.space.nix
     ./www/md.emile.space.nix
diff --git a/nix/hosts/corrino/ports.nix b/nix/hosts/corrino/ports.nix
index 10ae593..bb64934 100644
--- a/nix/hosts/corrino/ports.nix
+++ b/nix/hosts/corrino/ports.nix
@@ -24,6 +24,7 @@
     restic = 8002;
     nocodb = 8003;
     goatcounter = 8004;
+    goapp = 8005;
     r2wars-web = 8089;
     ctf = 8338;
     magic-hash = 8339;
diff --git a/nix/hosts/corrino/secrets/goapp_oidc_secret.age b/nix/hosts/corrino/secrets/goapp_oidc_secret.age
new file mode 100644
index 0000000..ca96981
--- /dev/null
+++ b/nix/hosts/corrino/secrets/goapp_oidc_secret.age
@@ -0,0 +1,7 @@
+age-encryption.org/v1
+-> ssh-ed25519 gvwQ2Q Efi2feeWex0ApMR1lvO6osGzW58wiT24zLxcvWlThyc
+/UnBx5j3slzIBoNhbdp9ccdk/p8rFdr/i602sO3abi4
+-> ssh-ed25519 m8VklA o9Y9PUYV9RTcQIu2PLouB9336WdJVhtrEy61UTF62WU
+NQ+VueAUIqP4LGazGz/cOKtDmao4LKRWLj7fT2/0g5c
+--- jjCarc6U6Mxp3VtnS7mElpuJhKjc4fjUTd6dicekLgg
+AU.#z̥8wwWS1)R?'}l
n/TC'>&<b_EƔōKBBylD,@(<4~̌rգ
\ No newline at end of file
diff --git a/nix/hosts/corrino/secrets/goapp_oidc_session_key.age b/nix/hosts/corrino/secrets/goapp_oidc_session_key.age
new file mode 100644
index 0000000..938f97f
--- /dev/null
+++ b/nix/hosts/corrino/secrets/goapp_oidc_session_key.age
@@ -0,0 +1,8 @@
+age-encryption.org/v1
+-> ssh-ed25519 gvwQ2Q BAvDdIEUEgmo963+9Wd5VLJgrp3MBISvWR3+27bfJW8
+NOEj2ObYe/cM2CaqzmbgexSEUNZIEo1ZmvlamJaSOjo
+-> ssh-ed25519 m8VklA d/hwd3rGkPD3GDdlOP2XUsi687VH+tfKrAsKnImk+kI
+gFAyyMZT5DK7da7YXOf/5gUd4Bi9cEe3ddMKUMuctMU
+--- 9tVE+AAvptrlMZe5+UGJGzH9usnxa+ZICbikcRT0PYI
+g!X+/0P	;*{Vp!4sa	I+/\IԖ,op웘DP7";pPp
+%cUڜ8
\ No newline at end of file
diff --git a/nix/hosts/corrino/vm.nix b/nix/hosts/corrino/vm.nix
index 37d1356..78d818f 100644
--- a/nix/hosts/corrino/vm.nix
+++ b/nix/hosts/corrino/vm.nix
@@ -1,4 +1,4 @@
-{ pkgs, ... }:
+{  pkgs, ... }:
 
 {
   services.emile.libvirtnix = {
@@ -15,6 +15,19 @@
           uuid = "E34DE478-1402-45BB-B3FD-FC960549258E";
           genid = "CA1E2462-1E9D-404C-8DDB-19EEF9D9651B";
 
+          os = {
+            nvram = {
+              type = "network";
+              source = {
+                mirror = {
+                  abi = "copy";
+                  ready = "yes";
+                  type = "network";
+                };
+              };
+            };
+          };
+
           packages = {
             libvirt = pkgs.libvirt;
             qemu = pkgs.qemu;
diff --git a/nix/hosts/corrino/www/goapp.emile.space.nix b/nix/hosts/corrino/www/goapp.emile.space.nix
new file mode 100644
index 0000000..361e95a
--- /dev/null
+++ b/nix/hosts/corrino/www/goapp.emile.space.nix
@@ -0,0 +1,89 @@
+{ config, pkgs, ... }:
+
+{
+  services.nginx.virtualHosts."goapp.emile.space" = {
+    forceSSL = true;
+    enableACME = true;
+
+    locations = {
+      "/" = {
+        proxyPass = "http://${config.services.emile.goapp-frontend.host}:${toString config.services.emile.goapp-frontend.port}";
+      };
+    };
+  };
+
+  services.authelia.instances.main.settings.identity_providers.oidc.clients = [
+    {
+      id = "goapp";
+
+      # ; nix run nixpkgs#authelia -- crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
+      secret = "$pbkdf2-sha512$310000$LPXJRoGR9RyTcaT6cADljg$FK8RV5CnKj5ano4fXmRzzvXcX/00F7k/G6nd67t.8iewpwyq8FntV4JgYZSV8AynYMxz1qnL4j3BzITLCM0KgQ";
+      public = false;
+      authorization_policy = "two_factor";
+      redirect_uris = [
+        "https://goapp.emile.space/oauth2/callback"
+      ];
+      scopes = [
+        "openid"
+        "email"
+        "profile"
+        "groups"
+      ];
+      grant_types = [
+        "refresh_token"
+        "authorization_code"
+      ];
+      response_types = [ "code" ];
+      response_modes = [
+        "form_post"
+        "query"
+        "fragment"
+      ];
+      token_endpoint_auth_method = "client_secret_post";
+    }
+  ];
+
+  environment.systemPackages = with pkgs; [ goapp-frontend ];
+
+  # deploy:
+  # - push code
+  # - build in order to get the new hash (nix build .#goapp-frontend-pkg)
+  # - update hash in the package (//nix/templates/goapp/frontent/default.nix)
+  # - deploy
+  #
+  # https://goapp.emile.space/oauth2/callback?code=authelia_ac_iZKCXtRMnj2yjUAmiSkg_LBWjiME2-ghE6KMkxdb6Zw.nDLgCVpu9ctH1llEKUml5rr8szd3bkZYaGa_MAOtNLI&iss=https%3A%2F%2Fsso.emile.space&scope=openid+profile+email+groups&state=random-string-here
+  #
+  # Unable to exchange authorization code for tokens
+  #
+  # unable to exchange authorization code for tokens: oauth2: "invalid_client" "Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)."
+
+  services.emile.goapp-frontend = {
+    enable = true;
+    package = pkgs.goapp-frontend;
+
+    host = "127.0.0.1";
+    port = config.emile.ports.goapp;
+    public-url = "https://goapp.emile.space/";
+
+    oidc = {
+      id = "goapp";
+      issuer = "https://sso.emile.space";
+      cookie-name = "oidc-client";
+      scopes = [
+        "openid"
+        "profile"
+        "email"
+        "groups"
+      ];
+      # secret-path = "/run/goapp-frontend_oidc_secret";
+      secret-path = config.age.secrets.goapp_oidc_secret.path;
+    };
+
+    # TODO(emile): change these when going live
+    session-key-path = config.age.secrets.goapp_oidc_secret.path;
+
+    logfile-path = "/var/log/goapp-frontend.log";
+    database-path = "/var/lib/goapp-frontend/main.db";
+    sessiondb-path = "/var/lib/goapp-frontend/session.db";
+  };
+}
diff --git a/nix/hosts/corrino/www/templates/goapp/default.nix b/nix/hosts/corrino/www/templates/goapp/default.nix
deleted file mode 100644
index 716d6ab..0000000
--- a/nix/hosts/corrino/www/templates/goapp/default.nix
+++ /dev/null
@@ -1,30 +0,0 @@
-
-{
-  services.authelia.instances.main.settings.identity_providers.oidc.clients = [
-    {
-      id = "goapp";
-
-      # ; nix run nixpkgs#authelia -- crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
-      secret = "$pbkdf2-sha512$310000$WUai4pp1ZVJDrJ8j6ICLiQ$NOMMaCZ3gt.x.a09MWatMkJWQIaH0QeWgRXSbuD2iWRwR.N6MWmJA6QO.LIKcxn6l.zHZN4bO1Ztsrbo9010Tw";
-      public = false;
-      authorization_policy = "two_factor";
-      redirect_uris = [ "https://127.0.0.1:8080/auth/oauth2/callback" ];
-      scopes = [
-        "openid"
-        "email"
-        "profile"
-      ];
-      grant_types = [
-        "refresh_token"
-        "authorization_code"
-      ];
-      response_types = [ "code" ];
-      response_modes = [
-        "form_post"
-        "query"
-        "fragment"
-      ];
-      token_endpoint_auth_method = "client_secret_post";
-    }
-  ];
-}
diff --git a/nix/lib/flake-helper.nix b/nix/lib/flake-helper.nix
index ddace97..f841fa5 100644
--- a/nix/lib/flake-helper.nix
+++ b/nix/lib/flake-helper.nix
@@ -83,8 +83,6 @@ rec {
             { ... }:
             {
               nixpkgs.overlays = [
-                self.overlays.emile
-
                 (
                   if system == "x86_64-linux" then
                     self.overlays.x86_64-linux
@@ -94,6 +92,11 @@ rec {
                     null
                 )
 
+                # no clue why, but when rebuilding corrino and this not being commented,
+                # something in the hardware.bluetooth module breaks
+                #
+                # (if system == "aarch64-darwin" then self.overlays.unstable-darwin else null)
+
                 (_: _: { inherit (agenix.packages."x86_64-linux") agenix; })
 
                 (_: _: {
@@ -197,8 +200,12 @@ rec {
         user = "root"; # user to install as
         sshUser = sshUser; # user to ssh to as
 
-        # make sure people can use sudo 
-        sshOpts = ["-A" "-t" "-S"];
+        # make sure people can use sudo
+        sshOpts = [
+          "-A"
+          "-t"
+          "-S"
+        ];
         # sshOpts = [ "-o"  "ProxyCommand=none" ];
 
         # make sure to add the nix foo on the darwin hosts to ~/.zshenv
diff --git a/nix/modules/goapp-frontend/default.nix b/nix/modules/goapp-frontend/default.nix
new file mode 100644
index 0000000..c5f62aa
--- /dev/null
+++ b/nix/modules/goapp-frontend/default.nix
@@ -0,0 +1,134 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+let
+  cfg = config.services.emile.goapp-frontend;
+in
+with lib;
+{
+  options.services.emile.goapp-frontend = {
+    enable = mkEnableOption "Enable goapp-frontend";
+    package = mkPackageOption pkgs "goapp-frontend" { };
+
+    # ip, port and external host to listen on
+    host = mkOption {
+      type = types.str;
+      default = "127.0.0.1";
+      example = "0.0.0.0";
+      description = "The host the service listens on";
+    };
+    port = mkOption {
+      type = types.int;
+      default = 8080;
+      example = 8080;
+      description = "The port the service listens on";
+    };
+    public-url = mkOption {
+      type = types.str;
+      default = "http://localhost:8080/";
+      example = "https://goapp.emile.space/";
+      description = ''
+        The domain that the service can be reached from externally. This is used by oidc for redirects and thus should be set, as you'll probably be running this behind some kind of reverse proxy.
+      '';
+    };
+
+    # the oidc config
+    oidc = mkOption {
+      type = types.submodule {
+        options = {
+          id = mkOption {
+            type = types.str;
+            default = "";
+            example = "AiliavahweiweeG5";
+            description = "The oidc id";
+          };
+          issuer = mkOption {
+            type = types.str;
+            default = "";
+            example = "https://sso.emile.space";
+            description = "The oidc identity provider";
+          };
+          cookie-name = mkOption {
+            type = types.str;
+            default = "oidc-client";
+            example = "CookieMcCookieface";
+            description = "The oidc cookie name";
+          };
+          scopes = mkOption {
+            type = types.listOf types.str;
+            default = [ "openid" "profile" "email" "groups" ];
+            example = [ "openid" "profile" "email" ];
+            description = "The openid scopes to request";
+          };
+          secret-path = mkOption {
+            type = types.str;
+            default = "";
+            example = "/run/goapp_oidc_secret";
+            description = "The path to the oidc secret";
+          };
+        };
+      };
+    };
+     
+    # paths to files
+    session-key-path = mkOption {
+      type = types.str;
+      default = "";
+      example = "/run/sesionkey";
+      description = "The path to a file containing the sessionKey";
+    };
+    logfile-path = mkOption {
+      type = types.str;
+      default = "/var/log/goapp-frontend.log";
+      example = "/var/log/goapp-frontend.log";
+      description = "The path to where the logfile should be written";
+    };
+
+    database-path = mkOption {
+      type = types.str;
+      default = "/var/lib/goapp-frontend/main.db";
+      example = "/var/lib/goapp-frontend/main.db";
+      description = "The path to the main database";
+    };
+    sessiondb-path = mkOption {
+      type = types.str;
+      default = "/var/lib/goapp-frontend/sessions.db";
+      example = "/var/lib/goapp-frontend/sessions.db";
+      description = "The path to the sessions database";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.goapp-frontend = {
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        RestartSec = 5;
+        Restart = "on-failure";
+      };
+      environment = {
+        VERSION = pkgs.goapp-frontend.version;
+      };
+      path = [ pkgs.goapp-frontend ];
+      serviceConfig.ExecStart = ''
+        ${pkgs.goapp-frontend}/bin/frontend \
+          --host ${cfg.host} \
+          --port ${toString cfg.port} \
+          --public-url ${cfg.public-url} \
+          --id ${cfg.oidc.id} \
+          --issuer ${cfg.oidc.issuer} \
+          --cookie-name ${cfg.oidc.cookie-name} \
+          --scopes ${concatStringsSep "," cfg.oidc.scopes} \
+          --oidc-secret-path ${cfg.oidc.secret-path} \
+          --logfilepath ${cfg.logfile-path} \
+          --databasepath ${cfg.database-path} \
+          --sessiondbpath ${cfg.sessiondb-path} \
+          --sessionkeypath ${cfg.session-key-path} \
+          --templatespath ${pkgs.goapp-frontend}/templates
+      '';
+    };
+  };
+}
diff --git a/nix/modules/x86_64-linux.nix b/nix/modules/x86_64-linux.nix
index e5dbc64..62945b3 100644
--- a/nix/modules/x86_64-linux.nix
+++ b/nix/modules/x86_64-linux.nix
@@ -4,6 +4,7 @@
     ./r2wars-web
     ./remarvin
     ./filebrowser
-    ./libvirtnix
+    # ./libvirtnix
+    ./goapp-frontend
   ];
 }
diff --git a/nix/pkgs/overlay.nix b/nix/pkgs/overlay.nix
deleted file mode 100644
index e213533..0000000
--- a/nix/pkgs/overlay.nix
+++ /dev/null
@@ -1,9 +0,0 @@
-final: prev: {
-  vokobe = final.callPackage ./vokobe { inherit (final) naersk; };
-  r2wars-web = final.callPackage ./r2wars-web { };
-  remarvin = final.callPackage ./remarvin { };
-
-  pretalx_old = prev.pretalx.overrideAttrs ( old: {
-    version = "2024.1.0";
-  });
-}
diff --git a/nix/pkgs/x86_64-linux.nix b/nix/pkgs/x86_64-linux.nix
index f5e8b60..c186cc4 100644
--- a/nix/pkgs/x86_64-linux.nix
+++ b/nix/pkgs/x86_64-linux.nix
@@ -2,5 +2,5 @@ final: prev: {
   vokobe = final.callPackage ./vokobe { inherit (final) naersk; };
   r2wars-web = final.callPackage ./r2wars-web { };
   remarvin = final.callPackage ./remarvin { };
-  libc-database = final.callPackage ./libc-database {};
+  # libc-database = final.callPackage ./libc-database {};
 }
diff --git a/nix/templates/goapp/flake.nix b/nix/templates/goapp/flake.nix
index 1ca876f..385f1bf 100644
--- a/nix/templates/goapp/flake.nix
+++ b/nix/templates/goapp/flake.nix
@@ -12,20 +12,26 @@
           overlays = [ ];
         };
 
+        # take a name and return an attrset with a corresponding package and docker container
         package-and-docker = name: (let
-          pkgname = name + "-pkg";
+          # define the name for the package and docker container
+          pkgname = name;
           dockername = name + "-docker";
 
+          # import the package itself
           package = import ./${name} { inherit pkgs name; };
+
+          # define the container
+          container = pkgs.dockerTools.buildImage {
+            name = "${name}"; # TODO(emile): this could simply be `inherit name;` iinw
+            config.Cmd = [ "${package}/bin/${name}" ];
+          };
         in {
           # the raw package
           ${pkgname} = package;
 
           # the docker image
-          ${dockername} = pkgs.dockerTools.buildImage {
-            name = "${name}";
-            config.Cmd = [ "${package}/bin/${name}" ];
-          };
+          ${dockername} = container;
         });
       in
       {
diff --git a/nix/templates/goapp/frontend/default.nix b/nix/templates/goapp/frontend/default.nix
index 42ccb79..7b5caa8 100644
--- a/nix/templates/goapp/frontend/default.nix
+++ b/nix/templates/goapp/frontend/default.nix
@@ -4,13 +4,20 @@ let
   version = "0.0.1";
 in
 pkgs.buildGoModule {
-  name = "${name}-${version}";
   pname = "${name}";
   version = "${version}";
 
   src = ./.;
-  subPackages = [ "src" ];
-  vendorHash = "sha256-VXuhsXejduIcthawj4qu7hruBEDegj27YY0ym5srMQY=";
 
-  doCheck = true;
+  # use the dependencies directly from the vendor/ folder
+  # vendorHash = null;
+   
+  vendorHash = "sha256-dXWwAP0XM24cAcDV87XHQX9dLg6TDQ7ZVfEFgW/Q+J4=";
+
+  doCheck = false;
+
+  postInstall = ''
+    cp -r templates $out
+    mv $out/bin/{src,${name}}
+  '';
 }
diff --git a/nix/templates/goapp/frontend/go.mod b/nix/templates/goapp/frontend/go.mod
index fecf4ac..a71f5a0 100644
--- a/nix/templates/goapp/frontend/go.mod
+++ b/nix/templates/goapp/frontend/go.mod
@@ -1,20 +1,20 @@
-module github.com/hanemile/goapp/backend
+module github.com/hanemile/goapp/frontend
 
 go 1.23.5
 
 require (
+	github.com/coreos/go-oidc/v3 v3.12.0
 	github.com/gorilla/handlers v1.5.2
 	github.com/gorilla/mux v1.8.1
 	github.com/gorilla/securecookie v1.1.2
 	github.com/gorilla/sessions v1.4.0
 	github.com/mattn/go-sqlite3 v1.14.24
-	golang.org/x/crypto v0.33.0
+	github.com/spf13/cobra v1.9.1
 	golang.org/x/oauth2 v0.21.0
 	modernc.org/sqlite v1.34.5
 )
 
 require (
-	github.com/coreos/go-oidc/v3 v3.12.0 // indirect
 	github.com/dustin/go-humanize v1.0.1 // indirect
 	github.com/felixge/httpsnoop v1.0.4 // indirect
 	github.com/go-jose/go-jose/v4 v4.0.2 // indirect
@@ -23,8 +23,8 @@ require (
 	github.com/mattn/go-isatty v0.0.20 // indirect
 	github.com/ncruces/go-strftime v0.1.9 // indirect
 	github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
-	github.com/spf13/cobra v1.9.1 // indirect
 	github.com/spf13/pflag v1.0.6 // indirect
+	golang.org/x/crypto v0.33.0 // indirect
 	golang.org/x/sys v0.30.0 // indirect
 	modernc.org/libc v1.55.3 // indirect
 	modernc.org/mathutil v1.6.0 // indirect
diff --git a/nix/templates/goapp/frontend/go.sum b/nix/templates/goapp/frontend/go.sum
index 365e2c5..15bbb6f 100644
--- a/nix/templates/goapp/frontend/go.sum
+++ b/nix/templates/goapp/frontend/go.sum
@@ -1,6 +1,8 @@
 github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo=
 github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
 github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
 github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
 github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
@@ -31,6 +33,8 @@ github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBW
 github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
 github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
 github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -38,6 +42,8 @@ github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
 github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
 github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
 github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
 golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
 golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
@@ -50,6 +56,7 @@ golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
 golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
 modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
diff --git a/nix/templates/goapp/frontend/run.sh b/nix/templates/goapp/frontend/run.sh
index fb3c7b3..b2624f3 100755
--- a/nix/templates/goapp/frontend/run.sh
+++ b/nix/templates/goapp/frontend/run.sh
@@ -1,3 +1,4 @@
+# these are tests creds that aren't valid, try it :D
 export CLIENT_ID=goapp
 export CLIENT_SECRET=KGFO5LQnUxu1Zs.35gOem3MaG8odthg1U0v0.kScVPS6TPTWVRnAdT_nj4PYYSfuU6jdzTM6
 export CLIENT_CALLBACK_URL=http://localhost:8080/oauth2/callback
@@ -6,4 +7,5 @@ export SESSION_KEY=aes1Itheich4aeQu9Ouz7ahcaiVoogh9
 go run ./... \
   --id goapp \
   --issuer "https://sso.emile.space" \
-  --secret "KGFO5LQnUxu1Zs.35gOem3MaG8odthg1U0v0.kScVPS6TPTWVRnAdT_nj4PYYSfuU6jdzTM6"
+  --secret "KGFO5LQnUxu1Zs.35gOem3MaG8odthg1U0v0.kScVPS6TPTWVRnAdT_nj4PYYSfuU6jdzTM6" \
+  $@
diff --git a/nix/templates/goapp/frontend/server.log b/nix/templates/goapp/frontend/server.log
index 4b6cff5..6c4d6dc 100644
--- a/nix/templates/goapp/frontend/server.log
+++ b/nix/templates/goapp/frontend/server.log
@@ -177,3 +177,5 @@
 ::1 - - [19/Feb/2025:19:43:29 +0100] "GET /oauth2/callback?code=authelia_ac_8UdV__GJCN9gxJrYa629TC3FToyDDhsbacPbJzhvcJ4.uPw2-_N4jQr7xf7JNZ_IZBNHEq-eeOFoZup7Vwjx1Y0&iss=https%3A%2F%2Fsso.emile.space&scope=openid+profile+email+groups&state=random-string-here HTTP/1.1" 500 142
 ::1 - - [19/Feb/2025:19:49:22 +0100] "GET / HTTP/1.1" 200 6587
 ::1 - - [19/Feb/2025:19:49:23 +0100] "GET /login HTTP/1.1" 302 242
+::1 - - [19/Feb/2025:19:56:09 +0100] "GET / HTTP/1.1" 200 6587
+::1 - - [19/Feb/2025:19:56:12 +0100] "GET /login HTTP/1.1" 302 242
diff --git a/nix/templates/goapp/frontend/src/handlers.go b/nix/templates/goapp/frontend/src/handlers.go
index 8fdd325..2cbacde 100644
--- a/nix/templates/goapp/frontend/src/handlers.go
+++ b/nix/templates/goapp/frontend/src/handlers.go
@@ -12,7 +12,7 @@ import (
 )
 
 func indexHandler(w http.ResponseWriter, r *http.Request) {
-	session, err := globalState.sessions.Get(r, "session")
+	session, err := globalState.sessions.Get(r, options.CookieName)
 	if err != nil {
 		log.Println("error getting the session")
 	}
@@ -37,9 +37,14 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
 			},
 		},
 	}
-	tpl.NextLinks = []Link{
-		{"Login", "/login"},
-	}
+
+	//  session.Values["id_token"] = claimsIDToken
+	//  session.Values["userinfo"] = claimsUserInfo
+	//  session.Values["logged"] = true
+	//
+	log.Println("logged", session.Values["logged"])
+	log.Println("id-token", session.Values["id_token"])
+	log.Println("userinfo", session.Values["userinfo"])
 
 	if logged, ok := session.Values["logged"].(bool); ok && logged {
 		tpl.LoggedIn = true
@@ -68,6 +73,10 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
 		tpl.Claims.UserInfo.Name = filterText(tpl.Claims.UserInfo.Name, options.Filters)
 		tpl.RawToken = rawTokens[tpl.Claims.IDToken.JWTIdentifier]
 		tpl.AuthorizeCodeURL = acURLs[tpl.Claims.IDToken.JWTIdentifier].String()
+
+		tpl.NextLinks = []Link{{"Logout", "/logout"}}
+	} else {
+		tpl.NextLinks = []Link{{"Login", "/login"}}
 	}
 
 	w.Header().Add("Content-Type", "text/html")
@@ -129,12 +138,11 @@ func logoutHandler(w http.ResponseWriter, r *http.Request) {
 	http.Redirect(w, r, "/", http.StatusFound)
 }
 
-func oauthCallbackHandler(res http.ResponseWriter, req *http.Request) {
+func oauthCallbackHandler(w http.ResponseWriter, r *http.Request) {
 	log.Println("hit the oauth callback handler")
-	if req.FormValue("error") != "" {
-		log.Printf("got an error from the idp: %s", req.FormValue("error"))
-		http.Redirect(res, req, fmt.Sprintf("/error?%s", req.Form.Encode()), http.StatusFound)
-
+	if r.FormValue("error") != "" {
+		log.Printf("got an error from the idp: %s", r.FormValue("error"))
+		http.Redirect(w, r, fmt.Sprintf("/error?%s", r.Form.Encode()), http.StatusFound)
 		return
 	}
 
@@ -146,24 +154,32 @@ func oauthCallbackHandler(res http.ResponseWriter, req *http.Request) {
 		ok         bool
 	)
 
+	log.Println(r.URL)
+
 	// The state should be checked here in production
-	if token, err = oauth2Config.Exchange(req.Context(), req.URL.Query().Get("code")); err != nil {
+	if token, err = oauth2Config.Exchange(
+		r.Context(),
+		r.URL.Query().Get("code"),
+		//  oauth2.SetAuthURLParam("client_id", oauth2Config.ClientID),
+		//  oauth2.SetAuthURLParam("client_secret", oauth2Config.ClientSecret),
+	); err != nil {
 		log.Println("Unable to exchange authorization code for tokens")
-		writeErr(res, err, "unable to exchange authorization code for tokens", http.StatusInternalServerError)
+		log.Println(err)
+		writeErr(w, err, "unable to exchange authorization code for tokens", http.StatusInternalServerError)
 		return
 	}
 
 	// Extract the ID Token from OAuth2 token.
 	if idTokenRaw, ok = token.Extra("id_token").(string); !ok {
 		log.Println("missing id token")
-		writeErr(res, nil, "missing id token", http.StatusInternalServerError)
+		writeErr(w, nil, "missing id token", http.StatusInternalServerError)
 		return
 	}
 
 	// Parse and verify ID Token payload.
-	if idToken, err = verifier.Verify(req.Context(), idTokenRaw); err != nil {
+	if idToken, err = verifier.Verify(r.Context(), idTokenRaw); err != nil {
 		log.Printf("unable to verify id token or token is invalid: %+v", idTokenRaw)
-		writeErr(res, err, "unable to verify id token or token is invalid", http.StatusInternalServerError)
+		writeErr(w, err, "unable to verify id token or token is invalid", http.StatusInternalServerError)
 		return
 	}
 
@@ -172,15 +188,15 @@ func oauthCallbackHandler(res http.ResponseWriter, req *http.Request) {
 
 	if err = idToken.Claims(&claimsIDToken); err != nil {
 		log.Printf("unable to decode id token claims: %+v", &claimsIDToken)
-		writeErr(res, err, "unable to decode id token claims", http.StatusInternalServerError)
+		writeErr(w, err, "unable to decode id token claims", http.StatusInternalServerError)
 		return
 	}
 
 	var userinfo *oidc.UserInfo
 
-	if userinfo, err = provider.UserInfo(req.Context(), oauth2.StaticTokenSource(token)); err != nil {
+	if userinfo, err = provider.UserInfo(r.Context(), oauth2.StaticTokenSource(token)); err != nil {
 		log.Printf("unable to retreive userinfo claims")
-		writeErr(res, err, "unable to retrieve userinfo claims", http.StatusInternalServerError)
+		writeErr(w, err, "unable to retrieve userinfo claims", http.StatusInternalServerError)
 		return
 	}
 
@@ -188,15 +204,15 @@ func oauthCallbackHandler(res http.ResponseWriter, req *http.Request) {
 
 	if err = userinfo.Claims(&claimsUserInfo); err != nil {
 		log.Printf("unable to decode userinfo claims")
-		writeErr(res, err, "unable to decode userinfo claims", http.StatusInternalServerError)
+		writeErr(w, err, "unable to decode userinfo claims", http.StatusInternalServerError)
 		return
 	}
 
 	var session *sessions.Session
 
-	if session, err = globalState.sessions.Get(req, options.CookieName); err != nil {
+	if session, err = globalState.sessions.Get(r, options.CookieName); err != nil {
 		log.Printf("unable to get session from cookie")
-		writeErr(res, err, "unable to get session from cookie", http.StatusInternalServerError)
+		writeErr(w, err, "unable to get session from cookie", http.StatusInternalServerError)
 		return
 	}
 
@@ -204,11 +220,11 @@ func oauthCallbackHandler(res http.ResponseWriter, req *http.Request) {
 	session.Values["userinfo"] = claimsUserInfo
 	session.Values["logged"] = true
 	rawTokens[claimsIDToken.JWTIdentifier] = idTokenRaw
-	acURLs[claimsIDToken.JWTIdentifier] = req.URL
+	acURLs[claimsIDToken.JWTIdentifier] = r.URL
 
-	if err = session.Save(req, res); err != nil {
+	if err = session.Save(r, w); err != nil {
 		log.Printf("unable to save session")
-		writeErr(res, err, "unable to save session", http.StatusInternalServerError)
+		writeErr(w, err, "unable to save session", http.StatusInternalServerError)
 		return
 	}
 
@@ -216,11 +232,11 @@ func oauthCallbackHandler(res http.ResponseWriter, req *http.Request) {
 
 	if redirectUrl, ok = session.Values["redirect-url"].(string); ok {
 		log.Printf("all fine!")
-		http.Redirect(res, req, redirectUrl, http.StatusFound)
+		http.Redirect(w, r, redirectUrl, http.StatusFound)
 		return
 	}
 
-	http.Redirect(res, req, "/", http.StatusFound)
+	http.Redirect(w, r, "/", http.StatusFound)
 }
 
 func writeErr(w http.ResponseWriter, err error, msg string, statusCode int) {
diff --git a/nix/templates/goapp/frontend/src/init.go b/nix/templates/goapp/frontend/src/init.go
index 97e58f0..75fd87d 100644
--- a/nix/templates/goapp/frontend/src/init.go
+++ b/nix/templates/goapp/frontend/src/init.go
@@ -2,8 +2,10 @@ package main
 
 import (
 	"context"
+	//  "crypto/tls"
 	"fmt"
 	"log"
+	//  "net/http"
 	"net/url"
 	"os"
 	"strings"
@@ -32,12 +34,17 @@ func dbInit() {
 
 func sessionInit() {
 	log.Println("[i] Setting up Session Storage...")
+	session_key, err := os.ReadFile(options.SessionKeyPath)
+	if err != nil {
+		log.Println("Could not read Session key")
+		panic(err)
+	}
 	store, err := NewSqliteStore(
 		sessiondbPath,
 		"sessions",
 		"/",
 		3600,
-		[]byte(os.Getenv("SESSION_KEY")))
+		session_key)
 	if err != nil {
 		panic(err)
 	}
@@ -60,17 +67,29 @@ func oauth2Init() (err error) {
 	}
 
 	verifier = provider.Verifier(&oidc.Config{ClientID: options.ClientID})
+
+	clientSecretBytes, err := os.ReadFile(options.ClientSecretPath)
+	if err != nil {
+		panic(err)
+	}
+	clientSecret := strings.TrimSpace(string(clientSecretBytes))
+
 	log.Printf("[ ] ClientID: %s", options.ClientID)
-	log.Printf("[ ] ClientSecret: %s", options.ClientSecret)
+	log.Printf("[ ] ClientSecret: %s", clientSecret)
 	log.Printf("[ ] redirectURL: %s", redirectURL.String())
 	log.Printf("[ ] providerEndpoint: %+v", provider.Endpoint())
 	log.Printf("[ ] Scopes: %s", options.Scopes)
+	log.Printf("[ ] Endpoint: %+v", provider.Endpoint())
+
 	oauth2Config = oauth2.Config{
 		ClientID:     options.ClientID,
-		ClientSecret: options.ClientSecret,
+		ClientSecret: clientSecret,
 		RedirectURL:  redirectURL.String(),
 		Endpoint:     provider.Endpoint(),
 		Scopes:       strings.Split(options.Scopes, ","),
 	}
+
+	oauth2Config.Endpoint.AuthStyle = oauth2.AuthStyleInParams
+
 	return nil
 }
diff --git a/nix/templates/goapp/frontend/src/main.go b/nix/templates/goapp/frontend/src/main.go
index fcf4224..72ec7ee 100644
--- a/nix/templates/goapp/frontend/src/main.go
+++ b/nix/templates/goapp/frontend/src/main.go
@@ -38,18 +38,21 @@ func main() {
 
 	rootCmd := &cobra.Command{Use: "goapp", RunE: root}
 
-	rootCmd.Flags().StringVar(&options.Host, "host", "0.0.0.0", "Specifies the tcp host to listen on")
+	rootCmd.Flags().StringVar(&options.Host, "host", "127.0.0.1", "Specifies the tcp host to listen on")
 	rootCmd.Flags().IntVar(&options.Port, "port", 8080, "Specifies the port to listen on")
 	rootCmd.Flags().StringVar(&options.PublicURL, "public-url", "http://localhost:8080/", "Specifies the root URL to generate the redirect URI")
 	rootCmd.Flags().StringVar(&options.ClientID, "id", "", "Specifies the OpenID Connect Client ID")
-	rootCmd.Flags().StringVarP(&options.ClientSecret, "secret", "s", "", "Specifies the OpenID Connect Client Secret")
+	rootCmd.Flags().StringVarP(&options.ClientSecretPath, "oidc-secret-path", "s", "", "Specifies the OpenID Connect Client Secret path")
 	rootCmd.Flags().StringVarP(&options.Issuer, "issuer", "i", "", "Specifies the URL for the OpenID Connect OP")
 	rootCmd.Flags().StringVar(&options.Scopes, "scopes", "openid,profile,email,groups", "Specifies the OpenID Connect scopes to request")
 	rootCmd.Flags().StringVar(&options.CookieName, "cookie-name", "oidc-client", "Specifies the storage cookie name to use")
 	rootCmd.Flags().StringSliceVar(&options.Filters, "filters", []string{}, "If specified filters the specified text from html output (not json) out of the email addresses, display names, audience, etc")
 	rootCmd.Flags().StringSliceVar(&options.GroupsFilter, "groups-filter", []string{}, "If specified only shows the groups in this list")
-	rootCmd.Flags().StringVar(&options.LogFilePath, "logpath", "./server.log", "Specifies the path to store the server logs at")
+	rootCmd.Flags().StringVar(&options.LogFilePath, "logfilepath", "./server.log", "Specifies the path to store the server logs at")
 	rootCmd.Flags().StringVar(&options.TemplatesPath, "templatespath", "./templates", "Specifies the path to where the templates are stored")
+	rootCmd.Flags().StringVar(&options.DatabasePath, "databasepath", "./main.db", "Specifies the path to where the database is stored")
+	rootCmd.Flags().StringVar(&options.SessionDBPath, "sessiondbpath", "./sessions.db", "Specifies the path to where the session database is stored")
+	rootCmd.Flags().StringVar(&options.SessionKeyPath, "sessionkeypath", "", "Specifies the path to where the session key is stored")
 
 	_ = rootCmd.MarkFlagRequired("id")
 	_ = rootCmd.MarkFlagRequired("secret")
diff --git a/nix/templates/goapp/frontend/src/types.go b/nix/templates/goapp/frontend/src/types.go
index 7efcc70..97e0db5 100644
--- a/nix/templates/goapp/frontend/src/types.go
+++ b/nix/templates/goapp/frontend/src/types.go
@@ -50,16 +50,19 @@ type ClamsAddress struct {
 }
 
 type Options struct {
-	Host          string
-	Port          int
-	LogFilePath   string
-	TemplatesPath string
-	ClientID      string
-	ClientSecret  string
-	Issuer        string
-	PublicURL     string
-	Scopes        string
-	CookieName    string
-	Filters       []string
-	GroupsFilter  []string
+	ClientID         string
+	ClientSecretPath string
+	CookieName       string
+	DatabasePath     string
+	Filters          []string
+	GroupsFilter     []string
+	Host             string
+	Issuer           string
+	LogFilePath      string
+	Port             int
+	PublicURL        string
+	Scopes           string
+	SessionDBPath    string
+	SessionKeyPath   string
+	TemplatesPath    string
 }
diff --git a/nix/templates/goapp/frontend/templates/index.html b/nix/templates/goapp/frontend/templates/index.html
index 1d21f3d..e4693af 100644
--- a/nix/templates/goapp/frontend/templates/index.html
+++ b/nix/templates/goapp/frontend/templates/index.html
@@ -5,6 +5,8 @@
 
 <h1>goapp</h1>
 
+{{ . }}
+
 {{- if .LoggedIn }}
 <p id="welcome">Logged in as {{ or .Claims.UserInfo.PreferredUsername .Claims.IDToken.Subject "unknown" }}!</p>
 <p><a href="/logout" id="log-out">Log out</a></p>