This project is containerized using Docker, making it easy to deploy to Digital Ocean Droplets.
- Digital Ocean account
- Domain name pointing to your Digital Ocean Droplet (optional but recommended)
- SSH access to your Droplet
-
Initial Server Setup:
# SSH into your server ssh root@your_droplet_ip # Update system packages apt update && apt upgrade -y # Install required packages (Docker already comes pre-installed on DO Ubuntu 24 images) apt install -y git curl certbot # Install Docker Compose v2 (Docker is already installed) mkdir -p ~/.docker/cli-plugins/ curl -SL https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose chmod +x ~/.docker/cli-plugins/docker-compose # Configure firewall if needed ufw allow ssh ufw allow http ufw allow https ufw enable
-
Create Project Directory:
mkdir -p /opt/bakery-app cd /opt/bakery-app -
Get the Application Code:
# Option 1: Clone your repository (if you have one) git clone https://your-repository-url.git . # Option 2: Use SFTP to upload files from your local machine # From your local machine in a new terminal: # sftp root@your_droplet_ip # mkdir /opt/bakery-app # cd /opt/bakery-app # put -r * .
-
Create Required Directories:
mkdir -p nginx/conf nginx/ssl nginx/logs mkdir -p certbot/www certbot/conf mkdir -p mysql/init mysql/conf
-
Set Up Environment Files:
# Create backend .env file (use echo with single quotes to prevent variable expansion) # IMPORTANT: Don't use actual credentials in your README - use placeholders touch ecspring/.env nano ecspring/.env # Add these configurations to the file (replace with your actual values) MYSQL_HOST=db MYSQL_PORT=3306 MYSQL_DATABASE=ec MYSQL_USER=bakery_user MYSQL_PASSWORD=your_secure_password MYSQL_ROOT_PASSWORD=your_secure_root_password GOOGLE_CLIENT_ID=your_google_client_id GOOGLE_CLIENT_SECRET=your_google_client_secret MAIL_HOST=smtp.gmail.com MAIL_PORT=587 MAIL_USERNAME=your_email@gmail.com MAIL_PASSWORD=your_app_password # Generate a secure random string for JWT_SECRET JWT_SECRET=$(openssl rand -base64 32) JWT_ACCESS_EXPIRATION=3600000 JWT_REFRESH_EXPIRATION=604800000 FRONTEND_URL=https://your-domain.com # Create frontend .env file touch ecfront/ec-front/.env nano ecfront/ec-front/.env # Add these configurations to the file NEXT_PUBLIC_API_BASE_URL=/api NEXT_PUBLIC_APP_URL=https://your-domain.com # Set proper permissions on .env files to restrict access chmod 600 ecspring/.env chmod 600 ecfront/ec-front/.env
-
Set Up Nginx Configuration:
# Create basic Nginx config cat > nginx/conf/default.conf << 'EOL' server { listen 80; server_name _; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { proxy_pass http://frontend:3000; 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_cache_bypass $http_upgrade; } location /api/ { proxy_pass http://backend:8080/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 90; } } EOL
-
Start the Application:
# Run Docker Compose to start all services docker compose up -d -
SSL Setup (if you have a domain):
# Install certbot Docker image docker run -it --rm \ -v "$(pwd)/certbot/conf:/etc/letsencrypt" \ -v "$(pwd)/certbot/www:/var/www/certbot" \ certbot/certbot certonly --webroot \ --webroot-path=/var/www/certbot \ --email your-email@example.com \ --agree-tos --no-eff-email \ -d your-domain.com # Update Nginx config with SSL cat > nginx/conf/default.conf << 'EOL' server { listen 80; server_name your-domain.com; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://$host$request_uri; } } server { listen 443 ssl; server_name your-domain.com; ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; location / { proxy_pass http://frontend:3000; 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_cache_bypass $http_upgrade; } location /api/ { proxy_pass http://backend:8080/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 90; } } EOL # Reload Nginx to apply SSL config docker compose restart nginx
-
Set Up Auto-Renewal for SSL Certificate:
# Create renewal script cat > renew-cert.sh << 'EOL' #!/bin/bash docker compose run --rm certbot renew docker compose restart nginx EOL chmod +x renew-cert.sh # Set up cron job to run twice a month (crontab -l 2>/dev/null; echo "0 0 1,15 * * /opt/bakery-app/renew-cert.sh") | crontab -
-
Verify Deployment:
# Check if containers are running docker compose ps # Check backend logs docker compose logs backend # Check frontend logs docker compose logs frontend
If you encounter issues:
-
Container won't start:
# Check logs docker compose logs [service_name] -
Database connection issues:
# Check if MySQL is running docker compose ps db # Check MySQL logs docker compose logs db
-
Nginx errors:
# Check Nginx logs docker compose logs nginx # Test Nginx configuration docker compose exec nginx nginx -t
-
Permission issues:
# Fix ownership chown -R 1001:1001 /opt/bakery-app/ecfront/ec-front/.next chown -R 1001:1001 /opt/bakery-app/ecfront/ec-front/node_modules
-
Restart services:
docker compose restart [service_name]
-
Update application:
# Pull latest code git pull # Rebuild and restart docker compose up -d --build
-
View application logs:
docker compose logs -f [service_name]
-
Backup database:
docker compose exec db sh -c 'exec mysqldump -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE' > backup.sql
- All sensitive environment variables are kept in
.envfiles - Database is only accessible within the Docker network
- Use strong passwords for all credentials
- Set up SSL for encrypted connections
- Keep your system updated with
apt update && apt upgrade -y - Consider using a firewall with limited open ports
- Set up regular database backups