#!/bin/bash # ============================================================================= # setup-d2testnas.sh # Post-install setup script for Debian 13 (Trixie) VM replacing D2TESTNAS # # Purpose: Configure a Debian VM as an SMB1-capable NAS for Dataforth DOS 6.22 # test infrastructure. Replaces Netgear ReadyNAS RN10400 appliance. # # Requirements: # - Fresh Debian 13 (Trixie) minimal install # - BTRFS partition mounted at /data (or available block device) # - Root access # - Network connectivity for package installation # # Usage: # chmod +x setup-d2testnas.sh # sudo ./setup-d2testnas.sh # # Author: Infrastructure automation for Dataforth DOS project # Date: 2026-03-12 # ============================================================================= set -euo pipefail # ============================================================================= # Configuration - Edit these values as needed # ============================================================================= # Network - The VM will initially use DHCP. Change STATIC_IP to the final # address (192.168.0.9) only during cutover when the old NAS is powered off. STATIC_IP="192.168.0.9" NETMASK="255.255.255.0" GATEWAY="192.168.0.254" DNS_SERVERS="192.168.0.27 192.168.0.6 192.168.1.254" HOSTNAME="D2TESTNAS" WORKGROUP="INTRANET" # Samba SMB_SHARE_PATH="/data/test" SMB_DATASHEETS_PATH="/data/datasheets" SMB_ENGINEER_USER="engineer" SMB_ENGINEER_PASS="Engineer1!" # rsync daemon RSYNC_MODULE="test" RSYNC_PATH="/data/test" RSYNC_USER="rsync" RSYNC_PASSWORD="IQ203s32119" # BTRFS snapshot retention SNAP_HOURLY_RETAIN=48 SNAP_DAILY_RETAIN=30 SNAP_WEEKLY_RETAIN=12 # SSH root password (set during Debian install, but ensure it is correct) ROOT_PASSWORD="Paper123!@#-nas" # ============================================================================= # Preflight Checks # ============================================================================= echo "============================================================" echo " D2TESTNAS Setup Script - Debian 13 (Trixie)" echo " Replacing Netgear ReadyNAS for DOS 6.22 infrastructure" echo "============================================================" echo "" if [[ $EUID -ne 0 ]]; then echo "[ERROR] This script must be run as root." exit 1 fi # Check Debian version if [[ -f /etc/os-release ]]; then . /etc/os-release echo "[INFO] Detected OS: ${PRETTY_NAME:-unknown}" else echo "[WARNING] Cannot determine OS version. Proceeding anyway." fi echo "" echo "[INFO] This script will:" echo " 1. Install required packages (samba, rsync, btrfs-progs, etc.)" echo " 2. Set hostname to ${HOSTNAME}" echo " 3. Create data directories on /data (BTRFS)" echo " 4. Configure Samba with SMB1 support for DOS machines" echo " 5. Configure rsync daemon on port 873" echo " 6. Set up BTRFS automated snapshots" echo " 7. Configure and enable all services" echo "" echo "Press Ctrl+C within 5 seconds to abort..." sleep 5 echo "" # ============================================================================= # Step 1: Package Installation # ============================================================================= echo "[INFO] Step 1: Installing required packages..." apt-get update -qq # Core packages: # samba - SMB file server (includes nmbd for NetBIOS) # rsync - rsync daemon # btrfs-progs - BTRFS filesystem utilities and snapshot management # openssh-server - SSH access # cron - scheduled tasks for snapshots # net-tools - ifconfig, netstat (useful for debugging) # dnsutils - nslookup, dig (debugging) DEBIAN_FRONTEND=noninteractive apt-get install -y \ samba \ samba-common \ rsync \ btrfs-progs \ openssh-server \ cron \ net-tools \ dnsutils echo "[OK] Packages installed successfully." echo "" # ============================================================================= # Step 2: Set Hostname # ============================================================================= echo "[INFO] Step 2: Setting hostname to ${HOSTNAME}..." hostnamectl set-hostname "${HOSTNAME}" # Update /etc/hosts so hostname resolves locally if ! grep -q "${HOSTNAME}" /etc/hosts; then sed -i "s/^127\.0\.1\.1.*/127.0.1.1\t${HOSTNAME}/" /etc/hosts # If no 127.0.1.1 line existed, add one if ! grep -q "127.0.1.1" /etc/hosts; then echo "127.0.1.1 ${HOSTNAME}" >> /etc/hosts fi fi echo "[OK] Hostname set to ${HOSTNAME}." echo "" # ============================================================================= # Step 3: Prepare BTRFS Data Directories # ============================================================================= echo "[INFO] Step 3: Preparing BTRFS data directories..." # Check if /data is a BTRFS mount if mountpoint -q /data 2>/dev/null; then FS_TYPE=$(df -T /data | tail -1 | awk '{print $2}') if [[ "${FS_TYPE}" == "btrfs" ]]; then echo "[OK] /data is mounted as BTRFS." else echo "[WARNING] /data is mounted but filesystem is '${FS_TYPE}', not BTRFS." echo " Snapshots will NOT work. Consider reformatting with BTRFS." fi else echo "[WARNING] /data is not currently mounted." echo " Checking for available block devices..." lsblk -f echo "" echo " You must mount a BTRFS partition at /data before this script" echo " can configure snapshots. The script will create directories" echo " but snapshot functionality requires BTRFS." echo "" echo " To create a BTRFS filesystem on /dev/sdX:" echo " mkfs.btrfs -L d2testnas-data /dev/sdX" echo " echo '/dev/sdX /data btrfs defaults,noatime,compress=zstd 0 2' >> /etc/fstab" echo " mkdir -p /data && mount /data" echo "" mkdir -p /data fi # Create BTRFS subvolumes if on BTRFS, otherwise plain directories if btrfs subvolume show /data >/dev/null 2>&1 || btrfs filesystem show /data >/dev/null 2>&1; then BTRFS_AVAILABLE=true echo "[INFO] BTRFS detected. Creating subvolumes..." # Create subvolumes for data areas (enables independent snapshots) if ! btrfs subvolume show /data/test >/dev/null 2>&1; then btrfs subvolume create /data/test echo "[OK] Created BTRFS subvolume: /data/test" else echo "[INFO] Subvolume /data/test already exists." fi if ! btrfs subvolume show /data/datasheets >/dev/null 2>&1; then btrfs subvolume create /data/datasheets echo "[OK] Created BTRFS subvolume: /data/datasheets" else echo "[INFO] Subvolume /data/datasheets already exists." fi # Create snapshot directory mkdir -p /data/.snapshots echo "[OK] Snapshot directory created at /data/.snapshots" else BTRFS_AVAILABLE=false echo "[WARNING] BTRFS not available on /data. Creating plain directories." echo " Snapshot functionality will be disabled." mkdir -p /data/test mkdir -p /data/datasheets fi # Set permissions - wide open for guest access from DOS machines chmod 777 /data/test chmod 777 /data/datasheets echo "[OK] Data directories ready." echo "" # ============================================================================= # Step 4: Configure Samba (SMB1 for DOS 6.22) # ============================================================================= echo "[INFO] Step 4: Configuring Samba with SMB1 support..." # Back up original config if [[ -f /etc/samba/smb.conf ]]; then cp /etc/samba/smb.conf /etc/samba/smb.conf.orig fi cat > /etc/samba/smb.conf << 'SMBCONF' # ============================================================================= # Samba Configuration for D2TESTNAS # Replacing Netgear ReadyNAS for Dataforth DOS 6.22 test infrastructure # # CRITICAL: DOS 6.22 machines require SMB1 (CORE/COREPLUS/LANMAN1/NT1) # Modern SMB2/SMB3 is NOT compatible with MS-DOS networking stack. # # Shares: # \\D2TESTNAS\test -> /data/test (T: drive on DOS machines) # \\D2TESTNAS\datasheets -> /data/datasheets (X: drive on DOS machines) # \\D2TESTNAS\snapshots -> /data/.snapshots (read-only, browse snapshots) # ============================================================================= [global] # --- Identity --- workgroup = INTRANET netbios name = D2TESTNAS server string = D2TESTNAS File Server (DOS Infrastructure) # --- Protocol: SMB1 Required for DOS 6.22 --- # CORE is the oldest SMB dialect. DOS MS Client 3.0 uses CORE/COREPLUS. # NT1 = SMB1 final revision. We allow the full SMB1 range. server min protocol = CORE server max protocol = NT1 client min protocol = CORE client max protocol = NT1 # --- Authentication --- # DOS machines authenticate with null passwords or guest. # Security mode must allow this. security = user map to guest = Bad User guest account = nobody null passwords = yes # --- NetBIOS / WINS --- # DOS machines rely on NetBIOS name resolution (no DNS). # This server acts as a WINS server for the 192.168.0.0/24 network. wins support = yes name resolve order = wins lmhosts host bcast dns proxy = no local master = yes preferred master = yes os level = 65 # --- File Handling for DOS Compatibility --- # DOS filenames: 8.3 format, case insensitive, no special chars mangled names = no case sensitive = no default case = upper preserve case = no short preserve case = no dos charset = CP437 unix charset = UTF-8 # --- Logging --- log file = /var/log/samba/log.%m max log size = 1000 log level = 1 # --- Performance --- socket options = TCP_NODELAY IPTOS_LOWDELAY read raw = yes write raw = yes # --- Disable features DOS cannot use --- unix extensions = no wide links = yes follow symlinks = yes # --- Disable printer sharing --- load printers = no printing = bsd printcap name = /dev/null disable spoolss = yes # ============================================================================= # Share: test (T: drive for DOS machines) # ============================================================================= [test] comment = Dataforth Test Data path = /data/test browseable = yes writable = yes guest ok = yes guest only = yes create mask = 0666 directory mask = 0777 force create mode = 0666 force directory mode = 0777 # DOS compatibility - no oplocks (can cause issues with DOS clients) oplocks = no level2 oplocks = no strict locking = yes # ============================================================================= # Share: datasheets (X: drive for DOS machines) # ============================================================================= [datasheets] comment = Dataforth Datasheets path = /data/datasheets browseable = yes writable = yes guest ok = yes guest only = yes create mask = 0666 directory mask = 0777 force create mode = 0666 force directory mode = 0777 oplocks = no level2 oplocks = no strict locking = yes # ============================================================================= # Share: snapshots (read-only access to BTRFS snapshots) # ============================================================================= [snapshots] comment = BTRFS Snapshots (Read Only) path = /data/.snapshots browseable = yes writable = no guest ok = yes guest only = yes SMBCONF echo "[OK] Samba configuration written to /etc/samba/smb.conf" # Create Samba users matching the old NAS configuration # DOS machines use station-specific users (ts-1 through ts-50) with null passwords echo "[INFO] Creating Samba users for DOS stations..." for i in $(seq 1 50); do USERNAME="ts-${i}" # Create system user if it does not exist (no home dir, no login shell) if ! id "${USERNAME}" >/dev/null 2>&1; then useradd --system --no-create-home --shell /usr/sbin/nologin "${USERNAME}" 2>/dev/null || true fi # Add to Samba with null password (echo ""; echo "") | smbpasswd -a -s "${USERNAME}" >/dev/null 2>&1 || true smbpasswd -n "${USERNAME}" >/dev/null 2>&1 || true smbpasswd -e "${USERNAME}" >/dev/null 2>&1 || true done echo "[OK] Created Samba users ts-1 through ts-50 (null passwords)." # Create engineer user with password if ! id "${SMB_ENGINEER_USER}" >/dev/null 2>&1; then useradd --system --no-create-home --shell /usr/sbin/nologin "${SMB_ENGINEER_USER}" 2>/dev/null || true fi (echo "${SMB_ENGINEER_PASS}"; echo "${SMB_ENGINEER_PASS}") | smbpasswd -a -s "${SMB_ENGINEER_USER}" >/dev/null 2>&1 || true smbpasswd -e "${SMB_ENGINEER_USER}" >/dev/null 2>&1 || true echo "[OK] Created Samba user 'engineer' with password." # Validate Samba configuration echo "[INFO] Validating Samba configuration..." testparm -s /etc/samba/smb.conf > /dev/null 2>&1 && echo "[OK] Samba config validation passed." || echo "[WARNING] Samba config validation had warnings (check with: testparm)" echo "" # ============================================================================= # Step 5: Configure rsync Daemon # ============================================================================= echo "[INFO] Step 5: Configuring rsync daemon..." cat > /etc/rsyncd.conf << RSYNCDCONF # ============================================================================= # rsyncd.conf - rsync daemon configuration for D2TESTNAS # # Module "test" provides read/write access to /data/test for the AD2 sync # script (Sync-FromNAS-rsync.ps1) running on the AD2 Windows server. # # The AD2 sync script runs every 15 minutes and does bidirectional sync: # PULL: NAS -> AD2 (test results: DAT files, TXT reports) # PUSH: AD2 -> NAS (software updates: ProdSW, UPDATE.BAT, TODO.BAT) # ============================================================================= uid = root gid = root use chroot = true max connections = 10 timeout = 300 read only = false # Logging log file = /var/log/rsyncd.log transfer logging = yes log format = %t %a %m %f %l [${RSYNC_MODULE}] path = ${RSYNC_PATH} comment = Dataforth Test Data read only = false use chroot = true auth users = ${RSYNC_USER} secrets file = /etc/rsyncd.secrets hosts allow = 192.168.0.0/24 172.16.0.0/12 RSYNCDCONF echo "[OK] rsync daemon configuration written to /etc/rsyncd.conf" # Create secrets file echo "${RSYNC_USER}:${RSYNC_PASSWORD}" > /etc/rsyncd.secrets chmod 600 /etc/rsyncd.secrets echo "[OK] rsync secrets file written to /etc/rsyncd.secrets (mode 600)." # Enable rsync daemon in defaults # Debian uses /etc/default/rsync to control daemon mode if [[ -f /etc/default/rsync ]]; then sed -i 's/^RSYNC_ENABLE=.*/RSYNC_ENABLE=true/' /etc/default/rsync else echo "RSYNC_ENABLE=true" > /etc/default/rsync fi # Create systemd override to ensure rsync runs as daemon mkdir -p /etc/systemd/system/rsync.service.d cat > /etc/systemd/system/rsync.service.d/override.conf << 'EOF' [Service] ExecStart= ExecStart=/usr/bin/rsync --daemon --no-detach EOF echo "[OK] rsync daemon configured to start on boot." echo "" # ============================================================================= # Step 6: Configure SSH (root login with password) # ============================================================================= echo "[INFO] Step 6: Configuring SSH..." # Enable root login with password (required for remote management) SSHD_CONFIG="/etc/ssh/sshd_config" # Ensure PermitRootLogin is set to yes if grep -q "^PermitRootLogin" "${SSHD_CONFIG}"; then sed -i 's/^PermitRootLogin.*/PermitRootLogin yes/' "${SSHD_CONFIG}" elif grep -q "^#PermitRootLogin" "${SSHD_CONFIG}"; then sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' "${SSHD_CONFIG}" else echo "PermitRootLogin yes" >> "${SSHD_CONFIG}" fi # Ensure password authentication is enabled if grep -q "^PasswordAuthentication" "${SSHD_CONFIG}"; then sed -i 's/^PasswordAuthentication.*/PasswordAuthentication yes/' "${SSHD_CONFIG}" elif grep -q "^#PasswordAuthentication" "${SSHD_CONFIG}"; then sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication yes/' "${SSHD_CONFIG}" else echo "PasswordAuthentication yes" >> "${SSHD_CONFIG}" fi # Debian 13 may use sshd_config.d drop-in files that override main config. # Disable any drop-in that forces PasswordAuthentication no. if [[ -d /etc/ssh/sshd_config.d ]]; then for f in /etc/ssh/sshd_config.d/*.conf; do if [[ -f "$f" ]] && grep -q "PasswordAuthentication no" "$f" 2>/dev/null; then sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' "$f" echo "[INFO] Updated ${f} to allow password authentication." fi done fi # Set root password echo "root:${ROOT_PASSWORD}" | chpasswd echo "[OK] Root password set." echo "[OK] SSH configured: root login enabled, password auth enabled." echo "" # ============================================================================= # Step 7: BTRFS Snapshot Automation # ============================================================================= echo "[INFO] Step 7: Setting up BTRFS snapshot automation..." # Create the snapshot management script cat > /usr/local/bin/btrfs-snapshot.sh << 'SNAPSCRIPT' #!/bin/bash # ============================================================================= # btrfs-snapshot.sh - Automated BTRFS snapshot management for D2TESTNAS # # Usage: # btrfs-snapshot.sh create # btrfs-snapshot.sh prune # btrfs-snapshot.sh list # # Snapshots are stored in /data/.snapshots/ with naming convention: # /data/.snapshots/_YYYY-MM-DD_HH-MM-SS # # Retention policy: # Hourly: 48 snapshots (2 days) # Daily: 30 snapshots (1 month) # Weekly: 12 snapshots (3 months) # ============================================================================= set -euo pipefail SNAP_DIR="/data/.snapshots" SUBVOLUME="/data/test" HOURLY_RETAIN=48 DAILY_RETAIN=30 WEEKLY_RETAIN=12 create_snapshot() { local snap_type="${1}" local timestamp timestamp=$(date '+%Y-%m-%d_%H-%M-%S') local snap_name="${snap_type}_${timestamp}" local snap_path="${SNAP_DIR}/${snap_name}" if [[ ! -d "${SNAP_DIR}" ]]; then mkdir -p "${SNAP_DIR}" fi # Verify source is a BTRFS subvolume if ! btrfs subvolume show "${SUBVOLUME}" >/dev/null 2>&1; then echo "[ERROR] ${SUBVOLUME} is not a BTRFS subvolume. Cannot create snapshot." exit 1 fi btrfs subvolume snapshot -r "${SUBVOLUME}" "${snap_path}" echo "[OK] Created snapshot: ${snap_name}" } prune_snapshots() { local snap_type="${1}" local retain="${2}" # List snapshots of this type, sorted oldest first local snaps snaps=$(find "${SNAP_DIR}" -maxdepth 1 -name "${snap_type}_*" -type d | sort) local count count=$(echo "${snaps}" | grep -c . 2>/dev/null || echo 0) if [[ ${count} -le ${retain} ]]; then return fi local to_delete=$((count - retain)) echo "[INFO] Pruning ${to_delete} old ${snap_type} snapshot(s) (keeping ${retain})..." echo "${snaps}" | head -n "${to_delete}" | while read -r snap; do if [[ -n "${snap}" && -d "${snap}" ]]; then btrfs subvolume delete "${snap}" echo "[OK] Deleted: $(basename "${snap}")" fi done } list_snapshots() { echo "=== BTRFS Snapshots in ${SNAP_DIR} ===" echo "" if [[ ! -d "${SNAP_DIR}" ]]; then echo "No snapshot directory found." return fi for snap_type in hourly daily weekly; do local count count=$(find "${SNAP_DIR}" -maxdepth 1 -name "${snap_type}_*" -type d 2>/dev/null | wc -l) echo "${snap_type}: ${count} snapshot(s)" find "${SNAP_DIR}" -maxdepth 1 -name "${snap_type}_*" -type d 2>/dev/null | sort | while read -r s; do echo " $(basename "${s}")" done echo "" done } case "${1:-}" in create) snap_type="${2:-hourly}" create_snapshot "${snap_type}" ;; prune) prune_snapshots "hourly" "${HOURLY_RETAIN}" prune_snapshots "daily" "${DAILY_RETAIN}" prune_snapshots "weekly" "${WEEKLY_RETAIN}" ;; list) list_snapshots ;; *) echo "Usage: $0 {create |prune|list}" exit 1 ;; esac SNAPSCRIPT chmod +x /usr/local/bin/btrfs-snapshot.sh # Install cron jobs for snapshot automation CRON_FILE="/etc/cron.d/btrfs-snapshots" cat > "${CRON_FILE}" << 'CRONEOF' # BTRFS Snapshot Automation for D2TESTNAS # Hourly snapshots: every hour on the hour # Daily snapshots: midnight # Weekly snapshots: Sunday at 00:15 # Pruning: runs after each snapshot creation SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # Hourly: create snapshot, then prune old ones 0 * * * * root /usr/local/bin/btrfs-snapshot.sh create hourly >> /var/log/btrfs-snapshots.log 2>&1 && /usr/local/bin/btrfs-snapshot.sh prune >> /var/log/btrfs-snapshots.log 2>&1 # Daily: create at midnight (separate from hourly for distinct retention) 1 0 * * * root /usr/local/bin/btrfs-snapshot.sh create daily >> /var/log/btrfs-snapshots.log 2>&1 && /usr/local/bin/btrfs-snapshot.sh prune >> /var/log/btrfs-snapshots.log 2>&1 # Weekly: create on Sunday at 00:15 15 0 * * 0 root /usr/local/bin/btrfs-snapshot.sh create weekly >> /var/log/btrfs-snapshots.log 2>&1 && /usr/local/bin/btrfs-snapshot.sh prune >> /var/log/btrfs-snapshots.log 2>&1 CRONEOF chmod 644 "${CRON_FILE}" # Set up log rotation for snapshot log cat > /etc/logrotate.d/btrfs-snapshots << 'LOGROTEOF' /var/log/btrfs-snapshots.log { weekly rotate 8 compress missingok notifempty } LOGROTEOF if [[ "${BTRFS_AVAILABLE}" == "true" ]]; then echo "[OK] BTRFS snapshot automation configured." echo " Hourly: retained ${SNAP_HOURLY_RETAIN} (2 days)" echo " Daily: retained ${SNAP_DAILY_RETAIN} (1 month)" echo " Weekly: retained ${SNAP_WEEKLY_RETAIN} (3 months)" echo " Snapshots browsable via: \\\\D2TESTNAS\\snapshots" else echo "[WARNING] BTRFS not available. Snapshot cron jobs installed but will" echo " fail until /data is a BTRFS filesystem with subvolumes." fi echo "" # ============================================================================= # Step 8: Network Configuration (prepare for cutover) # ============================================================================= echo "[INFO] Step 8: Preparing network configuration..." # Identify the primary network interface PRIMARY_IFACE=$(ip route show default 2>/dev/null | awk '{print $5}' | head -1) if [[ -z "${PRIMARY_IFACE}" ]]; then PRIMARY_IFACE="eth0" echo "[WARNING] Could not detect primary interface. Defaulting to ${PRIMARY_IFACE}." else echo "[INFO] Detected primary network interface: ${PRIMARY_IFACE}" fi # Write a static IP configuration file (NOT activated yet) # This file is for cutover day when we switch from old NAS to new VM. STATIC_CONFIG="/etc/network/interfaces.d/static-cutover" cat > "${STATIC_CONFIG}" << NETEOF # ============================================================================= # CUTOVER STATIC IP CONFIGURATION # ============================================================================= # This file is NOT active by default. The VM uses DHCP during testing. # # To activate for cutover: # 1. Power off the old D2TESTNAS (ReadyNAS) # 2. Edit /etc/network/interfaces: # - Comment out or remove the DHCP line for ${PRIMARY_IFACE} # - Add: source /etc/network/interfaces.d/static-cutover # 3. Run: systemctl restart networking # 4. Verify: ip addr show ${PRIMARY_IFACE} # # Alternatively, replace /etc/network/interfaces entirely with: # auto lo # iface lo inet loopback # auto ${PRIMARY_IFACE} # iface ${PRIMARY_IFACE} inet static # address ${STATIC_IP} # netmask ${NETMASK} # gateway ${GATEWAY} # dns-nameservers ${DNS_SERVERS} # ============================================================================= auto ${PRIMARY_IFACE} iface ${PRIMARY_IFACE} inet static address ${STATIC_IP} netmask ${NETMASK} gateway ${GATEWAY} dns-nameservers ${DNS_SERVERS} NETEOF echo "[OK] Static IP config prepared at ${STATIC_CONFIG}" echo " Current IP: $(ip -4 addr show "${PRIMARY_IFACE}" 2>/dev/null | grep -oP 'inet \K[\d.]+' | head -1 || echo 'unknown')" echo " Cutover IP: ${STATIC_IP} (activate during cutover)" echo "" # ============================================================================= # Step 9: Enable and Start Services # ============================================================================= echo "[INFO] Step 9: Enabling and starting services..." systemctl daemon-reload # Samba (smbd for file sharing, nmbd for NetBIOS name resolution) systemctl enable smbd systemctl enable nmbd systemctl restart smbd systemctl restart nmbd echo "[OK] Samba (smbd + nmbd) enabled and started." # rsync daemon systemctl enable rsync systemctl restart rsync echo "[OK] rsync daemon enabled and started." # SSH systemctl enable ssh systemctl restart ssh echo "[OK] SSH enabled and started." # cron (should already be running, ensure it is) systemctl enable cron systemctl restart cron echo "[OK] cron enabled and started." echo "" # ============================================================================= # Step 10: Firewall (if ufw/nftables is active) # ============================================================================= echo "[INFO] Step 10: Checking firewall..." if command -v ufw >/dev/null 2>&1 && ufw status | grep -q "active"; then echo "[INFO] UFW is active. Adding required rules..." ufw allow 22/tcp comment "SSH" ufw allow 137/udp comment "NetBIOS Name Service (nmbd)" ufw allow 138/udp comment "NetBIOS Datagram" ufw allow 139/tcp comment "NetBIOS Session (SMB1)" ufw allow 445/tcp comment "SMB" ufw allow 873/tcp comment "rsync daemon" echo "[OK] Firewall rules added." elif command -v nft >/dev/null 2>&1; then echo "[INFO] nftables available. If you enable a firewall later, allow these ports:" echo " 22/tcp (SSH), 137/udp (NetBIOS), 138/udp (NetBIOS)," echo " 139/tcp (SMB1), 445/tcp (SMB), 873/tcp (rsync)" else echo "[INFO] No active firewall detected. No rules needed." fi echo "" # ============================================================================= # Step 11: Verification # ============================================================================= echo "[INFO] Step 11: Running verification checks..." echo "" ERRORS=0 # Check smbd if systemctl is-active --quiet smbd; then echo "[OK] smbd is running." else echo "[ERROR] smbd is NOT running." ERRORS=$((ERRORS + 1)) fi # Check nmbd if systemctl is-active --quiet nmbd; then echo "[OK] nmbd is running." else echo "[ERROR] nmbd is NOT running." ERRORS=$((ERRORS + 1)) fi # Check rsync if systemctl is-active --quiet rsync; then echo "[OK] rsync daemon is running." else echo "[ERROR] rsync daemon is NOT running." ERRORS=$((ERRORS + 1)) fi # Check rsync port if ss -tlnp | grep -q ":873"; then echo "[OK] rsync daemon listening on port 873." else echo "[ERROR] rsync daemon NOT listening on port 873." ERRORS=$((ERRORS + 1)) fi # Check SSH if systemctl is-active --quiet ssh; then echo "[OK] SSH is running." else echo "[ERROR] SSH is NOT running." ERRORS=$((ERRORS + 1)) fi # Check Samba shares echo "" echo "[INFO] Samba shares configured:" smbclient -L localhost -N 2>/dev/null | grep -E "Disk|test|datasheets|snapshots" || echo "[WARNING] Could not list Samba shares (smbclient may not support -N with this config)." # Check data directories echo "" if [[ -d /data/test ]]; then echo "[OK] /data/test exists." else echo "[ERROR] /data/test does NOT exist." ERRORS=$((ERRORS + 1)) fi if [[ -d /data/datasheets ]]; then echo "[OK] /data/datasheets exists." else echo "[ERROR] /data/datasheets does NOT exist." ERRORS=$((ERRORS + 1)) fi echo "" # ============================================================================= # Summary # ============================================================================= CURRENT_IP=$(ip -4 addr show "${PRIMARY_IFACE}" 2>/dev/null | grep -oP 'inet \K[\d.]+' | head -1 || echo 'unknown') echo "============================================================" echo " SETUP COMPLETE" echo "============================================================" echo "" echo " Hostname: ${HOSTNAME}" echo " Current IP: ${CURRENT_IP} (DHCP - for testing)" echo " Cutover IP: ${STATIC_IP} (activate during cutover)" echo " Interface: ${PRIMARY_IFACE}" echo "" echo " Services:" echo " Samba (smbd): $(systemctl is-active smbd)" echo " NetBIOS (nmbd): $(systemctl is-active nmbd)" echo " rsync daemon: $(systemctl is-active rsync)" echo " SSH: $(systemctl is-active ssh)" echo " cron: $(systemctl is-active cron)" echo "" echo " Shares:" echo " \\\\${HOSTNAME}\\test -> /data/test" echo " \\\\${HOSTNAME}\\datasheets -> /data/datasheets" echo " \\\\${HOSTNAME}\\snapshots -> /data/.snapshots (read-only)" echo "" echo " rsync:" echo " Module: ${RSYNC_MODULE} -> ${RSYNC_PATH}" echo " Auth: ${RSYNC_USER} (port 873)" echo "" echo " BTRFS Snapshots: $(if [[ ${BTRFS_AVAILABLE} == true ]]; then echo 'ACTIVE'; else echo 'DISABLED (no BTRFS)'; fi)" echo " Hourly: ${SNAP_HOURLY_RETAIN} retained | Daily: ${SNAP_DAILY_RETAIN} retained | Weekly: ${SNAP_WEEKLY_RETAIN} retained" echo " List: btrfs-snapshot.sh list" echo " Manual: btrfs-snapshot.sh create " echo "" if [[ ${ERRORS} -gt 0 ]]; then echo " [WARNING] ${ERRORS} verification check(s) failed. Review output above." else echo " [OK] All verification checks passed." fi echo "" echo "============================================================" echo " CUTOVER CHECKLIST" echo "============================================================" echo "" echo " When ready to replace the old ReadyNAS:" echo "" echo " 1. Copy data from old NAS:" echo " rsync -avz rsync://rsync@192.168.0.9/test/ /data/test/" echo "" echo " 2. Stop the old NAS (power off D2TESTNAS ReadyNAS)" echo "" echo " 3. Switch this VM to static IP ${STATIC_IP}:" echo " Edit /etc/network/interfaces to source ${STATIC_CONFIG}" echo " systemctl restart networking" echo "" echo " 4. Verify from a Windows machine:" echo " net use T: \\\\${STATIC_IP}\\test" echo " rsync --list-only rsync://rsync@${STATIC_IP}/test/" echo "" echo " 5. Verify from a DOS machine:" echo " Boot a test station and confirm T: drive maps successfully" echo "" echo " 6. Create initial BTRFS snapshot:" echo " btrfs-snapshot.sh create daily" echo "" echo "============================================================"