chore(sterni/machines): move http services from edwin to ingeborg

* Make sterni.lv declarative
* Disable gopher server
* Disable likely-music.sterni.lv for now
* Don't give systemd too much leeway with scheduling git syncs

Change-Id: Ie8507d96f2df76ad8e393b2181ed7378c37829d0
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10480
Autosubmit: sterni <sternenseemann@systemli.org>
Reviewed-by: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
This commit is contained in:
sterni 2023-12-31 00:19:22 +01:00 committed by clbot
parent 12f9b95a2c
commit 06db871bd7
10 changed files with 46 additions and 22 deletions

View file

@ -13,6 +13,16 @@
(depot.path.origSrc + "/ops/modules/btrfs-auto-scrub.nix")
./monitoring.nix
./minecraft.nix
./http/sterni.lv.nix
./http/code.sterni.lv.nix
./http/flipdot.openlab-augsburg.de.nix
# Inactive:
# ./http/likely-music.sterni.lv.nix
# ./gopher.nix
# TODO(sterni): fail2ban
# TODO(sterni): automatic backups for full recovery
];
config = {

View file

@ -0,0 +1,19 @@
{ depot, ... }:
{
config = {
services.spacecookie = {
enable = true;
openFirewall = true;
settings = {
hostname = "sterni.lv";
root = depot.users.sterni.lv.gopher;
log = {
enable = true;
hide-ips = true;
hide-time = true;
};
};
};
};
}

View file

@ -0,0 +1,261 @@
{ depot, pkgs, lib, config, ... }:
let
virtualHost = "code.sterni.lv";
repoSections = [
{
section = "active";
repos = {
spacecookie = {
description = "gopher server (and library for Haskell)";
upstream = "https://github.com/sternenseemann/spacecookie.git";
};
"mirror/depot" = {
description = "monorepo for the virus lounge";
upstream = "https://code.tvl.fyi/depot.git";
cgit.defbranch = "canon";
};
"mirror/flipdot-gschichtler" = {
description = "message queue system for OpenLab's flipdot display";
upstream = "https://github.com/openlab-aux/flipdot-gschichtler.git";
};
"mirror/nixpkgs" = {
description = "Nix packages collection";
upstream = "https://github.com/nixos/nixpkgs.git";
cgit.enable-commit-graph = "0"; # too slow
};
"mirror/vuizvui" = {
description = "Nix(OS) expressions used by the OpenLab and its members";
upstream = "https://github.com/openlab-aux/vuizvui.git";
};
};
}
{
section = "poc";
repos = {
emoji-generic = {
description = "generic emoji library for Haskell";
upstream = "https://github.com/sternenseemann/emoji-generic.git";
};
grav2ty = {
description = "realistic 2d space game";
upstream = "https://github.com/sternenseemann/grav2ty.git";
};
haskell-dot-time = {
description = "UTC-centric time library for haskell with dot time support";
cgit.defbranch = "main";
};
buchstabensuppe = {
description = "toy font rendering for low pixelcount, high contrast displays";
upstream = "https://github.com/sternenseemann/buchstabensuppe.git";
cgit.defbranch = "main";
};
"mirror/saneterm" = {
description = "modern line-oriented terminal emulator without support for TUIs";
upstream = "https://git.8pit.net/saneterm.git";
};
};
}
{
# TODO(sterni): resisort, klammeraffe, cl-ca, ponify, tinyrl
section = "archive";
repos = {
gopher-proxy = {
description = "Gopher over HTTP proxy";
upstream = "https://github.com/sternenseemann/gopher-proxy.git";
};
likely-music = {
description = "experimental application for probabilistic music composition";
upstream = "https://github.com/sternenseemann/likely-music.git";
};
logbook = {
description = "file format for keeping a personal log";
upstream = "https://github.com/sternenseemann/logbook.git";
};
sternenblog = {
description = "file based cgi blog software";
upstream = "https://github.com/sternenseemann/sternenblog.git";
};
};
}
];
repoPath = name: repo: repo.path or "/srv/git/${name}.git";
cgitRepoEntry = name: repo:
lib.concatStringsSep "\n" (
[
"repo.url=${name}"
"repo.path=${repoPath name repo}"
]
++ lib.optional (repo ? description) "repo.desc=${repo.description}"
++ lib.mapAttrsToList (n: v: "repo.${n}=${v}") repo.cgit or { }
);
cgitHead = pkgs.writeText "cgit-head.html" ''
<style>
#summary {
max-width: 80em;
}
#summary * {
max-width: 100%;
}
</style>
'';
cgitConfig = pkgs.writeText "cgitrc" ''
virtual-root=/
enable-http-clone=1
clone-url=https://${virtualHost}/$CGIT_REPO_URL
enable-blame=1
enable-log-filecount=1
enable-log-linecount=1
enable-index-owner=0
enable-blame=1
enable-commit-graph=1
root-title=code.sterni.lv
css=/cgit.css
head-include=${cgitHead}
mimetype-file=${pkgs.mime-types}/etc/mime.types
about-filter=${depot.tools.cheddar.about-filter}/bin/cheddar-about
source-filter=${depot.tools.cheddar}/bin/cheddar
readme=:README.md
readme=:readme.md
section-sort=0
${
lib.concatMapStringsSep "\n" (section:
''
section=${section.section}
''
+ builtins.concatStringsSep "\n\n" (lib.mapAttrsToList cgitRepoEntry section.repos)
) repoSections
}
'';
/* Merge a list of attrs, but fail when the same attribute occurs twice.
Type: [ attrs ] -> attrs
*/
mergeManyDistinctAttrs = lib.foldAttrs
(
val: nul:
if nul == null then val else throw "Every attribute name may occur only once"
)
null;
flatRepos = mergeManyDistinctAttrs
(builtins.map (section: section.repos) repoSections);
reposToMirror = lib.filterAttrs (_: repo: repo ? upstream) flatRepos;
# User and group name used for running the mirror scripts
mirroredReposOwner = "git";
# Make repo name suitable for systemd unit/timer
unitName = name: "mirror-${lib.strings.sanitizeDerivationName name}";
in
{
imports = [
./nginx.nix
./fcgiwrap.nix
];
config = {
services.nginx.virtualHosts."${virtualHost}" = {
enableACME = true;
forceSSL = true;
root = "${pkgs.cgit-pink}/cgit/";
extraConfig = ''
try_files $uri @cgit;
location @cgit {
include ${pkgs.nginx}/conf/fastcgi_params;
fastcgi_param SCRIPT_FILENAME ${pkgs.cgit-pink}/cgit/cgit.cgi;
fastcgi_param PATH_INFO $uri;
fastcgi_param QUERY_STRING $args;
fastcgi_param HTTP_HOST $server_name;
fastcgi_param CGIT_CONFIG ${cgitConfig};
fastcgi_pass unix:${toString config.services.fcgiwrap.socketAddress};
}
'';
};
users = {
users.${mirroredReposOwner} = {
group = mirroredReposOwner;
isSystemUser = true;
};
groups.${mirroredReposOwner} = { };
};
systemd.timers = lib.mapAttrs'
(
name: repo:
{
name = unitName name;
value = {
description = "regularly update mirror git repository ${name}";
wantedBy = [ "timers.target" ];
enable = true;
timerConfig = {
# Fire every 6h and distribute the workload over next 6h randomly
OnCalendar = "*-*-* 00/6:00:00";
RandomizedDelaySec = "6h";
Persistent = true;
};
};
}
)
reposToMirror;
systemd.services = lib.mapAttrs'
(
name: repo:
{
name = unitName name;
value = {
description = "mirror git repository ${name}";
after = [ "network-online.target" ];
script =
let
path = repoPath name repo;
in
''
set -euo pipefail
export PATH="${lib.makeBinPath [ pkgs.coreutils pkgs.git ]}"
if test ! -d "${path}"; then
mkdir -p "$(dirname "${path}")"
git clone --mirror "${repo.upstream}" "${path}"
exit 0
fi
cd "${path}"
git fetch "${repo.upstream}" '+refs/*:refs/*' --prune
'';
serviceConfig = {
Type = "oneshot";
User = mirroredReposOwner;
Group = mirroredReposOwner;
};
};
}
)
reposToMirror;
};
}

