Release v1.2: hardening, version bump, README update
- Atomic settings.conf writes (write to tmp, then mv) - Secure temp dirs with mktemp (5 locations) - Add set -eo pipefail for pipe failure detection - Add timeout 10 to all docker stats calls - Update version from 1.2-Beta to 1.2 - Update URL from beta-releases to main - README updated for stable release
This commit is contained in:
20
README.md
20
README.md
@@ -10,7 +10,7 @@
|
|||||||
M A N A G E R
|
M A N A G E R
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
@@ -18,24 +18,22 @@
|
|||||||
|
|
||||||
A powerful management tool for deploying and managing Psiphon Conduit nodes on Linux servers. Help users access the open internet during network restrictions.
|
A powerful management tool for deploying and managing Psiphon Conduit nodes on Linux servers. Help users access the open internet during network restrictions.
|
||||||
|
|
||||||
## Quick Install (Beta)
|
## Quick Install
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sL https://raw.githubusercontent.com/SamNet-dev/conduit-manager/beta-releases/conduit.sh | sudo bash
|
curl -sL https://raw.githubusercontent.com/SamNet-dev/conduit-manager/main/conduit.sh | sudo bash
|
||||||
```
|
```
|
||||||
|
|
||||||
Or download and run manually:
|
Or download and run manually:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wget https://raw.githubusercontent.com/SamNet-dev/conduit-manager/beta-releases/conduit.sh
|
wget https://raw.githubusercontent.com/SamNet-dev/conduit-manager/main/conduit.sh
|
||||||
sudo bash conduit.sh
|
sudo bash conduit.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
> For stable release, use `main` instead of `beta-releases` in the URL above.
|
> For beta/preview releases, use `beta-releases` instead of `main` in the URL above.
|
||||||
|
|
||||||
## v1.2-Beta Changelog
|
## What's New in v1.2
|
||||||
|
|
||||||
> This list will grow as more features are added before the full v1.2 release.
|
|
||||||
|
|
||||||
**New Features**
|
**New Features**
|
||||||
- Per-container CPU and memory resource limits via Settings menu
|
- Per-container CPU and memory resource limits via Settings menu
|
||||||
@@ -72,6 +70,7 @@ sudo bash conduit.sh
|
|||||||
- PID management for background processes
|
- PID management for background processes
|
||||||
- Consistent `[STATS]` grep pattern across all screens
|
- Consistent `[STATS]` grep pattern across all screens
|
||||||
- Temp dir cleanup to prevent stale data reads
|
- Temp dir cleanup to prevent stale data reads
|
||||||
|
- Atomic settings file writes to prevent corruption
|
||||||
|
|
||||||
**Security**
|
**Security**
|
||||||
- Silent bot token input (not echoed)
|
- Silent bot token input (not echoed)
|
||||||
@@ -80,6 +79,7 @@ sudo bash conduit.sh
|
|||||||
- BotFather privacy guidance in setup wizard
|
- BotFather privacy guidance in setup wizard
|
||||||
- OPSEC warning for operators in censored regions
|
- OPSEC warning for operators in censored regions
|
||||||
- Curl calls with `--max-filesize` and `--max-time` limits
|
- Curl calls with `--max-filesize` and `--max-time` limits
|
||||||
|
- Secure temp directories with `mktemp`
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ conduit uninstall # Remove all components
|
|||||||
|
|
||||||
## Upgrading
|
## Upgrading
|
||||||
|
|
||||||
Just run the install command above. When prompted, select **"Open management menu"** — existing containers are recognized automatically. Telegram settings are preserved across upgrades.
|
Just run the install command above or use `conduit update` from the menu. Existing containers are recognized automatically. Telegram settings are preserved across upgrades.
|
||||||
|
|
||||||
## Claim Rewards (OAT Tokens)
|
## Claim Rewards (OAT Tokens)
|
||||||
|
|
||||||
@@ -172,8 +172,6 @@ MIT License
|
|||||||
|
|
||||||
Pull requests welcome. For major changes, open an issue first.
|
Pull requests welcome. For major changes, open an issue first.
|
||||||
|
|
||||||
This is a **beta release** — please report any issues.
|
|
||||||
|
|
||||||
## Links
|
## Links
|
||||||
|
|
||||||
- [Psiphon](https://psiphon.ca/)
|
- [Psiphon](https://psiphon.ca/)
|
||||||
|
|||||||
61
conduit.sh
61
conduit.sh
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# ╔═══════════════════════════════════════════════════════════════════╗
|
# ╔═══════════════════════════════════════════════════════════════════╗
|
||||||
# ║ 🚀 PSIPHON CONDUIT MANAGER v1.2-Beta ║
|
# ║ 🚀 PSIPHON CONDUIT MANAGER v1.2 ║
|
||||||
# ║ ║
|
# ║ ║
|
||||||
# ║ One-click setup for Psiphon Conduit ║
|
# ║ One-click setup for Psiphon Conduit ║
|
||||||
# ║ ║
|
# ║ ║
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
# -v, --verbose increase verbosity (-v for verbose, -vv for debug)
|
# -v, --verbose increase verbosity (-v for verbose, -vv for debug)
|
||||||
#
|
#
|
||||||
|
|
||||||
set -e
|
set -eo pipefail
|
||||||
|
|
||||||
# Require bash
|
# Require bash
|
||||||
if [ -z "$BASH_VERSION" ]; then
|
if [ -z "$BASH_VERSION" ]; then
|
||||||
@@ -31,7 +31,7 @@ if [ -z "$BASH_VERSION" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
VERSION="1.2-Beta"
|
VERSION="1.2"
|
||||||
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest"
|
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest"
|
||||||
INSTALL_DIR="${INSTALL_DIR:-/opt/conduit}"
|
INSTALL_DIR="${INSTALL_DIR:-/opt/conduit}"
|
||||||
BACKUP_DIR="$INSTALL_DIR/backups"
|
BACKUP_DIR="$INSTALL_DIR/backups"
|
||||||
@@ -701,7 +701,8 @@ save_settings_install() {
|
|||||||
_tg_label="${TELEGRAM_SERVER_LABEL:-}"
|
_tg_label="${TELEGRAM_SERVER_LABEL:-}"
|
||||||
_tg_start_hour="${TELEGRAM_START_HOUR:-0}"
|
_tg_start_hour="${TELEGRAM_START_HOUR:-0}"
|
||||||
fi
|
fi
|
||||||
cat > "$INSTALL_DIR/settings.conf" << EOF
|
local _tmp="$INSTALL_DIR/settings.conf.tmp.$$"
|
||||||
|
cat > "$_tmp" << EOF
|
||||||
MAX_CLIENTS=$MAX_CLIENTS
|
MAX_CLIENTS=$MAX_CLIENTS
|
||||||
BANDWIDTH=$BANDWIDTH
|
BANDWIDTH=$BANDWIDTH
|
||||||
CONTAINER_COUNT=${CONTAINER_COUNT:-1}
|
CONTAINER_COUNT=${CONTAINER_COUNT:-1}
|
||||||
@@ -720,8 +721,8 @@ TELEGRAM_WEEKLY_SUMMARY=$_tg_weekly
|
|||||||
TELEGRAM_SERVER_LABEL="$_tg_label"
|
TELEGRAM_SERVER_LABEL="$_tg_label"
|
||||||
TELEGRAM_START_HOUR=$_tg_start_hour
|
TELEGRAM_START_HOUR=$_tg_start_hour
|
||||||
EOF
|
EOF
|
||||||
|
chmod 600 "$_tmp" 2>/dev/null || true
|
||||||
chmod 600 "$INSTALL_DIR/settings.conf" 2>/dev/null || true
|
mv "$_tmp" "$INSTALL_DIR/settings.conf"
|
||||||
|
|
||||||
if [ ! -f "$INSTALL_DIR/settings.conf" ]; then
|
if [ ! -f "$INSTALL_DIR/settings.conf" ]; then
|
||||||
log_error "Failed to save settings. Check disk space and permissions."
|
log_error "Failed to save settings. Check disk space and permissions."
|
||||||
@@ -841,7 +842,7 @@ create_management_script() {
|
|||||||
# Reference: https://github.com/ssmirr/conduit/releases/latest
|
# Reference: https://github.com/ssmirr/conduit/releases/latest
|
||||||
#
|
#
|
||||||
|
|
||||||
VERSION="1.2-Beta"
|
VERSION="1.2"
|
||||||
INSTALL_DIR="REPLACE_ME_INSTALL_DIR"
|
INSTALL_DIR="REPLACE_ME_INSTALL_DIR"
|
||||||
BACKUP_DIR="$INSTALL_DIR/backups"
|
BACKUP_DIR="$INSTALL_DIR/backups"
|
||||||
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest"
|
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest"
|
||||||
@@ -1296,7 +1297,7 @@ get_container_stats() {
|
|||||||
for i in $(seq 1 $CONTAINER_COUNT); do
|
for i in $(seq 1 $CONTAINER_COUNT); do
|
||||||
names+=" $(get_container_name $i)"
|
names+=" $(get_container_name $i)"
|
||||||
done
|
done
|
||||||
local all_stats=$(docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" $names 2>/dev/null)
|
local all_stats=$(timeout 10 docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" $names 2>/dev/null)
|
||||||
if [ -z "$all_stats" ]; then
|
if [ -z "$all_stats" ]; then
|
||||||
echo "0% 0MiB"
|
echo "0% 0MiB"
|
||||||
elif [ "$CONTAINER_COUNT" -le 1 ]; then
|
elif [ "$CONTAINER_COUNT" -le 1 ]; then
|
||||||
@@ -1970,8 +1971,8 @@ show_advanced_stats() {
|
|||||||
|
|
||||||
# Fetch docker stats and all container logs in parallel
|
# Fetch docker stats and all container logs in parallel
|
||||||
local adv_running_names=""
|
local adv_running_names=""
|
||||||
local _adv_tmpdir="/tmp/.conduit_adv_$$"
|
local _adv_tmpdir=$(mktemp -d /tmp/.conduit_adv.XXXXXX)
|
||||||
rm -rf "$_adv_tmpdir"; mkdir -p "$_adv_tmpdir"
|
# mktemp already created the directory
|
||||||
for ci in $(seq 1 $CONTAINER_COUNT); do
|
for ci in $(seq 1 $CONTAINER_COUNT); do
|
||||||
local cname=$(get_container_name $ci)
|
local cname=$(get_container_name $ci)
|
||||||
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
||||||
@@ -1981,7 +1982,7 @@ show_advanced_stats() {
|
|||||||
done
|
done
|
||||||
local adv_all_stats=""
|
local adv_all_stats=""
|
||||||
if [ -n "$adv_running_names" ]; then
|
if [ -n "$adv_running_names" ]; then
|
||||||
( docker stats --no-stream --format "{{.Name}}|{{.CPUPerc}}|{{.MemUsage}}" $adv_running_names > "$_adv_tmpdir/stats" 2>/dev/null ) &
|
( timeout 10 docker stats --no-stream --format "{{.Name}}|{{.CPUPerc}}|{{.MemUsage}}" $adv_running_names > "$_adv_tmpdir/stats" 2>/dev/null ) &
|
||||||
fi
|
fi
|
||||||
wait
|
wait
|
||||||
[ -f "$_adv_tmpdir/stats" ] && adv_all_stats=$(cat "$_adv_tmpdir/stats")
|
[ -f "$_adv_tmpdir/stats" ] && adv_all_stats=$(cat "$_adv_tmpdir/stats")
|
||||||
@@ -2243,8 +2244,8 @@ show_peers() {
|
|||||||
# Get actual connected clients from docker logs (parallel)
|
# Get actual connected clients from docker logs (parallel)
|
||||||
local total_clients=0
|
local total_clients=0
|
||||||
local docker_ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null)
|
local docker_ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null)
|
||||||
local _peer_tmpdir="/tmp/.conduit_peer_$$"
|
local _peer_tmpdir=$(mktemp -d /tmp/.conduit_peer.XXXXXX)
|
||||||
rm -rf "$_peer_tmpdir"; mkdir -p "$_peer_tmpdir"
|
# mktemp already created the directory
|
||||||
for ci in $(seq 1 $CONTAINER_COUNT); do
|
for ci in $(seq 1 $CONTAINER_COUNT); do
|
||||||
local cname=$(get_container_name $ci)
|
local cname=$(get_container_name $ci)
|
||||||
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
||||||
@@ -2416,8 +2417,8 @@ show_status() {
|
|||||||
local uptime=""
|
local uptime=""
|
||||||
|
|
||||||
# Fetch all container logs in parallel
|
# Fetch all container logs in parallel
|
||||||
local _st_tmpdir="/tmp/.conduit_st_$$"
|
local _st_tmpdir=$(mktemp -d /tmp/.conduit_st.XXXXXX)
|
||||||
rm -rf "$_st_tmpdir"; mkdir -p "$_st_tmpdir"
|
# mktemp already created the directory
|
||||||
for i in $(seq 1 $CONTAINER_COUNT); do
|
for i in $(seq 1 $CONTAINER_COUNT); do
|
||||||
local cname=$(get_container_name $i)
|
local cname=$(get_container_name $i)
|
||||||
_c_running[$i]=false
|
_c_running[$i]=false
|
||||||
@@ -2518,8 +2519,8 @@ show_status() {
|
|||||||
if [ "$running_count" -gt 0 ]; then
|
if [ "$running_count" -gt 0 ]; then
|
||||||
|
|
||||||
# Run all 3 resource stat calls in parallel
|
# Run all 3 resource stat calls in parallel
|
||||||
local _rs_tmpdir="/tmp/.conduit_rs_$$"
|
local _rs_tmpdir=$(mktemp -d /tmp/.conduit_rs.XXXXXX)
|
||||||
rm -rf "$_rs_tmpdir"; mkdir -p "$_rs_tmpdir"
|
# mktemp already created the directory
|
||||||
( get_container_stats > "$_rs_tmpdir/cstats" ) &
|
( get_container_stats > "$_rs_tmpdir/cstats" ) &
|
||||||
( get_system_stats > "$_rs_tmpdir/sys" ) &
|
( get_system_stats > "$_rs_tmpdir/sys" ) &
|
||||||
( get_net_speed > "$_rs_tmpdir/net" ) &
|
( get_net_speed > "$_rs_tmpdir/net" ) &
|
||||||
@@ -3389,8 +3390,8 @@ manage_containers() {
|
|||||||
local docker_ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null)
|
local docker_ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null)
|
||||||
|
|
||||||
# Collect all docker data in parallel using a temp dir
|
# Collect all docker data in parallel using a temp dir
|
||||||
local _mc_tmpdir="/tmp/.conduit_mc_$$"
|
local _mc_tmpdir=$(mktemp -d /tmp/.conduit_mc.XXXXXX)
|
||||||
rm -rf "$_mc_tmpdir"; mkdir -p "$_mc_tmpdir"
|
# mktemp already created the directory
|
||||||
|
|
||||||
local running_names=""
|
local running_names=""
|
||||||
for ci in $(seq 1 $CONTAINER_COUNT); do
|
for ci in $(seq 1 $CONTAINER_COUNT); do
|
||||||
@@ -3403,7 +3404,7 @@ manage_containers() {
|
|||||||
done
|
done
|
||||||
# Fetch stats in parallel with logs
|
# Fetch stats in parallel with logs
|
||||||
if [ -n "$running_names" ]; then
|
if [ -n "$running_names" ]; then
|
||||||
( docker stats --no-stream --format "{{.Name}} {{.CPUPerc}} {{.MemUsage}}" $running_names > "$_mc_tmpdir/stats" 2>/dev/null ) &
|
( timeout 10 docker stats --no-stream --format "{{.Name}} {{.CPUPerc}} {{.MemUsage}}" $running_names > "$_mc_tmpdir/stats" 2>/dev/null ) &
|
||||||
fi
|
fi
|
||||||
wait
|
wait
|
||||||
|
|
||||||
@@ -3984,7 +3985,8 @@ set_data_cap() {
|
|||||||
|
|
||||||
# Save all settings to file
|
# Save all settings to file
|
||||||
save_settings() {
|
save_settings() {
|
||||||
cat > "$INSTALL_DIR/settings.conf" << EOF
|
local _tmp="$INSTALL_DIR/settings.conf.tmp.$$"
|
||||||
|
cat > "$_tmp" << EOF
|
||||||
MAX_CLIENTS=$MAX_CLIENTS
|
MAX_CLIENTS=$MAX_CLIENTS
|
||||||
BANDWIDTH=$BANDWIDTH
|
BANDWIDTH=$BANDWIDTH
|
||||||
CONTAINER_COUNT=$CONTAINER_COUNT
|
CONTAINER_COUNT=$CONTAINER_COUNT
|
||||||
@@ -4011,12 +4013,13 @@ EOF
|
|||||||
local bw_var="BANDWIDTH_${i}"
|
local bw_var="BANDWIDTH_${i}"
|
||||||
local cpu_var="CPUS_${i}"
|
local cpu_var="CPUS_${i}"
|
||||||
local mem_var="MEMORY_${i}"
|
local mem_var="MEMORY_${i}"
|
||||||
[ -n "${!mc_var}" ] && echo "${mc_var}=${!mc_var}" >> "$INSTALL_DIR/settings.conf"
|
[ -n "${!mc_var}" ] && echo "${mc_var}=${!mc_var}" >> "$_tmp"
|
||||||
[ -n "${!bw_var}" ] && echo "${bw_var}=${!bw_var}" >> "$INSTALL_DIR/settings.conf"
|
[ -n "${!bw_var}" ] && echo "${bw_var}=${!bw_var}" >> "$_tmp"
|
||||||
[ -n "${!cpu_var}" ] && echo "${cpu_var}=${!cpu_var}" >> "$INSTALL_DIR/settings.conf"
|
[ -n "${!cpu_var}" ] && echo "${cpu_var}=${!cpu_var}" >> "$_tmp"
|
||||||
[ -n "${!mem_var}" ] && echo "${mem_var}=${!mem_var}" >> "$INSTALL_DIR/settings.conf"
|
[ -n "${!mem_var}" ] && echo "${mem_var}=${!mem_var}" >> "$_tmp"
|
||||||
done
|
done
|
||||||
chmod 600 "$INSTALL_DIR/settings.conf" 2>/dev/null || true
|
chmod 600 "$_tmp" 2>/dev/null || true
|
||||||
|
mv "$_tmp" "$INSTALL_DIR/settings.conf"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ─── Telegram Bot Functions ───────────────────────────────────────────────────
|
# ─── Telegram Bot Functions ───────────────────────────────────────────────────
|
||||||
@@ -4827,7 +4830,7 @@ build_report() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# CPU / RAM
|
# CPU / RAM
|
||||||
local stats=$(docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" $(docker ps --format '{{.Names}}' 2>/dev/null | grep "^conduit") 2>/dev/null | head -1)
|
local stats=$(timeout 10 docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" $(docker ps --format '{{.Names}}' 2>/dev/null | grep "^conduit") 2>/dev/null | head -1)
|
||||||
local raw_cpu=$(echo "$stats" | awk '{print $1}')
|
local raw_cpu=$(echo "$stats" | awk '{print $1}')
|
||||||
local cores=$(get_cpu_cores)
|
local cores=$(get_cpu_cores)
|
||||||
local cpu=$(awk "BEGIN {printf \"%.1f%%\", ${raw_cpu%\%} / $cores}" 2>/dev/null || echo "$raw_cpu")
|
local cpu=$(awk "BEGIN {printf \"%.1f%%\", ${raw_cpu%\%} / $cores}" 2>/dev/null || echo "$raw_cpu")
|
||||||
@@ -6267,7 +6270,7 @@ update_conduit() {
|
|||||||
|
|
||||||
# --- Phase 1: Script update ---
|
# --- Phase 1: Script update ---
|
||||||
echo "Checking for script updates..."
|
echo "Checking for script updates..."
|
||||||
local update_url="https://raw.githubusercontent.com/SamNet-dev/conduit-manager/beta-releases/conduit.sh"
|
local update_url="https://raw.githubusercontent.com/SamNet-dev/conduit-manager/main/conduit.sh"
|
||||||
local tmp_script="/tmp/conduit_update_$$.sh"
|
local tmp_script="/tmp/conduit_update_$$.sh"
|
||||||
|
|
||||||
if curl -sL --max-time 30 --max-filesize 2097152 -o "$tmp_script" "$update_url" 2>/dev/null; then
|
if curl -sL --max-time 30 --max-filesize 2097152 -o "$tmp_script" "$update_url" 2>/dev/null; then
|
||||||
@@ -6645,7 +6648,7 @@ main() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
#
|
#
|
||||||
# REACHED END OF SCRIPT - VERSION 1.2-Beta
|
# REACHED END OF SCRIPT - VERSION 1.2
|
||||||
# ###############################################################################
|
# ###############################################################################
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user