Migrate Slack tokens to sops-nix, improve egress rate limits
- Remove beads from VPS deployment (kept locally for dev workflow) - Add slack-bot-token and slack-app-token secrets with devs group access - Remove dead acme-email secret reference - Increase egress limits from 30/min to 150/min (burst 60→300) - Change egress blocking from REJECT to DROP for better app behavior - Add egress-status script for user self-diagnosis - Update dev-slack-direct.md with new /run/secrets access patterns 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
df2cb13f9b
commit
92d7646d52
|
|
@ -1,4 +1,4 @@
|
||||||
{ pkgs, pkgs-unstable, beads, opencode, ... }:
|
{ pkgs, pkgs-unstable, opencode, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
|
|
@ -41,6 +41,12 @@ let
|
||||||
text = builtins.readFile ./scripts/dev-remove.sh;
|
text = builtins.readFile ./scripts/dev-remove.sh;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
egress-status = pkgs.writeShellApplication {
|
||||||
|
name = "egress-status";
|
||||||
|
runtimeInputs = with pkgs; [ systemd gnugrep gnused coreutils ];
|
||||||
|
text = builtins.readFile ./scripts/egress-status;
|
||||||
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# Main NixOS configuration for ops-jrz1 server
|
# Main NixOS configuration for ops-jrz1 server
|
||||||
|
|
@ -73,7 +79,6 @@ in
|
||||||
direnv
|
direnv
|
||||||
zig
|
zig
|
||||||
# AI coding tools (via flake inputs)
|
# AI coding tools (via flake inputs)
|
||||||
beads # Issue tracker (bd CLI)
|
|
||||||
opencode # AI coding agent (opencode CLI)
|
opencode # AI coding agent (opencode CLI)
|
||||||
# For JS-based AI tools (gemini-cli, claude-cli): users run bun/npm install
|
# For JS-based AI tools (gemini-cli, claude-cli): users run bun/npm install
|
||||||
nodejs_22
|
nodejs_22
|
||||||
|
|
@ -90,6 +95,7 @@ in
|
||||||
# Admin scripts (declarative deployment)
|
# Admin scripts (declarative deployment)
|
||||||
dev-add
|
dev-add
|
||||||
dev-remove
|
dev-remove
|
||||||
|
egress-status
|
||||||
];
|
];
|
||||||
|
|
||||||
# Add ~/.local/bin and /usr/local/bin to PATH for manually installed tools
|
# Add ~/.local/bin and /usr/local/bin to PATH for manually installed tools
|
||||||
|
|
@ -142,29 +148,25 @@ in
|
||||||
# UID range: 1000 (first regular user) to 65534 (nobody - excluded from controls)
|
# UID range: 1000 (first regular user) to 65534 (nobody - excluded from controls)
|
||||||
# This covers all dev accounts while excluding system services
|
# This covers all dev accounts while excluding system services
|
||||||
extraCommands = ''
|
extraCommands = ''
|
||||||
# Log all new outbound connections from regular users
|
# Rate limit new outbound connections (150/min sustained, burst 300)
|
||||||
|
# High enough for npm install, low enough to prevent abuse
|
||||||
|
# DROP instead of REJECT so apps back off naturally
|
||||||
iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
||||||
-j LOG --log-prefix "EGRESS: " --log-level info
|
-m limit --limit 150/min --limit-burst 300 -j ACCEPT
|
||||||
|
|
||||||
# Rate limit new outbound connections (30/min sustained, burst 60)
|
|
||||||
iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
|
||||||
-m limit --limit 30/min --limit-burst 60 -j ACCEPT
|
|
||||||
iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
||||||
-j LOG --log-prefix "EGRESS-LIMIT: " --log-level warning
|
-j LOG --log-prefix "EGRESS-LIMIT: " --log-level warning
|
||||||
iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
||||||
-j REJECT
|
-j DROP
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# Clean up on stop
|
# Clean up on stop
|
||||||
extraStopCommands = ''
|
extraStopCommands = ''
|
||||||
iptables -D OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
iptables -D OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
||||||
-j LOG --log-prefix "EGRESS: " --log-level info 2>/dev/null || true
|
-m limit --limit 150/min --limit-burst 300 -j ACCEPT 2>/dev/null || true
|
||||||
iptables -D OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
|
||||||
-m limit --limit 30/min --limit-burst 60 -j ACCEPT 2>/dev/null || true
|
|
||||||
iptables -D OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
iptables -D OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
||||||
-j LOG --log-prefix "EGRESS-LIMIT: " --log-level warning 2>/dev/null || true
|
-j LOG --log-prefix "EGRESS-LIMIT: " --log-level warning 2>/dev/null || true
|
||||||
iptables -D OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
iptables -D OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
||||||
-j REJECT 2>/dev/null || true
|
-j DROP 2>/dev/null || true
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,20 +21,20 @@ Devs write Python bots using `slack-bolt` that connect directly to Slack via Soc
|
||||||
|
|
||||||
### Credentials
|
### Credentials
|
||||||
|
|
||||||
Shared Slack App tokens stored in `/etc/slack-dev.env`:
|
Shared Slack App tokens managed via sops-nix, deployed to `/run/secrets/`:
|
||||||
|
|
||||||
| Variable | Purpose |
|
| Secret File | Purpose |
|
||||||
|----------|---------|
|
|-------------|---------|
|
||||||
| `SLACK_BOT_TOKEN` | Bot identity (xoxb-...) |
|
| `/run/secrets/slack-bot-token` | Bot identity (xoxb-...) |
|
||||||
| `SLACK_APP_TOKEN` | Socket Mode connection (xapp-...) |
|
| `/run/secrets/slack-app-token` | Socket Mode connection (xapp-...) |
|
||||||
|
|
||||||
These come from the existing mautrix-slack bridge login (Chochacho workspace, vlad's account).
|
These come from the existing mautrix-slack bridge login (Chochacho workspace, vlad's account).
|
||||||
|
|
||||||
### Access Control
|
### Access Control
|
||||||
|
|
||||||
- File owned by `root:devs`, mode `640`
|
- Files owned by `root:devs`, mode `0440`
|
||||||
- Dev users added to `devs` group on creation
|
- Dev users added to `devs` group on creation
|
||||||
- `.bashrc` sources the env file on login
|
- Secrets encrypted in git, decrypted at boot via sops-nix
|
||||||
|
|
||||||
### Scripts
|
### Scripts
|
||||||
|
|
||||||
|
|
@ -58,8 +58,12 @@ ssh root@ops-jrz1 'dev-add.sh alice "ssh-ed25519 AAAA..."'
|
||||||
ssh alice@<server-ip>
|
ssh alice@<server-ip>
|
||||||
```
|
```
|
||||||
|
|
||||||
Tokens are available immediately:
|
Load tokens from secrets:
|
||||||
```bash
|
```bash
|
||||||
|
export SLACK_BOT_TOKEN=$(cat /run/secrets/slack-bot-token)
|
||||||
|
export SLACK_APP_TOKEN=$(cat /run/secrets/slack-app-token)
|
||||||
|
|
||||||
|
# Verify they're set
|
||||||
echo $SLACK_BOT_TOKEN # xoxb-...
|
echo $SLACK_BOT_TOKEN # xoxb-...
|
||||||
echo $SLACK_APP_TOKEN # xapp-...
|
echo $SLACK_APP_TOKEN # xapp-...
|
||||||
```
|
```
|
||||||
|
|
@ -72,7 +76,18 @@ from slack_bolt import App
|
||||||
from slack_bolt.adapter.socket_mode import SocketModeHandler
|
from slack_bolt.adapter.socket_mode import SocketModeHandler
|
||||||
import os
|
import os
|
||||||
|
|
||||||
app = App(token=os.environ["SLACK_BOT_TOKEN"])
|
# Read tokens from sops-nix secrets (or fall back to env vars)
|
||||||
|
def read_secret(path, env_fallback):
|
||||||
|
try:
|
||||||
|
with open(path) as f:
|
||||||
|
return f.read().strip()
|
||||||
|
except FileNotFoundError:
|
||||||
|
return os.environ.get(env_fallback, "")
|
||||||
|
|
||||||
|
BOT_TOKEN = read_secret("/run/secrets/slack-bot-token", "SLACK_BOT_TOKEN")
|
||||||
|
APP_TOKEN = read_secret("/run/secrets/slack-app-token", "SLACK_APP_TOKEN")
|
||||||
|
|
||||||
|
app = App(token=BOT_TOKEN)
|
||||||
|
|
||||||
@app.message("hello")
|
@app.message("hello")
|
||||||
def hello(message, say):
|
def hello(message, say):
|
||||||
|
|
@ -81,11 +96,11 @@ def hello(message, say):
|
||||||
@app.message("dice")
|
@app.message("dice")
|
||||||
def dice(message, say):
|
def dice(message, say):
|
||||||
import random
|
import random
|
||||||
say(f"🎲 You rolled a {random.randint(1, 6)}!")
|
say(f"You rolled a {random.randint(1, 6)}!")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print("Bot starting...")
|
print("Bot starting...")
|
||||||
SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
|
SocketModeHandler(app, APP_TOKEN).start()
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Run It
|
### 4. Run It
|
||||||
|
|
@ -176,8 +191,8 @@ say(blocks=[
|
||||||
|
|
||||||
- Dedicated test channel in Slack
|
- Dedicated test channel in Slack
|
||||||
- Supervisor/systemd for process management (not yet set up)
|
- Supervisor/systemd for process management (not yet set up)
|
||||||
- Tokens in env vars, not code
|
- Tokens in sops-nix secrets, encrypted in git, decrypted only at runtime
|
||||||
- Can rotate tokens if leaked (re-login bridge)
|
- Can rotate tokens if leaked (re-login bridge, update secrets.yaml)
|
||||||
|
|
||||||
## Future Improvements
|
## Future Improvements
|
||||||
|
|
||||||
|
|
|
||||||
56
flake.lock
56
flake.lock
|
|
@ -1,45 +1,5 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"beads": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs-unstable"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1767403067,
|
|
||||||
"narHash": "sha256-HQ98HSZo/gJJmp3HrsGWSVbGYkXsnxjBsMof2j3Age0=",
|
|
||||||
"owner": "steveyegge",
|
|
||||||
"repo": "beads",
|
|
||||||
"rev": "32a4a9e0603957c467a03fbec65734ef91acaa0b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "steveyegge",
|
|
||||||
"repo": "beads",
|
|
||||||
"rev": "32a4a9e0603957c467a03fbec65734ef91acaa0b",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731533236,
|
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1735563628,
|
"lastModified": 1735563628,
|
||||||
|
|
@ -111,7 +71,6 @@
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"beads": "beads",
|
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||||
"opencode": "opencode",
|
"opencode": "opencode",
|
||||||
|
|
@ -139,21 +98,6 @@
|
||||||
"rev": "c2ea1186c0cbfa4d06d406ae50f3e4b085ddc9b3",
|
"rev": "c2ea1186c0cbfa4d06d406ae50f3e4b085ddc9b3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,6 @@
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
beads = {
|
|
||||||
url = "github:steveyegge/beads/32a4a9e0603957c467a03fbec65734ef91acaa0b";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
|
||||||
};
|
|
||||||
|
|
||||||
opencode = {
|
opencode = {
|
||||||
url = "github:sst/opencode/f6fe709f6ee75427ba64829af25b64d9a3111569";
|
url = "github:sst/opencode/f6fe709f6ee75427ba64829af25b64d9a3111569";
|
||||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||||
|
|
@ -48,7 +43,6 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
beads = inputs.beads.packages.x86_64-linux.default;
|
|
||||||
opencode = inputs.opencode.packages.x86_64-linux.default;
|
opencode = inputs.opencode.packages.x86_64-linux.default;
|
||||||
};
|
};
|
||||||
modules = [
|
modules = [
|
||||||
|
|
@ -71,7 +65,6 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
beads = inputs.beads.packages.x86_64-linux.default;
|
|
||||||
opencode = inputs.opencode.packages.x86_64-linux.default;
|
opencode = inputs.opencode.packages.x86_64-linux.default;
|
||||||
};
|
};
|
||||||
modules = [
|
modules = [
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,6 @@
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets.acme-email = {
|
|
||||||
owner = "root";
|
|
||||||
mode = "0444";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets.maubot-admin-password = {
|
sops.secrets.maubot-admin-password = {
|
||||||
# Maubot management interface admin password
|
# Maubot management interface admin password
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
|
|
@ -50,6 +45,19 @@
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Slack dev tokens - shared with devs group for learner bot development
|
||||||
|
sops.secrets.slack-bot-token = {
|
||||||
|
owner = "root";
|
||||||
|
group = "devs";
|
||||||
|
mode = "0440";
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets.slack-app-token = {
|
||||||
|
owner = "root";
|
||||||
|
group = "devs";
|
||||||
|
mode = "0440";
|
||||||
|
};
|
||||||
|
|
||||||
# Matrix homeserver configuration
|
# Matrix homeserver configuration
|
||||||
# NOTE: Disabled in favor of dev-platform.matrix which provides integrated
|
# NOTE: Disabled in favor of dev-platform.matrix which provides integrated
|
||||||
# bridge coordination and systemd credential-based secrets management
|
# bridge coordination and systemd credential-based secrets management
|
||||||
|
|
|
||||||
35
scripts/egress-status
Normal file
35
scripts/egress-status
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Check egress rate limit status for current user
|
||||||
|
# Users can run this to see if they're hitting connection limits
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo "=== Egress Rate Limit Status ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check recent limit hits (last 5 minutes)
|
||||||
|
RECENT_HITS=$(journalctl --since "5 minutes ago" -q 2>/dev/null | grep -c "EGRESS-LIMIT:" 2>/dev/null || true)
|
||||||
|
RECENT_HITS=${RECENT_HITS:-0}
|
||||||
|
RECENT_HITS=$(echo "$RECENT_HITS" | tr -d '[:space:]')
|
||||||
|
|
||||||
|
if [ "$RECENT_HITS" -gt 0 ] 2>/dev/null; then
|
||||||
|
echo -e "${RED}⚠ Rate limit hit ${RECENT_HITS} times in the last 5 minutes${NC}"
|
||||||
|
echo ""
|
||||||
|
echo "Recent blocked connections:"
|
||||||
|
journalctl --since "5 minutes ago" -q 2>/dev/null | grep "EGRESS-LIMIT:" | tail -5 | \
|
||||||
|
sed 's/.*DST=\([^ ]*\).*/ → \1/' || true
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Tip: Wait 1-2 minutes for the limit to reset, or run commands with fewer parallel connections.${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}✓ No rate limit hits in the last 5 minutes${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Current limits: 150 new connections/min, burst 300"
|
||||||
|
echo "Check logs: journalctl --since '1 hour ago' | grep EGRESS-LIMIT"
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
matrix-registration-token: ENC[AES256_GCM,data:H7BgtpsDLOYcywjOHru+u7t6BCbqhFrmPS3YXJWnMVcppD4lVh6ewZB/ZPM2ck5OcBQe8gmCYNGKchzPf0aeRw==,iv:9b8gPuxQaJIGep/YHpA02/yJx13bJZ3r6WmKEXRGFDc=,tag:/NxCSqkwPxhEOeWM+/3Hhg==,type:str]
|
matrix-registration-token: ENC[AES256_GCM,data:H7BgtpsDLOYcywjOHru+u7t6BCbqhFrmPS3YXJWnMVcppD4lVh6ewZB/ZPM2ck5OcBQe8gmCYNGKchzPf0aeRw==,iv:9b8gPuxQaJIGep/YHpA02/yJx13bJZ3r6WmKEXRGFDc=,tag:/NxCSqkwPxhEOeWM+/3Hhg==,type:str]
|
||||||
acme-email: ENC[AES256_GCM,data:+tN+nRfn2kpGLdF3Vg==,iv:uZvSw4viBWCTT35C718cLOCrSLM1EnkmEZH644aVuPI=,tag:tf6+7ubiOLVj7k4rfNI3lQ==,type:str]
|
acme-email: ENC[AES256_GCM,data:+tN+nRfn2kpGLdF3Vg==,iv:uZvSw4viBWCTT35C718cLOCrSLM1EnkmEZH644aVuPI=,tag:tf6+7ubiOLVj7k4rfNI3lQ==,type:str]
|
||||||
slack-oauth-token: ""
|
slack-oauth-token: null
|
||||||
slack-app-token: ""
|
slack-app-token: ENC[AES256_GCM,data:YRSu3h7xU9V6ymvOGa7lBRtUq794j/bh5gCOTBvNJXw+g6m3ypiJYOYVM6iN6hBLNQSPDtfxVnJiwiV00jcneYdTWN54RWzyU1O2yrVb10DA1GK2dOVFcfDjncdAVCsJwQ==,iv:wH6CTsLixT4kU5u8o0xd9Yyqy9wjomHIZoyg8aOP6ko=,tag:x9yh4qJolHzMMMramz+kjg==,type:str]
|
||||||
maubot-admin-password: ENC[AES256_GCM,data:Omh6VFsnlLgS+UktM5qHjj3+VK84YmMgWcQCvkiMchfb621RV0LBg1ZB3tg=,iv:cINVFlHJJGkAcasK8BJr3Sd2zqkpQOyRgF+V0JhBJXE=,tag:PnS9TdtuR/87yQfttJTLow==,type:str]
|
maubot-admin-password: ENC[AES256_GCM,data:Omh6VFsnlLgS+UktM5qHjj3+VK84YmMgWcQCvkiMchfb621RV0LBg1ZB3tg=,iv:cINVFlHJJGkAcasK8BJr3Sd2zqkpQOyRgF+V0JhBJXE=,tag:PnS9TdtuR/87yQfttJTLow==,type:str]
|
||||||
maubot-secret-key: ENC[AES256_GCM,data:krq8zjZelAYRNrFs+DYqh7j0bDd80YKRkro88hGiAxJOBCuFV6PdyyUKgqdSuGMhoFhZtMPmRKOQvAxKclOBEQ==,iv:PePSXEOcBKcReXYBzicDhGQ/yxJIZ/TNzARg4z9G7dA=,tag:ihVw9PAXScoZgrSzWkAMdQ==,type:str]
|
maubot-secret-key: ENC[AES256_GCM,data:krq8zjZelAYRNrFs+DYqh7j0bDd80YKRkro88hGiAxJOBCuFV6PdyyUKgqdSuGMhoFhZtMPmRKOQvAxKclOBEQ==,iv:PePSXEOcBKcReXYBzicDhGQ/yxJIZ/TNzARg4z9G7dA=,tag:ihVw9PAXScoZgrSzWkAMdQ==,type:str]
|
||||||
|
slack-bot-token: ENC[AES256_GCM,data:Ll4Ej2z8C810VsTtHNKdB+o4t43736dbNMBhbX9jFl3+l4N6xOpyHSi7EJE2B8Ce8mz1JsLeOvo=,iv:ct5yo21n4aBSVAIBgxzL+FG+P6gIMSP/f1UktVc7ya4=,tag:qOSkcR/m5KvpdwjxYVIxmQ==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- recipient: age1vuxcwvdvzl2u7w6kudqvnnf45czrnhwv9aevjq9hyjjpa409jvkqhkz32q
|
- recipient: age1vuxcwvdvzl2u7w6kudqvnnf45czrnhwv9aevjq9hyjjpa409jvkqhkz32q
|
||||||
|
|
@ -24,7 +25,7 @@ sops:
|
||||||
TzI2NGdaVHd1RFZWRE50bjZ0cHhBOXMKRXVYFMNxNIX+8uVxf1X4hu+OfOKKs2TK
|
TzI2NGdaVHd1RFZWRE50bjZ0cHhBOXMKRXVYFMNxNIX+8uVxf1X4hu+OfOKKs2TK
|
||||||
A2qdAMJIfdy9f7SPVrPnrGMIwl/prxIkbSRwYC/UNK5NNkjMrGoSwg==
|
A2qdAMJIfdy9f7SPVrPnrGMIwl/prxIkbSRwYC/UNK5NNkjMrGoSwg==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2025-10-27T04:21:51Z"
|
lastmodified: "2026-01-07T18:19:38Z"
|
||||||
mac: ENC[AES256_GCM,data:k1aBVnSUnpgq1y+AQjZFB7AXmQe2r/SpSVl9xVsJku2/lehBfY6vRGZutRHV4iTaB3FmxwgGCOV29gPZ5NGUQDf9tg5hMacZOREJGd7lMWoSlZbCGjjkOQEvpKLq3kJNuV66Lb1LzKQtR6ws5k/EmnXneyDtjuEbFs4AZZi+WRE=,iv:zc58CMvJqPsKbANOCGLBuo+AiUnoF4Wx3Z33j6a+sfI=,tag:ENek+3uial24ladKBqW3sg==,type:str]
|
mac: ENC[AES256_GCM,data:BkDv0FTRszUUyolWwhlK/hpVZHZvMmsvCZm2g7hDD5kPZGDR1lchsQ6x5rcWEecJ1HBXrFyAWslcuwLT+hBiWObVLi0Fp5VFHodBPHjgbwoFLgfWl9bpCc1TGSLozFxfOVlzZtm2paMl635hQROH1KJLSDXg5r9ZnQNjBgWn0LE=,iv:C1j7YBlagXl31CtNGCROnS0sTA8s1HijBrZ/bkDS+wA=,tag:zPIyXfRFDmDk7qof9C3jDg==,type:str]
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.10.2
|
version: 3.10.2
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue