mirror of
https://codeberg.org/polyteknisk-radiogruppe/the_prg_server_configuration.git
synced 2026-10-21 03:15:46 +02:00
Compare commits
6 commits
ee11c9171b
...
34abb21e0b
| Author | SHA1 | Date | |
|---|---|---|---|
| 34abb21e0b | |||
| a027b99446 | |||
| d234901432 | |||
| 139345f84e | |||
| 5dba269c18 | |||
| 39e044b757 |
4 changed files with 330 additions and 4 deletions
7
nix-system-configs/modules/songsheet/wavelog/notes.md
Normal file
7
nix-system-configs/modules/songsheet/wavelog/notes.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
How to change passwords in case of a major heck up
|
||||||
|
```zsh
|
||||||
|
sudo podman exec -it -u www-data partdb sh
|
||||||
|
# inside container:
|
||||||
|
cd /var/www/html
|
||||||
|
php bin/console partdb:users:set-password USERNAME
|
||||||
|
```
|
||||||
94
nix-system-configs/modules/system/teamspeak.nix
Normal file
94
nix-system-configs/modules/system/teamspeak.nix
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
options.local = {
|
||||||
|
hostname = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "nixos-default";
|
||||||
|
description = "System hostname";
|
||||||
|
};
|
||||||
|
username = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "user";
|
||||||
|
description = "Primary user username";
|
||||||
|
};
|
||||||
|
userDescription = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "NixOS User";
|
||||||
|
description = "Primary user description";
|
||||||
|
};
|
||||||
|
address = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "10.1.1.100";
|
||||||
|
description = "Static IP address";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
imports = [
|
||||||
|
./modules/desktop-manager/sway_greetd_homemanager.nix
|
||||||
|
./modules/local/hostname_username.nix
|
||||||
|
./modules/local/networking_local.nix
|
||||||
|
./modules/bootloader/seabios-assigned-iso-at-birth.nix
|
||||||
|
./modules/lix-default.nix
|
||||||
|
# Optionally: ./modules/toolsets/remote_building.nix
|
||||||
|
#
|
||||||
|
#
|
||||||
|
## Compose modules for Portainer service
|
||||||
|
./modules/songsheet/wavelog/docker-compose.nix
|
||||||
|
./modules/secrets-config/sops-composesongsheet.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
local.hostname = "christine-teamspeak";
|
||||||
|
local.username = "teamspeak_christine";
|
||||||
|
local.userDescription = "NixOS Teamspeak Service";
|
||||||
|
local.address = "10.1.1.248";
|
||||||
|
|
||||||
|
services.teamspeak3 = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
## Add Conduit for Matrix
|
||||||
|
|
||||||
|
# See https://search.nixos.org/options?channel=unstable&query=services.matrix-conduit.
|
||||||
|
# and https://docs.conduit.rs/configuration.html
|
||||||
|
services.matrix-conduit = {
|
||||||
|
enable = true;
|
||||||
|
settings.global = {
|
||||||
|
allow_registration = true;
|
||||||
|
# You will need this token when creating your first account.
|
||||||
|
#registration_token = "testtoken1234";
|
||||||
|
# server_name = yourDomainName;
|
||||||
|
port = 12244;
|
||||||
|
# Bind to all interfaces so Traefik on the network can reach Conduit.
|
||||||
|
address = "0.0.0.0";
|
||||||
|
database_backend = "rocksdb";
|
||||||
|
server_name = "lgbtq.prg-radio.org";
|
||||||
|
|
||||||
|
# See https://docs.conduit.rs/turn.html, and https://github.com/element-hq/synapse/blob/develop/docs/turn-howto.md for more details
|
||||||
|
# turn_uris = [
|
||||||
|
# "turn:your.turn.url?transport=udp"
|
||||||
|
# "turn:your.turn.url?transport=tcp"
|
||||||
|
# ];
|
||||||
|
# turn_secret = "your secret";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
80
|
||||||
|
443
|
||||||
|
12244
|
||||||
|
];
|
||||||
|
networking.firewall.allowedUDPPorts = [
|
||||||
|
80
|
||||||
|
443
|
||||||
|
12244
|
||||||
|
];
|
||||||
|
|
||||||
|
system.stateVersion = "25.11";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -67,6 +67,20 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
# Federation entrypoint: external TLS on 8448
|
||||||
|
federation = {
|
||||||
|
address = ":8448";
|
||||||
|
};
|
||||||
|
# TeamSpeak entry points
|
||||||
|
teamspeak-voice = {
|
||||||
|
address = ":9987/udp";
|
||||||
|
};
|
||||||
|
teamspeak-squery = {
|
||||||
|
address = ":10022/tcp";
|
||||||
|
};
|
||||||
|
teamspeak-data = {
|
||||||
|
address = ":30033/tcp";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
log = {
|
log = {
|
||||||
level = "INFO";
|
level = "INFO";
|
||||||
|
|
@ -90,7 +104,13 @@
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
tls = {};
|
tls = {};
|
||||||
};
|
};
|
||||||
|
# Matrix HTTP router for client requests (Element etc.)
|
||||||
|
matrix = {
|
||||||
|
rule = "Host(`lgbtq.prg-radio.org`)";
|
||||||
|
service = "matrix";
|
||||||
|
entryPoints = ["websecure"];
|
||||||
|
tls = {};
|
||||||
|
};
|
||||||
wavelog = {
|
wavelog = {
|
||||||
rule = "Host(`wavelog.prg-radio.org`)";
|
rule = "Host(`wavelog.prg-radio.org`)";
|
||||||
service = "wavelog";
|
service = "wavelog";
|
||||||
|
|
@ -111,7 +131,11 @@
|
||||||
{url = "http://10.1.1.4:3000";}
|
{url = "http://10.1.1.4:3000";}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
matrix.loadBalancer = {
|
||||||
|
servers = [
|
||||||
|
{url = "http://10.1.1.248:12244";}
|
||||||
|
];
|
||||||
|
};
|
||||||
wavelog.loadBalancer = {
|
wavelog.loadBalancer = {
|
||||||
servers = [
|
servers = [
|
||||||
{url = "http://10.1.1.249:8086";}
|
{url = "http://10.1.1.249:8086";}
|
||||||
|
|
@ -124,6 +148,60 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# TCP routing for TeamSpeak
|
||||||
|
tcp.routers = {
|
||||||
|
teamspeak-squery = {
|
||||||
|
rule = "HostSNI(`*`)";
|
||||||
|
service = "teamspeak-squery";
|
||||||
|
entryPoints = ["teamspeak-squery"];
|
||||||
|
};
|
||||||
|
teamspeak-data = {
|
||||||
|
rule = "HostSNI(`*`)";
|
||||||
|
service = "teamspeak-data";
|
||||||
|
entryPoints = ["teamspeak-data"];
|
||||||
|
};
|
||||||
|
# Federation TCP router: incoming on :8448 -> Conduit backend
|
||||||
|
matrix-federation = {
|
||||||
|
rule = "HostSNI(`*`)";
|
||||||
|
service = "matrix-federation";
|
||||||
|
entryPoints = ["federation"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
tcp.services = {
|
||||||
|
teamspeak-squery.loadBalancer = {
|
||||||
|
servers = [
|
||||||
|
{address = "10.1.1.248:10022";}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
teamspeak-data.loadBalancer = {
|
||||||
|
servers = [
|
||||||
|
{address = "10.1.1.248:30033";}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
matrix-federation.loadBalancer = {
|
||||||
|
servers = [
|
||||||
|
{address = "10.1.1.248:12244";}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# UDP routing for TeamSpeak voice
|
||||||
|
udp.routers = {
|
||||||
|
teamspeak-voice = {
|
||||||
|
entryPoints = ["teamspeak-voice"];
|
||||||
|
service = "teamspeak-voice";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
udp.services = {
|
||||||
|
teamspeak-voice.loadBalancer = {
|
||||||
|
servers = [
|
||||||
|
{address = "10.1.1.248:9987";}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -147,8 +225,8 @@
|
||||||
wants = ["acme-finished-prg-radio.org.target"];
|
wants = ["acme-finished-prg-radio.org.target"];
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [80 443];
|
networking.firewall.allowedTCPPorts = [80 443 10022 30033 8448];
|
||||||
networking.firewall.allowedUDPPorts = [80 443];
|
networking.firewall.allowedUDPPorts = [80 443 9987];
|
||||||
|
|
||||||
system.stateVersion = "25.11";
|
system.stateVersion = "25.11";
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,147 @@
|
||||||
|
#!/usr/bin/env zsh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PATH_TO_BACKUPGPG_KEY=${PATH_TO_BACKUPGPG_KEY:-}
|
||||||
|
PATH_TO_BACKUP_FILE=${PATH_TO_BACKUP_FILE:-}
|
||||||
|
PATH_TO_OUTPUT_DIR=${PATH_TO_OUTPUT_DIR:-}
|
||||||
|
|
||||||
|
KEEP=false
|
||||||
|
|
||||||
|
# TIL You can do these kind of scripts.
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [-f <backup-file>] [-k <private-key-file>] [-o <output-dir>] [--keep]
|
||||||
|
|
||||||
|
Decrypt and unpack a .gz.gpg backup file for inspection. The script will
|
||||||
|
create a temporary GNUPGHOME (if a key is provided), decrypt the file, and
|
||||||
|
if needed gunzip it to produce a .sql file. The resulting SQL file path will
|
||||||
|
be printed and a short preview will be shown.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-f <file> Path to the .sql.gz.gpg backup file (or set PATH_TO_BACKUP_FILE)
|
||||||
|
-k <key> Path to a private key file to import (optional; or set PATH_TO_BACKUPGPG_KEY)
|
||||||
|
-o <dir> Output directory for the final .sql file (defaults to current working directory)
|
||||||
|
--keep Keep temporary files (do not delete temp GNUPGHOME/dir)
|
||||||
|
-h, --help Show this message
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Simple arg parsing to allow flags
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-f)
|
||||||
|
PATH_TO_BACKUP_FILE="$2"; shift 2;;
|
||||||
|
-k)
|
||||||
|
PATH_TO_BACKUPGPG_KEY="$2"; shift 2;;
|
||||||
|
-o)
|
||||||
|
PATH_TO_OUTPUT_DIR="$2"; shift 2;;
|
||||||
|
--keep)
|
||||||
|
KEEP=true; shift;;
|
||||||
|
-h|--help)
|
||||||
|
usage;;
|
||||||
|
*)
|
||||||
|
echo "Unknown argument: $1" >&2; usage;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$PATH_TO_BACKUP_FILE" ]]; then
|
||||||
|
echo "Error: no backup file provided." >&2
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$PATH_TO_BACKUP_FILE" ]]; then
|
||||||
|
echo "Error: backup file does not exist: $PATH_TO_BACKUP_FILE" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
command -v gpg >/dev/null 2>&1 || { echo "gpg not found in PATH" >&2; exit 3; }
|
||||||
|
command -v gunzip >/dev/null 2>&1 || { echo "gunzip not found in PATH" >&2; exit 3; }
|
||||||
|
command -v file >/dev/null 2>&1 || { echo "file command not found in PATH" >&2; exit 3; }
|
||||||
|
|
||||||
|
TMPDIR=$(mktemp -d)
|
||||||
|
trap '[[ "$KEEP" = false ]] && rm -rf "$TMPDIR"' EXIT
|
||||||
|
|
||||||
|
# If a key is provided, use an isolated GNUPGHOME so we don't touch the user's keyring.
|
||||||
|
if [[ -n "$PATH_TO_BACKUPGPG_KEY" ]]; then
|
||||||
|
if [[ ! -f "$PATH_TO_BACKUPGPG_KEY" ]]; then
|
||||||
|
echo "Private key file not found: $PATH_TO_BACKUPGPG_KEY" >&2
|
||||||
|
exit 4
|
||||||
|
fi
|
||||||
|
export GNUPGHOME="$TMPDIR/gnupg"
|
||||||
|
# Create GNUPGHOME and explicitly set secure permissions
|
||||||
|
mkdir -p "$GNUPGHOME"
|
||||||
|
chmod 0700 "$GNUPGHOME"
|
||||||
|
echo "Importing provided private key into temporary GNUPGHOME..."
|
||||||
|
gpg --batch --import "$PATH_TO_BACKUPGPG_KEY" >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine output directory: prefer PATH_TO_OUTPUT_DIR, otherwise current directory
|
||||||
|
if [[ -n "$PATH_TO_OUTPUT_DIR" ]]; then
|
||||||
|
OUTDIR="$PATH_TO_OUTPUT_DIR"
|
||||||
|
else
|
||||||
|
OUTDIR="$(pwd)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
|
# Keep decrypted intermediate in TMPDIR, final .sql in OUTDIR (PWD by default)
|
||||||
|
DECRYPTED="$TMPDIR/backup.decrypted"
|
||||||
|
|
||||||
|
# Derive a reasonable final filename from the backup file name
|
||||||
|
orig_base=$(basename -- "$PATH_TO_BACKUP_FILE")
|
||||||
|
name_no_gpg=${orig_base%.gpg}
|
||||||
|
name_no_gz=${name_no_gpg%.gz}
|
||||||
|
if [[ "$name_no_gz" == *.sql ]]; then
|
||||||
|
final_name="$name_no_gz"
|
||||||
|
else
|
||||||
|
final_name="${name_no_gz}.sql"
|
||||||
|
fi
|
||||||
|
FINAL_SQL="$OUTDIR/$final_name"
|
||||||
|
# If file exists, append timestamp to avoid accidental overwrite
|
||||||
|
if [[ -e "$FINAL_SQL" ]]; then
|
||||||
|
ts=$(date +%Y%m%d%H%M%S)
|
||||||
|
FINAL_SQL="$OUTDIR/${name_no_gz}.${ts}.sql"
|
||||||
|
echo "Notice: output file already existed; writing to $FINAL_SQL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Decrypting: $PATH_TO_BACKUP_FILE"
|
||||||
|
# Decrypt to a temporary file. gpg will prompt for passphrase if needed (user must be present)
|
||||||
|
if ! gpg --batch --yes --decrypt --output "$DECRYPTED" "$PATH_TO_BACKUP_FILE"; then
|
||||||
|
echo "gpg decryption failed" >&2
|
||||||
|
exit 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Detect if the decrypted file is gzip compressed
|
||||||
|
if file --brief --mime-type "$DECRYPTED" | grep -q gzip; then
|
||||||
|
echo "Detected gzip compressed payload; decompressing to: $FINAL_SQL"
|
||||||
|
if ! gunzip -c "$DECRYPTED" > "$FINAL_SQL"; then
|
||||||
|
echo "gunzip failed" >&2
|
||||||
|
exit 6
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Not gzip: assume plain SQL or other plain text
|
||||||
|
echo "Writing decrypted payload to: $FINAL_SQL"
|
||||||
|
cp "$DECRYPTED" "$FINAL_SQL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Unpacked SQL available at: $FINAL_SQL"
|
||||||
|
|
||||||
|
# Show a short preview
|
||||||
|
echo
|
||||||
|
echo "--- File preview (first 80 lines) ---"
|
||||||
|
head -n 80 "$FINAL_SQL" || true
|
||||||
|
echo "--- end preview ---"
|
||||||
|
|
||||||
|
echo
|
||||||
|
if [[ "$KEEP" = true ]]; then
|
||||||
|
echo "Temporary files (including GNUPGHOME) retained under: $TMPDIR"
|
||||||
|
echo "Final SQL file retained at: $FINAL_SQL"
|
||||||
|
else
|
||||||
|
echo "Temporary files (excluding final SQL) were stored under: $TMPDIR (removed on exit)"
|
||||||
|
echo "Final SQL file is at: $FINAL_SQL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Print final path so callers can copy it if they used --keep or scripting
|
||||||
|
echo "$FINAL_SQL"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue