add hackyplayer/hacky-vouchproxy/emfminiserv bits
This commit is contained in:
parent
bcb2f287e1
commit
93d5a104da
8 changed files with 624 additions and 1 deletions
|
@ -15,6 +15,7 @@ args: {
|
|||
access = import ./access args;
|
||||
vault = import ./vault args;
|
||||
tumblrandom = import ./tumblrandom args;
|
||||
emfminiserv = import ./emfminiserv args;
|
||||
|
||||
buildgo2 = import ./buildgo2 args;
|
||||
}
|
||||
|
|
12
go/emfminiserv/default.nix
Normal file
12
go/emfminiserv/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
# SPDX-FileCopyrightText: 2024 Luke Granger-Brown <depot@lukegb.com>
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
{ depot, ... }:
|
||||
depot.third_party.buildGo.program {
|
||||
name = "emfminiserv";
|
||||
srcs = [ ./emfminiserv.go ];
|
||||
deps = with depot.third_party; [
|
||||
# gopkgs."github.com".golang.glog
|
||||
];
|
||||
}
|
216
go/emfminiserv/emfminiserv.go
Normal file
216
go/emfminiserv/emfminiserv.go
Normal file
|
@ -0,0 +1,216 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
baseDir = flag.String("base_dir", "/store/emf/2024/video/output/", "base directory for output")
|
||||
httpListen = flag.String("http_listen", "", "TCP address to listen&serve")
|
||||
httpListenUNIX = flag.String("http_listen_unix", "", "UNIX socket path to listen&serve")
|
||||
|
||||
computeForBase = flag.String("compute_base", "https://prerelease.voc.emf.camp/", "base URL to prepend when computing a secret")
|
||||
computeFor = flag.String("compute", "", "something to compute the secret for")
|
||||
|
||||
list = flag.Bool("list", false, "list the available content")
|
||||
|
||||
devMode = flag.Bool("dev_mode", false, "enable insecure dev mode")
|
||||
)
|
||||
|
||||
func computeSignature(content, secret string) string {
|
||||
mac := hmac.New(sha256.New, []byte(secret))
|
||||
mac.Write([]byte(content))
|
||||
return base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString(mac.Sum(nil))
|
||||
}
|
||||
|
||||
func validateSignature(content, secret, signature string) bool {
|
||||
computed := computeSignature(content, secret)
|
||||
if *devMode {
|
||||
log.Printf("got signature %q; computed signature %q", signature, computed)
|
||||
}
|
||||
return subtle.ConstantTimeCompare([]byte(computed), []byte(signature)) == 1
|
||||
}
|
||||
|
||||
const (
|
||||
talkRegexFragment = `[0-9]+(_[\p{L}\p{N}\-]+)?`
|
||||
fileEndRegexFragment = `[0-9]{8}-[0-9]{6}[.]mp4`
|
||||
)
|
||||
|
||||
var (
|
||||
validContentRegex = regexp.MustCompile("^" + talkRegexFragment + "$")
|
||||
validFileRegex = regexp.MustCompile("^" + fileEndRegexFragment + "$")
|
||||
filenameRegex = regexp.MustCompile(`^(` + talkRegexFragment + ")-(" + fileEndRegexFragment + ")$")
|
||||
)
|
||||
|
||||
func logResultFactory(r *http.Request, what string) func(string, ...any) {
|
||||
return func(f string, bits ...any) {
|
||||
log.Printf("%s{%s}: %s %s - %s", what, r.RemoteAddr, r.Method, r.RequestURI, fmt.Sprintf(f, bits...))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
contentFS := os.DirFS(*baseDir)
|
||||
|
||||
secret := os.Getenv("EMFMINISERV_SECRET")
|
||||
if secret == "" {
|
||||
if !*devMode {
|
||||
log.Fatal("set EMFMINISERV_SECRET or -dev_mode")
|
||||
}
|
||||
secret = "testing-do-not-use-in-production"
|
||||
log.Printf("secret is set to %q! development mode only.", secret)
|
||||
}
|
||||
|
||||
if *httpListen == "" && *httpListenUNIX == "" && *computeFor == "" && !*list {
|
||||
log.Printf("need -http_listen, -http_listen_unix, -compute or -list")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if *list {
|
||||
matches, err := fs.Glob(contentFS, "*.mp4")
|
||||
if err != nil {
|
||||
log.Fatalf("globbing for *.mp4: %v", err)
|
||||
}
|
||||
|
||||
available := map[string]bool{}
|
||||
|
||||
for _, m := range matches {
|
||||
bits := filenameRegex.FindStringSubmatch(m)
|
||||
if bits == nil {
|
||||
continue
|
||||
}
|
||||
available[bits[1]] = true
|
||||
}
|
||||
|
||||
availableKeys := make([]string, 0, len(available))
|
||||
for k := range available {
|
||||
availableKeys = append(availableKeys, k)
|
||||
}
|
||||
sort.Strings(availableKeys)
|
||||
|
||||
for _, k := range availableKeys {
|
||||
fmt.Printf("%s\n", k)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if *computeFor != "" {
|
||||
sig := computeSignature(*computeFor, secret)
|
||||
fmt.Printf("%s%s/%s/\n", *computeForBase, *computeFor, sig)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
http.HandleFunc("/{content}/{signature}/{file}", func(rw http.ResponseWriter, r *http.Request) {
|
||||
logResult := logResultFactory(r, "contentget")
|
||||
|
||||
if r.Method != "GET" {
|
||||
logResult("method not allowed")
|
||||
http.Error(rw, "GET only", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("contentget{%s}: %s %s", r.RemoteAddr, r.Method, r.RequestURI)
|
||||
|
||||
content := r.PathValue("content")
|
||||
file := r.PathValue("file")
|
||||
if !validContentRegex.MatchString(content) || !validFileRegex.MatchString(file) {
|
||||
logResult("404 invalid content or file segment")
|
||||
http.NotFound(rw, r)
|
||||
return
|
||||
}
|
||||
if !validateSignature(content, secret, r.PathValue("signature")) {
|
||||
logResult("404 invalid signature")
|
||||
http.NotFound(rw, r)
|
||||
return
|
||||
}
|
||||
|
||||
rw.Header().Set("x-accel-redir", fmt.Sprintf("/%s-%s", content, file))
|
||||
logResult("200 OK")
|
||||
})
|
||||
http.HandleFunc("/{content}/{signature}/{$}", func(rw http.ResponseWriter, r *http.Request) {
|
||||
logResult := logResultFactory(r, "contentdir")
|
||||
|
||||
if r.Method != "GET" {
|
||||
logResult("method not allowed")
|
||||
http.Error(rw, "GET only", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
content := r.PathValue("content")
|
||||
if !validContentRegex.MatchString(content) {
|
||||
logResult("404 invalid content segment")
|
||||
http.NotFound(rw, r)
|
||||
return
|
||||
}
|
||||
if !validateSignature(content, secret, r.PathValue("signature")) {
|
||||
logResult("404 invalid signature")
|
||||
http.NotFound(rw, r)
|
||||
return
|
||||
}
|
||||
|
||||
matches, err := fs.Glob(contentFS, fmt.Sprintf("%s-*", content))
|
||||
if err != nil {
|
||||
logResult("500 globbing with %s-*: %v", content, err)
|
||||
http.Error(rw, "internal server error finding content", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
sort.Strings(matches)
|
||||
|
||||
unprefixed := make([]string, len(matches))
|
||||
for n, m := range matches {
|
||||
unprefixed[n] = strings.TrimPrefix(m, fmt.Sprintf("%s-", content))
|
||||
}
|
||||
|
||||
rw.Header().Set("Content-type", "text/html; encoding=utf-8")
|
||||
|
||||
fmt.Fprintf(rw, "<ul>")
|
||||
for _, m := range unprefixed {
|
||||
fmt.Fprintf(rw, `<li><a href="%s">%s</a></li>`, m, m)
|
||||
}
|
||||
fmt.Fprintf(rw, "</ul>")
|
||||
logResult("200 OK")
|
||||
})
|
||||
|
||||
var wg sync.WaitGroup
|
||||
if *httpListen != "" {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
log.Fatal(http.ListenAndServe(*httpListen, nil))
|
||||
}()
|
||||
}
|
||||
if *httpListenUNIX != "" {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
l, err := net.Listen("unix", *httpListenUNIX)
|
||||
if err != nil {
|
||||
log.Fatalf("listening on unix:%v: %v", *httpListenUNIX, err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
if err := os.Chmod(*httpListenUNIX, 0770); err != nil {
|
||||
log.Fatalf("chmodding unix:%v: %v", *httpListenUNIX, err)
|
||||
}
|
||||
|
||||
log.Fatal(http.Serve(l, nil))
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
86
ops/nixos/lib/emfminiserv.nix
Normal file
86
ops/nixos/lib/emfminiserv.nix
Normal file
|
@ -0,0 +1,86 @@
|
|||
# SPDX-FileCopyrightText: 2024 Luke Granger-Brown <depot@lukegb.com>
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
{ depot, pkgs, lib, config, ... }:
|
||||
|
||||
let
|
||||
emfminiserv = depot.go.emfminiserv;
|
||||
|
||||
cfg = config.my.emfminiserv;
|
||||
in
|
||||
{
|
||||
options.my.emfminiserv = {
|
||||
enable = lib.mkEnableOption "emfminiserv";
|
||||
hostname = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "prerelease.voc.emf.camp";
|
||||
};
|
||||
listenAddresses = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.listOf lib.types.str);
|
||||
default = null;
|
||||
};
|
||||
serveDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/store/emf/2024/video/output/";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf cfg.enable {
|
||||
users.groups.hackyplayer = {};
|
||||
|
||||
systemd.services.emfminiserv = {
|
||||
serviceConfig = {
|
||||
User = "emfminiserv";
|
||||
Group = "hackyplayer";
|
||||
RuntimeDirectory = "emfminiserv";
|
||||
DynamicUser = true;
|
||||
ExecStart = "${emfminiserv}/bin/emfminiserv -http_listen_unix /run/emfminiserv/listen.sock -base_dir '${cfg.serveDir}'";
|
||||
EnvironmentFile = config.my.vault.secrets.emfminiserv-environment.path;
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
my.vault.secrets.emfminiserv-environment = {
|
||||
reloadOrRestartUnits = ["emfminiserv.service"];
|
||||
group = "hackyplayer";
|
||||
template = ''
|
||||
{{ with secret "kv/apps/emfminiserv" }}
|
||||
{{ .Data.data.environment }}
|
||||
{{ end }}
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeShellApplication {
|
||||
name = "emfminiserv";
|
||||
text = ''
|
||||
read -ra vars < <(xargs <"${config.my.vault.secrets.emfminiserv-environment.path}")
|
||||
export "''${vars[@]}"
|
||||
exec "${emfminiserv}/bin/emfminiserv" -base_dir '${cfg.serveDir}' "$@"
|
||||
'';
|
||||
})
|
||||
];
|
||||
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
virtualHosts."${cfg.hostname}" = {
|
||||
listenAddresses = lib.mkIf (cfg.listenAddresses != null) cfg.listenAddresses;
|
||||
extraConfig = ''
|
||||
reverse_proxy unix//run/emfminiserv/listen.sock {
|
||||
@accel header X-Accel-Redir *
|
||||
handle_response @accel {
|
||||
root * ${cfg.serveDir}
|
||||
rewrite * {rp.header.X-Accel-Redir}
|
||||
method * GET
|
||||
file_server
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
systemd.services.caddy.serviceConfig.SupplementaryGroups = lib.mkAfter [ "hackyplayer" ];
|
||||
})
|
||||
];
|
||||
}
|
271
ops/nixos/lib/hackyplayer.nix
Normal file
271
ops/nixos/lib/hackyplayer.nix
Normal file
|
@ -0,0 +1,271 @@
|
|||
# SPDX-FileCopyrightText: 2024 Luke Granger-Brown <depot@lukegb.com>
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
{ depot, pkgs, lib, config, ... }:
|
||||
|
||||
let
|
||||
hackyplayerSrc = /home/lukegb/Projects/hackyplayer;
|
||||
hackyplayer = import hackyplayerSrc { inherit pkgs; };
|
||||
|
||||
yamlFormat = pkgs.formats.yaml {};
|
||||
|
||||
cfg = config.my.hackyplayer;
|
||||
processedConfig = lib.mapAttrs' (name: value: lib.nameValuePair "FLASK_${name}" (builtins.toJSON value)) cfg.config;
|
||||
readWritePaths = [
|
||||
cfg.config.VIDEO_OUTPUT
|
||||
cfg.config.VIDEO_TEMP
|
||||
cfg.config.LOG_DIR
|
||||
]
|
||||
++ (map (value: value.OUTPUT_DIR) cfg.config.WATCHFOLDERS)
|
||||
++ (map (value: value.FULLPATH) cfg.config.WATCHFOLDERS);
|
||||
in
|
||||
{
|
||||
options.my.hackyplayer = {
|
||||
enable = lib.mkEnableOption "hackyplayer";
|
||||
hostname = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
listenAddresses = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.listOf lib.types.str);
|
||||
default = null;
|
||||
};
|
||||
config = lib.mkOption {
|
||||
type = lib.types.anything;
|
||||
default = let
|
||||
paths = {
|
||||
input = "/store/emf/2024/video/input";
|
||||
source = "/store/emf/2024/video/source";
|
||||
output = "/store/emf/2024/video/output";
|
||||
temp = "/store/emf/2024/video/tmp";
|
||||
logs = "/store/emf/2024/video/logs";
|
||||
};
|
||||
in {
|
||||
VIDEO_SOURCES = [{
|
||||
DISKDIR = paths.source;
|
||||
WEBDIR = "source";
|
||||
EXT = [".mp4"];
|
||||
NAME = "Source";
|
||||
} {
|
||||
DISKDIR = paths.output;
|
||||
WEBDIR = "output";
|
||||
EXT = [".mp4"];
|
||||
NAME = "Output";
|
||||
}];
|
||||
VIDEO_OUTPUT = paths.output;
|
||||
VIDEO_TEMP = paths.temp;
|
||||
WATCHFOLDERS = [{
|
||||
NAME = "input";
|
||||
FULLPATH = paths.input;
|
||||
OUTPUT_DIR = paths.source;
|
||||
}];
|
||||
LOG_DIR = paths.logs;
|
||||
};
|
||||
};
|
||||
caddyPrefixExtraHandles = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
};
|
||||
caddyPrefixExtraConfig = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
};
|
||||
gunicornConcurrency = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 4;
|
||||
};
|
||||
workerConcurrency = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 4;
|
||||
};
|
||||
vouch = {
|
||||
enable = lib.mkEnableOption "hackyplayer-vouch";
|
||||
config = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = yamlFormat.type;
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf cfg.enable {
|
||||
users.users.hackyplayer = {
|
||||
isSystemUser = true;
|
||||
group = "hackyplayer";
|
||||
};
|
||||
users.groups.hackyplayer = {};
|
||||
|
||||
systemd.services.hackyplayer = {
|
||||
serviceConfig = {
|
||||
User = "hackyplayer";
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = "read-only";
|
||||
PrivateTmp = true;
|
||||
RemoveIPC = true;
|
||||
RuntimeDirectory = "hackyplayer";
|
||||
ExecStart = "${hackyplayer}/bin/gunicorn -w ${toString cfg.gunicornConcurrency} --bind unix:/run/hackyplayer/hackyplayer.sock hackyplayer.app:app";
|
||||
EnvironmentFile = config.my.vault.secrets.hackyplayer-environment.path;
|
||||
};
|
||||
wantedBy = [ "hackyplayer.target" ];
|
||||
environment = processedConfig;
|
||||
};
|
||||
systemd.services.hackyplayer-celery = {
|
||||
serviceConfig = {
|
||||
User = "hackyplayer";
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = "read-only";
|
||||
PrivateTmp = true;
|
||||
RemoveIPC = true;
|
||||
RuntimeDirectory = "hackyplayer-celery";
|
||||
ExecStart = "${hackyplayer}/bin/celery -A hackyplayer.tasks worker --concurrency ${toString cfg.workerConcurrency} --loglevel INFO --statedb /run/hackyplayer-celery/state.db";
|
||||
ReadWritePaths = readWritePaths;
|
||||
EnvironmentFile = config.my.vault.secrets.hackyplayer-environment.path;
|
||||
};
|
||||
wantedBy = [ "hackyplayer.target" ];
|
||||
environment = processedConfig;
|
||||
};
|
||||
systemd.targets.hackyplayer = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
my.vault.secrets.hackyplayer-environment = {
|
||||
reloadOrRestartUnits = ["hackyplayer.service"];
|
||||
group = "root";
|
||||
template = ''
|
||||
{{ with secret "kv/apps/hackyplayer" }}
|
||||
{{ .Data.data.environment }}
|
||||
{{ end }}
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = let
|
||||
envPrelude = lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList (var: val: "export ${var}=${lib.escapeShellArg val}") processedConfig);
|
||||
in [
|
||||
(pkgs.writeShellApplication {
|
||||
name = "hackyplayer-celery";
|
||||
text = ''
|
||||
${envPrelude}
|
||||
exec ${hackyplayer}/bin/celery -A hackyplayer.tasks "$@"
|
||||
'';
|
||||
})
|
||||
(pkgs.writeShellApplication {
|
||||
name = "hackyplayer-flask";
|
||||
text = ''
|
||||
${envPrelude}
|
||||
exec ${hackyplayer}/bin/flask -A hackyplayer.app:app "$@"
|
||||
'';
|
||||
})
|
||||
];
|
||||
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
virtualHosts."${cfg.hostname}" = {
|
||||
listenAddresses = lib.mkIf (cfg.listenAddresses != null) cfg.listenAddresses;
|
||||
extraConfig = ''
|
||||
${cfg.caddyPrefixExtraHandles}
|
||||
handle {
|
||||
${cfg.caddyPrefixExtraConfig}
|
||||
${lib.concatMapStrings (src: ''
|
||||
route /static/video/${src.WEBDIR}/* {
|
||||
uri strip_prefix /static/video/${src.WEBDIR}
|
||||
root * ${src.DISKDIR}
|
||||
file_server
|
||||
}
|
||||
'') cfg.config.VIDEO_SOURCES}
|
||||
route /static/* {
|
||||
uri strip_prefix /static
|
||||
root * ${hackyplayer}/${hackyplayer.python.sitePackages}/hackyplayer/static
|
||||
file_server
|
||||
}
|
||||
reverse_proxy unix//run/hackyplayer/hackyplayer.sock
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
systemd.services.caddy.serviceConfig.SupplementaryGroups = lib.mkAfter [ "hackyplayer" ];
|
||||
|
||||
services.redis.servers."".enable = true;
|
||||
|
||||
my.hackyplayer.vouch.enable = lib.mkDefault true;
|
||||
my.hackyplayer.vouch.config = lib.mkDefault {
|
||||
vouch = {
|
||||
allowAllUsers = true;
|
||||
cookie.domain = "voc.emf.camp";
|
||||
listen = "unix:/run/hacky-vouchproxy/sock";
|
||||
socket_mode = "0770";
|
||||
socket_group = "hackyplayer";
|
||||
document_root = "/_vouch";
|
||||
};
|
||||
|
||||
oauth = let
|
||||
base = "https://identity.emfcamp.org";
|
||||
in {
|
||||
provider = "oidc";
|
||||
auth_url = "${base}/oauth2/authorize";
|
||||
token_url = "${base}/oauth2/token";
|
||||
user_info_url = "${base}/oauth2/userinfo";
|
||||
scopes = [ "profile" ];
|
||||
callback_url = "https://hackyplayer.voc.emf.camp/auth";
|
||||
};
|
||||
};
|
||||
}) (lib.mkIf cfg.vouch.enable {
|
||||
environment.etc."hacky-vouchproxy/config.yaml".source = yamlFormat.generate "hackyplayer-vouch-config.yaml" cfg.vouch.config;
|
||||
systemd.services.hacky-vouchproxy = {
|
||||
serviceConfig = {
|
||||
User = "hacky-vouchproxy";
|
||||
SupplementaryGroups = [ "hackyplayer" ];
|
||||
DynamicUser = true;
|
||||
RuntimeDirectory = "hacky-vouchproxy";
|
||||
ExecStart = "${pkgs.vouch-proxy}/bin/vouch-proxy -config /etc/hacky-vouchproxy/config.yaml";
|
||||
EnvironmentFile = config.my.vault.secrets.hacky-vouchproxy-environment.path;
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
my.vault.secrets.hacky-vouchproxy-environment = {
|
||||
reloadOrRestartUnits = ["hacky-vouchproxy.service"];
|
||||
group = "root";
|
||||
template = ''
|
||||
{{ with secret "kv/apps/hacky-vouchproxy" }}
|
||||
{{ .Data.data.environment }}
|
||||
{{ end }}
|
||||
'';
|
||||
};
|
||||
|
||||
my.hackyplayer.caddyPrefixExtraHandles = lib.mkBefore ''
|
||||
handle /auth {
|
||||
reverse_proxy unix//run/hacky-vouchproxy/sock {
|
||||
rewrite /_vouch/auth
|
||||
}
|
||||
}
|
||||
handle /_vouch/* {
|
||||
reverse_proxy unix//run/hacky-vouchproxy/sock
|
||||
}
|
||||
'';
|
||||
my.hackyplayer.caddyPrefixExtraConfig = lib.mkBefore ''
|
||||
reverse_proxy unix//run/hacky-vouchproxy/sock {
|
||||
method GET
|
||||
rewrite /_vouch/validate
|
||||
|
||||
header_up Host {host}
|
||||
|
||||
@good status 2xx
|
||||
handle_response @good {
|
||||
request_header X-Vouch-User {rp.header.X-Vouch-User}
|
||||
}
|
||||
|
||||
@bad status 4xx
|
||||
handle_response @bad {
|
||||
header Location /_vouch/login?url=https://{host}{uri}&vouch-failcount={rp.header.X-Vouch-Failcount}&X-Vouch-Token={rp.header.X-Vouch-JWT}&error={rp.header.X-Vouch-Err}
|
||||
respond 303 {
|
||||
close
|
||||
}
|
||||
}
|
||||
}
|
||||
'';
|
||||
})
|
||||
];
|
||||
}
|
|
@ -15,6 +15,7 @@ in {
|
|||
../lib/rexxar-distributed.nix
|
||||
../lib/quadv-ca/default.nix
|
||||
((import ../../../third_party/lanzaboote.nix { }).nixosModules.lanzaboote)
|
||||
../lib/hackyplayer.nix
|
||||
];
|
||||
|
||||
boot = lib.mkMerge [{
|
||||
|
@ -299,6 +300,12 @@ in {
|
|||
enable = true;
|
||||
};
|
||||
|
||||
my.hackyplayer = {
|
||||
enable = true;
|
||||
listenAddresses = [ "127.0.0.1" "::1" ];
|
||||
hostname = "hackyplayer.localhost";
|
||||
};
|
||||
|
||||
# This value determines the NixOS release with which your system is to be
|
||||
# compatible, in order to avoid breaking some software such as database
|
||||
# servers. You should change this only after NixOS release notes say you
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
../lib/bgp.nix
|
||||
../lib/gitlab-runner-cacher.nix
|
||||
#../lib/nixbuild-distributed.nix # error: build of '/nix/store/3r7456yr8r9g4fl7w6xbgqlbsdjwfvr4-stdlib-pkgs.json.drv' on 'ssh://eu.nixbuild.net' failed: unexpected: Built outputs are invalid
|
||||
../lib/hackyplayer.nix
|
||||
../lib/emfminiserv.nix
|
||||
];
|
||||
|
||||
# Otherwise _this_ machine won't enumerate things properly.
|
||||
|
@ -56,6 +58,13 @@
|
|||
"/store" = zfs "zu2/safe/store";
|
||||
"/home" = zfs "zu2/safe/home";
|
||||
|
||||
"/store/emf" = zfs "zu2/safe/store/emf";
|
||||
"/store/emf/2024" = zfs "zu2/safe/store/emf/2024";
|
||||
"/store/emf/2024/video" = zfs "zu2/safe/store/emf/2024/video";
|
||||
"/store/emf/2024/video/source" = zfs "zu2/safe/store/emf/2024/video/source";
|
||||
"/store/emf/2024/video/input" = zfs "zu2/safe/store/emf/2024/video/input";
|
||||
"/store/emf/2024/video/output" = zfs "zu2/safe/store/emf/2024/video/output";
|
||||
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-label/ESP";
|
||||
fsType = "vfat";
|
||||
|
@ -81,6 +90,10 @@
|
|||
allowedUDPPorts = [
|
||||
51821 51822 51823
|
||||
34197 # factorio
|
||||
443
|
||||
];
|
||||
allowedTCPPorts = [
|
||||
80 443
|
||||
];
|
||||
};
|
||||
};
|
||||
|
@ -348,8 +361,10 @@
|
|||
wg-cofractal-ams01-private = wireguardSecret "privateKeyToCofractalAms01";
|
||||
};
|
||||
|
||||
users.users.lukegb.extraGroups = lib.mkAfter [ "hackyplayer" ];
|
||||
users.users.samw = {
|
||||
isNormalUser = true;
|
||||
extraGroups = lib.mkAfter [ "hackyplayer "];
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDQdGzwYiallvWXIHgSAf2GOwMJKA8bxPmwyuO+vsd1HwB65hMRPCpKS+FNLIpkrADNnuhGS3xGCGSSuQ+zAu/g="
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNLrJyUXmiFWb9vhlTWZLYr64IsKut+c9TGqq3/uwPDeF4X0Qb2jzxqXfQcDSztjR09JHbC8BOqfpYYT9LHahIo="
|
||||
|
@ -377,5 +392,17 @@
|
|||
};
|
||||
};
|
||||
|
||||
my.hackyplayer = {
|
||||
enable = true;
|
||||
hostname = "hackyplayer.voc.emf.camp";
|
||||
workerConcurrency = 13;
|
||||
};
|
||||
my.emfminiserv = {
|
||||
enable = true;
|
||||
hostname = "prerelease.voc.emf.camp";
|
||||
};
|
||||
|
||||
hardware.rasdaemon.enable = true;
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
}
|
||||
|
|
|
@ -72,6 +72,9 @@
|
|||
my.apps.nixbuild = {};
|
||||
my.apps.tumblrandom = {};
|
||||
my.apps.netbox = {};
|
||||
my.apps.hacky-vouchproxy = {};
|
||||
my.apps.hackyplayer = {};
|
||||
my.apps.emfminiserv = {};
|
||||
|
||||
my.servers.etheroute-lon01.apps = [ "pomerium" ];
|
||||
my.servers.howl.apps = [ "nixbuild" ];
|
||||
|
@ -88,5 +91,5 @@
|
|||
my.servers.bvm-nixosmgmt.apps = [ "plex-pass" ];
|
||||
my.servers.blade-tuvok.apps = [ "fup" ];
|
||||
my.servers.bvm-netbox.apps = [ "netbox" ];
|
||||
my.servers.rexxar.apps = [ "deluge" "gitlab-runner" "nixbuild" ];
|
||||
my.servers.rexxar.apps = [ "deluge" "gitlab-runner" "nixbuild" "hacky-vouchproxy" "hackyplayer" "emfminiserv" ];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue