blob: b05e05c5ac3e08a12ff38f5d679898d4764076b8 (
plain) (
tree)
|
|
{
inputs = {
flake-utils.url = "github:numtide/flake-utils";
rust = {
type = "github";
owner = "oxalica";
repo = "rust-overlay";
ref = "master";
inputs.flake-utils.follows = "flake-utils";
inputs.nixpkgs.follows = "nixpkgs";
};
naersk = {
type = "github";
owner = "nmattia";
repo = "naersk";
ref = "master";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, rust, flake-utils, naersk }: let
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 official 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.";
};
redisUri = mkOption {
type = types.nullOr types.str;
default = null;
example = "redis://192.168.1.200:6379/";
description = "Set the Redis instance used as backing storage. If null, Redis will be configured on localhost. Use services.redis to change parameters.";
};
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.";
};
};
};
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.redisUri cfg.tokenEndpoint
cfg.authorizationEndpoint
cfg.bind cfg.port
];
environment = {
SERVE_AT = "${cfg.bind}:${builtins.toString cfg.port}";
AUTHORIZATION_ENDPOINT = cfg.authorizationEndpoint;
TOKEN_ENDPOINT = cfg.tokenEndpoint;
REDIS_URI = if (cfg.redisUri == null) then "redis://127.0.0.1:6379/" else cfg.redisUri;
};
serviceConfig = {
ExecStart = "${cfg.package}/bin/kittybox";
DynamicUser = true;
};
};
services.redis = lib.mkIf (cfg.redisUri == null) {
enable = true;
};
};
};
} // forAllSystems (system: let
pkgs = import nixpkgs {
localSystem.system = system;
overlays = [ rust.overlay ];
};
rust-bin = pkgs.rust-bin.stable.latest;
packages = {
kittybox = { stdenv, lib, redis, naersk-lib }:
naersk-lib.buildPackage {
pname = "kittybox";
version = "0.1.0";
src = ./.;
checkInputs = [ redis ];
doCheck = stdenv.hostPlatform == stdenv.targetPlatform;
meta = with lib.meta; {
maintainers = with maintainers; [ vika_nezrimaya ];
platforms = supportedSystems;
mainProgram = "kittybox";
};
};
};
in {
packages = let
naersk-lib = naersk.lib.${system}.override {
rustc = pkgs.rust-bin.nightly.latest.minimal;
cargo = pkgs.rust-bin.nightly.latest.minimal;
};
in {
kittybox = pkgs.callPackage packages.kittybox { inherit naersk-lib; };
};
defaultPackage = self.packages.${system}.kittybox;
checks = {
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";
};
environment.systemPackages = with pkgs; [
curl
];
};
};
testScript = ''
kittybox.start()
kittybox.wait_for_unit("default.target")
kittybox.succeed("curl --silent http://localhost:8080/micropub")
'';
});
};
devShell = pkgs.mkShell {
name = "rust-dev-shell";
nativeBuildInputs = with pkgs; [
pkg-config lld
rust-bin.default
rust-bin.rls
redis
];
};
});
}
|