{ description = "Automoderation web app"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; inputs.nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-23.05"; inputs.flake-utils.url = "github:numtide/flake-utils"; outputs = { self, nixpkgs, flake-utils, nixpkgs-stable }: flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; pkgs-stable = nixpkgs-stable.legacyPackages.${system}; pname = "some-automoderation"; version = "0.0.1"; in rec { devShells.default = pkgs.mkShell { buildInputs = [ pkgs.go pkgs-stable.wgo pkgs.semgrep pkgs.gopls pkgs.nodePackages.tailwindcss pkgs.nodePackages.prettier pkgs.gnumake pkgs.redis pkgs.prometheus pkgs.grafana ]; shellHook = '' export GOPATH=$PWD/.go export PATH=$GOPATH/bin:$PATH export GRAPHANA_PATH=${pkgs.grafana} ''; }; packages = rec { some-automoderation = pkgs.buildGoModule { inherit pname version; src = pkgs.nix-gitignore.gitignoreSource [ ] ./.; vendorHash = "sha256-FOIDFJNBViicvcpDG3T1KYABmI5Xyrv+IdQvT2Elhjg="; preBuild = '' ${pkgs.nodePackages.tailwindcss}/bin/tailwindcss -i routes/in.css -o routes/static/out.css ''; }; default = some-automoderation; # for testing whole deployment locally # nixos-rebuild build-vm --flake .#test-container nixosConfigurations.test-container = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ nixosModules.some-automoderation-module ({ ... }: { nix = { extraOptions = '' experimental-features = nix-command flakes ''; }; networking.firewall.enable = false; users.groups.test = { }; users.mutableUsers = false; users.users.test = { isNormalUser = true; password = "test"; extraGroups = [ "wheel" "networkmanager" ]; group = "test"; }; services.some-automoderation = { enable = true; host = "some-automoderation.sunshine.industries"; useNginx = false; port = 9090; metricsPort = 9091; redisPort = 9999; enablePrometheus = true; }; services.prometheus = { enable = true; port = 9998; # scrape config will be set up by the module }; services.grafana = { enable = true; settings.server.http_port = 3000; settings.server.http_addr = "0.0.0.0"; provision.datasources = { settings.datasources = [{ name = "local-prometheus"; type = "prometheus"; url = "http://localhost:9998"; }]; }; }; }) ]; }; }; nixosModules.some-automoderation-module = { lib, pkgs, config, ... }: let cfg = config.services.${pname}; in { options.services.${pname} = { enable = lib.mkEnableOption "Enable Some-Automoderation web service"; host = lib.mkOption { type = lib.types.str; default = "127.0.0.1"; description = "Host to bind to."; }; useNginx = lib.mkOption { type = lib.types.bool; default = true; description = "Whether to set up nginx reverse proxy"; }; port = lib.mkOption { type = lib.types.int; default = 8090; description = "Port to listen on. Use 443 for tls when no nginx, usual plaintext is 8090."; }; redisPort = lib.mkOption { type = lib.types.int; default = 7777; description = "Port on which to connect to redis database."; }; metricsPort = lib.mkOption { type = lib.types.int; default = 8091; description = "Port on which server exposes metrics."; }; enablePrometheus = lib.mkOption { type = lib.types.bool; default = false; description = "Whether to add scrape rules to prometheus"; }; useHostTls = lib.mkOption { type = lib.types.bool; default = false; description = "Whether virtual host should enable NixOS ACME certs"; }; }; config = let username = "${pname}"; groupname = "${pname}"; in lib.mkIf cfg.enable { users.groups."${groupname}" = { }; users.users."${username}" = { isNormalUser = true; # needed to allow for home dir group = "${groupname}"; }; systemd.services.${pname} = { description = "Some Automoderation systemd service"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; startLimitIntervalSec = 30; startLimitBurst = 10; serviceConfig = { ExecStart = let serveCliArg = "--port ${toString cfg.port} --redisPort ${ toString cfg.redisPort } --metricsPort ${toString cfg.metricsPort}"; in "${packages.some-automoderation}/bin/${pname} ${serveCliArg}"; Restart = "on-failure"; User = "${username}"; Group = "${groupname}"; }; }; services.nginx = lib.mkIf cfg.useNginx { virtualHosts.${cfg.host} = { forceSSL = cfg.useHostTls; enableACME = cfg.useHostTls; locations."/" = { proxyPass = "http://127.0.0.1:${toString cfg.port}"; }; extraConfig = '' # check http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive proxy_set_header Connection ""; proxy_http_version 1.1; ''; }; }; services.redis.servers.${pname} = { enable = true; user = "${username}"; port = cfg.redisPort; settings = { notify-keyspace-events = "KEA"; }; }; services.prometheus = lib.mkIf cfg.enablePrometheus { scrapeConfigs = [{ job_name = "some-automoderation"; static_configs = [{ targets = [ "localhost:${toString cfg.metricsPort}" ]; }]; }]; }; }; }; }); }