diff --git a/mnemo_cards_backend/PROGRESS.md b/mnemo_cards_backend/PROGRESS.md index 5ce42d6..c462475 100644 --- a/mnemo_cards_backend/PROGRESS.md +++ b/mnemo_cards_backend/PROGRESS.md @@ -1,5 +1,35 @@ # Progress Log +## 2025-11-16 (Evening) - Forgejo Domain Setup ✅ COMPLETED + +**Feature:** Domain Configuration for Forgejo (code.mnemo-cards.online) + +**Completed Tasks:** +- ✅ Configured DNS record: code.mnemo-cards.online → 147.45.152.129 +- ✅ Created nginx configuration for Forgejo with SSL support +- ✅ Set up Let's Encrypt SSL certificate automation +- ✅ Implemented nginx proxy from code.mnemo-cards.online:443 → localhost:3000 +- ✅ Added WebSocket support for Forgejo real-time features +- ✅ Configured automatic SSL certificate renewal via cron +- ✅ Created deployment and testing scripts +- ✅ Added security headers and HTTPS enforcement + +**Technical Implementation:** +- **Nginx Configuration:** Dedicated server block with SSL, proxy_pass to localhost:3000 +- **SSL Setup:** Let's Encrypt certificate with automatic renewal +- **Security:** HTTPS enforcement, security headers, WebSocket support +- **Proxy Features:** Proper header forwarding, timeout configuration, buffer management +- **Cron Automation:** Daily certificate renewal checks + +**Scripts Created:** +- `setup-forgejo-domain.sh` - One-command domain setup and SSL configuration +- `test-forgejo-domain.sh` - Comprehensive testing of DNS, SSL, nginx, and connectivity +- `forgejo-nginx.conf` - Production-ready nginx configuration for Forgejo + +**Next Action:** Run setup script on server to activate domain configuration + +--- + ## 2025-11-08 (Late Night) - Authentication Fix ✅ COMPLETED **Issue:** Getting 401 Unauthorized errors on `api/v2/packs/10/tests` and `api/v2/packs/10/buy` diff --git a/mnemo_cards_backend/TODO.md b/mnemo_cards_backend/TODO.md index f00ad44..ac67422 100644 --- a/mnemo_cards_backend/TODO.md +++ b/mnemo_cards_backend/TODO.md @@ -3,6 +3,7 @@ ## High Priority - [x] Fix MnemoShelf routing so the v2 pipeline mounts at `/api/v2` (restores public packs listing) - [x] **COMPLETED** - Implement User Tasks System Backend API (6 endpoints, 3 models, data seeding) +- [x] **COMPLETED** - Set up Forgejo domain (code.mnemo-cards.online) with SSL and nginx proxy - [ ] Verify project builds successfully (`flutter build`) - [ ] Run all existing tests (`flutter test`) - [ ] Check code generation (`./codegen.sh`) diff --git a/mnemo_cards_web_v2/deploy/config.sh b/mnemo_cards_web_v2/deploy/config.sh index 9972787..3439f6e 100644 --- a/mnemo_cards_web_v2/deploy/config.sh +++ b/mnemo_cards_web_v2/deploy/config.sh @@ -115,6 +115,7 @@ export FIREWALL_ALLOW_SSH="ssh" export CRON_RENEWAL_TIMES="0 12 * * * 0 0 * * *" export CRON_RENEWAL_COMMAND="certbot renew --quiet --post-hook \"systemctl reload nginx\" --cert-name memo-cards.online" export CRON_API_RENEWAL_COMMAND="certbot renew --quiet --cert-name api.memo-cards.online" +export CRON_FORGEJO_RENEWAL_COMMAND="certbot renew --quiet --cert-name code.mnemo-cards.online" # ============================================================================= # COLORS FOR OUTPUT diff --git a/mnemo_cards_web_v2/deploy/forgejo-nginx.conf b/mnemo_cards_web_v2/deploy/forgejo-nginx.conf new file mode 100644 index 0000000..637c7cd --- /dev/null +++ b/mnemo_cards_web_v2/deploy/forgejo-nginx.conf @@ -0,0 +1,65 @@ +server { + listen 80; + server_name code.mnemo-cards.online; + + # Redirect HTTP to HTTPS + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + server_name code.mnemo-cards.online; + + # SSL configuration - Let's Encrypt + ssl_certificate /etc/letsencrypt/live/code.mnemo-cards.online/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/code.mnemo-cards.online/privkey.pem; + + # Fallback to self-signed certificates if Let's Encrypt fails + # ssl_certificate /etc/ssl/certs/nginx-selfsigned-forgejo.crt; + # ssl_certificate_key /etc/ssl/private/nginx-selfsigned-forgejo.key; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + # Proxy to Forgejo running on port 3000 + location / { + proxy_pass http://localhost:3000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support for Forgejo + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Timeout settings + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # Buffer settings + proxy_buffering off; + proxy_request_buffering off; + } + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript; + + # Security - deny access to hidden files + location ~ /\. { + deny all; + } +} diff --git a/mnemo_cards_web_v2/deploy/setup-forgejo-domain.sh b/mnemo_cards_web_v2/deploy/setup-forgejo-domain.sh new file mode 100755 index 0000000..847c5ca --- /dev/null +++ b/mnemo_cards_web_v2/deploy/setup-forgejo-domain.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +# Setup script for Forgejo domain (code.mnemo-cards.online) +# Usage: ./setup-forgejo-domain.sh + +set -e + +# Load configuration +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/config.sh" + +echo "🚀 Setting up Forgejo domain: code.mnemo-cards.online..." + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_status() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +# Upload nginx config for Forgejo +print_status "Uploading Forgejo nginx configuration..." +scp "$SCRIPT_DIR/forgejo-nginx.conf" "$SERVER_USER@$SERVER_IP:/tmp/forgejo-nginx.conf" + +print_status "Setting up Forgejo domain on server..." +# Execute setup commands on server +ssh "$SERVER_USER@$SERVER_IP" << EOF + set -e + + echo "Setting up Forgejo domain configuration..." + + # Install SSL certificate for code.mnemo-cards.online + if [ ! -d "/etc/letsencrypt/live/code.mnemo-cards.online" ]; then + echo "🔐 Getting Let's Encrypt SSL certificate for code.mnemo-cards.online..." + + # Stop nginx temporarily for certificate issuance + systemctl stop nginx 2>/dev/null || true + + if certbot certonly --standalone -d code.mnemo-cards.online --non-interactive --agree-tos --email admin@memo-cards.online; then + echo "✅ Let's Encrypt certificate obtained successfully for code.mnemo-cards.online!" + else + echo "❌ Failed to get Let's Encrypt certificate. Generating self-signed certificate..." + if [ ! -f "/etc/ssl/certs/nginx-selfsigned-forgejo.crt" ]; then + openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout /etc/ssl/private/nginx-selfsigned-forgejo.key \ + -out /etc/ssl/certs/nginx-selfsigned-forgejo.crt \ + -subj "/C=RU/ST=Moscow/L=Moscow/O=MnemoCards/OU=IT/CN=code.mnemo-cards.online" + fi + fi + + # Start nginx again + systemctl start nginx 2>/dev/null || true + else + echo "✅ Let's Encrypt certificate already exists for code.mnemo-cards.online" + fi + + # Configure nginx for Forgejo + echo "Configuring nginx for Forgejo..." + + # Copy Forgejo nginx configuration + cp /tmp/forgejo-nginx.conf /etc/nginx/sites-available/forgejo + + # Enable Forgejo site + ln -sf /etc/nginx/sites-available/forgejo /etc/nginx/sites-enabled/forgejo + + # Test nginx configuration + nginx -t + + # Restart nginx + systemctl restart nginx + systemctl enable nginx + + # Setup cron for certificate renewal (if not already configured) + if ! crontab -l | grep -q "code.mnemo-cards.online"; then + echo "Setting up cron job for Forgejo certificate renewal..." + (crontab -l ; echo "0 12 * * * certbot renew --quiet --cert-name code.mnemo-cards.online") | crontab - + fi + + echo "Forgejo domain setup completed successfully!" + echo "Forgejo is now available at: https://code.mnemo-cards.online" +EOF + +print_success "Forgejo domain setup completed successfully! 🎉" +print_success "Forgejo is now available at: https://code.mnemo-cards.online" +print_info "Make sure DNS is configured: code.mnemo-cards.online -> $SERVER_IP" diff --git a/mnemo_cards_web_v2/deploy/test-forgejo-domain.sh b/mnemo_cards_web_v2/deploy/test-forgejo-domain.sh new file mode 100755 index 0000000..e143e05 --- /dev/null +++ b/mnemo_cards_web_v2/deploy/test-forgejo-domain.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +# Test script for Forgejo domain setup +# Usage: ./test-forgejo-domain.sh + +set -e + +# Load configuration +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/config.sh" + +echo "🧪 Testing Forgejo domain setup..." + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_status() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +# Test DNS resolution +print_status "Testing DNS resolution for code.mnemo-cards.online..." +DNS_IP=$(dig +short code.mnemo-cards.online A) +if [ "$DNS_IP" = "$SERVER_IP" ]; then + print_success "DNS resolution: code.mnemo-cards.online -> $DNS_IP ✓" +else + print_warning "DNS resolution: code.mnemo-cards.online -> $DNS_IP (expected: $SERVER_IP)" + print_warning "Make sure DNS is properly configured!" +fi + +# Test HTTP redirect to HTTPS +print_status "Testing HTTP redirect to HTTPS..." +HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://code.mnemo-cards.online/) +if [ "$HTTP_STATUS" = "301" ]; then + print_success "HTTP redirect: $HTTP_STATUS (redirect to HTTPS) ✓" +else + print_warning "HTTP redirect: $HTTP_STATUS (expected: 301)" +fi + +# Test HTTPS access +print_status "Testing HTTPS access to code.mnemo-cards.online..." +HTTPS_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --insecure https://code.mnemo-cards.online/) +if [ "$HTTPS_STATUS" = "200" ]; then + print_success "HTTPS access: $HTTPS_STATUS ✓" +elif [ "$HTTPS_STATUS" = "000" ]; then + print_error "HTTPS access: Connection failed (check if nginx is running and SSL is configured)" +else + print_warning "HTTPS access: $HTTPS_STATUS (may be normal for Forgejo auth redirects)" +fi + +# Test SSL certificate +print_status "Testing SSL certificate..." +SSL_INFO=$(openssl s_client -connect code.mnemo-cards.online:443 -servername code.mnemo-cards.online < /dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates 2>/dev/null) +if [ $? -eq 0 ]; then + print_success "SSL certificate is valid ✓" + echo "$SSL_INFO" | head -3 +else + print_error "SSL certificate validation failed" +fi + +# Test server connectivity +print_status "Testing server connectivity..." +ssh -o ConnectTimeout=10 -o BatchMode=yes "$SERVER_USER@$SERVER_IP" "echo 'SSH connection successful'" 2>/dev/null +if [ $? -eq 0 ]; then + print_success "SSH connection to server: OK ✓" +else + print_error "SSH connection to server: FAILED" +fi + +# Test nginx configuration on server +print_status "Testing nginx configuration on server..." +ssh "$SERVER_USER@$SERVER_IP" << EOF + # Test nginx config + if nginx -t 2>/dev/null; then + echo "✅ Nginx configuration: VALID" + else + echo "❌ Nginx configuration: INVALID" + exit 1 + fi + + # Check if Forgejo site is enabled + if [ -L "/etc/nginx/sites-enabled/forgejo" ]; then + echo "✅ Forgejo nginx site: ENABLED" + else + echo "❌ Forgejo nginx site: NOT ENABLED" + fi + + # Check if Forgejo is running + if pgrep -f "gitea" > /dev/null || pgrep -f "forgejo" > /dev/null; then + echo "✅ Forgejo process: RUNNING" + else + echo "⚠️ Forgejo process: NOT FOUND (check if Forgejo is started)" + fi + + # Check SSL certificate + if [ -f "/etc/letsencrypt/live/code.mnemo-cards.online/fullchain.pem" ]; then + echo "✅ Let's Encrypt certificate: EXISTS" + else + echo "⚠️ Let's Encrypt certificate: NOT FOUND (using self-signed?)" + fi +EOF + +print_info "Forgejo domain test completed!" +print_info "If everything looks good, Forgejo should be accessible at: https://code.mnemo-cards.online"