Outline: Difference between revisions

From NixOS Wiki
imported>Sleepful
No edit summary
imported>Sleepful
using staticpasswords instead
Line 84: Line 84:
== Setup with Nginx ==
== Setup with Nginx ==


Similar as before but this time with Nginx handling SSL
Similar as before but this time with Nginx handling SSL. We are also going to use a better way of adding static passwords in our configuration. Previous example used the <code>mockPassword</code> connector, which is [https://github.com/dexidp/dex/blob/8e07edc188222fed79a6db7c8e3e57e6d8e82df7/server/server.go#L566 an undocumented configuration option] in Dex, used solely to [https://github.com/dexidp/dex/blob/8e07edc188222fed79a6db7c8e3e57e6d8e82df7/server/handlers_test.go#L250 run some tests]. In the following example the [https://dexidp.io/docs/connectors/local/ staticPasswords] configuration is used instead, this allows using a hash for the password instead of clear text. This also allows setting a real email to the users which can be used to send notifications if an SMTP server is configured (e.g. <code>AWS SES, Postmark, Sendgrid</code>) through [https://search.nixos.org/options?channel=23.11&from=0&size=50&sort=relevance&type=packages&query=services.outline.smtp services.outline.smtp].
 
Keep in mind, if you created your first user with the previous method (mockPassword), that user is your only <code>admin</code> user and you need to keep it around in order to confer <code>admin</code> privileges to the next user.


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
Line 120: Line 122:
     enable = true;
     enable = true;
     publicUrl = "https://outline.example.tld";
     publicUrl = "https://outline.example.tld";
     port = 3003; # using 3003 instead of default 3000
     port = 3003; # using 3003 instead of default 3000 just in case another service is already using 3000
     forceHttps = false;
     forceHttps = false;
     storage.storageType = "local";
     storage.storageType = "local";
Line 149: Line 151:
         }
         }
       ];
       ];
       connectors = [
       staticPasswords = [
         {
         {
           type = "mockPassword";
           email = "user.email@example.com";
           id = "mock";
           # bcrypt hash of the string "password": $(echo password | htpasswd -BinC 10 admin | cut -d: -f2)
           name = "Test";
           hash = "10$TDh68T5XUK10$TDh68T5XUK10$TDh68T5XUK";
           config = {
           username = "test";
            # this is the dex user/pass combo to log into outline
          # easily generated with `$ uuidgen`
            username = "testuser";
          userID = "6D196B03-8A28-4D6E-B849-9298168CBA34";
            password = "pass123";
          };
         }
         }
       ];  
       ];
     };
     };
   };
   };
Line 169: Line 169:
== Reminder ==
== Reminder ==


If you see an error that says something like `option "services.outline.storage.storageType" does not exist"` you may need to update your channels (`nix-channel --update`)
If you see an error that says something like <code>option "services.outline.storage.storageType" does not exist"</code> you may need to update your channels (<code>nix-channel --update</code>)


== See also ==
== See also ==

Revision as of 09:49, 30 January 2024

Outline is a modern web based wiki and knowledge base for teams.

Setup

The most minimal local installation of Outline can be enabled with the following configuration

