diff options
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | configuration.nix | 158 | ||||
-rw-r--r-- | distributed-test.nix | 2 | ||||
-rw-r--r-- | docker.nix | 43 | ||||
-rw-r--r-- | flake.nix | 279 | ||||
-rwxr-xr-x | fonts/update.sh | 8 | ||||
-rw-r--r-- | kittybox-rs/Cargo.lock (renamed from Cargo.lock) | 0 | ||||
-rw-r--r-- | kittybox-rs/Cargo.toml (renamed from Cargo.toml) | 0 | ||||
-rwxr-xr-x | kittybox-rs/dev.sh (renamed from dev.sh) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/bin/kittybox_bulk_import.rs (renamed from src/bin/kittybox_bulk_import.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/bin/kittybox_database_converter.rs (renamed from src/bin/kittybox_database_converter.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/bin/pyindieblog_to_kittybox.rs (renamed from src/bin/pyindieblog_to_kittybox.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/database/file/mod.rs (renamed from src/database/file/mod.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/database/memory.rs (renamed from src/database/memory.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/database/mod.rs (renamed from src/database/mod.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/database/redis/edit_post.lua (renamed from src/database/redis/edit_post.lua) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/database/redis/mod.rs (renamed from src/database/redis/mod.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/frontend/login.rs (renamed from src/frontend/login.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/frontend/mod.rs (renamed from src/frontend/mod.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/frontend/onboarding.css (renamed from src/frontend/onboarding.css) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/frontend/onboarding.js (renamed from src/frontend/onboarding.js) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/frontend/style.css (renamed from src/frontend/style.css) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/index.html (renamed from src/index.html) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/indieauth.rs (renamed from src/indieauth.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/lib.rs (renamed from src/lib.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/main.rs (renamed from src/main.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/media/mod.rs (renamed from src/media/mod.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/metrics.rs (renamed from src/metrics.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/micropub/get.rs (renamed from src/micropub/get.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/micropub/mod.rs (renamed from src/micropub/mod.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/src/micropub/post.rs (renamed from src/micropub/post.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/templates/Cargo.toml (renamed from templates/Cargo.toml) | 0 | ||||
-rw-r--r-- | kittybox-rs/templates/src/lib.rs (renamed from templates/src/lib.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/templates/src/login.rs (renamed from templates/src/login.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/templates/src/onboarding.rs (renamed from templates/src/onboarding.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/templates/src/templates.rs (renamed from templates/src/templates.rs) | 0 | ||||
-rw-r--r-- | kittybox-rs/util/Cargo.toml (renamed from util/Cargo.toml) | 0 | ||||
-rw-r--r-- | kittybox-rs/util/src/lib.rs (renamed from util/src/lib.rs) | 0 | ||||
-rw-r--r-- | kittybox.nix | 19 | ||||
-rw-r--r-- | smoke-test.nix | 36 |
41 files changed, 275 insertions, 281 deletions
diff --git a/.gitignore b/.gitignore index 8b721e8..71a754a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/target +/kittybox-rs/target .direnv /result-* /result @@ -8,6 +8,6 @@ dump.rdb .\#* .*~ *~ -/test-dir -fonts/* +/kittybox-rs/test-dir +/kittybox-rs/fonts/* /token.txt diff --git a/README.md b/README.md index be18318..b756805 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ any C libraries for building, preferring to use their Rust equivalents for memory safety and ease of building. ```console +$ cd ./kittybox-rs/ $ cargo build ``` @@ -66,10 +67,10 @@ $ cargo check { config, pkgs, lib, ...}: let # Included as an example. You should probably use `flake.nix` instead. # You will get version pinning and you will probably be happier. - kittybox-flake = (builtins.getFlake "git+https://git.sr.ht/~vikanezrimaya/kittybox?ref=main"); + kittybox = (builtins.getFlake "git+https://git.sr.ht/~vikanezrimaya/kittybox?ref=main"); in { imports = [ - kittybox-flake.nixosModule + kittybox.nixosModules.default ]; services.kittybox = { diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..411b7b2 --- /dev/null +++ b/configuration.nix @@ -0,0 +1,158 @@ +kittybox: +{ config, pkgs, lib, ... }: +with lib; +let + cfg = config.services.kittybox; +in { + options = { + services.kittybox = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable Kittybox, the IndieWeb blogging solution. + ''; + }; + package = mkOption { + type = types.package; + default = kittybox.packages.${config.nixpkgs.localSystem.system}.kittybox; + defaultText = "<kittybox package from the upstream flake>"; + description = "Which Kittybox derivation to use."; + }; + + bind = mkOption { + type = types.nullOr types.str; + default = "127.0.0.1"; + description = "The host for Kittybox to bind to."; + example = "192.168.1.100"; + }; + port = mkOption { + type = types.int; + default = 8080; + description = "The port for Kittybox to listen at."; + example = 16420; + }; + logLevel = mkOption { + type = types.str; + default = "warn"; + example = "info"; + description = "Specify the server verbosity level. Uses RUST_LOG environment variable internally."; + }; + backendUri = mkOption { + type = types.str; + default = "file:///var/lib/kittybox/data"; + example = "redis://192.168.1.200:6379"; + description = '' + Set the backend used for storing data. Available backends are: + - file:// - static folder backend (recommended) + - redis:// - Redis backend + + Make sure that if you are using the file backend, the state + directory is accessible by Kittybox. By default, the unit config + uses DynamicUser=true, which prevents the unit from accessing + data outside of its directory. It is recommended to use a + bind-mount to /var/lib/private/kittybox if you require the state + directory to reside elsewhere. + ''; + }; + tokenEndpoint = mkOption { + type = types.str; + example = "https://tokens.indieauth.com/token"; + description = "Token endpoint to use for authenticating Micropub requests. Use the example if you are unsure."; + }; + authorizationEndpoint = mkOption { + type = types.str; + example = "https://indieauth.com/auth"; + description = "Authorization endpoint to use to authenticate the user. You can use the default if you are unsure."; + }; + mediaEndpoint = mkOption { + type = types.nullOr types.str; + default = null; + description = "The URL of a media endpoint to announce when asked by a Micropub client. Strongly recommended if you plan to upload images."; + }; + microsubServer = mkOption { + type = types.nullOr types.str; + default = null; + example = "https://aperture.p3k.io/microsub/69420"; + description = '' + The URL of your Microsub server, which saves feeds for you + and allows you to browse Web content from one place. Try + https://aperture.p3k.io/ if you don't have one yet! + ''; + }; + webmentionEndpoint = mkOption { + type = types.nullOr types.str; + default = null; + example = "https://webmention.io/example.com/webmention"; + description = '' + The URL of your webmention endpoint, which allows you to + receive notifications about your site's content being featured + or interacted with elsewhere on the IndieWeb. + + By default Kittybox expects the Webmention endpoint to post + updates using an internal token. kittybox-webmention is an + endpoint capable of that. + ''; + }; + internalTokenFile = mkOption { + type = types.nullOr types.str; + default = null; + example = "/run/secrets/kittybox-shared-secret"; + description = "A shared secret that will, when passed, allow unlimited editing access to database. Keep it safe."; + }; + cookieSecretFile = mkOption { + type = types.str; + default = "/var/lib/kittybox/cookie_secret_key"; + example = "/run/secrets/kittybox-cookie-secret"; + description = "A secret file to encrypt cookies with the contents of. Should be at least 32 bytes in length. A random persistent file will be generated if this variable is left untouched."; + }; + }; + }; + config = lib.mkIf cfg.enable { + systemd.services.kittybox = { + description = "An IndieWeb-enabled blog engine"; + + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + restartTriggers = [ + cfg.package + cfg.backendUri cfg.tokenEndpoint + cfg.authorizationEndpoint + cfg.internalTokenFile + cfg.bind cfg.port + cfg.cookieSecretFile + ]; + + environment = { + SERVE_AT = "${cfg.bind}:${builtins.toString cfg.port}"; + AUTHORIZATION_ENDPOINT = cfg.authorizationEndpoint; + TOKEN_ENDPOINT = cfg.tokenEndpoint; + MEDIA_ENDPOINT = cfg.mediaEndpoint; + MICROSUB_ENDPOINT = cfg.microsubServer; + WEBMENTION_ENDPOINT = cfg.webmentionEndpoint; + #REDIS_URI = if (cfg.redisUri == null) then "redis://127.0.0.1:6379/" else cfg.redisUri; + BACKEND_URI = cfg.backendUri; + RUST_LOG = "${cfg.logLevel}"; + COOKIE_SECRET_FILE = "${cfg.cookieSecretFile}"; + }; + + script = '' + ${lib.optionalString (cfg.internalTokenFile != null) '' + if [[ -f ${cfg.internalTokenFile} ]]; then + export KITTYBOX_INTERNAL_TOKEN=$(${pkgs.coreutils}/bin/cat ${cfg.internalTokenFile}) + fi + ''} + if [[ ${cfg.cookieSecretFile} == /var/lib/kittybox/cookie_secret_key && ! -f /var/lib/kittybox/cookie_secret_key ]]; then + cat /dev/urandom | tr -Cd '[:alnum:]' | head -c 128 > /var/lib/kittybox/cookie_secret_key + fi + exec ${cfg.package}/bin/kittybox + ''; + + serviceConfig = { + DynamicUser = true; + StateDirectory = "kittybox"; + }; + }; + }; +} diff --git a/distributed-test.nix b/distributed-test.nix index 9b62542..539bd0c 100644 --- a/distributed-test.nix +++ b/distributed-test.nix @@ -3,7 +3,7 @@ kittybox: { lib, system, ... }: let kittyboxModule = { config, pkgs, lib, ... }: { - imports = [ kittybox.nixosModule commonModule ]; + imports = [ kittybox.nixosModules.default commonModule ]; services.kittybox = { enable = true; diff --git a/docker.nix b/docker.nix new file mode 100644 index 0000000..2ac09b6 --- /dev/null +++ b/docker.nix @@ -0,0 +1,43 @@ +{ kittybox, dockerTools, runtimeShell, rev ? "development", lastModifiedDate }: +dockerTools.buildImage { + name = "kittybox"; + tag = rev; + created = let + date = lastModifiedDate; + in builtins.concatStringsSep "" [ + (builtins.substring 0 4 date) + "-" + (builtins.substring 4 2 date) + "-" + (builtins.substring 6 2 date) + "T" + (builtins.substring 8 2 date) + ":" + (builtins.substring 10 2 date) + ":" + (builtins.substring 12 2 date) + "Z" + ]; + + runAsRoot = '' + #!${runtimeShell} + ${dockerTools.shadowSetup} + groupadd -r kittybox + useradd -r -g kittybox kittybox + mkdir -p /data + chown kittybox:kittybox /data + ''; + + config = { + Cmd = [ "${kittybox}/bin/kittybox" ]; + Env = [ + "SERVE_AT=0.0.0.0:8080" + "BACKEND_URI=file:///data" + "RUST_LOG=info" + ]; + WorkingDir = "/data"; + Volumes = { "/data" = {}; }; + User = "kittybox"; + ExposedPorts = { "8080" = {}; }; + }; +} diff --git a/flake.nix b/flake.nix index 5eae2da..d437310 100644 --- a/flake.nix +++ b/flake.nix @@ -18,285 +18,30 @@ supportedSystems = ["aarch64-linux" "x86_64-linux"]; forAllSystems = f: flake-utils.lib.eachSystem supportedSystems f; in { - nixosModule = { config, pkgs, lib, ... }: with lib; let - cfg = config.services.kittybox; - in { - options = { - services.kittybox = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable Kittybox, the IndieWeb blogging solution. - ''; - }; - package = mkOption { - type = types.package; - default = self.packages.${config.nixpkgs.localSystem.system}.kittybox; - defaultText = "<kittybox package from the upstream flake>"; - description = "Which Kittybox derivation to use."; - }; - - bind = mkOption { - type = types.nullOr types.str; - default = "127.0.0.1"; - description = "The host for Kittybox to bind to."; - example = "192.168.1.100"; - }; - port = mkOption { - type = types.int; - default = 8080; - description = "The port for Kittybox to listen at."; - example = 16420; - }; - logLevel = mkOption { - type = types.str; - default = "warn"; - example = "info"; - description = "Specify the server verbosity level. Uses RUST_LOG environment variable internally."; - }; - backendUri = mkOption { - type = types.str; - default = "file:///var/lib/kittybox/data"; - example = "redis://192.168.1.200:6379"; - description = '' - Set the backend used for storing data. Available backends are: - - file:// - static folder backend (recommended) - - redis:// - Redis backend - - Make sure that if you are using the file backend, the state - directory is accessible by Kittybox. By default, the unit config - uses DynamicUser=true, which prevents the unit from accessing - data outside of its directory. It is recommended to use a - bind-mount to /var/lib/private/kittybox if you require the state - directory to reside elsewhere. - ''; - }; - tokenEndpoint = mkOption { - type = types.str; - example = "https://tokens.indieauth.com/token"; - description = "Token endpoint to use for authenticating Micropub requests. Use the example if you are unsure."; - }; - authorizationEndpoint = mkOption { - type = types.str; - example = "https://indieauth.com/auth"; - description = "Authorization endpoint to use to authenticate the user. You can use the default if you are unsure."; - }; - mediaEndpoint = mkOption { - type = types.nullOr types.str; - default = null; - description = "The URL of a media endpoint to announce when asked by a Micropub client. Strongly recommended if you plan to upload images."; - }; - microsubServer = mkOption { - type = types.nullOr types.str; - default = null; - example = "https://aperture.p3k.io/microsub/69420"; - description = '' - The URL of your Microsub server, which saves feeds for you - and allows you to browse Web content from one place. Try - https://aperture.p3k.io/ if you don't have one yet! - ''; - }; - webmentionEndpoint = mkOption { - type = types.nullOr types.str; - default = null; - example = "https://webmention.io/example.com/webmention"; - description = '' - The URL of your webmention endpoint, which allows you to - receive notifications about your site's content being featured - or interacted with elsewhere on the IndieWeb. - - By default Kittybox expects the Webmention endpoint to post - updates using an internal token. kittybox-webmention is an - endpoint capable of that. - ''; - }; - internalTokenFile = mkOption { - type = types.nullOr types.str; - default = null; - example = "/run/secrets/kittybox-shared-secret"; - description = "A shared secret that will, when passed, allow unlimited editing access to database. Keep it safe."; - }; - cookieSecretFile = mkOption { - type = types.str; - default = "/var/lib/kittybox/cookie_secret_key"; - example = "/run/secrets/kittybox-cookie-secret"; - description = "A secret file to encrypt cookies with the contents of. Should be at least 32 bytes in length. A random persistent file will be generated if this variable is left untouched."; - }; - }; - }; - config = lib.mkIf cfg.enable { - systemd.services.kittybox = { - description = "An IndieWeb-enabled blog engine"; - - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - restartTriggers = [ - cfg.package - cfg.backendUri cfg.tokenEndpoint - cfg.authorizationEndpoint - cfg.internalTokenFile - cfg.bind cfg.port - cfg.cookieSecretFile - ]; - - environment = { - SERVE_AT = "${cfg.bind}:${builtins.toString cfg.port}"; - AUTHORIZATION_ENDPOINT = cfg.authorizationEndpoint; - TOKEN_ENDPOINT = cfg.tokenEndpoint; - MEDIA_ENDPOINT = cfg.mediaEndpoint; - MICROSUB_ENDPOINT = cfg.microsubServer; - WEBMENTION_ENDPOINT = cfg.webmentionEndpoint; - #REDIS_URI = if (cfg.redisUri == null) then "redis://127.0.0.1:6379/" else cfg.redisUri; - BACKEND_URI = cfg.backendUri; - RUST_LOG = "${cfg.logLevel}"; - COOKIE_SECRET_FILE = "${cfg.cookieSecretFile}"; - }; - - script = '' - ${lib.optionalString (cfg.internalTokenFile != null) '' - if [[ -f ${cfg.internalTokenFile} ]]; then - export KITTYBOX_INTERNAL_TOKEN=$(${pkgs.coreutils}/bin/cat ${cfg.internalTokenFile}) - fi - ''} - if [[ ${cfg.cookieSecretFile} == /var/lib/kittybox/cookie_secret_key && ! -f /var/lib/kittybox/cookie_secret_key ]]; then - cat /dev/urandom | tr -Cd '[:alnum:]' | head -c 128 > /var/lib/kittybox/cookie_secret_key - fi - exec ${cfg.package}/bin/kittybox - ''; - - serviceConfig = { - DynamicUser = true; - StateDirectory = "kittybox"; - }; - }; - }; - }; + nixosModules.default = import ./configuration.nix self; } // forAllSystems (system: let pkgs = nixpkgs.legacyPackages.${system}; - packages = { - kittybox = { stdenv, lib, runCommandNoCC, openssl, zlib, pkg-config, protobuf, naersk-lib, lld, mold }: - naersk-lib.buildPackage { - pname = "kittybox"; - version = "0.1.0"; - - src = runCommandNoCC "kittybox-src" {} '' - mkdir -p $out - cp -r ${./Cargo.toml} $out/Cargo.toml - cp -r ${./Cargo.lock} $out/Cargo.lock - cp -r ${./src} $out/src - cp -r ${./templates} $out/templates - cp -r ${./util} $out/util - cp -r ${./fonts} $out/fonts - ''; - - checkInputs = [ openssl.dev zlib ]; - nativeBuildInputs = [ pkg-config protobuf ]; - nativeCheckInputs = [ pkg-config ]; - - doCheck = stdenv.hostPlatform == stdenv.targetPlatform; - - meta = with lib.meta; { - maintainers = with lib.maintainers; [ vikanezrimaya ]; - platforms = supportedSystems; - mainProgram = "kittybox"; - }; - }; + naersk-lib = naersk.lib.${system}.override { + inherit (pkgs) rustc cargo; }; in { - packages = let - naersk-lib = naersk.lib.${system}.override { - inherit (pkgs) rustc cargo; - }; - in { - kittybox = pkgs.callPackage packages.kittybox { inherit naersk-lib; }; + packages = { + kittybox = pkgs.callPackage ./kittybox.nix { inherit naersk-lib; }; + default = self.packages.${system}.kittybox; }; - defaultPackage = self.packages.${system}.kittybox; checks = { kittybox = self.packages.${system}.kittybox; distributed-test = pkgs.nixosTest (import ./distributed-test.nix self); - nixos-test = (pkgs.nixosTest ({ lib }: { - name = "nixos-kittybox"; - - nodes = { - kittybox = { config, pkgs, lib, ... }: { - imports = [ self.nixosModule ]; - - services.kittybox = { - enable = true; - # It never actually contacts those endpoints anyway unless we use Micropub so it's fine! - # TODO: Once we have self-hosted software for those endpoints, - # make an e2e test for common workflows (e.g. making a post) - tokenEndpoint = "https://example.com"; - authorizationEndpoint = "https://example.com"; - logLevel = "info,kittybox=debug,retainer::cache=warn,h2=warn,rustls=warn"; - }; - - environment.systemPackages = with pkgs; [ - curl - ]; - }; - }; - - testScript = '' - with subtest("Verify that Kittybox started correctly..."): - kittybox.wait_for_open_port(8080) - kittybox.succeed("curl --silent http://localhost:8080/micropub") - - with subtest("Onboarding should correctly work..."): - kittybox.copy_from_host("${./onboarding.json}", "/root/onboarding.json") - kittybox.succeed("curl -vvv http://localhost:8080/onboarding -d@/root/onboarding.json -H 'Content-Type: application/json'") - # Testing for a known string is the easiest way to determine that the onboarding worked - kittybox.succeed("curl --silent http://localhost:8080/ | grep 'vestige of the past long gone'") - ''; - })); - dockerContainer = pkgs.dockerTools.buildImage { - name = "kittybox"; - tag = self.rev or "development"; - created = let - date = self.lastModifiedDate; - in builtins.concatStringsSep "" [ - (builtins.substring 0 4 date) - "-" - (builtins.substring 4 2 date) - "-" - (builtins.substring 6 2 date) - "T" - (builtins.substring 8 2 date) - ":" - (builtins.substring 10 2 date) - ":" - (builtins.substring 12 2 date) - "Z" - ]; - - runAsRoot = '' - #!${pkgs.runtimeShell} - ${pkgs.dockerTools.shadowSetup} - groupadd -r kittybox - useradd -r -g kittybox kittybox - mkdir -p /data - chown kittybox:kittybox /data - ''; - - config = { - Cmd = [ "${self.packages.${system}.kittybox}/bin/kittybox" ]; - Env = [ - "SERVE_AT=0.0.0.0:8080" - "BACKEND_URI=file:///data" - "RUST_LOG=info" - ]; - WorkingDir = "/data"; - Volumes = { "/data" = {}; }; - User = "kittybox"; - ExposedPorts = { "8080" = {}; }; - }; + nixos-test = pkgs.nixosTest (import ./smoke-test.nix self); + dockerContainer = pkgs.callPackage ./docker.nix { + inherit (self.packages.${system}) kittybox; + rev = self.rev or "development"; + inherit (self) lastModifiedDate; }; }; - devShell = pkgs.mkShell { + devShells.default = pkgs.mkShell { name = "rust-dev-shell"; nativeBuildInputs = with pkgs; [ diff --git a/fonts/update.sh b/fonts/update.sh deleted file mode 100755 index 02dcbee..0000000 --- a/fonts/update.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -set -e -cd fonts -url='https://fonts.google.com/download?family=Lato|Caveat|Noto%20Color%20Emoji|Noto%20Colr%20Emoji%20Glyf' -tmp=$(mktemp) -curl "$url" > "$tmp" -unzip -uo "$tmp" -rm "$tmp" diff --git a/Cargo.lock b/kittybox-rs/Cargo.lock index 7b2bbef..7b2bbef 100644 --- a/Cargo.lock +++ b/kittybox-rs/Cargo.lock diff --git a/Cargo.toml b/kittybox-rs/Cargo.toml index d43f0f4..d43f0f4 100644 --- a/Cargo.toml +++ b/kittybox-rs/Cargo.toml diff --git a/dev.sh b/kittybox-rs/dev.sh index fa39dcc..fa39dcc 100755 --- a/dev.sh +++ b/kittybox-rs/dev.sh diff --git a/src/bin/kittybox_bulk_import.rs b/kittybox-rs/src/bin/kittybox_bulk_import.rs index 7e1f6af..7e1f6af 100644 --- a/src/bin/kittybox_bulk_import.rs +++ b/kittybox-rs/src/bin/kittybox_bulk_import.rs diff --git a/src/bin/kittybox_database_converter.rs b/kittybox-rs/src/bin/kittybox_database_converter.rs index bc355c9..bc355c9 100644 --- a/src/bin/kittybox_database_converter.rs +++ b/kittybox-rs/src/bin/kittybox_database_converter.rs diff --git a/src/bin/pyindieblog_to_kittybox.rs b/kittybox-rs/src/bin/pyindieblog_to_kittybox.rs index 38590c3..38590c3 100644 --- a/src/bin/pyindieblog_to_kittybox.rs +++ b/kittybox-rs/src/bin/pyindieblog_to_kittybox.rs diff --git a/src/database/file/mod.rs b/kittybox-rs/src/database/file/mod.rs index 1e7aa96..1e7aa96 100644 --- a/src/database/file/mod.rs +++ b/kittybox-rs/src/database/file/mod.rs diff --git a/src/database/memory.rs b/kittybox-rs/src/database/memory.rs index 786466c..786466c 100644 --- a/src/database/memory.rs +++ b/kittybox-rs/src/database/memory.rs diff --git a/src/database/mod.rs b/kittybox-rs/src/database/mod.rs index 6bf5409..6bf5409 100644 --- a/src/database/mod.rs +++ b/kittybox-rs/src/database/mod.rs diff --git a/src/database/redis/edit_post.lua b/kittybox-rs/src/database/redis/edit_post.lua index a398f8d..a398f8d 100644 --- a/src/database/redis/edit_post.lua +++ b/kittybox-rs/src/database/redis/edit_post.lua diff --git a/src/database/redis/mod.rs b/kittybox-rs/src/database/redis/mod.rs index eeaa3f2..eeaa3f2 100644 --- a/src/database/redis/mod.rs +++ b/kittybox-rs/src/database/redis/mod.rs diff --git a/src/frontend/login.rs b/kittybox-rs/src/frontend/login.rs index 9665ce7..9665ce7 100644 --- a/src/frontend/login.rs +++ b/kittybox-rs/src/frontend/login.rs diff --git a/src/frontend/mod.rs b/kittybox-rs/src/frontend/mod.rs index b87f9c6..b87f9c6 100644 --- a/src/frontend/mod.rs +++ b/kittybox-rs/src/frontend/mod.rs diff --git a/src/frontend/onboarding.css b/kittybox-rs/src/frontend/onboarding.css index 6f191b9..6f191b9 100644 --- a/src/frontend/onboarding.css +++ b/kittybox-rs/src/frontend/onboarding.css diff --git a/src/frontend/onboarding.js b/kittybox-rs/src/frontend/onboarding.js index 7f9aa32..7f9aa32 100644 --- a/src/frontend/onboarding.js +++ b/kittybox-rs/src/frontend/onboarding.js diff --git a/src/frontend/style.css b/kittybox-rs/src/frontend/style.css index 109bba0..109bba0 100644 --- a/src/frontend/style.css +++ b/kittybox-rs/src/frontend/style.css diff --git a/src/index.html b/kittybox-rs/src/index.html index 1fc2a96..1fc2a96 100644 --- a/src/index.html +++ b/kittybox-rs/src/index.html diff --git a/src/indieauth.rs b/kittybox-rs/src/indieauth.rs index 57c0301..57c0301 100644 --- a/src/indieauth.rs +++ b/kittybox-rs/src/indieauth.rs diff --git a/src/lib.rs b/kittybox-rs/src/lib.rs index 1800b5b..1800b5b 100644 --- a/src/lib.rs +++ b/kittybox-rs/src/lib.rs diff --git a/src/main.rs b/kittybox-rs/src/main.rs index eb70885..eb70885 100644 --- a/src/main.rs +++ b/kittybox-rs/src/main.rs diff --git a/src/media/mod.rs b/kittybox-rs/src/media/mod.rs index 0d46e0c..0d46e0c 100644 --- a/src/media/mod.rs +++ b/kittybox-rs/src/media/mod.rs diff --git a/src/metrics.rs b/kittybox-rs/src/metrics.rs index 48f5d9b..48f5d9b 100644 --- a/src/metrics.rs +++ b/kittybox-rs/src/metrics.rs diff --git a/src/micropub/get.rs b/kittybox-rs/src/micropub/get.rs index 718714a..718714a 100644 --- a/src/micropub/get.rs +++ b/kittybox-rs/src/micropub/get.rs diff --git a/src/micropub/mod.rs b/kittybox-rs/src/micropub/mod.rs index f426c77..f426c77 100644 --- a/src/micropub/mod.rs +++ b/kittybox-rs/src/micropub/mod.rs diff --git a/src/micropub/post.rs b/kittybox-rs/src/micropub/post.rs index cf9f3d9..cf9f3d9 100644 --- a/src/micropub/post.rs +++ b/kittybox-rs/src/micropub/post.rs diff --git a/templates/Cargo.toml b/kittybox-rs/templates/Cargo.toml index fe8ac19..fe8ac19 100644 --- a/templates/Cargo.toml +++ b/kittybox-rs/templates/Cargo.toml diff --git a/templates/src/lib.rs b/kittybox-rs/templates/src/lib.rs index 39f1075..39f1075 100644 --- a/templates/src/lib.rs +++ b/kittybox-rs/templates/src/lib.rs diff --git a/templates/src/login.rs b/kittybox-rs/templates/src/login.rs index 042c308..042c308 100644 --- a/templates/src/login.rs +++ b/kittybox-rs/templates/src/login.rs diff --git a/templates/src/onboarding.rs b/kittybox-rs/templates/src/onboarding.rs index 9d0f2e1..9d0f2e1 100644 --- a/templates/src/onboarding.rs +++ b/kittybox-rs/templates/src/onboarding.rs diff --git a/templates/src/templates.rs b/kittybox-rs/templates/src/templates.rs index 0054c91..0054c91 100644 --- a/templates/src/templates.rs +++ b/kittybox-rs/templates/src/templates.rs diff --git a/util/Cargo.toml b/kittybox-rs/util/Cargo.toml index 31c6bca..31c6bca 100644 --- a/util/Cargo.toml +++ b/kittybox-rs/util/Cargo.toml diff --git a/util/src/lib.rs b/kittybox-rs/util/src/lib.rs index bc41689..bc41689 100644 --- a/util/src/lib.rs +++ b/kittybox-rs/util/src/lib.rs diff --git a/kittybox.nix b/kittybox.nix new file mode 100644 index 0000000..f42884a --- /dev/null +++ b/kittybox.nix @@ -0,0 +1,19 @@ +{ stdenv, lib, openssl, zlib, pkg-config, protobuf, naersk-lib, lld, mold }: +naersk-lib.buildPackage { + pname = "kittybox"; + version = "0.1.0"; + + src = ./kittybox-rs; + + checkInputs = [ openssl.dev zlib ]; + nativeBuildInputs = [ pkg-config protobuf ]; + nativeCheckInputs = [ pkg-config ]; + + doCheck = stdenv.hostPlatform == stdenv.targetPlatform; + + meta = with lib.meta; { + maintainers = with lib.maintainers; [ vikanezrimaya ]; + platforms = ["aarch64-linux" "x86_64-linux"]; + mainProgram = "kittybox"; + }; +} diff --git a/smoke-test.nix b/smoke-test.nix new file mode 100644 index 0000000..fbbc8a7 --- /dev/null +++ b/smoke-test.nix @@ -0,0 +1,36 @@ +kittybox: +{ lib, ... }: { + name = "nixos-kittybox"; + + nodes = { + kittybox = { config, pkgs, lib, ... }: { + imports = [ kittybox.nixosModules.default ]; + + services.kittybox = { + enable = true; + # It never actually contacts those endpoints anyway unless we use Micropub so it's fine! + # TODO: Once we have self-hosted software for those endpoints, + # make an e2e test for common workflows (e.g. making a post) + tokenEndpoint = "https://example.com"; + authorizationEndpoint = "https://example.com"; + logLevel = "info,kittybox=debug,retainer::cache=warn,h2=warn,rustls=warn"; + }; + + environment.systemPackages = with pkgs; [ + curl + ]; + }; + }; + + testScript = '' + with subtest("Verify that Kittybox started correctly..."): + kittybox.wait_for_open_port(8080) + kittybox.succeed("curl --silent http://localhost:8080/micropub") + + with subtest("Onboarding should correctly work..."): + kittybox.copy_from_host("${./onboarding.json}", "/root/onboarding.json") + kittybox.succeed("curl -vvv http://localhost:8080/onboarding -d@/root/onboarding.json -H 'Content-Type: application/json'") + # Testing for a known string is the easiest way to determine that the onboarding worked + kittybox.succeed("curl --silent http://localhost:8080/ | grep 'vestige of the past long gone'") +''; +} |