summaryrefslogtreecommitdiff
path: root/flora
diff options
context:
space:
mode:
Diffstat (limited to 'flora')
-rw-r--r--flora/configuration.nix72
-rw-r--r--flora/hardware-configuration.nix25
-rw-r--r--flora/services/blog.nix9
-rw-r--r--flora/services/cgit.nix94
-rw-r--r--flora/services/daemoniones.nix34
-rw-r--r--flora/services/dockerhub.nix23
-rw-r--r--flora/services/hedgedoc.nix77
-rw-r--r--flora/services/nginx.nix17
-rw-r--r--flora/services/picarones.nix26
-rw-r--r--flora/services/pleroma.nix178
-rw-r--r--flora/services/surveys.nix23
11 files changed, 578 insertions, 0 deletions
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;
+ }
+ '';
+}