mirror of
https://github.com/pvlnes/homelab.git
synced 2026-04-05 16:11:46 +00:00
228 lines
4.9 KiB
Bash
228 lines
4.9 KiB
Bash
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
# =========================
|
|
# Config
|
|
# =========================
|
|
ADMIN_USER="${ADMIN_USER:-pvlx}"
|
|
SSH_PORT="${SSH_PORT:-22}"
|
|
|
|
NODE_NAME="${NODE_NAME:-fin-node-01}"
|
|
NODE_DIR="${NODE_DIR:-/opt/remnanode}"
|
|
|
|
SECRET_KEY="${SECRET_KEY:-}"
|
|
MASTER_API_URL="${MASTER_API_URL:-https://rat-api.sesur.dev}"
|
|
NODE_PORT="${NODE_PORT:-2222}"
|
|
|
|
ENABLE_UFW="${ENABLE_UFW:-true}"
|
|
|
|
# =========================
|
|
# Helpers
|
|
# =========================
|
|
log() {
|
|
echo
|
|
echo "==> $1"
|
|
}
|
|
|
|
require_root() {
|
|
if [[ "${EUID}" -ne 0 ]]; then
|
|
echo "Run as root"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
require_secret() {
|
|
if [[ -z "${SECRET_KEY}" ]]; then
|
|
echo "SECRET_KEY is empty."
|
|
echo 'Run like:'
|
|
echo 'SECRET_KEY="your-secret" MASTER_API_URL="https://rat-api.sesur.dev" bash bootstrap-remnanode.sh'
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# =========================
|
|
# Main
|
|
# =========================
|
|
require_root
|
|
require_secret
|
|
|
|
log "Updating system"
|
|
apt-get update
|
|
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y
|
|
|
|
log "Installing base packages"
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
|
ca-certificates curl gnupg lsb-release \
|
|
ufw unattended-upgrades nano logrotate
|
|
|
|
log "Enable automatic security updates"
|
|
dpkg-reconfigure -f noninteractive unattended-upgrades || true
|
|
|
|
log "Creating admin user"
|
|
if ! id -u "${ADMIN_USER}" >/dev/null 2>&1; then
|
|
adduser --disabled-password --gecos "" "${ADMIN_USER}"
|
|
fi
|
|
|
|
usermod -aG sudo "${ADMIN_USER}"
|
|
|
|
log "Configuring passwordless sudo for ${ADMIN_USER}"
|
|
echo "${ADMIN_USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/90-${ADMIN_USER}
|
|
chmod 440 /etc/sudoers.d/90-${ADMIN_USER}
|
|
|
|
if [[ -f /root/.ssh/authorized_keys ]]; then
|
|
mkdir -p "/home/${ADMIN_USER}/.ssh"
|
|
cp /root/.ssh/authorized_keys "/home/${ADMIN_USER}/.ssh/authorized_keys"
|
|
chown -R "${ADMIN_USER}:${ADMIN_USER}" "/home/${ADMIN_USER}/.ssh"
|
|
chmod 700 "/home/${ADMIN_USER}/.ssh"
|
|
chmod 600 "/home/${ADMIN_USER}/.ssh/authorized_keys"
|
|
fi
|
|
|
|
log "Hardening SSH"
|
|
|
|
SSHD_CONFIG="/etc/ssh/sshd_config"
|
|
cp "${SSHD_CONFIG}" "${SSHD_CONFIG}.bak.$(date +%s)"
|
|
|
|
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' "${SSHD_CONFIG}"
|
|
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' "${SSHD_CONFIG}"
|
|
sed -i 's/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/' "${SSHD_CONFIG}"
|
|
|
|
if grep -q '^AllowUsers' "${SSHD_CONFIG}"; then
|
|
sed -i "s/^AllowUsers.*/AllowUsers ${ADMIN_USER}/" "${SSHD_CONFIG}"
|
|
else
|
|
echo "AllowUsers ${ADMIN_USER}" >> "${SSHD_CONFIG}"
|
|
fi
|
|
|
|
systemctl restart ssh || systemctl restart sshd
|
|
|
|
log "Installing Docker"
|
|
|
|
if ! command -v docker >/dev/null; then
|
|
curl -fsSL https://get.docker.com | sh
|
|
fi
|
|
|
|
systemctl enable docker
|
|
systemctl start docker
|
|
|
|
usermod -aG docker "${ADMIN_USER}"
|
|
|
|
log "Configure Docker logs"
|
|
|
|
mkdir -p /etc/docker
|
|
|
|
cat >/etc/docker/daemon.json <<'EOF'
|
|
{
|
|
"log-driver": "json-file",
|
|
"log-opts": {
|
|
"max-size": "50m",
|
|
"max-file": "3"
|
|
}
|
|
}
|
|
EOF
|
|
|
|
systemctl restart docker
|
|
|
|
log "Applying kernel network hardening"
|
|
|
|
cat >/etc/sysctl.d/99-remnanode-security.conf <<'EOF'
|
|
net.ipv4.tcp_syncookies = 1
|
|
net.ipv4.conf.all.rp_filter = 1
|
|
net.ipv4.conf.default.rp_filter = 1
|
|
net.ipv4.icmp_echo_ignore_broadcasts = 1
|
|
net.ipv4.conf.all.accept_redirects = 0
|
|
net.ipv4.conf.default.accept_redirects = 0
|
|
net.ipv4.conf.all.send_redirects = 0
|
|
net.ipv4.conf.default.send_redirects = 0
|
|
net.ipv4.conf.all.accept_source_route = 0
|
|
net.ipv4.conf.default.accept_source_route = 0
|
|
EOF
|
|
|
|
sysctl --system
|
|
|
|
if [[ "${ENABLE_UFW}" == "true" ]]; then
|
|
log "Configuring firewall"
|
|
|
|
ufw --force reset
|
|
ufw default deny incoming
|
|
ufw default allow outgoing
|
|
|
|
ufw allow "${SSH_PORT}/tcp"
|
|
ufw allow 443/tcp
|
|
ufw allow 1080/tcp
|
|
ufw allow 1080/udp
|
|
ufw allow "${NODE_PORT}/tcp"
|
|
|
|
ufw --force enable
|
|
fi
|
|
|
|
log "Creating log directory"
|
|
mkdir -p /var/log/remnanode
|
|
chown root:root /var/log/remnanode
|
|
chmod 755 /var/log/remnanode
|
|
|
|
log "Configuring logrotate for remnanode"
|
|
cat >/etc/logrotate.d/remnanode <<'EOF'
|
|
/var/log/remnanode/*.log {
|
|
size 50M
|
|
rotate 5
|
|
compress
|
|
missingok
|
|
notifempty
|
|
copytruncate
|
|
}
|
|
EOF
|
|
|
|
log "Creating Remnawave node"
|
|
|
|
mkdir -p "${NODE_DIR}"
|
|
|
|
cat >"${NODE_DIR}/.env" <<EOF
|
|
SECRET_KEY=${SECRET_KEY}
|
|
NODE_PORT=${NODE_PORT}
|
|
API_HOST=${MASTER_API_URL}
|
|
EOF
|
|
|
|
cat >"${NODE_DIR}/docker-compose.yml" <<EOF
|
|
services:
|
|
remnanode:
|
|
image: remnawave/node:latest
|
|
container_name: remnanode
|
|
hostname: ${NODE_NAME}
|
|
network_mode: host
|
|
restart: unless-stopped
|
|
|
|
env_file:
|
|
- .env
|
|
|
|
cap_add:
|
|
- NET_ADMIN
|
|
|
|
volumes:
|
|
- /var/log/remnanode:/var/log/remnanode
|
|
|
|
ulimits:
|
|
nofile:
|
|
soft: 1048576
|
|
hard: 1048576
|
|
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "3"
|
|
EOF
|
|
|
|
cd "${NODE_DIR}"
|
|
|
|
log "Starting node"
|
|
docker compose up -d
|
|
docker compose ps
|
|
|
|
echo
|
|
echo "Node installation complete"
|
|
echo
|
|
echo "Master API: ${MASTER_API_URL}"
|
|
echo "Node name: ${NODE_NAME}"
|
|
echo "Node dir: ${NODE_DIR}"
|
|
echo "Logs dir: /var/log/remnanode"
|
|
echo
|