diff --git a/nix-system-configs/modules/scripts/pull.zsh b/nix-system-configs/modules/scripts/pull.zsh
index 234e66e..0e2775b 100755
--- a/nix-system-configs/modules/scripts/pull.zsh
+++ b/nix-system-configs/modules/scripts/pull.zsh
@@ -137,11 +137,27 @@ else
print_warn "Secrets directory not found: ${SECRETS_DIR}"
fi
-# Step 2.2: Sync system_scripts directory
+# Step 2.2: Sync styling directory (copy custom themes, templates, css etc.)
+STYLING_DIR="${SCRIPT_DIR}/../styling"
+STYLING_TARGET="/etc/styling"
+
+if [[ -d "$STYLING_DIR" ]]; then
+ print_info "Syncing styling to ${BOLD}${STYLING_TARGET}${RESET}..."
+ if sudo rsync -av --delete "${STYLING_DIR}/" "${STYLING_TARGET}/"; then
+ print_success "Styling synced"
+ else
+ print_error "Failed to sync styling"
+ exit 1
+ fi
+else
+ print_warn "Styling directory not found: ${STYLING_DIR}"
+fi
+
+# Step 2.3: Sync system_scripts directory
SYSTEM_SCRIPT_DIR="${SCRIPT_DIR}/../system_scripts"
SYSTEM_SCRIPT_TARGET="/etc/nixos/system_scripts"
-if [[ -d "$SECRETS_DIR" ]]; then
+if [[ -d "$SYSTEM_SCRIPT_DIR" ]]; then
print_info "Syncing system scripts to ${BOLD}${SYSTEM_SCRIPT_TARGET}${RESET}..."
if sudo rsync -av --delete "${SYSTEM_SCRIPT_DIR}/" "${SYSTEM_SCRIPT_TARGET}/"; then
print_success "System scripts synced"
diff --git a/nix-system-configs/modules/styling/forgejo/header.tmpl b/nix-system-configs/modules/styling/forgejo/header.tmpl
new file mode 100644
index 0000000..007fdb6
--- /dev/null
+++ b/nix-system-configs/modules/styling/forgejo/header.tmpl
@@ -0,0 +1,21 @@
+{{/* Custom header content - inject custom fonts that apply to all themes */}}
+
+
+
+
diff --git a/nix-system-configs/modules/styling/forgejo/home.tmpl b/nix-system-configs/modules/styling/forgejo/home.tmpl
new file mode 100644
index 0000000..1f5db13
--- /dev/null
+++ b/nix-system-configs/modules/styling/forgejo/home.tmpl
@@ -0,0 +1,13 @@
+{{template "base/head" .}}
+
+{{template "base/footer" .}}
diff --git a/nix-system-configs/modules/styling/forgejo/theme-custom.css b/nix-system-configs/modules/styling/forgejo/theme-custom.css
new file mode 100644
index 0000000..ff5554f
--- /dev/null
+++ b/nix-system-configs/modules/styling/forgejo/theme-custom.css
@@ -0,0 +1,16 @@
+
+@font-face {
+ font-family: 'Maple Mono NF';
+ src: url('/assets/fonts/MapleMonoNerd.ttf') format('truetype');
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
+/* import base Forgejo theme so we only override what we need */
+@import "./theme-forgejo-auto.css";
+
+:root {
+ /* prefer the Maple Mono Nerd Font for monospace usage */
+ --fonts-monospace: 'Maple Mono NF' !important;
+}
\ No newline at end of file
diff --git a/nix-system-configs/modules/system/forgejo.nix b/nix-system-configs/modules/system/forgejo.nix
index 4da5e8b..0108c14 100644
--- a/nix-system-configs/modules/system/forgejo.nix
+++ b/nix-system-configs/modules/system/forgejo.nix
@@ -8,6 +8,23 @@
cfg = config.services.forgejo;
srv = cfg.settings.server;
choose = paths: builtins.head (builtins.filter (p: builtins.pathExists p) paths);
+ mapleZip = pkgs.fetchurl {
+ url = "https://github.com/subframe7536/maple-font/releases/download/v7.9/MapleMonoNormal-NF-unhinted.zip";
+ sha256 = "1j8bh8fzrnrj4348xj8l1jpbchbblhi2a7gryarf2mi88xr1yc3f";
+ };
+
+ # Add a runCommand that unpacks the downloaded zip and exposes a stable ttf path
+ mapleFonts = pkgs.runCommand "maple-fonts" {buildInputs = [pkgs.unzip];} ''
+ mkdir -p $out/tmp
+ unzip -q ${mapleZip} -d $out/tmp
+ f="$(find $out/tmp -type f -name '*.ttf' | head -n1)"
+ if [ -z "$f" ]; then
+ echo "no ttf found" >&2
+ exit 1
+ fi
+ mkdir -p $out/fonts
+ cp "$f" $out/fonts/MapleMonoNerd.ttf
+ '';
in {
options.local = {
hostname = lib.mkOption {
@@ -67,6 +84,9 @@ in {
# Forgejo configuration
services.forgejo = {
enable = true;
+ # Explicit custom directory where Forgejo will look for custom templates/assets
+ # Ensure this matches what systemd.tmpfiles will populate below.
+ customDir = "/var/lib/forgejo/custom";
database = {
createDatabase = false; # Database already created, DO NOT REMOVE THIS OR IT WILL DEFAULT INTO INTERNAL ONE
type = "postgres";
@@ -100,6 +120,56 @@ in {
# ENABLED = false;
# };
};
+
+ settings.ui = {
+ DEFAULT_THEME = "forgejo-auto";
+ THEMES = "forgejo-auto,forgejo-light,forgejo-dark";
+ };
+ };
+
+ systemd.tmpfiles.rules = [
+ "d '${config.services.forgejo.customDir}/templates' - forgejo forgejo - -"
+ # create the custom/templates/custom folder so header.tmpl can live under templates/custom
+ "d '${config.services.forgejo.customDir}/templates/custom' - forgejo forgejo - -"
+ "d '${config.services.forgejo.customDir}/public' - forgejo forgejo - -"
+ "d '${config.services.forgejo.customDir}/public/assets' - forgejo forgejo - -"
+ # ensure fonts directory exists
+ "d '${config.services.forgejo.customDir}/public/assets/fonts' - forgejo forgejo - -"
+ # ensure css directory exists so we can place theme css
+ "d '${config.services.forgejo.customDir}/public/assets/css' - forgejo forgejo - -"
+ # install the TTF from the Nix store into the Forgejo customDir
+ "C+ '${config.services.forgejo.customDir}/public/assets/fonts/MapleMonoNerd.ttf' - forgejo forgejo - ${mapleFonts}/fonts/MapleMonoNerd.ttf"
+ "C+ '${config.services.forgejo.customDir}/templates/home.tmpl' - forgejo forgejo - ${
+ ../styling/forgejo/home.tmpl
+ }"
+ # copy header.tmpl into templates/custom so we can inject custom CSS into the
+ "C+ '${config.services.forgejo.customDir}/templates/custom/header.tmpl' - forgejo forgejo - ${
+ ../styling/forgejo/header.tmpl
+ }"
+ # copy your theme CSS into the public assets so Forgejo serves it directly
+ "C+ '${config.services.forgejo.customDir}/public/assets/css/theme-custom.css' - forgejo forgejo - ${
+ ../styling/forgejo/theme-custom.css
+ }"
+ ];
+
+ # Fallback: one-shot systemd service to copy custom assets on activation (works even if tmpfiles isn't applied or for live testing)
+ systemd.services."forgejo-custom-files" = {
+ description = "Install Forgejo custom templates and assets into customDir";
+ after = [ "network.target" ];
+ serviceConfig = {
+ Type = "oneshot";
+ # Use bash -c to run a compact copy/install script that ensures dirs exist and files are owned by forgejo
+ ExecStart = ''${pkgs.bash}/bin/bash -c "set -eu; \
+ install -d -m0755 -o forgejo -g forgejo ${config.services.forgejo.customDir}/public/assets/fonts; \
+ install -d -m0755 -o forgejo -g forgejo ${config.services.forgejo.customDir}/public/assets/css; \
+ install -d -m0755 -o forgejo -g forgejo ${config.services.forgejo.customDir}/templates/custom; \
+ cp -a ${mapleFonts}/fonts/MapleMonoNerd.ttf ${config.services.forgejo.customDir}/public/assets/fonts/MapleMonoNerd.ttf; \
+ cp -a ${toString ../styling/forgejo/header.tmpl} ${config.services.forgejo.customDir}/templates/custom/header.tmpl; \
+ cp -a ${toString ../styling/forgejo/home.tmpl} ${config.services.forgejo.customDir}/templates/home.tmpl; \
+ cp -a ${toString ../styling/forgejo/theme-custom.css} ${config.services.forgejo.customDir}/public/assets/css/theme-custom.css; \
+ chown -R forgejo:forgejo ${config.services.forgejo.customDir}"'';
+ };
+ wantedBy = [ "multi-user.target" ];
};
# Open ports in the firewall.