View file

@ -0,0 +1,15 @@
{ ... }:
{
imports = [
./nginx.nix
];
config.services.fcgiwrap = {
enable = true;
socketType = "unix";
socketAddress = "/run/fcgiwrap.sock";
user = "http";
group = "http";
};
}

View file

@ -0,0 +1,36 @@
{ depot, lib, config, ... }:
let
inherit (depot.users.sterni.external.flipdot-gschichtler)
bahnhofshalle
warteraum
nixosModule
;
in
{
imports = [
nixosModule
./nginx.nix
];
config = {
age.secrets = lib.genAttrs [
"warteraum-salt"
"warteraum-tokens"
]
(name: {
file = depot.users.sterni.secrets."${name}.age";
});
services.flipdot-gschichtler = {
enable = true;
virtualHost = "flipdot.openlab-augsburg.de";
packages = {
inherit bahnhofshalle warteraum;
};
saltFile = config.age.secretsDir + "/warteraum-salt";
tokensFile = config.age.secretsDir + "/warteraum-tokens";
};
};
}

View file

@ -0,0 +1,23 @@
{ depot, ... }:
let
inherit (depot.users.sterni.external.likely-music)
nixosModule
likely-music
;
in
{
imports = [
./nginx.nix
nixosModule
];
config = {
services.likely-music = {
enable = true;
virtualHost = "likely-music.sterni.lv";
package = likely-music;
};
};
}

View file

@ -0,0 +1,30 @@
{ ... }:
{
config = {
users = {
users.http = {
isSystemUser = true;
group = "http";
};
groups.http = { };
};
services.nginx = {
enable = true;
recommendedTlsSettings = true;
recommendedGzipSettings = true;
recommendedProxySettings = true;
user = "http";
group = "http";
appendHttpConfig = ''
charset utf-8;
'';
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
};
}

View file

@ -0,0 +1,34 @@
{ pkgs, depot, ... }:
let
inherit (depot.users.sterni.nix.html)
__findFile
withDoctype
;
in
{
imports = [
./nginx.nix
];
config = {
services.nginx.virtualHosts."sterni.lv" = {
enableACME = true;
forceSSL = true;
root = pkgs.writeTextFile {
name = "sterni.lv-http-root";
destination = "/index.html";
text = withDoctype (<html> { } [
(<head> { } [
(<meta> { charset = "utf-8"; } null)
(<title> { } "no thoughts")
])
(<body> { } "🦩")
]);
};
# TODO(sterni): tmp.sterni.lv
locations."/tmp/".root = toString /srv/http;
};
};
}