Redeploy game em

This commit is contained in:
Aner Zakobar
2026-07-30 13:40:44 +03:00
parent cc4803bb82
commit fc457ddf7c
9 changed files with 1353 additions and 25 deletions
+139
View File
@@ -0,0 +1,139 @@
{ config, lib, pkgs, homeyConfig, ... }:
# EmulatorJS — self-hosted web game emulator with per-user save sync.
#
# The Python sidecar (emulatorjs-server.py) serves:
# / → game launcher (lists ROMs)
# /roms/ → ROM listing (JSON) and ROM files
# /play/<name> → EmulatorJS player page for a specific game
# /saves/<name>→ GET/PUT save file (SRAM), keyed by Remote-User header
# /static/ → EmulatorJS JS/CSS/WASM assets (served from Nix store)
#
# Multi-device sync: saves are stored server-side keyed by Authelia
# Remote-User header, so any device the user logs into shares the same save.
#
# EmulatorJS assets are fetched from GitHub at build time — no manual
# download step. To upgrade, change `rev` and replace `hash` with the
# value Nix reports after a failed build (same pattern as caddy.nix).
#
# Setup after first enable:
# 1. Drop ROM files into /mnt/data/emulatorjs/roms/
# Supported: .gb .gbc .gba .nes .snes .sfc .md .gen .n64 .z64
# 2. Visit https://games.<domain> — saves go to
# /mnt/data/emulatorjs/saves/<username>/ automatically.
let
cfg = config.homey.emulatorjs;
dataDir = config.homey.storage.mountPoint;
domain = homeyConfig.domain;
port = 8085;
# EmulatorJS static assets fetched from GitHub at build time.
# Pre-built WASM cores are committed to the repo so no build step is needed.
#
# To upgrade to a new version:
# 1. Find the latest tag:
# git ls-remote --tags https://github.com/EmulatorJS/EmulatorJS | tail -10
# 2. Prefetch the tarball hash:
# nix-prefetch-url --unpack "https://github.com/EmulatorJS/EmulatorJS/archive/refs/tags/vX.Y.Z.tar.gz"
# 3. Convert to SRI format:
# nix hash convert --hash-algo sha256 --to sri <base32-from-step-2>
# 4. Update rev and hash below.
emulatorjsAssets = pkgs.fetchFromGitHub {
owner = "EmulatorJS";
repo = "EmulatorJS";
rev = "v4.2.3";
hash = "sha256-hIgvcVNjl9qGJw0GgkkLQQyd2JhdUOVOQhLAeZuQcMk=";
};
in
{
options.homey.emulatorjs.enable =
lib.mkEnableOption "EmulatorJS self-hosted game emulator";
config = lib.mkIf cfg.enable {
# -------------------------------------------------------------------------
# Dedicated system user so save-file ownership is stable across restarts
# -------------------------------------------------------------------------
users.users.emulatorjs = {
isSystemUser = true;
group = "emulatorjs";
description = "EmulatorJS save-sync server";
};
users.groups.emulatorjs = {};
# -------------------------------------------------------------------------
# Launcher + save-sync server
# -------------------------------------------------------------------------
systemd.services.emulatorjs = {
description = "EmulatorJS launcher and save-sync server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" "mnt-data.mount" "systemd-tmpfiles-setup.service" ];
requires = [ "mnt-data.mount" ];
environment = {
PORT = toString port;
SAVE_DIR = "${dataDir}/emulatorjs/saves";
ROM_DIR = "${dataDir}/emulatorjs/roms";
# EmulatorJS assets live in the Nix store — read-only, no manual setup.
# The data/ subdirectory contains loader.js and the emulator cores.
STATIC_DIR = "${emulatorjsAssets}/data";
THUMBNAILS_DIR = "${dataDir}/emulatorjs/thumbnails";
};
serviceConfig = {
ExecStart = "${pkgs.python3}/bin/python3 ${./emulatorjs-server.py}";
User = "emulatorjs";
Group = "emulatorjs";
Restart = "on-failure";
RestartSec = "5s";
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
ReadWritePaths = [ "${dataDir}/emulatorjs" ];
};
};
# -------------------------------------------------------------------------
# Caddy — one_factor SSO; Remote-User header forwarded to the sidecar
# -------------------------------------------------------------------------
homey.caddy.virtualHosts = [{
subdomain = "games";
port = port;
auth = true;
}];
# -------------------------------------------------------------------------
# Storage directories (owned by the service user)
# -------------------------------------------------------------------------
homey.storage.extraDirs = [
{ path = "emulatorjs"; user = "emulatorjs"; group = "emulatorjs"; }
{ path = "emulatorjs/saves"; user = "emulatorjs"; group = "emulatorjs"; }
{ path = "emulatorjs/roms"; user = "emulatorjs"; group = "emulatorjs"; }
{ path = "emulatorjs/thumbnails"; user = "emulatorjs"; group = "emulatorjs"; }
];
# Only saves need backing up; ROMs and static assets are easy to restore
homey.backup.extraPaths = [ "${dataDir}/emulatorjs/saves" ];
# -------------------------------------------------------------------------
# Authelia access control — one_factor for all household users
# -------------------------------------------------------------------------
homey.authelia.accessControlRules = [{
priority = 57;
domain = [ "games.${domain}" ];
policy = "one_factor";
}];
# -------------------------------------------------------------------------
# Uptime Kuma monitor
# -------------------------------------------------------------------------
homey.monitoring.monitors = [{
name = "EmulatorJS";
url = "https://games.${domain}";
interval = 60;
}];
};
}