diff --git a/home/features/neovim/config/ftplugin/just.lua b/home/features/neovim/config/ftplugin/just.lua new file mode 100644 index 0000000..a9127ec --- /dev/null +++ b/home/features/neovim/config/ftplugin/just.lua @@ -0,0 +1 @@ +vim.opt.commentstring = "# %s" diff --git a/home/features/wayland/hyprland/hyprland.conf b/home/features/wayland/hyprland/hyprland.conf index 274b8e2..8fda7eb 100644 --- a/home/features/wayland/hyprland/hyprland.conf +++ b/home/features/wayland/hyprland/hyprland.conf @@ -65,6 +65,7 @@ windowrulev2 = workspace 2 silent, title:^(.*Firefox.*)$ windowrulev2 = workspace 3 silent, title:^(.*(Disc|WebC)ord.*)$ windowrulev2 = workspace 3 silent, title:^(.*(V|v)esktop.*)$ windowrulev2 = workspace 3 silent, title:^(.*Element.*)$ +windowrulev2 = workspace 4 silent, title:^(.*angelfold.*)$ windowrulev2 = workspace 6 silent, title:^(.*(S|s)pot(ify)?.*)$ windowrulev2 = workspace 7 silent, class:^(.*Obsidian.*)$ windowrulev2 = workspace 8 silent, class:^(.*Smos.*)$ diff --git a/hosts/nixos/common/global/ports.nix b/hosts/nixos/common/global/ports.nix index 21a0581..e73773b 100644 --- a/hosts/nixos/common/global/ports.nix +++ b/hosts/nixos/common/global/ports.nix @@ -26,5 +26,8 @@ syncthing = 8422; forgejo-ssh = 8423; "5d-diplomacy" = 8424; + glass-server = 8425; + glass-server-lp-tcp = 8426; + glass-server-lp-udp = 8427; }; } diff --git a/hosts/nixos/common/global/unicode.nix b/hosts/nixos/common/global/unicode.nix index 5872be3..053657f 100644 --- a/hosts/nixos/common/global/unicode.nix +++ b/hosts/nixos/common/global/unicode.nix @@ -1,11 +1,12 @@ { pkgs, ... }: { i18n.inputMethod = { - enabled = "fcitx5"; + type = "fcitx5"; + enable = true; fcitx5.addons = with pkgs; [ + fcitx5-mozc # for japanese input fcitx5-gtk - fcitx5-configtool ]; + fcitx5.waylandFrontend = true; }; } - diff --git a/hosts/nixos/common/secrets.yaml b/hosts/nixos/common/secrets.yaml index 6b5ab79..92647a0 100644 --- a/hosts/nixos/common/secrets.yaml +++ b/hosts/nixos/common/secrets.yaml @@ -63,8 +63,8 @@ sops: YnQ4SnljYXBBOUZWQisxZTBrcERYZVUKvMK8LbBt482Vs5i+yBE6SmKWiLLIaEwD oSnmItFMeqtW+D1YR+YfODckgKjCuDYoIHmHe0TGYnYZpd/xo0vHTA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-09-11T13:44:03Z" - mac: ENC[AES256_GCM,data:uRdBwVDRiagp3Wh8e/JxxVK4p8SE5BardFh8Jin0wDg9VIILzPrYjoqb3qMS10xqrM3QcXy3CfobrogfWLaS2G88FziiUFGm0eSQnq29gGrFDJFOu7zUwGHwFIQ4BaABytj04bLY6u4E1AAEIpaTCs9ODc0c/WS0Cpaad/XtdF0=,iv:dkkH0/cBVk4WjqXgsbhjHMjF2QhcrRlA9ckok83jlfw=,tag:hHobJ9oWlTIo2PQgt6WnTA==,type:str] + lastmodified: "2025-02-07T15:00:36Z" + mac: ENC[AES256_GCM,data:tab2DGDutayRJ9+LgL6Ctv6MZbVWFDGCYcRYBxZfffHS1Qb4R6y76TG1zGGTugwDQUXvmto/RF4E7tB7bHmHGsT/vTwNt3W2Mj2hpxk2azutXU8lxiIz2QMMEi4nQSQYYjba1UN/Yv/YC0fsdIBK0E7TthcW4ytlWw/mRFp9uLE=,iv:x++zthM7yv8CTiVFC85P6GRD+pTFER8N1caz59CmM2w=,tag:i6bLMksP6Gqspko/Fx2vAw==,type:str] pgp: [] unencrypted_suffix: _unencrypted - version: 3.8.1 + version: 3.9.1 diff --git a/hosts/nixos/lapetus/secrets.yaml b/hosts/nixos/lapetus/secrets.yaml index b254038..b7461a1 100644 --- a/hosts/nixos/lapetus/secrets.yaml +++ b/hosts/nixos/lapetus/secrets.yaml @@ -9,6 +9,8 @@ forgejo_mail_password: ENC[AES256_GCM,data:linrpmA8b+8e1+tWNl0=,iv:Mk7suPq0Jt960 javi_password: ENC[AES256_GCM,data:5Ifh/DclUz0/AL69Th/GckolrjerLOnDW77SOf+/L3v39T+EOYgK2GDNKtWGGWYX5sdxZ9JwLS3ZVsIOnN4zjFhgV+GChJWkkzjdpJEtpHlmmBKlyS31Fw7SixVkL3y3VJhw72aVv3bMKQ==,iv:FzAmvIlrhna5InsQCRrWVdrKZGmHMb0njWdvgBurdYs=,tag:/Iguu2FbdV/4RSGTnFdyYA==,type:str] vpn_env: ENC[AES256_GCM,data:+61Ft1xj1WnaGH6SdUj3sQunDeTWTQ/G2GVQr1KxXVmLehAdO3W2qwqPRsq0qaad3E6eXd7kMU78w1/9fXM34mJXArmXNPW1X+0549+NX4t3QVP83cIRw6B5vwlWMIA8ixEk46a+t7/C6A10hqpyhqHmeyQEOwJvG+Pou61lBmhSkMQy5gjH4ZNsHHZV0/6ZxSk0yAPQq76cPz4dFvyDzdonLnb+2s1KhHC3D7P6SfuWnfJ1EglrDT8R+A==,iv:mw26zTyFnq9CjN06eRmBTWNjh6SRDY7WOCyhBCmyglg=,tag:cPJvzgtruQNLSg7B+br6xQ==,type:str] guacamole_users: ENC[AES256_GCM,data:0oJdvTX/9SXV5fBdY0qr9BmSO1HMXX/7+R/f7UxeC/eQcFC9uptkdmLUYfghPvNFlmDNE8yllDylqqTk76qdFFYez78IhBmwj3MbY3C5C81PLI8yNroU0odaW1vgBvg9f8TdoQikMunnl8usNk71t8zxtZAtEbs3nogAbxFMouVy75TSnV+fx+Tb+SdSOQef3XgGrCK8BxaGnR+5LitXiFAIQwwiLV8NIf8alhklHrs3anQ1my83mSfeDYbyNd+ycTtlDa/9HVSGd/UErFP+guM4PNSuzVpNc91/3nm2gFYshMbVb36Z3zmG08fr1o3aoIs0X82XQLQuPmTDaH13RRNlTKPzoUjmXcBziryqqd3OBFRMM9BKlj7An1gZCbTzp2oNYjW2ReNQl6PyDhTZChf+Fgzx3wVXFYcGTueYQ3a1cuBWNvLrzNDFwTiYDfIP6scbEL2A07O2lhQArAGRFlvifNnhEayvzFR3Pzj10UoRhhyMSIWu2CThVKWVfRKCdvwLpTMCY4Yfn89krQu3UBYN2tFpJ9xiqRBmGCyjLNU2X6a5YxCMJkd56ptvnoc+TBF63c9W3sK91R4uLH673xf+LW+izLNFU4eQ66jtMGVx0MkX9uPAbP5+Pp+/J/OiQgsm6dL8r75lEGhKP0sMABc5I5oUNnAy6y52NY5BLOnJp5M/ulGvC4+cSdyaO0Ey2Zj+iPotxmyS60iY+mn0TMT5RnGF/Dx7q5YKzZKV2Gd5Trdum+pFta1k/ljwdLE0EwYZ0Y5bKVjV/tHYabZctrmrqmjmBHjraeYww6yqJka7HeyceBqFCt/fSAIi5WyhPlqYG4QSxM41fR50C6Y4BWeFlVmISoqx2fyq4HOZKbmG9qxvt/AofFi/X+YoBJ5w78MpOVBWRG/bRjqN2AfBFZIEpkUFXT3P1KHIqKXk6ueaMl50ftCZt0wZ770V6TNsssChsA==,iv:L5jR23mTV5oMNGM4s41Qe0fubj2PNZpjhNpNJakgUvM=,tag:IBELh0mxyHdGlAtRuQo9Uw==,type:str] +glass_server_admin_password: ENC[AES256_GCM,data:i6nLp5Jo4LmdsBQilSh9,iv:E3ukSNRlZWe+bmSANRXP0m1GBfA8GKhWAzEdT8Kyncw=,tag:M0gD9kv2P9Kv+PjwX8WuGQ==,type:str] +glass_server_secret_key: ENC[AES256_GCM,data:lfrUSUfNk9yuX++2UxDZddP5iyk+zYdA2lbTNwOvrZRRQLVHky0HE8G/D3g=,iv:E6ET35pG/4Xo83sOo9Ukb4b+zvussaDsq2Nr5vyDFRI=,tag:1CamjtZNnlMjqdO75TKTBg==,type:str] sops: kms: [] gcp_kms: [] @@ -51,8 +53,8 @@ sops: RkpibTJpVzVtR0txL1dHbmFkdlkvUk0KDgqO8c7CggeXhEMzx/tcLqtMG6MmuOi/ UmG9eSUO9im0Q7q7FG4Z+/lZ7+Iu15Dj8qA2/5MtDYPW+vxN3gzZrg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-06-13T14:52:30Z" - mac: ENC[AES256_GCM,data:EXVbpc8P8SzTSYw0TWwJBEWYZRpGOAXm4wFS0JbzeiNaWEybZk6Y07Vr5tyaEWucpu52VxLrVwoZn8YSdF9JPAHtTQYYY35MccBkB01+GVXpVDQfxCG9UNYO24qExNboQIs5QRWmtaX7zTbut+ETcOFKHlkqR9g95PZQhsNZx4c=,iv:1Bu9g4/V2ixRvJJBijlkdNO9pdoR+qwDGTeUgr24dsg=,tag:gyF34lCSbF0It4KPmtQYJA==,type:str] + lastmodified: "2025-02-07T14:19:08Z" + mac: ENC[AES256_GCM,data:Wb0+mRwt/FAihMIf2+pU+mYDAfk38VU6oPk9nXTZRbD2bQnry9Qqbqqmz3I/HUm99C0pPrqD0KbEsj/D7x0QD+mE7nbfQCtKXqHNZNRnv9CSXTWo63ZL2jzg2QRknANRMNXb7mZCnnRCzB/KWgTxQN7jqR2K/QxXV/2zJXOdbzo=,iv:Gj6Q/h+xy7vwFqPb/yqUI6ZTLhwl0KqCdVu9Ega85L4=,tag:Mv6MGHr0xsSmGbjKQXodOA==,type:str] pgp: [] unencrypted_suffix: _unencrypted - version: 3.8.1 + version: 3.9.1 diff --git a/hosts/nixos/lapetus/services/glass-server/default.nix b/hosts/nixos/lapetus/services/glass-server/default.nix new file mode 100644 index 0000000..dce4b4b --- /dev/null +++ b/hosts/nixos/lapetus/services/glass-server/default.nix @@ -0,0 +1,45 @@ +{ config, ... }: +{ + imports = [ ./module.nix ]; + + # {{{ Secrets + sops.secrets.glass_server_secret_key = { + owner = config.services.glass-server.user; + group = config.services.glass-server.user; + sopsFile = ../../secrets.yaml; + }; + + sops.secrets.glass_server_admin_password = { + owner = config.services.glass-server.user; + group = config.services.glass-server.user; + sopsFile = ../../secrets.yaml; + }; + + sops.templates.glass-server-config = { + owner = config.services.glass-server.user; + group = config.services.glass-server.user; + content = '' + { + "SECRET_KEY": "${config.sops.placeholder.glass_server_secret_key}", + "PASSWORD": "${config.sops.placeholder.glass_server_admin_password}" + } + ''; + }; + # }}} + + satellite.cloudflared.at.arcaea.port = config.satellite.ports.glass-server; + satellite.cloudflared.at."tcp.lp.arcaea".port = config.satellite.ports.glass-server-lp-tcp; + satellite.cloudflared.at."udp.lp.arcaea".port = config.satellite.ports.glass-server-lp-udp; + + services.glass-server = { + enable = true; + adminUsername = "prescientmoon"; + + dataDir = "/persist/state/var/lib/arcaea/server"; + secretConfig = config.sops.templates.glass-server-config.path; + + port = config.satellite.ports.glass-server; + linkPlayTCPPort = config.satellite.ports.glass-server-lp-tcp; + linkPlayUDPPort = config.satellite.ports.glass-server-lp-udp; + }; +} diff --git a/hosts/nixos/lapetus/services/glass-server/module.nix b/hosts/nixos/lapetus/services/glass-server/module.nix new file mode 100644 index 0000000..d96142b --- /dev/null +++ b/hosts/nixos/lapetus/services/glass-server/module.nix @@ -0,0 +1,128 @@ +{ + config, + lib, + pkgs, + ... +}: +let + defaultUser = "taritsu"; + cfg = config.services.glass-server; + pkg = pkgs.glassServer; + + glassServerConfig = { + # {{{ Public config + HOST = "0.0.0.0"; + PORT = cfg.port; + USERNAME = cfg.adminUsername; + + LOG_BASE_DIR = "${cfg.dataDir}/log"; + WORLD_MAP_FOLDER_PATH = "${cfg.dataDir}/map/"; + SONG_FILE_FOLDER_PATH = "${cfg.dataDir}/songs/"; + SONGLIST_FILE_PATH = "${cfg.dataDir}/songs/songlist"; + CONTENT_BUNDLE_FOLDER_PATH = "${cfg.dataDir}/bundle/"; + SQLITE_DATABASE_BACKUP_FOLDER_PATH = "${cfg.dataDir}/backup/"; + + DATABASE_INIT_PATH = "${pkg}/source/database/init/"; + SQLITE_DATABASE_PATH = "${cfg.dataDir}/database/arcaea_database.db"; + SQLITE_LOG_DATABASE_PATH = "${cfg.dataDir}/database/arcaea_log.db"; + SQLITE_DATABASE_DELETED_PATH = "${cfg.dataDir}/database/arcaea_database_deleted.db"; + + SET_LINKPLAY_SERVER_AS_SUB_PROCESS = true; + LINKPLAY_HOST = "0.0.0.0"; + LINKPLAY_TCP_PORT = cfg.linkPlayTCPPort; + LINKPLAY_UDP_PORT = cfg.linkPlayUDPPort; + LINKPLAY_DISPLAY_HOST = config.networking.hostName; + + WORLD_RANK_MAX = 200; + IS_APRILFOOLS = true; + UPDATE_WITH_NEW_CHARACTER_DATA = true; + CHARACTER_FULL_UNLOCK = true; + WORLD_SONG_FULL_UNLOCK = true; + WORLD_SCENERY_FULL_UNLOCK = true; + SAVE_FULL_UNLOCK = true; + # }}} + }; + + serverConfigPath = pkgs.writeTextFile { + name = "glass-server-public-config"; + text = builtins.toJSON glassServerConfig; + }; + + configPath = "${cfg.dataDir}/config.json"; +in +{ + # {{{ Options + options.services.glass-server = { + enable = lib.mkEnableOption "Arcaea private server"; + + dataDir = lib.mkOption { type = lib.types.str; }; + port = lib.mkOption { type = lib.types.port; }; + linkPlayTCPPort = lib.mkOption { type = lib.types.port; }; + linkPlayUDPPort = lib.mkOption { type = lib.types.port; }; + adminUsername = lib.mkOption { type = lib.types.str; }; + + user = lib.mkOption { + type = lib.types.str; + default = defaultUser; + description = '' + User account under which the server runs. If not specified, a default + user will be created. + ''; + }; + + secretConfig = lib.mkOption { + type = lib.types.path; + description = '' + Path to additional config that might be generated at runtime by a tool + like sops. This might be useful for things like the admin password + ''; + }; + }; + # }}} + + config = { + # {{{ Create directory structure + systemd.tmpfiles.rules = [ + "f ${cfg.dataDir}/config.json 0700 ${cfg.user} ${cfg.user}" + "d ${cfg.dataDir}/log 0700 ${cfg.user} ${cfg.user}" + "d ${cfg.dataDir}/map 0700 ${cfg.user} ${cfg.user}" + "d ${cfg.dataDir}/songs 0700 ${cfg.user} ${cfg.user}" + "d ${cfg.dataDir}/bundle 0700 ${cfg.user} ${cfg.user}" + "d ${cfg.dataDir}/backup 0700 ${cfg.user} ${cfg.user}" + "d ${cfg.dataDir}/database 0700 ${cfg.user} ${cfg.user}" + ]; + # }}} + # {{{ Systemd service + systemd.services.arcaea-server = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + description = "Arcaea private server"; + serviceConfig = { + User = cfg.user; + Group = cfg.user; + ExecStart = pkgs.writeShellScript "glass-server-startup" '' + # Merge the given configs + ${lib.getExe pkgs.jq} -s ".[0] * .[1]" \ + ${cfg.secretConfig} \ + ${serverConfigPath} \ + > ${configPath} + + # Start the server + ARCAEA_JSON_CONFIG_PATH=${configPath} ${pkg}/bin/glass-server + ''; + Restart = "on-failure"; + }; + }; + # }}} + # {{{ Create default user + users = lib.optionalAttrs (cfg.user == defaultUser) { + users.${defaultUser} = { + group = defaultUser; + isSystemUser = true; + }; + + groups.${defaultUser} = { }; + }; + # }}} + }; +} diff --git a/hosts/nixos/tethys/default.nix b/hosts/nixos/tethys/default.nix index 7945643..0a16bea 100644 --- a/hosts/nixos/tethys/default.nix +++ b/hosts/nixos/tethys/default.nix @@ -23,6 +23,7 @@ ../common/optional/services/restic ../common/optional/services/nginx.nix ./services/syncthing.nix + ./services/glass-server ./hardware ./boot.nix @@ -62,15 +63,4 @@ # {{{ SSH keys users.users.pilot.openssh.authorizedKeys.keyFiles = [ ../calypso/keys/id_ed25519.pub ]; # }}} - - i18n.inputMethod = { - type = "fcitx5"; - enable = true; - fcitx5.addons = with pkgs; [ - fcitx5-mozc # for japanese input - fcitx5-gtk - ]; - fcitx5.waylandFrontend = true; - }; - } diff --git a/hosts/nixos/tethys/hardware/default.nix b/hosts/nixos/tethys/hardware/default.nix index 153e01c..9d1a3b7 100644 --- a/hosts/nixos/tethys/hardware/default.nix +++ b/hosts/nixos/tethys/hardware/default.nix @@ -17,12 +17,12 @@ # }}} # {{{ Power management powerManagement.cpuFreqGovernor = "performance"; - services.tlp = { - enable = true; - settings = { - CPU_SCALING_GOVERNOR_ON_BAT = "performance"; - CPU_SCALING_GOVERNOR_ON_AC = "performance"; - }; - }; + # services.tlp = { + # enable = true; + # settings = { + # CPU_SCALING_GOVERNOR_ON_BAT = "performance"; + # CPU_SCALING_GOVERNOR_ON_AC = "performance"; + # }; + # }; # }}} } diff --git a/hosts/nixos/tethys/hardware/generated.nix b/hosts/nixos/tethys/hardware/generated.nix index e1b882a..4b4f7eb 100644 --- a/hosts/nixos/tethys/hardware/generated.nix +++ b/hosts/nixos/tethys/hardware/generated.nix @@ -1,33 +1,40 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, modulesPath, ... }: +{ + config, + lib, + modulesPath, + ... +}: { - imports = - [ - (modulesPath + "/installer/scan/not-detected.nix") - ]; + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "sd_mod" "sdhci_pci" ]; + boot.initrd.availableKernelModules = [ + "xhci_pci" + "ahci" + "nvme" + "sd_mod" + "sdhci_pci" + ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; - fileSystems."/" = - { - device = "/dev/disk/by-uuid/57846041-f177-45eb-aff3-503006bac638"; - fsType = "ext4"; - }; + fileSystems."/" = { + device = "/dev/disk/by-uuid/57846041-f177-45eb-aff3-503006bac638"; + fsType = "ext4"; + }; - fileSystems."/boot" = - { - device = "/dev/disk/by-uuid/01E6-A013"; - fsType = "vfat"; - }; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/01E6-A013"; + fsType = "vfat"; + }; - swapDevices = - [{ device = "/dev/disk/by-uuid/5cf4167c-77f4-4afe-b978-65ed5472e3d0"; }]; + swapDevices = [ { device = "/dev/disk/by-uuid/5cf4167c-77f4-4afe-b978-65ed5472e3d0"; } ]; # Enables DHCP on each ethernet and wireless interface. In case of scripted networking # (the default) this is the recommended approach. When using systemd-networkd it's diff --git a/pkgs/default.nix b/pkgs/default.nix index 6e3f8c7..f7c8f0c 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -13,4 +13,5 @@ in plymouthThemeCutsAlt = plymouthThemes.cuts_alt; vimclip = pkgs.callPackage (import ./vimclip.nix) { }; homer = pkgs.callPackage (import ./homer.nix) { }; + glassServer = pkgs.callPackage (import ./glass-server.nix) { }; } diff --git a/pkgs/glass-server.nix b/pkgs/glass-server.nix new file mode 100644 index 0000000..3ea5576 --- /dev/null +++ b/pkgs/glass-server.nix @@ -0,0 +1,43 @@ +{ + pkgs ? import { }, +}: +let + python3 = pkgs.python3.withPackages ( + ps: with ps; [ + flask + cryptography + limits + ] + ); +in +pkgs.stdenv.mkDerivation { + pname = "arcaea-server-fork"; + version = "unstable-2025-02-07"; + + src = pkgs.fetchFromGitHub { + owner = "starlitcanopy"; + repo = "ArcaeaServerFork"; + rev = "10cb099a072cc6feb390e3249ecff7867ccd22c6"; + sha256 = "1wzf2si9zvvsb36cg1mghw80fjnv8jic3krlf0nppsm8qmkb03hg"; + }; + + buildPhase = '' + runHook preBuild + + echo "#!/usr/bin/env bash" > glass-server + echo "${python3}/bin/python $out/source/main.py" >> glass-server + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + install -Dm755 glass-server -t $out/bin/ + mkdir -p $out/source + cp -r * $out/source + rm $out/source/glass-server + + runHook postInstall + ''; +}