From 0bcabe1c4b1dd74af233674dfa6c6ec3011ce2c0 Mon Sep 17 00:00:00 2001 From: stuebinm Date: Tue, 18 Jan 2022 09:43:24 +0100 Subject: restructuring directories --- flora/configuration.nix | 72 ++++++++++++++++ flora/hardware-configuration.nix | 25 ++++++ flora/services/blog.nix | 9 ++ flora/services/cgit.nix | 94 +++++++++++++++++++++ flora/services/daemoniones.nix | 34 ++++++++ flora/services/dockerhub.nix | 23 +++++ flora/services/hedgedoc.nix | 77 +++++++++++++++++ flora/services/nginx.nix | 17 ++++ flora/services/picarones.nix | 26 ++++++ flora/services/pleroma.nix | 178 +++++++++++++++++++++++++++++++++++++++ flora/services/surveys.nix | 23 +++++ 11 files changed, 578 insertions(+) create mode 100644 flora/configuration.nix create mode 100644 flora/hardware-configuration.nix create mode 100644 flora/services/blog.nix create mode 100644 flora/services/cgit.nix create mode 100644 flora/services/daemoniones.nix create mode 100644 flora/services/dockerhub.nix create mode 100644 flora/services/hedgedoc.nix create mode 100644 flora/services/nginx.nix create mode 100644 flora/services/picarones.nix create mode 100644 flora/services/pleroma.nix create mode 100644 flora/services/surveys.nix (limited to 'flora') diff --git a/flora/configuration.nix b/flora/configuration.nix new file mode 100644 index 0000000..b2699b7 --- /dev/null +++ b/flora/configuration.nix @@ -0,0 +1,72 @@ +{ config, pkgs, ... }: + +{ + imports = [ + ./hardware-configuration.nix + # ./services/hedgedoc.nix + #./services/daemoniones.nix + ./services/nginx.nix + ./services/pleroma.nix + ./services/cgit.nix + # ./services/surveys.nix + #./services/picarones.nix + ./services/dockerhub.nix + ./services/blog.nix + ]; + + # Use the GRUB 2 boot loader. + boot.loader.grub.enable = true; + boot.loader.grub.version = 2; + boot.loader.grub.devices = [ "/dev/sda" ]; + + networking = { + hostName = "flora"; + + enableIPv6 = true; + defaultGateway6 = { + address = "fe80::1"; + interface = "ens3"; + }; + + interfaces.ens3.ipv6.addresses = [ { + address = "2a01:4f9:c010:df15::1"; + prefixLength = 64; + } ]; + + useDHCP = false; + interfaces.ens3.useDHCP = true; + + firewall.logRefusedConnections = false; + + + }; + + services.fail2ban = { + enable = true; + bantime-increment.enable = true; + bantime-increment.overalljails = true; + bantime-increment.maxtime = "1312m"; + ignoreIP = [ "88.133.194.232" ]; + }; + + services.logrotate = { + enable = true; + paths.nginx = { + path = "/var/log/nginx"; + frequency = "weekly"; + }; + }; + + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system = { + stateVersion = "20.09"; # Did you read the comment? + }; + +} + diff --git a/flora/hardware-configuration.nix b/flora/hardware-configuration.nix new file mode 100644 index 0000000..2ce21f4 --- /dev/null +++ b/flora/hardware-configuration.nix @@ -0,0 +1,25 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ modulesPath, config, lib, pkgs, inputs, ... }: + +{ + imports = + [ "${modulesPath}/profiles/qemu-guest.nix" + ]; + + boot.initrd.availableKernelModules = [ "ata_piix" "virtio_pci" "xhci_pci" "sd_mod" "sr_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/5d31cad5-9076-4d2f-93f6-6af817bc368b"; + fsType = "ext4"; + }; + + swapDevices = [ ]; + + nix.maxJobs = lib.mkDefault 1; +} + diff --git a/flora/services/blog.nix b/flora/services/blog.nix new file mode 100644 index 0000000..056a63b --- /dev/null +++ b/flora/services/blog.nix @@ -0,0 +1,9 @@ +{ config, lib, pkgs, inputs, ... }: + +{ + services.nginx.virtualHosts."stuebinm.eu" = { + enableACME = true; + forceSSL = true; + locations."/".root = (import inputs.blog); + }; +} diff --git a/flora/services/cgit.nix b/flora/services/cgit.nix new file mode 100644 index 0000000..094bfd5 --- /dev/null +++ b/flora/services/cgit.nix @@ -0,0 +1,94 @@ +{pkgs, config, ...}: + +{ + containers.cgit = { + autoStart = true; + privateNetwork = true; + hostAddress6 = "fd00::42:12"; + localAddress6 = "fd00::42:13"; + + bindMounts."/git" = { + hostPath = "/var/git/public"; + isReadOnly = true; + }; + + config = {pkgs, config, ...}: { + services.lighttpd.enable = true; + services.lighttpd.extraConfig = ''server.use-ipv6 = "enable"''; + services.lighttpd.cgit = { + enable = true; + subdir = "git"; + configText = '' + source-filter=${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py + about-filter=${pkgs.cgit}/lib/cgit/filters/about-formatting.sh + cache-size=1000 + logo=/git/cgit.png + favicon=/git/favicon.ico + + # take css from an assumed repo `config` + css=/git/config/plain/cgit.css + + # remove .git extensions from repo names + remove-suffix=1 + + # readme formats which may be parsed + readme=:README.md + readme=:README + readme=:README.txt + readme=:README.org + + # allow cloning repos + enable-http-clone=1 + + enable-follow-links=1 + enable-html-serving=1 + enable-index-owner=0 + + mimetype.css=text/css + mimetype.jpg=image/jpeg + mimetype.jpeg=image/jpeg + mimetype.pdf=application/pdf + mimetype.png=image/png + mimetype.svg=image/svg+xml + + # some nice formatting + root-title=An Assortment of Stuff + root-desc=hand-squished into git repos + enable-commit-graph=1 + enable-log-linecount=1 + enable-log-filecount=1 + branch-sort=age + # suppress email addresses in html logs + noplainemail=1 + + # maximum file size for plain blobs in kilobyte + max-blob-size=100 + + cache-scanrc-ttl=1 + + scan-path=/git + ''; + }; + + networking.firewall.allowedTCPPorts = [ 80 ]; + }; + }; + + services.nginx.recommendedProxySettings = true; + services.nginx.virtualHosts."stuebinm.eu" = { + locations."/git/".proxyPass = "http://[${config.containers.cgit.localAddress6}]"; + enableACME = true; + forceSSL = true; + }; + + # user for git repo administration + users.users.git = { + openssh.authorizedKeys.keys = config.users.users.root.openssh.authorizedKeys.keys; + home = "/var/git"; + isNormalUser = true; + packages = [ pkgs.git ]; + }; + + networking.firewall.allowedTCPPorts = [ 80 443 ]; + +} diff --git a/flora/services/daemoniones.nix b/flora/services/daemoniones.nix new file mode 100644 index 0000000..ae9d3cb --- /dev/null +++ b/flora/services/daemoniones.nix @@ -0,0 +1,34 @@ +{ config, pkgs, ...}: + +{ + systemd.services = + let simpledaemon = name: command: { + enable = true; + description = name; + wantedBy = [ "multi-user.target" ]; + serviceConfig.Type = "simple"; + script = command; + }; + in { + choclo = simpledaemon "choclo signalling server" "/root/simple-signalling/target/release/chaski -b 127.0.0.1:5000"; + wasi = simpledaemon "wasi backend" "/root/wasi-minimal/target/release/wasi"; +# picarones = simpledaemon "picarones backend" "/root/picarones-server/target/release/picarones -b 127.0.0.1:6000"; + }; + + services.nginx = { + virtualHosts = + let websocketproxy = addr: { + locations."/".proxyPass = addr; + forceSSL = true; + enableACME = true; + locations."/".proxyWebsockets = true; + }; + in { + "wasi.stuebinm.eu" = websocketproxy "http://127.0.0.1:9000"; + "choclo.stuebinm.eu" = websocketproxy "http://127.0.0.1:5000"; +# "picarones.stuebinm.eu" = websocketproxy "http://127.0.0.1:6000"; + }; + }; + + +} diff --git a/flora/services/dockerhub.nix b/flora/services/dockerhub.nix new file mode 100644 index 0000000..c9b84b3 --- /dev/null +++ b/flora/services/dockerhub.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, ... }: + +{ + services.dockerRegistry = { + enable = true; + port = 6000; + enableRedisCache = false; + extraConfig = { + storage.maintenance.readonly.enabled = true; + }; + }; + + services.nginx.virtualHosts."registry.stuebinm.eu" = { + locations."/" = { + proxyPass = "http://localhost:6000"; + proxyWebsockets = true; + }; + enableACME = true; + forceSSL = true; + }; + + services.nginx.clientMaxBodySize = "0"; +} diff --git a/flora/services/hedgedoc.nix b/flora/services/hedgedoc.nix new file mode 100644 index 0000000..038f99f --- /dev/null +++ b/flora/services/hedgedoc.nix @@ -0,0 +1,77 @@ +{ config, lib, pkgs, ... }: +let + hedgedoc-patched = pkgs.hedgedoc.overrideAttrs (old: { + src = pkgs.fetchgit { + url = "https://stuebinm.eu/git/hedgedoc"; + rev = "b0f98a43381486995b99ed79e0eabb3af149dbf3"; + sha256 = "1199k5q8wampkw2ri4wgwzqgh1ff0l4kdxx9h8ywqy2f7faf922c"; + }; + }); +in +{ + # Container containing CodiMD and its database + # has its own internal network; needs a reverse-proxy to be reachable from the outside + # TODO: persistent memory for pads + containers.codimd = { + autoStart = true; + privateNetwork = true; + hostAddress6 = "fd00::42:10"; + localAddress6 = "fd00::42:11"; + + config = {config, pkgs, ... }: { + # open CodiMD port + networking.firewall.allowedTCPPorts = [ config.services.hedgedoc.configuration.port ]; + + # database (postgres 11), with default database reachable for CodiMD; no imperative config needed! + services.postgresql = { + enable = true; + package = pkgs.postgresql_11; + ensureDatabases = [ "codimd" ]; + ensureUsers = [ { + name = "hedgedoc"; + ensurePermissions = { "DATABASE codimd" = "ALL PRIVILEGES";}; + } ]; + # ugly workaround to allow CodiMD to login without password — this service has lots of options, + # but apparently not for authentification, which even needs to be forced … + authentication = pkgs.lib.mkForce '' + # Generated file; do not edit! + local all all trust + host codimd hedgedoc ::1/18 trust + host codimd codimd ::1/128 trust + ''; + }; + # CodiMD itself + services.hedgedoc = { + enable = true; + workDir = "/var/codimd/"; + configuration = { + dbURL = "postgres:///codimd"; + port = 3000; + domain = "nix.stuebinm.eu"; + urlAddPort = false; + protocolUseSSL = true; + allowPDFExport = true; + host = "::"; + allowEmailRegister = false; + allowFreeURL = true; + uploadsPath = "/var/codimd/uploads"; + #email = false; + }; + }; + + systemd.services.hedgedoc.serviceConfig.ExecStart = pkgs.lib.mkForce "${hedgedoc-patched}/bin/hedgedoc"; + }; + }; + + + networking.firewall.allowedTCPPorts = [ 80 443 ]; + + services.nginx.virtualHosts."nix.stuebinm.eu" = { + locations."/" = { + proxyPass = "http://[" + config.containers.codimd.localAddress6 + "]:3000"; + proxyWebsockets = true; + }; + forceSSL = true; + enableACME = true; + }; +} diff --git a/flora/services/nginx.nix b/flora/services/nginx.nix new file mode 100644 index 0000000..bbcacb7 --- /dev/null +++ b/flora/services/nginx.nix @@ -0,0 +1,17 @@ +{ config, lib, pkgs, ... }: + +{ + networking.firewall.allowedTCPPorts = [ 80 443 ]; + + services.nginx = { + enable = true; + + recommendedOptimisation = true; + recommendedTlsSettings = true; + recommendedProxySettings = true; + + appendHttpConfig = '' + add_header Permissions-Policy "interest-cohort=()"; + ''; + }; +} diff --git a/flora/services/picarones.nix b/flora/services/picarones.nix new file mode 100644 index 0000000..c2e3c7b --- /dev/null +++ b/flora/services/picarones.nix @@ -0,0 +1,26 @@ +{config, pkgs, ...}: +let + source = builtins.fetchGit { + url = "https://stuebinm.eu/git/picarones/"; + rev = "0596b9f6c561daa67945adb81570efd30650dffd"; + }; +in +{ + + imports = [ source.outPath ]; + + services.picarones = { + enable = true; + frontend = { + enable = true; + domain = "picarones.stuebinm.eu"; + proxyBackend = true; + config = { + enableACME = true; + forceSSL = true; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [ 80 443 ]; +} diff --git a/flora/services/pleroma.nix b/flora/services/pleroma.nix new file mode 100644 index 0000000..e0f60ed --- /dev/null +++ b/flora/services/pleroma.nix @@ -0,0 +1,178 @@ +{config, pkgs, inputs, ...}: + + +let + domain = "pleroma.stuebinm.eu"; +in +{ + + containers.pleroma = { + autoStart = true; + privateNetwork = true; + + hostAddress = "192.168.42.30"; + localAddress = "192.168.42.31"; + hostAddress6 = "fd00::42:30"; + localAddress6 = "fd00::42:31"; + + + config = {pkgs, config, ...}: { + + # generating the manual will fail when mixing nixos channels, + # so disable it here or this won't build at all. + documentation.enable = false; + + # pleroma has a cli tool for configuration + environment.systemPackages = [ pkgs.dnsutils ]; + + services.pleroma = { + enable = true; + + + # package = (import inputs.nixpkgs-unstable {}).pleroma; + + # this is barely necessary at this point — all that's + # set in here is the default_signer for joken, and the + # secret_key_base and signing_salt for phoenix. + secretConfigFile = "/var/lib/pleroma/secrets.exs"; + + # for a list of available config options, see + # https://docs-develop.pleroma.social/backend/configuration/cheatsheet/ + # + # Additionally, some parts of pleroma's config (e.g. Pleroma.Repo) + # are better documented in their respective libraries (in this + # case, see the documentation for Ecto on Adapters). + configs = [ '' + import Config + + config :pleroma, Pleroma.Web.Endpoint, + url: [host: "${domain}", scheme: "https", port: 443], + http: [ip: {0, 0, 0, 0, 0, 0, 0, 0}, port: 4000] + + config :pleroma, :instance, + name: "Pleroma", + limit: 5000, + registrations_open: false, + federating: true, + healthcheck: true, + allow_relay: true + + config :pleroma, :media_proxy, + enabled: false, + redirect_on_failure: true + + config :pleroma, Pleroma.Upload, + filters: [ + Pleroma.Upload.Filter.Exiftool, + Pleroma.Upload.Filter.AnonymizeFilename, + Pleroma.Upload.Filter.Dedupe + ] + + config :pleroma, Pleroma.Uploaders.Local, + uploads: "/var/lib/pleroma/uploads" + + config :pleroma, Pleroma.Repo, + adapter: Ecto.Adapters.Postgres, + username: "pleroma", + database: "pleroma", + socket_dir: "/run/postgresql", + pool_size: 10, + prepare: :named, + parameters: [ + plan_cache_mode: "force_custom_plan" + ] + + + + config :pleroma, :database, rum_enabled: false + config :pleroma, configurable_from_database: false + + config :pleroma, :instance, static_dir: "/var/lib/pleroma/static" + + '' ]; + }; + + # otherwise, the exiftool will fail to run + systemd.services.pleroma.path = [ pkgs.exiftool ]; + + services.postgresql = { + enable = true; + package = pkgs.postgresql_12; + + ensureDatabases = [ "pleroma" ]; + ensureUsers = [ { + name = "pleroma"; + ensurePermissions."DATABASE pleroma" = "ALL PRIVILEGES"; + } ]; + + # give pleroma access. must be done with lib.mkForce, for some reason + authentication = pkgs.lib.mkForce '' + # Generated file; do not edit! + local all all trust + host pleroma pleroma ::1/128 trust + ''; + + # pleroma wants to do some initial config on startup, which it + # can't do by itself since those needs superuser access + # + # unfortunatly, this is executed /before/ the database is created, + # i.e. we have to create user and database by hand, even though + # they would otherwise created by ensureUsers / ensureDatabse. + # Using those does still prevent us from accidentally deleting + # them, though (but not from deleting the database's content!) + initialScript = pkgs.writeScript "postgres-pleroma-initial" '' + CREATE USER pleroma; + CREATE DATABASE pleroma OWNER pleroma; + \c pleroma; + --Extensions made by ecto.migrate that need superuser access + CREATE EXTENSION IF NOT EXISTS citext; + CREATE EXTENSION IF NOT EXISTS pg_trgm; + CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + ''; + }; + + networking.firewall.allowedTCPPorts = [ 4000 10022 ]; + }; + }; + + # give the container access to the external internet (necessary for + # fetching content from other instances). Doesn't appear to work with + # IPv6, though ... + networking.nat = { + enable = true; + internalInterfaces = [ "ve-pleroma" ]; + externalInterface = "ens3"; + + }; + networking.firewall.allowedTCPPorts = [ 10022 ]; + + services.nginx.virtualHosts."${domain}" = { + forceSSL = true; + enableACME = true; + + locations."/" = { + proxyPass = "http://[${config.containers.pleroma.localAddress6}]:4000"; + proxyWebsockets = true; + # these headers are in the example config in the NixOS manual. + # take some time to figure out what they all do, and if these + # are necessary + extraConfig = '' + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Idempotency-Key' always; + add_header 'Access-Control-Expose-Headers' 'Link, X-RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-Request-Id' always; + if ($request_method = OPTIONS) { + return 204; + } + add_header X-XSS-Protection "1; mode=block"; + add_header X-Permitted-Cross-Domain-Policies none; + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + add_header Referrer-Policy same-origin; + add_header X-Download-Options noopen; + client_max_body_size 16m; + ''; + }; + }; +} + diff --git a/flora/services/surveys.nix b/flora/services/surveys.nix new file mode 100644 index 0000000..befa673 --- /dev/null +++ b/flora/services/surveys.nix @@ -0,0 +1,23 @@ +{pkgs, config, ...}: + +let survey = pkgs.fetchgit { + url = "https://stuebinm.eu/git/slightly-better-surveys"; + rev = "c255269db0c739400b62d4c4041e3238b1045d22"; + sha256 = "007q6s5xc3kn3dy1zj7hc94wyn495qam2x1020br3crwgpxy3hmp"; + }; +in +{ + services.nginx.virtualHosts."survey.stuebinm.eu" = { + locations."/".root = survey.outPath + "/site"; + locations."/upload".proxyPass = "http://localhost:8080"; + + enableACME = true; + forceSSL = true; + }; + + services.nginx.appendHttpConfig = '' + types { + application/wasm wasm; + } + ''; +} -- cgit v1.2.3