From 48a837a91959efbc7da7f98447c50f32b4ee7c94 Mon Sep 17 00:00:00 2001 From: Collin Williams <96917990+bluedragon1221@users.noreply.github.com> Date: Thu, 2 Apr 2026 16:18:29 -0500 Subject: jta, other changes --- modules/services/nixos/default.nix | 3 +- modules/services/nixos/jta/default.nix | 49 ++++++++++ modules/services/nixos/jta/go.mod | 5 + modules/services/nixos/jta/go.sum | 2 + modules/services/nixos/jta/index.html | 129 +++++++++++++++++++++++++ modules/services/nixos/jta/main.go | 95 ++++++++++++++++++ modules/services/nixos/jta/md_template.html | 11 +++ modules/services/nixos/jta/pkg.nix | 6 ++ modules/services/nixos/jta/style.css | 143 ++++++++++++++++++++++++++++ modules/services/nixos/openssh.nix | 2 +- modules/services/options.nix | 5 + 11 files changed, 447 insertions(+), 3 deletions(-) create mode 100644 modules/services/nixos/jta/default.nix create mode 100644 modules/services/nixos/jta/go.mod create mode 100644 modules/services/nixos/jta/go.sum create mode 100644 modules/services/nixos/jta/index.html create mode 100644 modules/services/nixos/jta/main.go create mode 100644 modules/services/nixos/jta/md_template.html create mode 100644 modules/services/nixos/jta/pkg.nix create mode 100644 modules/services/nixos/jta/style.css (limited to 'modules/services') diff --git a/modules/services/nixos/default.nix b/modules/services/nixos/default.nix index d0e170c..32efb1c 100644 --- a/modules/services/nixos/default.nix +++ b/modules/services/nixos/default.nix @@ -8,9 +8,8 @@ ./btopweb.nix ./cgit + ./jta ./polaris.nix - # ./mopidy.nix - # ./jellyfin.nix ./agate.nix ./minecraft.nix ./copyparty.nix diff --git a/modules/services/nixos/jta/default.nix b/modules/services/nixos/jta/default.nix new file mode 100644 index 0000000..c1ea012 --- /dev/null +++ b/modules/services/nixos/jta/default.nix @@ -0,0 +1,49 @@ +{ + pkgs, + config, + lib, + ... +}: let + cfg = config.collinux.services.jta; + + package = pkgs.callPackage ./pkg.nix {}; +in { + imports = [ + (import ../mkCaddyCfg.nix cfg) + ]; + + config = lib.mkIf cfg.enable { + users.groups."jta" = {}; + users.users."jta" = { + isSystemUser = true; + group = "jta"; + extraGroups = ["fileserver"]; + + home = "/var/lib/jta"; + createHome = true; + homeMode = "755"; + }; + + systemd.services."jta" = { + description = "Juksere trives aldri, kids"; + restartIfChanged = true; + wants = ["network-online.target" "caddy.service"]; + after = ["network-online.target" "caddy.service"]; + + environment = { + PORT = toString cfg.port; + ROOT_DIR = "/media/jta"; + }; + + serviceConfig = { + User = "jta"; + Type = "simple"; + + WorkingDirectory = "/var/lib/jta"; + ExecStart = "${package}/bin/jta"; + }; + + wantedBy = ["multi-user.target"]; + }; + }; +} diff --git a/modules/services/nixos/jta/go.mod b/modules/services/nixos/jta/go.mod new file mode 100644 index 0000000..8f27af1 --- /dev/null +++ b/modules/services/nixos/jta/go.mod @@ -0,0 +1,5 @@ +module git.ganymede/jta + +go 1.25.5 + +require github.com/yuin/goldmark v1.8.2 diff --git a/modules/services/nixos/jta/go.sum b/modules/services/nixos/jta/go.sum new file mode 100644 index 0000000..6a37955 --- /dev/null +++ b/modules/services/nixos/jta/go.sum @@ -0,0 +1,2 @@ +github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= +github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= diff --git a/modules/services/nixos/jta/index.html b/modules/services/nixos/jta/index.html new file mode 100644 index 0000000..fd93de6 --- /dev/null +++ b/modules/services/nixos/jta/index.html @@ -0,0 +1,129 @@ + + + + + + jta@ganymede + + + + +
Juksere Trives Aldri
+ +
+ + + + diff --git a/modules/services/nixos/jta/main.go b/modules/services/nixos/jta/main.go new file mode 100644 index 0000000..3e5fc1f --- /dev/null +++ b/modules/services/nixos/jta/main.go @@ -0,0 +1,95 @@ +package main + +import ( + "bytes" + _ "embed" + "html/template" + "net/http" + "os" + "path/filepath" + "strings" + + "github.com/yuin/goldmark" + "github.com/yuin/goldmark/extension" +) + +// Configure Goldmark with GitHub Flavored Markdown +var mdParser = goldmark.New( + goldmark.WithExtensions( + extension.GFM, + ), +) + +//go:embed md_template.html +var mdTemplate string + +//go:embed style.css +var styleCSS string + +//go:embed index.html +var indexHTML string + +var pageTmpl = template.Must(template.New("md_template.html").Parse(mdTemplate)) + +func serveMarkdown(w http.ResponseWriter, r *http.Request) { + // Prevent path traversal + clean := filepath.Clean(r.URL.Path) + path := filepath.Join(rootDir, strings.TrimPrefix(clean, "/")) + + mdBytes, err := os.ReadFile(path) + if err != nil { + http.NotFound(w, r) + return + } + + var buf bytes.Buffer + if err := mdParser.Convert(mdBytes, &buf); err != nil { + http.Error(w, "failed to render markdown", 500) + return + } + + w.Header().Set("Content-Type", "text/html; charset=utf-8") + + pageTmpl.Execute(w, map[string]template.HTML{ + "Content": template.HTML(buf.String()), + }) +} + +var rootDir = "." + +func main() { + if envRootDir := os.Getenv("ROOT_DIR"); envRootDir != "" { + rootDir = envRootDir + } + + fs := http.FileServer(http.Dir(rootDir)) + port := os.Getenv("PORT") + if port == "" { + port = "8080" + } + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" || r.URL.Path == "/index.html" { + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.Write([]byte(indexHTML)) + return + } + + if r.URL.Path == "/style.css" { + w.Header().Set("Content-Type", "text/css; charset=utf-8") + w.Write([]byte(styleCSS)) + return + } + + // Intercept markdown files + if strings.HasSuffix(r.URL.Path, ".md") { + serveMarkdown(w, r) + return + } + + // Otherwise serve normally + fs.ServeHTTP(w, r) + }) + + http.ListenAndServe(":"+port, nil) +} diff --git a/modules/services/nixos/jta/md_template.html b/modules/services/nixos/jta/md_template.html new file mode 100644 index 0000000..daa57b7 --- /dev/null +++ b/modules/services/nixos/jta/md_template.html @@ -0,0 +1,11 @@ + + + + + JTA + + + + {{.Content}} + + diff --git a/modules/services/nixos/jta/pkg.nix b/modules/services/nixos/jta/pkg.nix new file mode 100644 index 0000000..c8f7d77 --- /dev/null +++ b/modules/services/nixos/jta/pkg.nix @@ -0,0 +1,6 @@ +{pkgs ? import {system = "x86_64-linux";}, ...}: +pkgs.buildGoModule { + name = "jta"; + src = ./.; + vendorHash = "sha256-aeJYO52ALbGxyTFPw6eGCmPlmuCvbXEoX9gcXatN29E="; +} diff --git a/modules/services/nixos/jta/style.css b/modules/services/nixos/jta/style.css new file mode 100644 index 0000000..1d52d19 --- /dev/null +++ b/modules/services/nixos/jta/style.css @@ -0,0 +1,143 @@ +:root { + --bg: #0f172a; + --card: #1e293b; + --accent: #22c55e; + --text: #e2e8f0; + --text-soft: #cbd5e1; + --muted: #94a3b8; + --border: #334155; + + --font-body: "Avenir Next", "Segoe UI", "Noto Sans", "Helvetica Neue", sans-serif; + --font-heading: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", Palatino, serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + + --step--1: clamp(0.88rem, 0.86rem + 0.12vw, 0.96rem); + --step-0: clamp(1rem, 0.98rem + 0.16vw, 1.08rem); + --step-1: clamp(1.14rem, 1.08rem + 0.26vw, 1.28rem); + --step-2: clamp(1.3rem, 1.2rem + 0.45vw, 1.56rem); + --step-3: clamp(1.7rem, 1.45rem + 1.1vw, 2.25rem); +} + +/* Base layout */ +body { + font-family: var(--font-body); + font-size: var(--step-0); + background: var(--bg); + color: var(--text); + max-width: 850px; + margin: 2rem auto; + padding: 1.5rem; + line-height: 1.7; + text-rendering: optimizeLegibility; +} + +/* Headings */ +h1 { + font-family: var(--font-heading); + font-size: var(--step-3); + line-height: 1.15; + font-weight: 700; + letter-spacing: -0.02em; + text-align: center; + margin: 0 0 1.25rem; +} + +h2 { + font-family: var(--font-heading); + margin-top: 2.25rem; + margin-bottom: 0.75rem; + font-size: var(--step-2); + line-height: 1.25; + letter-spacing: -0.01em; +} + +h3 { + font-family: var(--font-heading); + margin-top: 1.5rem; + margin-bottom: 0.6rem; + font-size: var(--step-1); + line-height: 1.3; + color: var(--text-soft); +} + +/* Text */ +p { + color: var(--text); + margin-bottom: 1rem; + max-width: 65ch; +} + +/* Ordered list (questions) */ +ol { + padding-left: 1.2rem; + max-width: 65ch; +} + +/* Answer list */ +ul { + list-style: none; + padding-left: 1.2rem; + max-width: 65ch; +} + +ul li { + display: flex; + align-items: flex-start; + gap: 0.6rem; + padding: 0.35rem 0.4rem; + border-radius: 8px; + transition: background 0.15s ease; +} + +/* Checkbox styling */ +input[type="checkbox"] { + accent-color: var(--accent); + transform: scale(1.2); + margin-top: 0.2rem; + pointer-events: none; +} + +/* Correct answers */ +li:has(input[type="checkbox"]:checked) { + color: #86efac; + font-weight: 500; +} + +/* Code blocks */ +pre { + font-family: var(--font-mono); + font-size: var(--step--1); + line-height: 1.6; + background: #020617; + padding: 1rem; + border-radius: 10px; + overflow-x: auto; + margin: 1rem 0; + max-width: 65ch; +} + +code { + font-family: var(--font-mono); + font-size: 0.95em; + background: #020617; + padding: 2px 6px; + border-radius: 6px; +} + +/* Links */ +a { + color: #93c5fd; + text-decoration-line: underline; + text-decoration-thickness: 2px; + text-underline-offset: 0.14em; + text-decoration-color: rgba(147, 197, 253, 0.45); +} + +a:hover { + text-decoration-color: currentColor; +} + +/* Optional: make everything feel tighter and nicer */ +* { + box-sizing: border-box; +} diff --git a/modules/services/nixos/openssh.nix b/modules/services/nixos/openssh.nix index 2d0c45c..1ce1abc 100644 --- a/modules/services/nixos/openssh.nix +++ b/modules/services/nixos/openssh.nix @@ -18,7 +18,7 @@ in { services.openssh = { enable = true; - allowSFTP = false; + allowSFTP = true; hostKeys = [ { diff --git a/modules/services/options.nix b/modules/services/options.nix index 0484b6b..bb43180 100644 --- a/modules/services/options.nix +++ b/modules/services/options.nix @@ -109,6 +109,11 @@ in { default_port = 8076; }; + jta = webserviceOptions { + service_name = "jta"; + default_port = 8072; + }; + copyparty = (webserviceOptions { service_name = "copyparty"; -- cgit v1.3.1