/etc/nixos/configuration.nix
{ config, pkgs, lib, ... }: {

networking.extraHosts = ''
  127.0.0.1 dex.localhost
'';

services = {

  outline = {
    enable = true;
    publicUrl = "http://localhost:3000";
    forceHttps = false;
    storage.storageType = "local";
    oidcAuthentication = {
      # Parts taken from
      # http://dex.localhost/.well-known/openid-configuration
      authUrl = "http://dex.localhost/auth";
      tokenUrl = "http://dex.localhost/token";
      userinfoUrl = "http://dex.localhost/userinfo";
      clientId = "outline";
      clientSecretFile = (builtins.elemAt config.services.dex.settings.staticClients 0).secretFile;
      scopes = [ "openid" "email" "profile" ];
      usernameClaim = "preferred_username";
      displayName = "Dex";
    };
  };

  dex = {
    enable = true;
    settings = {
      issuer = "http://dex.localhost";
      storage.type = "sqlite3";
      web.http = "127.0.0.1:5556";
      staticClients = [
        {
          id = "outline";
          name = "Outline Client";
          redirectURIs = [ "http://localhost:3000/auth/oidc.callback" ];
          secretFile = "${pkgs.writeText "outline-oidc-secret" "test123"}";
        }
      ];
      connectors = [
        {
          type = "mockPassword";
          id = "mock";
          name = "Example";
          config = {
            username = "admin";
            password = "password";
          };
        }
      ]; 
    };
  };

  nginx = {
    enable = true;
    virtualHosts = {
      "localhost" = {
        locations."/" = {
          proxyPass = "${config.services.outline.publicUrl}";
        };
      };
      "dex.localhost" = {
        locations."/" = {
          proxyPass = "http://${config.services.dex.settings.web.http}";
        };
      };
    };
  };

};

Outline is available at http://localhost . Choose login provider "Dex" and authenticate with the example mock login admin and password.

Setup with Nginx

Similar as before but this time with Nginx handling SSL. We are also going to use a better way of adding static passwords in our configuration. Previous example used the mockPassword connector, which is an undocumented configuration option in Dex, used solely to run some tests. In the following example the staticPasswords configuration is used instead, this allows using a hash for the password instead of clear text. This also allows setting a real email to the users which can be used to send notifications if an SMTP server is configured (e.g. AWS SES, Postmark, Sendgrid) through services.outline.smtp.

Keep in mind, if you created your first user with the previous method (mockPassword), that user is your only admin user and you need to keep it around in order to confer admin privileges to the next user.

/etc/nixos/configuration.nix
{ config, pkgs, lib, ... }: {

  services.nginx = {
    enable = true;
    recommendedProxySettings = true;
    recommendedTlsSettings = true;
    virtualHosts = {
      "outline.example.tld" = {
        onlySSL = true;
        useACMEHost = "example.tld"; # assuming security.acme.certs."example.tld" with `extraDomainNames = [ "outline.example.tld" ]`
        locations."/" = {
          proxyPass = "http://localhost:${toString config.services.outline.port}";
          proxyWebsockets = true;
          extraConfig = ''
                proxy_set_header X-Scheme $scheme;
          '';
        };
      };
      "dex.example.tld" = {
        onlySSL = true;
        useACMEHost = "example.tld";
        locations."/" = {
          proxyPass = "http://${config.services.dex.settings.web.http}";
          proxyWebsockets = true;
        };
      };
    };
  };


  services.outline = {
    enable = true;
    publicUrl = "https://outline.example.tld";
    port = 3003; # using 3003 instead of default 3000 just in case another service is already using 3000
    forceHttps = false;
    storage.storageType = "local";
    oidcAuthentication = {
      authUrl = "https://dex.example.tld/auth";
      tokenUrl = "https://dex.example.tld/token";
      userinfoUrl = "https://dex.example.tld/userinfo";
      clientId = "outline";
      clientSecretFile = (builtins.elemAt config.services.dex.settings.staticClients 0).secretFile;
      scopes = [ "openid" "email" "profile" ];
      usernameClaim = "preferred_username";
      displayName = "Dex";
    };
  };

  services.dex = {
    enable = true;
    settings = {
      issuer = "https://dex.example.tld";
      storage.type = "sqlite3";
      web.http = "127.0.0.1:5556";
      staticClients = [
        {
          id = "outline";
          name = "Outline Client";
          redirectURIs = [ "https://outline.example.tld/auth/oidc.callback" ];
          secretFile = "${pkgs.writeText "outline-oidc-secret" "test123"}";
        }
      ];
      staticPasswords = [
        {
          email = "user.email@example.com";
          # bcrypt hash of the string "password": $(echo password | htpasswd -BinC 10 admin | cut -d: -f2)
          hash = "10$TDh68T5XUK10$TDh68T5XUK10$TDh68T5XUK";
          username = "test";
          # easily generated with `$ uuidgen`
          userID = "6D196B03-8A28-4D6E-B849-9298168CBA34";
        }
      ];
    };
  };

Reminder

If you see an error that says something like option "services.outline.storage.storageType" does not exist" you may need to update your channels (nix-channel --update)

See also

  • Mediawiki, PHP- and web-based wiki software.
  • Dokuwiki, simple PHP- and web-based wiki software which uses file based storage for its content.