observer effect content
This commit is contained in:
parent
625a847a81
commit
e4ee25295c
23 changed files with 2982 additions and 0 deletions
86
services/observer-effect.nix
Normal file
86
services/observer-effect.nix
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
let
|
||||
# Tiny Rust WebSocket relay. cargoLock.lockFile pins deps from the committed
|
||||
# Cargo.lock, so there's no vendor hash to chase on dependency bumps.
|
||||
relay = pkgs.rustPlatform.buildRustPackage {
|
||||
pname = "observer-relay";
|
||||
version = "0.1.0";
|
||||
src = ./observer-effect/relay;
|
||||
cargoLock.lockFile = ./observer-effect/relay/Cargo.lock;
|
||||
};
|
||||
|
||||
# The two static pages (player chronometer + Handler panel) and their assets.
|
||||
site = pkgs.copyPathToStore ./observer-effect/site;
|
||||
|
||||
domain = "observer.ellie.town";
|
||||
port = 8770;
|
||||
in
|
||||
{
|
||||
# Shared control key. Decrypts to a file the relay reads at startup, so it
|
||||
# never lands in /nix/store.
|
||||
sops.secrets."observer/token" = {
|
||||
sopsFile = ./secrets/observer_vps.yaml;
|
||||
owner = "observer";
|
||||
group = "observer";
|
||||
mode = "0400";
|
||||
};
|
||||
|
||||
users.users.observer = {
|
||||
isSystemUser = true;
|
||||
group = "observer";
|
||||
};
|
||||
users.groups.observer = { };
|
||||
|
||||
systemd.services.observer-relay = {
|
||||
description = "Observer Effect doomsday-clock relay";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
environment = {
|
||||
OBSERVER_ADDR = "127.0.0.1:${toString port}";
|
||||
OBSERVER_TOKEN_FILE = config.sops.secrets."observer/token".path;
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${relay}/bin/observer-relay";
|
||||
User = "observer";
|
||||
Group = "observer";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "5s";
|
||||
|
||||
# Hardening — it only needs a loopback socket and to read one secret.
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
NoNewPrivileges = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictSUIDSGID = true;
|
||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
SystemCallFilter = [ "@system-service" ];
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${domain} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
root = site;
|
||||
|
||||
locations."/" = {
|
||||
index = "clock.html";
|
||||
};
|
||||
|
||||
# Tidy URL for the Handler's panel.
|
||||
locations."= /control".return = "302 /control.html";
|
||||
|
||||
# Relay socket: upgrade to WebSocket and hand off to the local service.
|
||||
locations."/ws" = {
|
||||
proxyPass = "http://127.0.0.1:${toString port}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue