Files
picpeak/setup-remaining-files.sh
T

381 lines
9.8 KiB
Bash

#!/bin/bash
# Setup script to create remaining files
echo "Creating remaining project files..."
# Create directories
mkdir -p backend/src/services
mkdir -p backend/src/utils
mkdir -p backend/src/routes
mkdir -p backend/migrations
mkdir -p backend/scripts
mkdir -p backend/__tests__
mkdir -p frontend/public
mkdir -p frontend/src/components
mkdir -p frontend/src/contexts
mkdir -p frontend/src/hooks
mkdir -p frontend/src/pages/admin
mkdir -p frontend/src/services
mkdir -p frontend/src/config
mkdir -p nginx/sites-enabled
mkdir -p scripts
mkdir -p storage/events/active
mkdir -p storage/events/archived
mkdir -p storage/thumbnails
mkdir -p data
mkdir -p logs
mkdir -p certbot/conf
mkdir -p certbot/www
# Create .gitkeep files
touch storage/events/active/.gitkeep
touch storage/events/archived/.gitkeep
touch storage/thumbnails/.gitkeep
touch data/.gitkeep
touch logs/.gitkeep
# Create remaining backend services
cat > backend/src/services/imageProcessor.js << 'EOF'
const sharp = require('sharp');
const path = require('path');
const fs = require('fs').promises;
const THUMBNAIL_WIDTH = 300;
const THUMBNAIL_PATH = path.join(__dirname, '../../../storage/thumbnails');
async function generateThumbnail(imagePath) {
const filename = path.basename(imagePath);
const thumbnailFilename = `thumb_${filename}`;
const thumbnailPath = path.join(THUMBNAIL_PATH, thumbnailFilename);
// Ensure thumbnail directory exists
await fs.mkdir(THUMBNAIL_PATH, { recursive: true });
// Generate thumbnail
await sharp(imagePath)
.resize(THUMBNAIL_WIDTH, null, {
withoutEnlargement: true,
fit: 'inside'
})
.jpeg({ quality: 80 })
.toFile(thumbnailPath);
return path.relative(path.join(__dirname, '../../../storage'), thumbnailPath);
}
module.exports = { generateThumbnail };
EOF
# Create logger utility
cat > backend/src/utils/logger.js << 'EOF'
const winston = require('winston');
const path = require('path');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.File({
filename: path.join(__dirname, '../../../logs/error.log'),
level: 'error'
}),
new winston.transports.File({
filename: path.join(__dirname, '../../../logs/combined.log')
})
]
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
)
}));
}
module.exports = logger;
EOF
echo "Backend services created."
# Create migration init script
cat > backend/migrations/init.js << 'EOF'
const bcrypt = require('bcrypt');
const { db, initializeDatabase } = require('../src/database/db');
async function runMigrations() {
console.log('Running database migrations...');
try {
// Initialize tables
await initializeDatabase();
// Create default admin user if none exists
const adminExists = await db('admin_users').first();
if (!adminExists) {
const defaultPassword = 'admin123'; // Change this!
const passwordHash = await bcrypt.hash(defaultPassword, 10);
await db('admin_users').insert({
username: 'admin',
email: 'admin@example.com',
password_hash: passwordHash
});
console.log('Default admin user created:');
console.log('Username: admin');
console.log('Password: admin123');
console.log('⚠️ Please change this password immediately!');
}
console.log('Migrations completed successfully');
process.exit(0);
} catch (error) {
console.error('Migration failed:', error);
process.exit(1);
}
}
runMigrations();
EOF
echo "Migration script created."
# Create README
cat > README.md << 'EOF'
# Photo Sharing Platform
A secure, self-hosted photo sharing platform designed for weddings and events. Features automatic expiration, email notifications, and simple file-based management.
## Features
- 🔒 Password Protected Galleries
- ⏰ Automatic Expiration
- 📧 Email Notifications
- 📁 Simple File Management
- 📊 Analytics Integration
- 🎨 Customizable Themes
- 📱 Mobile Responsive
- ⚡ Docker Ready
## Quick Start
1. Clone the repository
2. Run `./scripts/install.sh`
3. Configure `.env` file
4. Setup SSL: `./scripts/setup-ssl.sh`
5. Start: `docker-compose -f docker-compose.prod.yml up -d`
Default credentials: admin / admin123 (change immediately!)
## Documentation
See DEPLOYMENT.md for detailed deployment instructions.
## License
MIT License
EOF
echo "README created."
# Create main installation script
cat > scripts/install.sh << 'EOF'
#!/bin/bash
set -e
echo "Photo Sharing Platform - Docker Installation"
echo "==========================================="
# Check if running as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
# Function to check if command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Check prerequisites
echo "Checking prerequisites..."
# Install Docker if not present
if ! command_exists docker; then
echo "Installing Docker..."
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
rm get-docker.sh
fi
# Install Docker Compose if not present
if ! command_exists docker-compose; then
echo "Installing Docker Compose..."
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
fi
# Create necessary directories
echo "Creating directory structure..."
mkdir -p storage/events/{active,archived}
mkdir -p storage/thumbnails
mkdir -p data
mkdir -p logs
mkdir -p nginx/sites-enabled
mkdir -p certbot/{conf,www}
# Set permissions
chmod -R 755 storage
chmod -R 755 data
chmod -R 755 logs
# Copy environment file
if [ ! -f .env ]; then
cp .env.example .env
echo "Created .env file. Please edit it with your configuration."
fi
# Generate secure passwords
echo "Generating secure passwords..."
JWT_SECRET=$(openssl rand -base64 32)
DB_PASSWORD=$(openssl rand -base64 32)
UMAMI_HASH_SALT=$(openssl rand -base64 32)
# Update .env file with generated values
sed -i "s/JWT_SECRET=.*/JWT_SECRET=$JWT_SECRET/" .env
sed -i "s/DB_PASSWORD=.*/DB_PASSWORD=$DB_PASSWORD/" .env
sed -i "s/UMAMI_HASH_SALT=.*/UMAMI_HASH_SALT=$UMAMI_HASH_SALT/" .env
echo ""
echo "Installation complete!"
echo "Next steps:"
echo "1. Edit .env file with your domain names and SMTP settings"
echo "2. Run: ./scripts/setup-ssl.sh to configure SSL certificates"
echo "3. Run: docker-compose -f docker-compose.prod.yml up -d"
echo "4. Run: docker-compose -f docker-compose.prod.yml exec backend npm run migrate"
EOF
chmod +x scripts/install.sh
echo "Installation script created."
# Create nginx config
cat > nginx/nginx.conf << 'EOF'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Rate limiting
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=auth:10m rate=5r/m;
include /etc/nginx/sites-enabled/*.conf;
}
EOF
echo "Nginx config created."
# Create frontend package.json
cat > frontend/package.json << 'EOF'
{
"name": "photo-sharing-frontend",
"version": "1.0.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.8.0",
"axios": "^1.3.2",
"react-query": "^3.39.3",
"date-fns": "^2.29.3",
"react-toastify": "^9.1.1",
"react-dropzone": "^14.2.3",
"react-image-gallery": "^1.2.11",
"react-countdown": "^2.3.5",
"tailwindcss": "^3.2.4",
"autoprefixer": "^10.4.13",
"postcss": "^8.4.21",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"react-scripts": "5.0.1"
},
"proxy": "http://localhost:3000"
}
EOF
echo "Frontend package.json created."
echo ""
echo "Setup script complete!"
echo "Most important files have been created."
echo ""
echo "To complete the setup:"
echo "1. Run this script: chmod +x setup-remaining-files.sh && ./setup-remaining-files.sh"
echo "2. Review and update the created files as needed"
echo "3. Install dependencies: cd backend && npm install && cd ../frontend && npm install"
echo "4. Follow the deployment instructions in the README"