diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 0000000..b244e77 --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,161 @@ +# TrueCV Deployment Guide + +## Quick Start + +### 1. Server Setup (run once on fresh Ubuntu server) + +```bash +# Copy server-setup.sh to your server +scp deploy/server-setup.sh user@your-server:/tmp/ + +# SSH into server and run setup +ssh user@your-server +sudo bash /tmp/server-setup.sh +``` + +**Before running**, edit the script and update: +- `DOMAIN` - Your domain name +- `DB_PASSWORD` - Strong password for SQL Server +- `ADMIN_EMAIL` - Email for SSL certificate notifications + +### 2. Deploy Application (run from dev machine) + +```bash +# Edit deploy.sh and update configuration +nano deploy/deploy.sh + +# Make executable and run +chmod +x deploy/deploy.sh +./deploy/deploy.sh +``` + +**Update these values in deploy.sh:** +- `SERVER_USER` - SSH username +- `SERVER_HOST` - Server hostname or IP +- `DOMAIN` - Your domain name + +### 3. Enable SSL + +After DNS is configured and app is deployed: + +```bash +ssh user@your-server +sudo certbot --nginx -d truecv.yourdomain.com +``` + +## Configuration + +### Environment Variables + +The systemd service sets these environment variables: +- `ASPNETCORE_ENVIRONMENT=Production` +- `ASPNETCORE_URLS=http://localhost:5000` +- `ConnectionStrings__DefaultConnection=...` + +To add more (like API keys), edit: +```bash +sudo systemctl edit truecv +``` + +Add: +```ini +[Service] +Environment=OpenAI__ApiKey=your-key-here +``` + +### appsettings.Production.json + +For sensitive settings, create `/var/www/truecv/appsettings.Production.json`: + +```json +{ + "ConnectionStrings": { + "DefaultConnection": "Server=127.0.0.1;Database=TrueCV;User Id=SA;Password=YourPassword;TrustServerCertificate=True" + }, + "OpenAI": { + "ApiKey": "your-openai-key" + } +} +``` + +## Maintenance + +### View Logs +```bash +# Application logs +sudo journalctl -u truecv -f + +# Nginx logs +sudo tail -f /var/log/nginx/access.log +sudo tail -f /var/log/nginx/error.log + +# SQL Server logs +docker logs truecv-sql -f +``` + +### Restart Services +```bash +sudo systemctl restart truecv +sudo systemctl restart nginx +docker restart truecv-sql +``` + +### Database Backup +```bash +# Backup +docker exec truecv-sql /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U SA -P 'YourPassword' -C \ + -Q "BACKUP DATABASE TrueCV TO DISK='/var/opt/mssql/backup/truecv.bak'" + +# Copy backup from container +docker cp truecv-sql:/var/opt/mssql/backup/truecv.bak ./truecv-backup.bak +``` + +### Rollback Deployment +```bash +# On server - restore previous version +sudo systemctl stop truecv +sudo rm -rf /var/www/truecv +sudo mv /var/www/truecv.backup.YYYYMMDD_HHMMSS /var/www/truecv +sudo systemctl start truecv +``` + +## Troubleshooting + +### App won't start +```bash +# Check status +sudo systemctl status truecv + +# Check logs +sudo journalctl -u truecv -n 100 + +# Test manually +cd /var/www/truecv +sudo -u www-data dotnet TrueCV.Web.dll +``` + +### Database connection issues +```bash +# Check SQL Server is running +docker ps | grep truecv-sql + +# Test connection +docker exec -it truecv-sql /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U SA -P 'YourPassword' -C \ + -Q "SELECT name FROM sys.databases" +``` + +### Blazor SignalR issues +Ensure Nginx is configured for WebSocket support (included in setup script). + +Check browser console for connection errors. + +## Security Checklist + +- [ ] Change default SQL Server password +- [ ] Enable SSL with Let's Encrypt +- [ ] Configure firewall (UFW) +- [ ] Set up automated backups +- [ ] Enable fail2ban for SSH protection +- [ ] Keep system updated regularly diff --git a/deploy/deploy.sh b/deploy/deploy.sh new file mode 100644 index 0000000..7837b0d --- /dev/null +++ b/deploy/deploy.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# TrueCV Deployment Script +# Run this from your development machine to deploy to a Linux server + +set -e + +# Configuration - UPDATE THESE VALUES +SERVER_USER="deploy" +SERVER_HOST="your-server.com" +SERVER_PATH="/var/www/truecv" +DOMAIN="truecv.yourdomain.com" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${GREEN}=== TrueCV Deployment Script ===${NC}" + +# Check if configuration is set +if [[ "$SERVER_HOST" == "your-server.com" ]]; then + echo -e "${RED}Error: Please update SERVER_HOST in this script${NC}" + exit 1 +fi + +# Step 1: Build and publish +echo -e "${YELLOW}Step 1: Publishing application...${NC}" +cd "$(dirname "$0")/.." +dotnet publish src/TrueCV.Web -c Release -o ./publish --nologo + +# Step 2: Create deployment package +echo -e "${YELLOW}Step 2: Creating deployment package...${NC}" +tar -czf deploy/truecv-release.tar.gz -C publish . + +# Step 3: Transfer to server +echo -e "${YELLOW}Step 3: Transferring to server...${NC}" +scp deploy/truecv-release.tar.gz ${SERVER_USER}@${SERVER_HOST}:/tmp/ + +# Step 4: Deploy on server +echo -e "${YELLOW}Step 4: Deploying on server...${NC}" +ssh ${SERVER_USER}@${SERVER_HOST} << 'ENDSSH' +set -e + +# Stop the service if running +sudo systemctl stop truecv 2>/dev/null || true + +# Backup current deployment +if [ -d "/var/www/truecv" ]; then + sudo mv /var/www/truecv /var/www/truecv.backup.$(date +%Y%m%d_%H%M%S) +fi + +# Create directory and extract +sudo mkdir -p /var/www/truecv +sudo tar -xzf /tmp/truecv-release.tar.gz -C /var/www/truecv +sudo chown -R www-data:www-data /var/www/truecv + +# Start the service +sudo systemctl start truecv + +# Clean up +rm /tmp/truecv-release.tar.gz + +echo "Deployment complete on server" +ENDSSH + +# Step 5: Verify deployment +echo -e "${YELLOW}Step 5: Verifying deployment...${NC}" +sleep 3 +if ssh ${SERVER_USER}@${SERVER_HOST} "sudo systemctl is-active truecv" | grep -q "active"; then + echo -e "${GREEN}=== Deployment successful! ===${NC}" + echo -e "Site should be available at: https://${DOMAIN}" +else + echo -e "${RED}Warning: Service may not be running. Check with: sudo systemctl status truecv${NC}" +fi + +# Cleanup local files +rm -f deploy/truecv-release.tar.gz + +echo -e "${GREEN}Done!${NC}" diff --git a/deploy/server-setup.sh b/deploy/server-setup.sh new file mode 100644 index 0000000..fd2a719 --- /dev/null +++ b/deploy/server-setup.sh @@ -0,0 +1,159 @@ +#!/bin/bash +# TrueCV Server Setup Script +# Run this ONCE on a fresh Linux server (Ubuntu 22.04/24.04) + +set -e + +# Configuration - UPDATE THESE VALUES +DOMAIN="truecv.yourdomain.com" +DB_PASSWORD="YourStrong!Password123" +ADMIN_EMAIL="admin@yourdomain.com" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +echo -e "${GREEN}=== TrueCV Server Setup ===${NC}" + +# Check if running as root +if [[ $EUID -ne 0 ]]; then + echo -e "${RED}This script must be run as root (use sudo)${NC}" + exit 1 +fi + +# Step 1: Update system +echo -e "${YELLOW}Step 1: Updating system...${NC}" +apt update && apt upgrade -y + +# Step 2: Install .NET 8 Runtime +echo -e "${YELLOW}Step 2: Installing .NET 8 Runtime...${NC}" +apt install -y wget apt-transport-https +wget https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb +dpkg -i packages-microsoft-prod.deb +rm packages-microsoft-prod.deb +apt update +apt install -y aspnetcore-runtime-8.0 + +# Step 3: Install Nginx +echo -e "${YELLOW}Step 3: Installing Nginx...${NC}" +apt install -y nginx +systemctl enable nginx + +# Step 4: Install Docker (for SQL Server) +echo -e "${YELLOW}Step 4: Installing Docker...${NC}" +apt install -y docker.io docker-compose +systemctl enable docker +systemctl start docker + +# Step 5: Set up SQL Server container +echo -e "${YELLOW}Step 5: Setting up SQL Server...${NC}" +docker run -e 'ACCEPT_EULA=Y' \ + -e "SA_PASSWORD=${DB_PASSWORD}" \ + -p 127.0.0.1:1433:1433 \ + --name truecv-sql \ + --restart unless-stopped \ + -v truecv-sqldata:/var/opt/mssql \ + -d mcr.microsoft.com/mssql/server:2022-latest + +echo "Waiting for SQL Server to start..." +sleep 30 + +# Create the database +docker exec truecv-sql /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U SA -P "${DB_PASSWORD}" -C \ + -Q "CREATE DATABASE TrueCV" + +# Step 6: Create application directory +echo -e "${YELLOW}Step 6: Creating application directory...${NC}" +mkdir -p /var/www/truecv +chown -R www-data:www-data /var/www/truecv + +# Step 7: Create systemd service +echo -e "${YELLOW}Step 7: Creating systemd service...${NC}" +cat > /etc/systemd/system/truecv.service << EOF +[Unit] +Description=TrueCV Web Application +After=network.target docker.service +Requires=docker.service + +[Service] +WorkingDirectory=/var/www/truecv +ExecStart=/usr/bin/dotnet /var/www/truecv/TrueCV.Web.dll +Restart=always +RestartSec=10 +KillSignal=SIGINT +SyslogIdentifier=truecv +User=www-data +Environment=ASPNETCORE_ENVIRONMENT=Production +Environment=ASPNETCORE_URLS=http://localhost:5000 +Environment=ConnectionStrings__DefaultConnection=Server=127.0.0.1;Database=TrueCV;User Id=SA;Password=${DB_PASSWORD};TrustServerCertificate=True + +[Install] +WantedBy=multi-user.target +EOF + +systemctl daemon-reload +systemctl enable truecv + +# Step 8: Configure Nginx +echo -e "${YELLOW}Step 8: Configuring Nginx...${NC}" +cat > /etc/nginx/sites-available/truecv << EOF +server { + listen 80; + server_name ${DOMAIN}; + + location / { + proxy_pass http://localhost:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + 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; + proxy_cache_bypass \$http_upgrade; + + # WebSocket support for Blazor Server + proxy_read_timeout 86400; + proxy_send_timeout 86400; + } +} +EOF + +ln -sf /etc/nginx/sites-available/truecv /etc/nginx/sites-enabled/ +rm -f /etc/nginx/sites-enabled/default +nginx -t +systemctl reload nginx + +# Step 9: Install Certbot for SSL +echo -e "${YELLOW}Step 9: Setting up SSL with Let's Encrypt...${NC}" +apt install -y certbot python3-certbot-nginx + +echo -e "${YELLOW}To enable SSL, run:${NC}" +echo " certbot --nginx -d ${DOMAIN} --email ${ADMIN_EMAIL} --agree-tos --non-interactive" + +# Step 10: Configure firewall +echo -e "${YELLOW}Step 10: Configuring firewall...${NC}" +ufw allow 22/tcp +ufw allow 80/tcp +ufw allow 443/tcp +ufw --force enable + +# Summary +echo "" +echo -e "${GREEN}=== Server Setup Complete! ===${NC}" +echo "" +echo "Next steps:" +echo "1. Update DNS to point ${DOMAIN} to this server's IP" +echo "2. Deploy the application using deploy.sh from your dev machine" +echo "3. Run SSL setup: certbot --nginx -d ${DOMAIN}" +echo "" +echo "Useful commands:" +echo " sudo systemctl status truecv - Check app status" +echo " sudo journalctl -u truecv -f - View app logs" +echo " docker logs truecv-sql - View SQL Server logs" +echo "" +echo -e "${YELLOW}Database connection string:${NC}" +echo " Server=127.0.0.1;Database=TrueCV;User Id=SA;Password=${DB_PASSWORD};TrustServerCertificate=True"