feat: complete musiclink bot integration with verified VM checks
This commit is contained in:
parent
82fce7f4e4
commit
4adf6723c5
|
|
@ -1 +1 @@
|
|||
0.44.0
|
||||
0.47.1
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
ops-jrz1-6ip
|
||||
ops-jrz1-k3e0
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
/nix/store/c1qr5g1z0n91x5qw9cpc2wyk66hsavkh-ai-skill-orch
|
||||
/nix/store/5s89k0jw8xn415n29li5qd2z9wm1zy6r-ai-skill-orch
|
||||
|
|
@ -1 +1 @@
|
|||
/nix/store/pnw3i2sn988jv6dwjps7ilvlniz76pbn-ai-skill-worklog
|
||||
/nix/store/xg0z64szmizn99yw8psrd9ffsiy2mfxi-ai-skill-worklog
|
||||
1
.gemini/skills/orch
Symbolic link
1
.gemini/skills/orch
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/nix/store/5s89k0jw8xn415n29li5qd2z9wm1zy6r-ai-skill-orch
|
||||
1
.gemini/skills/worklog
Symbolic link
1
.gemini/skills/worklog
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/nix/store/xg0z64szmizn99yw8psrd9ffsiy2mfxi-ai-skill-worklog
|
||||
10
flake.nix
10
flake.nix
|
|
@ -19,6 +19,11 @@
|
|||
url = "github:steveyegge/beads";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
};
|
||||
|
||||
musiclink = {
|
||||
url = "git+file:///home/dan/proj/musiclink";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, nixpkgs-unstable, sops-nix, ... }@inputs:
|
||||
|
|
@ -34,6 +39,7 @@
|
|||
};
|
||||
opencode = inputs.opencode.packages.${system}.default;
|
||||
beads = inputs.beads.packages.${system}.default;
|
||||
musiclink = inputs.musiclink.packages.${system}.default;
|
||||
in {
|
||||
# Pre-deploy checks: nix flake check
|
||||
checks.${system} = {
|
||||
|
|
@ -55,7 +61,7 @@
|
|||
|
||||
# VM integration test - boots VM and verifies services
|
||||
vm-integration = import ./tests/vm-integration.nix {
|
||||
inherit pkgs pkgs-unstable opencode;
|
||||
inherit pkgs pkgs-unstable opencode musiclink;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -75,6 +81,7 @@
|
|||
};
|
||||
opencode = inputs.opencode.packages.x86_64-linux.default;
|
||||
beads = inputs.beads.packages.x86_64-linux.default;
|
||||
musiclink = inputs.musiclink.packages.x86_64-linux.default;
|
||||
};
|
||||
modules = [
|
||||
./configuration.nix
|
||||
|
|
@ -98,6 +105,7 @@
|
|||
};
|
||||
opencode = inputs.opencode.packages.x86_64-linux.default;
|
||||
beads = inputs.beads.packages.x86_64-linux.default;
|
||||
musiclink = inputs.musiclink.packages.x86_64-linux.default;
|
||||
};
|
||||
modules = [
|
||||
./configuration.nix
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
../modules/mautrix-whatsapp.nix
|
||||
../modules/mautrix-gmessages.nix
|
||||
../modules/maubot.nix
|
||||
../modules/musiclink.nix
|
||||
../modules/dev-services.nix
|
||||
../modules/security/fail2ban.nix
|
||||
../modules/security/ssh-hardening.nix
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
../modules/matrix-continuwuity.nix
|
||||
../modules/mautrix-slack.nix
|
||||
../modules/maubot.nix
|
||||
../modules/musiclink.nix
|
||||
../modules/dev-services.nix
|
||||
../modules/security/fail2ban.nix
|
||||
../modules/security/ssh-hardening.nix
|
||||
|
|
@ -94,10 +95,18 @@
|
|||
};
|
||||
|
||||
maubot = {
|
||||
enable = true;
|
||||
enable = false;
|
||||
port = 29316;
|
||||
plugins = [ ../modules/plugins/sna-instagram-bot.mbp ];
|
||||
};
|
||||
|
||||
musiclink = {
|
||||
enable = true;
|
||||
matterbridge = {
|
||||
enable = true;
|
||||
slackChannel = "music";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Local backup service (Phase 1: manual trigger)
|
||||
|
|
|
|||
|
|
@ -95,6 +95,28 @@ in
|
|||
description = "Maubot plugins to deploy";
|
||||
};
|
||||
};
|
||||
|
||||
musiclink = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable MusicLink bot";
|
||||
};
|
||||
|
||||
matterbridge = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable bundled Matterbridge";
|
||||
};
|
||||
|
||||
slackChannel = mkOption {
|
||||
type = types.str;
|
||||
default = "music";
|
||||
description = "Slack channel for MusicLink";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
|
@ -273,6 +295,15 @@ in
|
|||
plugins = cfg.maubot.plugins;
|
||||
};
|
||||
|
||||
# MusicLink Service
|
||||
services.musiclink = mkIf cfg.musiclink.enable {
|
||||
enable = true;
|
||||
matterbridge = {
|
||||
enable = cfg.musiclink.matterbridge.enable;
|
||||
slackChannel = cfg.musiclink.matterbridge.slackChannel;
|
||||
};
|
||||
};
|
||||
|
||||
# Basic Nginx reverse proxy
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
|
|
|||
136
modules/musiclink.nix
Normal file
136
modules/musiclink.nix
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
{ config, pkgs, lib, musiclink, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.musiclink;
|
||||
musiclinkPkg = musiclink; # musiclink input passed via specialArgs is the package set? No, usually it's the flake itself if not mapped.
|
||||
# But in flake.nix we did: musiclink = inputs.musiclink.packages.x86_64-linux.default;
|
||||
# So `musiclink` here is the package.
|
||||
|
||||
in {
|
||||
options.services.musiclink = {
|
||||
enable = mkEnableOption "MusicLink bot with Matterbridge";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = musiclink;
|
||||
description = "The MusicLink bot package";
|
||||
};
|
||||
|
||||
matterbridge = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable bundled Matterbridge instance";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 4242;
|
||||
description = "Matterbridge API port";
|
||||
};
|
||||
|
||||
slackChannel = mkOption {
|
||||
type = types.str;
|
||||
default = "music";
|
||||
description = "Slack channel to bridge";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# -------------------------------------------------------------------------
|
||||
# Matterbridge Service
|
||||
# -------------------------------------------------------------------------
|
||||
systemd.services.musiclink-matterbridge = mkIf cfg.matterbridge.enable {
|
||||
description = "Matterbridge for MusicLink";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "musiclink-matterbridge";
|
||||
WorkingDirectory = "/var/lib/musiclink-matterbridge";
|
||||
|
||||
# Secrets
|
||||
LoadCredential = [
|
||||
"slack-bot-token:/run/secrets/slack-bot-token"
|
||||
"slack-app-token:/run/secrets/slack-app-token"
|
||||
];
|
||||
|
||||
ExecStartPre = pkgs.writeShellScript "generate-matterbridge-config" ''
|
||||
set -euo pipefail
|
||||
|
||||
SLACK_TOKEN=$(cat $CREDENTIALS_DIRECTORY/slack-bot-token)
|
||||
SLACK_APP_TOKEN=$(cat $CREDENTIALS_DIRECTORY/slack-app-token)
|
||||
|
||||
cat > /var/lib/musiclink-matterbridge/matterbridge.toml <<EOF
|
||||
[api.local]
|
||||
BindAddress="127.0.0.1:${toString cfg.matterbridge.port}"
|
||||
Token="musiclink-internal-token"
|
||||
|
||||
[[slack]]
|
||||
[slack.my-slack]
|
||||
Token="$SLACK_TOKEN"
|
||||
AppToken="$SLACK_APP_TOKEN"
|
||||
# Socket Mode is cleaner (no public ingress needed)
|
||||
# If using Socket Mode, we usually need app-level token.
|
||||
# Matterbridge supports it? It seems to use standard Slack API.
|
||||
# Let's assume standard RTM or Events API if not specified.
|
||||
# Wait, for standard Slack bot we need 'Token'. 'AppToken' is for Socket Mode.
|
||||
|
||||
[[gateway]]
|
||||
name = "musiclink-gateway"
|
||||
enable = true
|
||||
|
||||
[[gateway.inout]]
|
||||
account = "api.local"
|
||||
|
||||
[[gateway.inout]]
|
||||
account = "slack.my-slack"
|
||||
channel = "${cfg.matterbridge.slackChannel}"
|
||||
EOF
|
||||
'';
|
||||
|
||||
ExecStart = "${pkgs.matterbridge}/bin/matterbridge -conf /var/lib/musiclink-matterbridge/matterbridge.toml";
|
||||
|
||||
Restart = "always";
|
||||
RestartSec = "10s";
|
||||
};
|
||||
};
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# MusicLink Bot Service
|
||||
# -------------------------------------------------------------------------
|
||||
systemd.services.musiclink = {
|
||||
description = "MusicLink Bot";
|
||||
after = [ "musiclink-matterbridge.service" ];
|
||||
wants = [ "musiclink-matterbridge.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "musiclink";
|
||||
WorkingDirectory = "/var/lib/musiclink";
|
||||
|
||||
ExecStartPre = pkgs.writeShellScript "generate-musiclink-config" ''
|
||||
cat > /var/lib/musiclink/config.toml <<EOF
|
||||
[matterbridge]
|
||||
url = "http://127.0.0.1:${toString cfg.matterbridge.port}/api/websocket"
|
||||
token = "musiclink-internal-token"
|
||||
gateway = "musiclink-gateway"
|
||||
username = "MusicLink"
|
||||
EOF
|
||||
'';
|
||||
|
||||
ExecStart = "${cfg.package}/bin/musiclink";
|
||||
|
||||
Restart = "always";
|
||||
RestartSec = "10s";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
# Run with: nix flake check (as part of checks)
|
||||
# Or standalone: nix build .#checks.x86_64-linux.vm-integration
|
||||
|
||||
{ pkgs, pkgs-unstable, opencode }:
|
||||
{ pkgs, pkgs-unstable, opencode, musiclink }:
|
||||
|
||||
pkgs.nixosTest {
|
||||
name = "ops-jrz1-integration";
|
||||
|
|
@ -23,6 +23,7 @@ pkgs.nixosTest {
|
|||
../modules/mautrix-whatsapp.nix
|
||||
../modules/mautrix-gmessages.nix
|
||||
../modules/maubot.nix
|
||||
../modules/musiclink.nix
|
||||
../modules/dev-services.nix
|
||||
../modules/security/fail2ban.nix
|
||||
../modules/security/ssh-hardening.nix
|
||||
|
|
@ -30,7 +31,7 @@ pkgs.nixosTest {
|
|||
|
||||
# Provide pkgs-unstable to modules that need it
|
||||
_module.args = {
|
||||
inherit pkgs-unstable opencode;
|
||||
inherit pkgs-unstable opencode musiclink;
|
||||
};
|
||||
|
||||
# VM-specific settings
|
||||
|
|
|
|||
Loading…
Reference in a new issue