#!/bin/bash set -e # Exit immediately if a command exits with a non-zero status echo "=====================================================" echo " COTI Full Node Automated Installer" echo "=====================================================" # --- 0. OS VALIDATION --- if [ -f /etc/os-release ]; then . /etc/os-release if [[ "$ID" != "ubuntu" ]] || [[ ! "$VERSION_ID" =~ ^24\.04 ]]; then echo "WARNING: This script only supports Ubuntu 24.04 LTS." echo "Detected: $PRETTY_NAME" read -p "Proceed at your own risk? (y/N): " PROCEED if [[ ! "$PROCEED" =~ ^[yY] ]]; then echo "Aborted." exit 1 fi fi fi # --- 1. VALIDATE REQUIRED INPUTS (from frontend: export PK=... DNS=...) --- if [ -z "$DNS" ] || [ -z "$PK" ]; then echo "ERROR: DNS and PK must be set. Run with: export PK=\"0x...\" DNS=\"your.domain\" && curl -sL \"https://raw.githubusercontent.com/coti-io/coti-full-node/coti-testnet/install.sh?t=\$(date +%s)\" | bash" exit 1 fi # Strip 0x prefix from PK for nodekey format PK_CLEAN="${PK#0x}" # --- 2. INSTALL HOST DEPENDENCIES --- echo "--> Installing necessary system dependencies (Docker, Certbot)..." sudo apt-get update -y sudo apt-get install -y docker.io docker-compose certbot curl git # Add current user to docker group (takes effect after re-login); use sudo for docker during this run sudo usermod -aG docker "$USER" 2>/dev/null || true # --- 3. CLONE/PREPARE DIRECTORY --- # If they downloaded the script outside the repo, clone it. Otherwise, use current dir. if [ ! -f "docker-compose.yml" ]; then echo "--> Cloning COTI full-node repository..." git clone -b coti-testnet https://github.com/coti-io/coti-full-node.git cd coti-full-node fi # --- 4. GENERATE .ENV FILE --- echo "--> Generating environment variables..." EXT_IP=$(curl -s https://api.ipify.org) cat < .env FULLNODE_EXT_IP=$EXT_IP FULLNODE_DNS_ADDRESS=$DNS NODE_IMAGE_VERSION=1.2.0 EOF # --- 5. CONFIGURE PRIVATE KEY (NODEKEY) --- echo "--> Setting up identity and node keys..." mkdir -p ./execution/geth # Ethereum/Geth based clients read the nodekey from a file echo -n "$PK_CLEAN" > ./execution/geth/nodekey chmod 600 ./execution/geth/nodekey # --- 6. SSL SETUP (Docker profile approach) --- echo "--> Preparing for Let's Encrypt challenge..." mkdir -p ./nginx/certbot ./nginx/sites-enabled # Start temporary nginx-init (profile: setup) - serves only port 80 for ACME challenge echo "--> Starting temporary Nginx to verify domain..." sudo docker-compose --profile setup up -d nginx-init # --- 7. RUN CERTBOT --- echo "--> Requesting SSL Certificate for $DNS..." sudo certbot certonly --webroot -w "$(pwd)/nginx/certbot" -d "$DNS" --register-unsafely-without-email --agree-tos --non-interactive # Tear down temporary nginx-init so port 80 is free for main nginx echo "--> Tearing down temporary Nginx..." sudo docker-compose --profile setup down # --- 8. APPLY FINAL NGINX CONFIG --- echo "--> Applying full HTTPS proxy configurations..." cat < ./nginx/sites-enabled/fullnode.conf server { listen 443 ssl; server_name $DNS; ssl_certificate /etc/letsencrypt/live/$DNS/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/$DNS/privkey.pem; ssl_session_timeout 5m; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305; ssl_prefer_server_ciphers on; location /ws { proxy_http_version 1.1; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host \$http_host; proxy_pass http://fullnode_8546/; } location /rpc { proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_pass http://fullnode_8545/; } location /metrics { proxy_set_header Host \$host; proxy_pass http://fullnode_6000/debug/metrics/prometheus; } } server { listen 80; server_name $DNS; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://\$host\$request_uri; } } EOF # --- 9. FINAL LAUNCH --- # Use start_coti-full-node.sh (sources .env, pulls images, starts services) echo "--> Starting up the full node stack..." ./start_coti-full-node.sh echo "=====================================================" echo " SUCCESS! Your COTI full node is initializing." echo " DNS: https://$DNS" echo " Use 'docker logs -f coti-testnet-full-node' to monitor." echo "====================================================="