Redeploy game em
This commit is contained in:
@@ -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;
|
||||
}];
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user