From 52e31832443ad3b74910b4dbd28fe4a0263812a0 Mon Sep 17 00:00:00 2001 From: Nikolaos Karaolidis Date: Sun, 18 May 2025 19:45:21 +0100 Subject: [PATCH] Add outline Signed-off-by: Nikolaos Karaolidis --- flake.nix | 6 +- .../console/podman/authelia/default.nix | 1 + .../storm/configs/console/podman/default.nix | 1 + .../console/podman/outline/default.nix | 161 ++++++++++++++++++ packages/default.nix | 1 + packages/docker/base/default.nix | 4 + packages/docker/outline/default.nix | 25 +++ packages/docker/sish/default.nix | 15 +- 8 files changed, 204 insertions(+), 10 deletions(-) create mode 100644 hosts/jupiter/users/storm/configs/console/podman/outline/default.nix create mode 100644 packages/docker/outline/default.nix diff --git a/flake.nix b/flake.nix index c99099e..a7cdf36 100644 --- a/flake.nix +++ b/flake.nix @@ -171,7 +171,11 @@ // inputs.flake-utils.lib.eachSystem [ "x86_64-linux" ] ( system: let - pkgs = nixpkgs.legacyPackages.${system}; + pkgs = import nixpkgs { + inherit system; + config.allowUnfree = true; + }; + treefmt = inputs.treefmt-nix.lib.evalModule pkgs ./treefmt.nix; in { diff --git a/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix b/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix index 1f607e3..e3916ea 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix @@ -129,6 +129,7 @@ in groups = [ "admins" "git" + "docs" ]; }; } diff --git a/hosts/jupiter/users/storm/configs/console/podman/default.nix b/hosts/jupiter/users/storm/configs/console/podman/default.nix index 7bf6bc3..8065bba 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/default.nix @@ -12,6 +12,7 @@ in (import ./gitea { inherit user home; }) (import ./grafana { inherit user home; }) (import ./ntfy { inherit user home; }) + (import ./outline { inherit user home; }) (import ./prometheus { inherit user home; }) (import ./sish { inherit user home; }) (import ./traefik { inherit user home; }) diff --git a/hosts/jupiter/users/storm/configs/console/podman/outline/default.nix b/hosts/jupiter/users/storm/configs/console/podman/outline/default.nix new file mode 100644 index 0000000..b92fe49 --- /dev/null +++ b/hosts/jupiter/users/storm/configs/console/podman/outline/default.nix @@ -0,0 +1,161 @@ +{ + user ? throw "user argument is required", + home ? throw "home argument is required", +}: +{ + config, + inputs, + pkgs, + system, + ... +}: +let + selfPkgs = inputs.self.packages.${system}; + hmConfig = config.home-manager.users.${user}; + inherit (hmConfig.virtualisation.quadlet) volumes networks; + autheliaClientId = "3U5O3TkoIFb3bz3MMqscGEDx2wkT2G48iLLJalqSKA40zCweSBfgORGNMjDEidz4qiQ93qIoW2UlgTyLfzAwbklTvwHJPcarmXaq"; +in +{ + home-manager.users.${user} = { + sops = { + secrets = { + "outline/postgresql".sopsFile = ../../../../../../secrets/secrets.yaml; + "outline/secretKey".sopsFile = ../../../../../../secrets/secrets.yaml; + "outline/utilsSecret".sopsFile = ../../../../../../secrets/secrets.yaml; + "outline/authelia/password".sopsFile = ../../../../../../secrets/secrets.yaml; + "outline/authelia/digest".sopsFile = ../../../../../../secrets/secrets.yaml; + "outline/smtp".sopsFile = ../../../../../../secrets/secrets.yaml; + }; + + templates = { + outline-postgresql-env.content = '' + POSTGRES_PASSWORD=${hmConfig.sops.placeholder."outline/postgresql"} + ''; + + outline-env.content = '' + SECRET_KEY=${hmConfig.sops.placeholder."outline/secretKey"} + UTILS_SECRET=${hmConfig.sops.placeholder."outline/utilsSecret"} + DATABASE_URL=postgres://outline:${ + hmConfig.sops.placeholder."outline/postgresql" + }@outline-postgresql:5432/outline + OIDC_CLIENT_SECRET=${hmConfig.sops.placeholder."outline/authelia/password"} + SMTP_PASSWORD=${hmConfig.sops.placeholder."outline/smtp"} + ''; + + authelia-outline.content = builtins.readFile ( + (pkgs.formats.yaml { }).generate "outline.yaml" { + identity_providers.oidc = { + authorization_policies.docs = { + default_policy = "deny"; + rules = [ + { + policy = "one_factor"; + subject = "group:docs"; + } + ]; + }; + + clients = [ + { + client_id = autheliaClientId; + client_name = "Outline"; + client_secret = hmConfig.sops.placeholder."outline/authelia/digest"; + redirect_uris = [ "https://docs.karaolidis.com/auth/oidc.callback" ]; + authorization_policy = "docs"; + scopes = [ + "openid" + "profile" + "email" + "offline_access" + ]; + token_endpoint_auth_method = "client_secret_post"; + } + ]; + }; + } + ); + }; + }; + + virtualisation.quadlet = { + networks.outline.networkConfig.internal = true; + + volumes = { + outline-redis = { }; + outline-postgresql = { }; + outline = { }; + }; + + containers = { + outline = { + containerConfig = { + image = "docker-archive:${selfPkgs.docker-outline}"; + networks = [ + networks.outline.ref + networks.traefik.ref + ]; + volumes = [ + "${volumes.outline.ref}:/var/lib/outline/data" + ]; + environments = { + URL = "https://docs.karaolidis.com"; + PGSSLMODE = "disable"; + REDIS_URL = "redis://outline-redis:6379"; + FILE_STORAGE = "local"; + FILE_STORAGE_UPLOAD_MAX_SIZE = "1048576000"; + FORCE_HTTPS = "false"; + OIDC_CLIENT_ID = autheliaClientId; + OIDC_AUTH_URI = "https://id.karaolidis.com/api/oidc/authorization"; + OIDC_TOKEN_URI = "https://id.karaolidis.com/api/oidc/token"; + OIDC_USERINFO_URI = "https://id.karaolidis.com/api/oidc/userinfo"; + OIDC_LOGOUT_URI = "https://id.karaolidis.com/logout"; + OIDC_DISPLAY_NAME = "Authelia"; + OIDC_SCOPES = "openid profile email offline_access"; + OIDC_DISABLE_REDIRECT = "true"; + SMTP_HOST = "smtp.protonmail.ch"; + SMTP_PORT = "587"; + SMTP_USERNAME = "jupiter@karaolidis.com"; + SMTP_FROM_EMAIL = "jupiter@karaolidis.com"; + SMTP_SECURE = "false"; + ENABLE_UPDATES = "false"; + DEBUG = ""; + }; + environmentFiles = [ hmConfig.sops.templates.outline-env.path ]; + labels = [ + "traefik.enable=true" + "traefik.http.routers.outline.rule=Host(`docs.karaolidis.com`)" + ]; + }; + + unitConfig.After = [ "sops-nix.service" ]; + }; + + outline-postgresql = { + containerConfig = { + image = "docker-archive:${selfPkgs.docker-postgresql}"; + networks = [ networks.outline.ref ]; + volumes = [ "${volumes.outline-postgresql.ref}:/var/lib/postgresql/data" ]; + environments = { + POSTGRES_DB = "outline"; + POSTGRES_USER = "outline"; + }; + environmentFiles = [ hmConfig.sops.templates.outline-postgresql-env.path ]; + }; + + unitConfig.After = [ "sops-nix.service" ]; + }; + + outline-redis.containerConfig = { + image = "docker-archive:${selfPkgs.docker-redis}"; + networks = [ networks.outline.ref ]; + volumes = [ "${volumes.outline-redis.ref}:/var/lib/redis" ]; + exec = [ "--save 60 1" ]; + }; + + authelia-init.containerConfig.volumes = [ + "${hmConfig.sops.templates.authelia-outline.path}:/etc/authelia/conf.d/outline.yaml:ro" + ]; + }; + }; + }; +} diff --git a/packages/default.nix b/packages/default.nix index 9166063..f0af9b0 100644 --- a/packages/default.nix +++ b/packages/default.nix @@ -15,6 +15,7 @@ docker-grafana = import ./docker/grafana { inherit pkgs; }; docker-grafana-image-renderer = import ./docker/grafana-image-renderer { inherit pkgs; }; docker-ntfy = import ./docker/ntfy { inherit pkgs; }; + docker-outline = import ./docker/outline { inherit pkgs; }; docker-postgresql = import ./docker/postgresql { inherit pkgs; }; docker-prometheus = import ./docker/prometheus { inherit pkgs; }; docker-prometheus-fail2ban-exporter = import ./docker/prometheus-fail2ban-exporter { diff --git a/packages/docker/base/default.nix b/packages/docker/base/default.nix index 74034f5..589d9d4 100644 --- a/packages/docker/base/default.nix +++ b/packages/docker/base/default.nix @@ -22,4 +22,8 @@ pkgs.dockerTools.buildImage { "/usr" ]; }; + + runAsRoot = '' + mkdir -p /tmp + ''; } diff --git a/packages/docker/outline/default.nix b/packages/docker/outline/default.nix new file mode 100644 index 0000000..5275d7a --- /dev/null +++ b/packages/docker/outline/default.nix @@ -0,0 +1,25 @@ +{ pkgs, ... }: +pkgs.dockerTools.buildImage { + name = "outline"; + fromImage = import ../base { inherit pkgs; }; + + copyToRoot = pkgs.buildEnv { + name = "root"; + paths = with pkgs; [ outline ]; + pathsToLink = [ + "/bin" + "/share" + ]; + }; + + config = { + Entrypoint = [ "/bin/outline-server" ]; + ExposedPorts = { + "3000/tcp" = { }; + }; + Volumes = { + "/var/lib/outline/data" = { }; + }; + WorkingDir = "${pkgs.outline}/share/outline"; + }; +} diff --git a/packages/docker/sish/default.nix b/packages/docker/sish/default.nix index 77ba346..74e2a8c 100644 --- a/packages/docker/sish/default.nix +++ b/packages/docker/sish/default.nix @@ -1,22 +1,19 @@ { pkgs, ... }: +let + sish = pkgs.sish.overrideAttrs (oldAttrs: { + patches = oldAttrs.patches or [ ] ++ [ ./proxy-ssl-termination.patch ]; + }); +in pkgs.dockerTools.buildImage { name = "sish"; fromImage = import ../base { inherit pkgs; }; copyToRoot = pkgs.buildEnv { name = "root"; - paths = with pkgs; [ - (sish.overrideAttrs (oldAttrs: { - patches = oldAttrs.patches or [ ] ++ [ ./proxy-ssl-termination.patch ]; - })) - ]; + paths = [ sish ]; pathsToLink = [ "/bin" ]; }; - runAsRoot = '' - mkdir -p /tmp - ''; - config = { Entrypoint = [ "/bin/sish" ]; Cmd = [