mirror of
https://github.com/m1ngsama/automa.git
synced 2026-03-25 18:23:49 +00:00
feat: add missing service deploy scripts (sing-box, tnt, minio, galene)
Infrastructure audit revealed services running in production with no corresponding deploy scripts. Closes #11. - sing-box: server + client deploy scripts. Config generated by sing-box-yg (https://github.com/yonggekkk/sing-box-yg), stored in infra for recovery. - tnt: terminal chat server via official install.sh; proper systemd unit with unprivileged user and security hardening. - minio: single-binary install from dl.min.io; minio-user, /etc/default/minio. - galene: binary install from GitHub releases; configurable UDP range for WebRTC. - frp/server: add FRP_WEB_USER to .env.example and frps.toml.example; fix hardcoded "root" username in web dashboard config.
This commit is contained in:
parent
9d8a08900d
commit
b91512e97f
14 changed files with 450 additions and 6 deletions
47
README.md
47
README.md
|
|
@ -50,7 +50,7 @@ INFRA_DIR=/path/to/infra/services/nginx ./services/nginx/deploy.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Shadowsocks
|
### Shadowsocks
|
||||||
GFW-resistant proxy.
|
GFW-resistant proxy (legacy; new deployments should use sing-box).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Server (VPS)
|
# Server (VPS)
|
||||||
|
|
@ -60,6 +60,18 @@ INFRA_DIR=/path/to/infra/services/shadowsocks/server ./services/shadowsocks/serv
|
||||||
INFRA_DIR=/path/to/infra/services/shadowsocks/client ./services/shadowsocks/client/deploy.sh
|
INFRA_DIR=/path/to/infra/services/shadowsocks/client ./services/shadowsocks/client/deploy.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Sing-box
|
||||||
|
Multi-protocol proxy (VLESS/Reality, VMess/WS, Hysteria2). Config generated once
|
||||||
|
by [sing-box-yg](https://github.com/yonggekkk/sing-box-yg), then stored in infra.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Server (VPS)
|
||||||
|
INFRA_DIR=/path/to/infra/services/sing-box/server ./services/sing-box/server/deploy.sh
|
||||||
|
|
||||||
|
# Client (home machine)
|
||||||
|
INFRA_DIR=/path/to/infra/services/sing-box/client ./services/sing-box/client/deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
### FRP
|
### FRP
|
||||||
Reverse tunnel — expose home services through VPS.
|
Reverse tunnel — expose home services through VPS.
|
||||||
|
|
||||||
|
|
@ -71,6 +83,27 @@ INFRA_DIR=/path/to/infra/services/frp/server ./services/frp/server/deploy.sh
|
||||||
INFRA_DIR=/path/to/infra/services/frp/client ./services/frp/client/deploy.sh
|
INFRA_DIR=/path/to/infra/services/frp/client ./services/frp/client/deploy.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### TNT
|
||||||
|
SSH-based terminal chat server.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
INFRA_DIR=/path/to/infra/services/tnt ./services/tnt/deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### MinIO
|
||||||
|
S3-compatible object storage.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
INFRA_DIR=/path/to/infra/services/minio ./services/minio/deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Galene
|
||||||
|
WebRTC video conferencing server.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
INFRA_DIR=/path/to/infra/services/galene ./services/galene/deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
## Home Services
|
## Home Services
|
||||||
|
|
||||||
Docker-based services with their own config.
|
Docker-based services with their own config.
|
||||||
|
|
@ -143,9 +176,15 @@ automa/
|
||||||
│ ├── shadowsocks/
|
│ ├── shadowsocks/
|
||||||
│ │ ├── server/deploy.sh
|
│ │ ├── server/deploy.sh
|
||||||
│ │ └── client/deploy.sh
|
│ │ └── client/deploy.sh
|
||||||
│ └── frp/
|
│ ├── sing-box/
|
||||||
│ ├── server/deploy.sh
|
│ │ ├── server/deploy.sh
|
||||||
│ └── client/deploy.sh
|
│ │ └── client/deploy.sh
|
||||||
|
│ ├── frp/
|
||||||
|
│ │ ├── server/deploy.sh
|
||||||
|
│ │ └── client/deploy.sh
|
||||||
|
│ ├── tnt/deploy.sh
|
||||||
|
│ ├── minio/deploy.sh
|
||||||
|
│ └── galene/deploy.sh
|
||||||
├── minecraft/ # Minecraft server (Docker)
|
├── minecraft/ # Minecraft server (Docker)
|
||||||
├── teamspeak/ # TeamSpeak server (Docker)
|
├── teamspeak/ # TeamSpeak server (Docker)
|
||||||
├── nextcloud/ # Nextcloud (Docker)
|
├── nextcloud/ # Nextcloud (Docker)
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,6 @@
|
||||||
# description: FRP server (frps) — public entry point for reverse tunnels
|
# description: FRP server (frps) — public entry point for reverse tunnels
|
||||||
|
|
||||||
FRP_TOKEN=
|
FRP_TOKEN=
|
||||||
|
FRP_WEB_USER=admin
|
||||||
FRP_WEB_PASSWORD=
|
FRP_WEB_PASSWORD=
|
||||||
FRP_BIND_PORT=7000
|
FRP_BIND_PORT=7000
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ ENV_FILE="${INFRA_DIR:-.}/.env"
|
||||||
[ -f "$ENV_FILE" ] || { log_error "No .env found at $ENV_FILE"; exit 1; }
|
[ -f "$ENV_FILE" ] || { log_error "No .env found at $ENV_FILE"; exit 1; }
|
||||||
set -a; source "$ENV_FILE"; set +a
|
set -a; source "$ENV_FILE"; set +a
|
||||||
|
|
||||||
require_env FRP_TOKEN FRP_WEB_PASSWORD FRP_BIND_PORT
|
require_env FRP_TOKEN FRP_WEB_USER FRP_WEB_PASSWORD FRP_BIND_PORT
|
||||||
|
|
||||||
find_template() {
|
find_template() {
|
||||||
local f="$1"
|
local f="$1"
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ vhostHTTPSPort = 8443
|
||||||
|
|
||||||
webServer.addr = "127.0.0.1"
|
webServer.addr = "127.0.0.1"
|
||||||
webServer.port = 7500
|
webServer.port = 7500
|
||||||
webServer.user = "root"
|
webServer.user = "${FRP_WEB_USER}"
|
||||||
webServer.password = "${FRP_WEB_PASSWORD}"
|
webServer.password = "${FRP_WEB_PASSWORD}"
|
||||||
|
|
||||||
log.to = "./frps.log"
|
log.to = "./frps.log"
|
||||||
|
|
|
||||||
6
services/galene/.env.example
Normal file
6
services/galene/.env.example
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
# role: vps
|
||||||
|
# description: Galene video conferencing server
|
||||||
|
GALENE_VERSION=0.9.2
|
||||||
|
GALENE_HTTP_ADDR=127.0.0.1:8443
|
||||||
|
GALENE_TURN_ADDR=x.x.x.x:1194
|
||||||
|
GALENE_UDP_RANGE=10000-10100
|
||||||
81
services/galene/deploy.sh
Executable file
81
services/galene/deploy.sh
Executable file
|
|
@ -0,0 +1,81 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Deploys Galene video conferencing server.
|
||||||
|
# https://github.com/jech/galene
|
||||||
|
#
|
||||||
|
# Usage: INFRA_DIR=/path/to/infra/services/galene ./deploy.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/../../bin/lib/common.sh"
|
||||||
|
|
||||||
|
ENV_FILE="${INFRA_DIR:-.}/.env"
|
||||||
|
[ -f "$ENV_FILE" ] || { log_error "No .env found at $ENV_FILE"; exit 1; }
|
||||||
|
set -a; source "$ENV_FILE"; set +a
|
||||||
|
|
||||||
|
require_env GALENE_VERSION GALENE_HTTP_ADDR GALENE_TURN_ADDR
|
||||||
|
|
||||||
|
INSTALL_DIR="/opt/galene"
|
||||||
|
BIN="$INSTALL_DIR/galene"
|
||||||
|
|
||||||
|
if [[ -x "$BIN" ]]; then
|
||||||
|
log_info "galene already at $BIN, skipping download"
|
||||||
|
else
|
||||||
|
log_info "Downloading Galene ${GALENE_VERSION}..."
|
||||||
|
ARCH="$(uname -m)"
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64) ARCH="amd64" ;;
|
||||||
|
aarch64) ARCH="arm64" ;;
|
||||||
|
*) log_error "Unsupported arch: $ARCH"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
URL="https://github.com/jech/galene/releases/download/galene-${GALENE_VERSION}/galene-${GALENE_VERSION}-linux-${ARCH}.tar.gz"
|
||||||
|
TMP="$(mktemp -d)"
|
||||||
|
wget -qO "$TMP/galene.tar.gz" "$URL"
|
||||||
|
mkdir -p "$INSTALL_DIR"
|
||||||
|
tar -xf "$TMP/galene.tar.gz" -C "$INSTALL_DIR" --strip-components=1
|
||||||
|
chmod +x "$BIN"
|
||||||
|
rm -rf "$TMP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Creating directories..."
|
||||||
|
mkdir -p "$INSTALL_DIR"/{data,groups,static}
|
||||||
|
|
||||||
|
log_info "Deploying groups config from INFRA_DIR..."
|
||||||
|
if [[ -d "${INFRA_DIR}/groups" ]]; then
|
||||||
|
cp -r "${INFRA_DIR}/groups/." "$INSTALL_DIR/groups/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Installing systemd service..."
|
||||||
|
cat > /etc/systemd/system/galene.service <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=Galene videoconference server
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
WorkingDirectory=$INSTALL_DIR
|
||||||
|
ExecStart=$BIN \\
|
||||||
|
-insecure \\
|
||||||
|
-http ${GALENE_HTTP_ADDR} \\
|
||||||
|
-static $INSTALL_DIR/static \\
|
||||||
|
-groups $INSTALL_DIR/groups \\
|
||||||
|
-data $INSTALL_DIR/data \\
|
||||||
|
-turn ${GALENE_TURN_ADDR} \\
|
||||||
|
-udp-range ${GALENE_UDP_RANGE:-10000-10100}
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
LimitNOFILE=65536
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now galene
|
||||||
|
|
||||||
|
log_info "Galene deployed"
|
||||||
|
echo " Listening: ${GALENE_HTTP_ADDR}"
|
||||||
|
echo ""
|
||||||
|
echo "Remaining manual steps:"
|
||||||
|
echo " 1. Configure nginx reverse proxy (see infra/services/nginx/sites/)"
|
||||||
|
echo " 2. Get TLS cert for frontend domain"
|
||||||
|
echo " 3. Open UDP ports ${GALENE_UDP_RANGE:-10000-10100} in firewall"
|
||||||
8
services/minio/.env.example
Normal file
8
services/minio/.env.example
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# role: vps
|
||||||
|
# description: MinIO object storage server
|
||||||
|
MINIO_ROOT_USER=minioadmin
|
||||||
|
MINIO_ROOT_PASSWORD=
|
||||||
|
MINIO_VOLUMES=/data/minio
|
||||||
|
MINIO_OPTS=--console-address :9001
|
||||||
|
MINIO_BROWSER_REDIRECT_URL=https://console.example.com
|
||||||
|
MINIO_SERVER_URL=https://oss.example.com
|
||||||
83
services/minio/deploy.sh
Executable file
83
services/minio/deploy.sh
Executable file
|
|
@ -0,0 +1,83 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Deploys MinIO object storage server.
|
||||||
|
# https://min.io/docs/minio/linux/index.html
|
||||||
|
#
|
||||||
|
# Usage: INFRA_DIR=/path/to/infra/services/minio ./deploy.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/../../bin/lib/common.sh"
|
||||||
|
|
||||||
|
ENV_FILE="${INFRA_DIR:-.}/.env"
|
||||||
|
[ -f "$ENV_FILE" ] || { log_error "No .env found at $ENV_FILE"; exit 1; }
|
||||||
|
set -a; source "$ENV_FILE"; set +a
|
||||||
|
|
||||||
|
require_env MINIO_ROOT_USER MINIO_ROOT_PASSWORD MINIO_VOLUMES
|
||||||
|
|
||||||
|
BIN="/usr/local/bin/minio"
|
||||||
|
|
||||||
|
if [[ -x "$BIN" ]]; then
|
||||||
|
log_info "minio already at $BIN, skipping download"
|
||||||
|
else
|
||||||
|
log_info "Downloading MinIO..."
|
||||||
|
wget -qO "$BIN" https://dl.min.io/server/minio/release/linux-amd64/minio
|
||||||
|
chmod +x "$BIN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Creating minio-user..."
|
||||||
|
if ! id minio-user &>/dev/null; then
|
||||||
|
useradd --system --no-create-home --shell /usr/sbin/nologin minio-user
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Creating data directory: ${MINIO_VOLUMES}..."
|
||||||
|
mkdir -p "${MINIO_VOLUMES}"
|
||||||
|
chown minio-user:minio-user "${MINIO_VOLUMES}"
|
||||||
|
|
||||||
|
log_info "Writing /etc/default/minio..."
|
||||||
|
cat > /etc/default/minio <<EOF
|
||||||
|
MINIO_ROOT_USER=${MINIO_ROOT_USER}
|
||||||
|
MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
|
||||||
|
MINIO_VOLUMES=${MINIO_VOLUMES}
|
||||||
|
MINIO_OPTS=${MINIO_OPTS:---console-address :9001}
|
||||||
|
MINIO_BROWSER_REDIRECT_URL=${MINIO_BROWSER_REDIRECT_URL:-}
|
||||||
|
MINIO_SERVER_URL=${MINIO_SERVER_URL:-}
|
||||||
|
EOF
|
||||||
|
chmod 640 /etc/default/minio
|
||||||
|
chown root:minio-user /etc/default/minio
|
||||||
|
|
||||||
|
log_info "Installing systemd service..."
|
||||||
|
cat > /etc/systemd/system/minio.service <<'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=MinIO
|
||||||
|
Documentation=https://min.io/docs/minio/linux/index.html
|
||||||
|
Wants=network-online.target
|
||||||
|
After=network-online.target
|
||||||
|
AssertFileIsExecutable=/usr/local/bin/minio
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
WorkingDirectory=/usr/local
|
||||||
|
User=minio-user
|
||||||
|
Group=minio-user
|
||||||
|
EnvironmentFile=/etc/default/minio
|
||||||
|
ExecStartPre=/bin/bash -c 'if [ -z "${MINIO_VOLUMES}" ]; then echo "MINIO_VOLUMES not set"; exit 1; fi'
|
||||||
|
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES
|
||||||
|
Restart=always
|
||||||
|
LimitNOFILE=65536
|
||||||
|
TasksMax=infinity
|
||||||
|
TimeoutStopSec=infinity
|
||||||
|
SendSIGKILL=no
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now minio
|
||||||
|
|
||||||
|
log_info "MinIO deployed"
|
||||||
|
echo " API: http://localhost:9000"
|
||||||
|
echo " Console: http://localhost:9001"
|
||||||
|
echo ""
|
||||||
|
echo "Remaining manual steps:"
|
||||||
|
echo " 1. Configure nginx reverse proxy (see infra/services/nginx/sites/)"
|
||||||
|
echo " 2. Get TLS cert: certbot --nginx -d ${MINIO_SERVER_URL#https://}"
|
||||||
3
services/sing-box/client/.env.example
Normal file
3
services/sing-box/client/.env.example
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# role: homeserver
|
||||||
|
# description: sing-box transparent proxy client connecting to sing-box server
|
||||||
|
SING_BOX_VERSION=1.11.0
|
||||||
66
services/sing-box/client/deploy.sh
Executable file
66
services/sing-box/client/deploy.sh
Executable file
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Deploys sing-box as a transparent proxy client (home machine / LAN gateway).
|
||||||
|
#
|
||||||
|
# Usage: INFRA_DIR=/path/to/infra/services/sing-box/client ./deploy.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/../../../bin/lib/common.sh"
|
||||||
|
|
||||||
|
ENV_FILE="${INFRA_DIR:-.}/.env"
|
||||||
|
[ -f "$ENV_FILE" ] || { log_error "No .env found at $ENV_FILE"; exit 1; }
|
||||||
|
set -a; source "$ENV_FILE"; set +a
|
||||||
|
|
||||||
|
require_env SING_BOX_VERSION
|
||||||
|
|
||||||
|
INSTALL_DIR="/etc/sing-box"
|
||||||
|
BIN="$INSTALL_DIR/sing-box"
|
||||||
|
|
||||||
|
if [[ -x "$BIN" ]]; then
|
||||||
|
log_info "sing-box already at $BIN, skipping download"
|
||||||
|
else
|
||||||
|
log_info "Downloading sing-box ${SING_BOX_VERSION}..."
|
||||||
|
ARCH="$(uname -m)"
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64) ARCH="amd64" ;;
|
||||||
|
aarch64) ARCH="arm64" ;;
|
||||||
|
*) log_error "Unsupported arch: $ARCH"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
URL="https://github.com/SagerNet/sing-box/releases/download/v${SING_BOX_VERSION}/sing-box-${SING_BOX_VERSION}-linux-${ARCH}.tar.gz"
|
||||||
|
TMP="$(mktemp -d)"
|
||||||
|
wget -qO "$TMP/sing-box.tar.gz" "$URL"
|
||||||
|
tar -xf "$TMP/sing-box.tar.gz" -C "$TMP"
|
||||||
|
mkdir -p "$INSTALL_DIR"
|
||||||
|
install -m 755 "$TMP/sing-box-${SING_BOX_VERSION}-linux-${ARCH}/sing-box" "$BIN"
|
||||||
|
rm -rf "$TMP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Deploying client config..."
|
||||||
|
CONFIG_SRC="${INFRA_DIR}/sing_box_client.json"
|
||||||
|
[ -f "$CONFIG_SRC" ] || { log_error "sing_box_client.json not found in INFRA_DIR"; exit 1; }
|
||||||
|
cp "$CONFIG_SRC" "$INSTALL_DIR/config.json"
|
||||||
|
|
||||||
|
log_info "Installing systemd service..."
|
||||||
|
cat > /etc/systemd/system/sing-box-client.service <<'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=sing-box Client
|
||||||
|
After=network.target nss-lookup.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=root
|
||||||
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
|
||||||
|
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
|
||||||
|
ExecStart=/etc/sing-box/sing-box run -c /etc/sing-box/config.json
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=10
|
||||||
|
LimitNOFILE=65536
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now sing-box-client
|
||||||
|
|
||||||
|
log_info "sing-box client deployed"
|
||||||
3
services/sing-box/server/.env.example
Normal file
3
services/sing-box/server/.env.example
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# role: vps
|
||||||
|
# description: sing-box proxy server (VLESS/Reality, VMess/WS, Hysteria2 via sing-box-yg)
|
||||||
|
SING_BOX_VERSION=1.11.0
|
||||||
77
services/sing-box/server/deploy.sh
Executable file
77
services/sing-box/server/deploy.sh
Executable file
|
|
@ -0,0 +1,77 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Deploys sing-box proxy server on VPS.
|
||||||
|
#
|
||||||
|
# Config generated by https://github.com/yonggekkk/sing-box-yg — run that
|
||||||
|
# script once interactively to create /etc/s-box/sb.json, certs, and keys.
|
||||||
|
# Then commit the generated files into infra for future re-deployment.
|
||||||
|
#
|
||||||
|
# Usage: INFRA_DIR=/path/to/infra/services/sing-box/server ./deploy.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/../../../bin/lib/common.sh"
|
||||||
|
|
||||||
|
ENV_FILE="${INFRA_DIR:-.}/.env"
|
||||||
|
[ -f "$ENV_FILE" ] || { log_error "No .env found at $ENV_FILE"; exit 1; }
|
||||||
|
set -a; source "$ENV_FILE"; set +a
|
||||||
|
|
||||||
|
require_env SING_BOX_VERSION
|
||||||
|
|
||||||
|
INSTALL_DIR="/etc/s-box"
|
||||||
|
BIN="$INSTALL_DIR/sing-box"
|
||||||
|
|
||||||
|
if [[ -x "$BIN" ]]; then
|
||||||
|
log_info "sing-box already at $BIN, skipping download"
|
||||||
|
else
|
||||||
|
log_info "Downloading sing-box ${SING_BOX_VERSION}..."
|
||||||
|
ARCH="$(uname -m)"
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64) ARCH="amd64" ;;
|
||||||
|
aarch64) ARCH="arm64" ;;
|
||||||
|
*) log_error "Unsupported arch: $ARCH"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
URL="https://github.com/SagerNet/sing-box/releases/download/v${SING_BOX_VERSION}/sing-box-${SING_BOX_VERSION}-linux-${ARCH}.tar.gz"
|
||||||
|
TMP="$(mktemp -d)"
|
||||||
|
wget -qO "$TMP/sing-box.tar.gz" "$URL"
|
||||||
|
tar -xf "$TMP/sing-box.tar.gz" -C "$TMP"
|
||||||
|
mkdir -p "$INSTALL_DIR"
|
||||||
|
install -m 755 "$TMP/sing-box-${SING_BOX_VERSION}-linux-${ARCH}/sing-box" "$BIN"
|
||||||
|
rm -rf "$TMP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Deploying config from INFRA_DIR..."
|
||||||
|
for f in sb.json cert.pem private.key public.key; do
|
||||||
|
src="${INFRA_DIR}/$f"
|
||||||
|
if [[ -f "$src" ]]; then
|
||||||
|
cp "$src" "$INSTALL_DIR/$f"
|
||||||
|
log_info " copied $f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log_info "Installing systemd service..."
|
||||||
|
cat > /etc/systemd/system/sing-box.service <<'EOF'
|
||||||
|
[Unit]
|
||||||
|
After=network.target nss-lookup.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/root
|
||||||
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
|
||||||
|
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
|
||||||
|
ExecStart=/etc/s-box/sing-box run -c /etc/s-box/sb.json
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=10
|
||||||
|
LimitNOFILE=infinity
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now sing-box
|
||||||
|
|
||||||
|
log_info "sing-box server deployed"
|
||||||
|
echo ""
|
||||||
|
echo "Note: initial config must be generated via sing-box-yg:"
|
||||||
|
echo " bash <(curl -Ls https://raw.githubusercontent.com/yonggekkk/sing-box-yg/main/sb.sh)"
|
||||||
7
services/tnt/.env.example
Normal file
7
services/tnt/.env.example
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# role: any
|
||||||
|
# description: TNT terminal chat server (SSH-based, github.com/m1ngsama/TNT)
|
||||||
|
TNT_PORT=2222
|
||||||
|
TNT_ACCESS_TOKEN=
|
||||||
|
TNT_BIND_ADDR=0.0.0.0
|
||||||
|
TNT_MAX_CONNECTIONS=50
|
||||||
|
TNT_MAX_CONN_PER_IP=3
|
||||||
70
services/tnt/deploy.sh
Executable file
70
services/tnt/deploy.sh
Executable file
|
|
@ -0,0 +1,70 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Deploys TNT terminal chat server.
|
||||||
|
# https://github.com/m1ngsama/TNT
|
||||||
|
#
|
||||||
|
# Usage: INFRA_DIR=/path/to/infra/services/tnt ./deploy.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/../../bin/lib/common.sh"
|
||||||
|
|
||||||
|
ENV_FILE="${INFRA_DIR:-.}/.env"
|
||||||
|
[ -f "$ENV_FILE" ] || { log_error "No .env found at $ENV_FILE"; exit 1; }
|
||||||
|
set -a; source "$ENV_FILE"; set +a
|
||||||
|
|
||||||
|
require_env TNT_PORT TNT_ACCESS_TOKEN
|
||||||
|
|
||||||
|
BIN="/usr/local/bin/tnt"
|
||||||
|
DATA_DIR="/var/lib/tnt"
|
||||||
|
|
||||||
|
if [[ -x "$BIN" ]]; then
|
||||||
|
log_info "tnt already at $BIN, skipping download"
|
||||||
|
else
|
||||||
|
log_info "Installing tnt via official installer..."
|
||||||
|
curl -sSL https://raw.githubusercontent.com/m1ngsama/TNT/main/install.sh | sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Setting up data directory..."
|
||||||
|
mkdir -p "$DATA_DIR"
|
||||||
|
|
||||||
|
# Create unprivileged user if not exists
|
||||||
|
if ! id tnt &>/dev/null; then
|
||||||
|
useradd --system --no-create-home --shell /usr/sbin/nologin tnt
|
||||||
|
fi
|
||||||
|
chown tnt:tnt "$DATA_DIR"
|
||||||
|
|
||||||
|
log_info "Installing systemd service..."
|
||||||
|
cat > /etc/systemd/system/tnt.service <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=TNT Terminal Chat Server
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=tnt
|
||||||
|
Group=tnt
|
||||||
|
WorkingDirectory=$DATA_DIR
|
||||||
|
ExecStart=$BIN -p ${TNT_PORT}
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
Environment="TNT_ACCESS_TOKEN=${TNT_ACCESS_TOKEN}"
|
||||||
|
Environment="TNT_BIND_ADDR=${TNT_BIND_ADDR:-0.0.0.0}"
|
||||||
|
Environment="TNT_MAX_CONNECTIONS=${TNT_MAX_CONNECTIONS:-50}"
|
||||||
|
Environment="TNT_MAX_CONN_PER_IP=${TNT_MAX_CONN_PER_IP:-3}"
|
||||||
|
|
||||||
|
NoNewPrivileges=true
|
||||||
|
PrivateTmp=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=true
|
||||||
|
ReadWritePaths=$DATA_DIR
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now tnt
|
||||||
|
|
||||||
|
log_info "TNT deployed on port ${TNT_PORT}"
|
||||||
|
echo " Connect: ssh -p ${TNT_PORT} <host>"
|
||||||
Loading…
Reference in a new issue