From d74105529ed36794fbe68ab36bbd6bd18396a661 Mon Sep 17 00:00:00 2001 From: Oier Bravo Urtasun Date: Sun, 22 Jun 2025 03:13:03 +0200 Subject: [PATCH] dockerize stack --- DOCKER_README.md | 262 +++++++++++++++++++++++++++++++++++++++ client/.dockerignore | 16 +++ client/Dockerfile | 19 +++ docker-compose.env | 30 +++++ docker-compose.yml | 81 ++++++++++++ server/.dockerignore | 17 +++ server/Dockerfile | 22 ++++ server/package-lock.json | 138 +++++++++++++++++++++ server/package.json | 2 +- setup-env.sh | 57 +++++++++ 10 files changed, 643 insertions(+), 1 deletion(-) create mode 100644 DOCKER_README.md create mode 100644 client/.dockerignore create mode 100644 client/Dockerfile create mode 100644 docker-compose.env create mode 100644 docker-compose.yml create mode 100644 server/.dockerignore create mode 100644 server/Dockerfile create mode 100755 setup-env.sh diff --git a/DOCKER_README.md b/DOCKER_README.md new file mode 100644 index 00000000..b3e814a2 --- /dev/null +++ b/DOCKER_README.md @@ -0,0 +1,262 @@ +# Strapi with PostgreSQL and Astro Client - Docker Compose Setup + +This setup provides a complete Docker Compose environment for running Strapi with PostgreSQL and an Astro frontend client. + +## Prerequisites + +- Docker +- Docker Compose + +## Quick Start + +1. **Clone and navigate to the project directory** + ```bash + cd /path/to/your/project + ``` + +2. **Install PostgreSQL dependencies** + ```bash + cd server + npm install pg + cd .. + ``` + +3. **Generate secure environment variables** + ```bash + # Generate JWT secrets (you can use any secure random string generator) + echo "JWT_SECRET=$(openssl rand -base64 32)" + echo "ADMIN_JWT_SECRET=$(openssl rand -base64 32)" + echo "APP_KEYS=$(openssl rand -base64 32),$(openssl rand -base64 32),$(openssl rand -base64 32),$(openssl rand -base64 32)" + echo "API_TOKEN_SALT=$(openssl rand -base64 32)" + echo "TRANSFER_TOKEN_SALT=$(openssl rand -base64 32)" + ``` + +4. **Create a .env file** (copy from docker-compose.env and update with your generated secrets) + ```bash + cp docker-compose.env .env + # Edit .env file with your generated secrets + ``` + +5. **Start the services** + ```bash + docker-compose up -d + ``` + +6. **Access the applications** + - Strapi Admin Panel: http://localhost:1337/admin + - Strapi API: http://localhost:1337/api + - Astro Client: http://localhost:4321 + +## Environment Variables Setup + +### Automatic Setup (Recommended) +Use the provided setup script to automatically configure environment variables: + +```bash +./setup-env.sh +``` + +This script will: +- Copy `docker-compose.env` to `.env` +- Generate secure random secrets for JWT tokens and salts +- Set up all necessary environment variables + +### Manual Setup +If you prefer to set up environment variables manually: + +1. **Copy the environment template** + ```bash + cp docker-compose.env .env + ``` + +2. **Edit the .env file** + ```bash + nano .env # or use your preferred editor + ``` + +3. **Update sensitive values** + - Replace all `your-*-here-change-this-in-production` values with secure random strings + - Modify database credentials if needed + - Adjust URLs and ports as required + +### Environment Variables Reference + +The following variables are available in `docker-compose.env`: + +#### Database Configuration +- `DATABASE_CLIENT`: Database type (postgres) +- `DATABASE_HOST`: Database host (postgres) +- `DATABASE_PORT`: Database port (5432) +- `DATABASE_NAME`: Database name (strapi) +- `DATABASE_USERNAME`: Database username (strapi) +- `DATABASE_PASSWORD`: Database password (strapi_password) +- `DATABASE_SSL`: SSL connection (false) + +#### Strapi Configuration +- `NODE_ENV`: Environment (development/production) +- `JWT_SECRET`: JWT signing secret +- `ADMIN_JWT_SECRET`: Admin JWT signing secret +- `APP_KEYS`: Application keys (comma-separated) +- `API_TOKEN_SALT`: API token salt +- `TRANSFER_TOKEN_SALT`: Transfer token salt +- `HOST`: Server host (0.0.0.0) +- `PORT`: Server port (1337) + +#### Client Configuration +- `CLIENT_NODE_ENV`: Client environment (development/production) +- `STRAPI_URL`: Strapi API URL (http://strapi:1337) + +### Security Notes +- The `.env` file is gitignored for security reasons +- Never commit sensitive secrets to version control +- Use different secrets for development and production +- Regularly rotate secrets in production environments + +## Services + +### Strapi Application (Backend) +- **Port**: 1337 +- **Container**: strapi-app +- **Database**: PostgreSQL +- **Purpose**: Headless CMS and API + +### Astro Client (Frontend) +- **Port**: 4321 +- **Container**: astro-client +- **Purpose**: Frontend application +- **Backend**: Connects to Strapi API + +### PostgreSQL Database +- **Port**: 5432 +- **Container**: strapi-postgres +- **Database**: strapi +- **Username**: strapi +- **Password**: strapi_password + +## Environment Variables + +The following environment variables are configured: + +### Strapi Configuration +- `DATABASE_CLIENT`: postgres +- `DATABASE_HOST`: postgres (Docker service name) +- `DATABASE_PORT`: 5432 +- `DATABASE_NAME`: strapi +- `DATABASE_USERNAME`: strapi +- `DATABASE_PASSWORD`: strapi_password +- `NODE_ENV`: development + +### Client Configuration +- `NODE_ENV`: development +- `STRAPI_URL`: http://strapi:1337 (internal Docker network) + +## Volumes + +- `postgres_data`: Persistent PostgreSQL data +- `./server/public/uploads`: Strapi uploads directory +- `./server/.tmp`: Strapi temporary files +- `./client/src`: Astro source code (for development) +- `./client/public`: Astro public assets +- `./client/astro.config.mjs`: Astro configuration +- `./client/tsconfig.json`: TypeScript configuration + +## Useful Commands + +```bash +# Start all services +docker-compose up -d + +# View logs for specific services +docker-compose logs -f strapi +docker-compose logs -f client +docker-compose logs -f postgres + +# View all logs +docker-compose logs -f + +# Stop all services +docker-compose down + +# Stop and remove volumes (WARNING: This will delete all data) +docker-compose down -v + +# Rebuild and start +docker-compose up -d --build + +# Rebuild specific service +docker-compose up -d --build client + +# Access PostgreSQL directly +docker-compose exec postgres psql -U strapi -d strapi + +# Access Strapi container +docker-compose exec strapi sh + +# Access Astro client container +docker-compose exec client sh +``` + +## Development Workflow + +### Hot Reload +Both Strapi and Astro support hot reloading in development mode: +- Changes to Strapi files will automatically restart the server +- Changes to Astro files will automatically reload the browser + +### API Communication +The Astro client can communicate with Strapi using: +- Internal Docker network: `http://strapi:1337` +- External access: `http://localhost:1337` + +### Example API call from Astro +```javascript +// In your Astro component or page +const response = await fetch('http://strapi:1337/api/your-content-type'); +const data = await response.json(); +``` + +## First Time Setup + +1. After starting the services, visit http://localhost:1337/admin +2. Create your first admin user +3. Configure your content types and permissions +4. Visit http://localhost:4321 to see your Astro frontend +5. Configure your Astro app to fetch data from Strapi + +## Production Considerations + +For production deployment: + +1. Change all default passwords and secrets +2. Use proper SSL certificates +3. Set `NODE_ENV=production` for both services +4. Configure proper backup strategies for PostgreSQL +5. Use environment-specific configuration files +6. Consider using Docker secrets for sensitive data +7. Build the Astro app for production: `npm run build` +8. Use a production-ready web server for the Astro build + +## Troubleshooting + +### Strapi won't start +- Check if PostgreSQL is running: `docker-compose logs postgres` +- Verify database connection settings +- Check if all environment variables are set correctly + +### Astro client won't start +- Check if Strapi is running: `docker-compose logs strapi` +- Verify the STRAPI_URL environment variable +- Check for port conflicts on 4321 + +### Database connection issues +- Ensure PostgreSQL container is healthy: `docker-compose ps` +- Check database logs: `docker-compose logs postgres` +- Verify network connectivity between containers + +### Permission issues +- Ensure proper file permissions on mounted volumes +- Check if the Docker user has access to the project files + +### Network connectivity between services +- Verify all services are on the same network: `docker network ls` +- Check if services can reach each other using container names \ No newline at end of file diff --git a/client/.dockerignore b/client/.dockerignore new file mode 100644 index 00000000..4beba7a6 --- /dev/null +++ b/client/.dockerignore @@ -0,0 +1,16 @@ +node_modules +npm-debug.log +.git +.gitignore +README.md +.env +.nyc_output +coverage +.cache +.parcel-cache +.next +.nuxt +dist +build +.astro +.vscode \ No newline at end of file diff --git a/client/Dockerfile b/client/Dockerfile new file mode 100644 index 00000000..47e0746a --- /dev/null +++ b/client/Dockerfile @@ -0,0 +1,19 @@ +FROM node:18-alpine + +# Set working directory +WORKDIR /opt/app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm ci + +# Copy source code +COPY . . + +# Expose port +EXPOSE 4321 + +# Start the development server +CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] \ No newline at end of file diff --git a/docker-compose.env b/docker-compose.env new file mode 100644 index 00000000..37e72d77 --- /dev/null +++ b/docker-compose.env @@ -0,0 +1,30 @@ +# ======================================== +# Environment Variables for Docker Compose +# ======================================== +# Copy this file to .env and modify values as needed +# cp docker-compose.env .env + +# Database Configuration +DATABASE_CLIENT=postgres +DATABASE_HOST=postgres +DATABASE_PORT=5432 +DATABASE_NAME=strapi +DATABASE_USERNAME=strapi +DATABASE_PASSWORD=strapi_password +DATABASE_SSL=false + +# Strapi Configuration +NODE_ENV=development +JWT_SECRET=your-jwt-secret-here-change-this-in-production +ADMIN_JWT_SECRET=your-admin-jwt-secret-here-change-this-in-production +APP_KEYS=your-app-keys-here-change-this-in-production +API_TOKEN_SALT=your-api-token-salt-here-change-this-in-production +TRANSFER_TOKEN_SALT=your-transfer-token-salt-here-change-this-in-production + +# Server Configuration +HOST=0.0.0.0 +PORT=1337 + +# Client Configuration +CLIENT_NODE_ENV=development +STRAPI_URL=http://strapi:1337 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..540a16b0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,81 @@ +version: '3.8' + +services: + strapi: + build: + context: ./server + dockerfile: Dockerfile + container_name: strapi-app + restart: unless-stopped + ports: + - "1337:1337" + env_file: + - docker-compose.env + environment: + DATABASE_CLIENT: ${DATABASE_CLIENT} + DATABASE_HOST: ${DATABASE_HOST} + DATABASE_PORT: ${DATABASE_PORT} + DATABASE_NAME: ${DATABASE_NAME} + DATABASE_USERNAME: ${DATABASE_USERNAME} + DATABASE_PASSWORD: ${DATABASE_PASSWORD} + DATABASE_SSL: ${DATABASE_SSL} + NODE_ENV: ${NODE_ENV} + JWT_SECRET: ${JWT_SECRET} + ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET} + APP_KEYS: ${APP_KEYS} + API_TOKEN_SALT: ${API_TOKEN_SALT} + TRANSFER_TOKEN_SALT: ${TRANSFER_TOKEN_SALT} + volumes: + - ./server/public/uploads:/opt/app/public/uploads + - ./server/.tmp:/opt/app/.tmp + depends_on: + - postgres + networks: + - strapi-network + + client: + build: + context: ./client + dockerfile: Dockerfile + container_name: astro-client + restart: unless-stopped + ports: + - "4321:4321" + env_file: + - docker-compose.env + environment: + NODE_ENV: ${CLIENT_NODE_ENV} + STRAPI_URL: ${STRAPI_URL} + volumes: + - ./client/src:/opt/app/src + - ./client/public:/opt/app/public + - ./client/astro.config.mjs:/opt/app/astro.config.mjs + - ./client/tsconfig.json:/opt/app/tsconfig.json + depends_on: + - strapi + networks: + - strapi-network + + postgres: + image: postgres:15-alpine + container_name: strapi-postgres + restart: unless-stopped + env_file: + - docker-compose.env + environment: + POSTGRES_DB: ${DATABASE_NAME} + POSTGRES_USER: ${DATABASE_USERNAME} + POSTGRES_PASSWORD: ${DATABASE_PASSWORD} + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" + networks: + - strapi-network + +volumes: + postgres_data: + +networks: + strapi-network: + driver: bridge \ No newline at end of file diff --git a/server/.dockerignore b/server/.dockerignore new file mode 100644 index 00000000..471e7239 --- /dev/null +++ b/server/.dockerignore @@ -0,0 +1,17 @@ +node_modules +npm-debug.log +.git +.gitignore +README.md +.env +.nyc_output +coverage +.cache +.parcel-cache +.next +.nuxt +dist +build +.strapi-updater.json +.strapi +.tmp \ No newline at end of file diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 00000000..17585700 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,22 @@ +FROM node:22-alpine + +# Set working directory +WORKDIR /opt/app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm ci --only=production + +# Copy source code +COPY . . + +# Build the application +RUN npm run build + +# Expose port +EXPOSE 1337 + +# Start the application +CMD ["npm", "start"] \ No newline at end of file diff --git a/server/package-lock.json b/server/package-lock.json index 3457ef7d..a438e96f 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -12,6 +12,7 @@ "@strapi/plugin-users-permissions": "^5.16.0", "@strapi/strapi": "^5.16.0", "better-sqlite3": "11.3.0", + "pg": "^8.16.2", "react": "^18.0.0", "react-dom": "^18.0.0", "react-router-dom": "^6.0.0", @@ -13894,12 +13895,101 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, + "node_modules/pg": { + "version": "8.16.2", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.2.tgz", + "integrity": "sha512-OtLWF0mKLmpxelOt9BqVq83QV6bTfsS0XLegIeAKqKjurRnRKie1Dc1iL89MugmSLhftxw6NNCyZhm1yQFLMEQ==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.9.1", + "pg-pool": "^3.10.1", + "pg-protocol": "^1.10.2", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.2.6" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.6.tgz", + "integrity": "sha512-uxmJAnmIgmYgnSFzgOf2cqGQBzwnRYcrEgXuFjJNEkpedEIPBSEzxY7ph4uA9k1mI+l/GR0HjPNS6FKNZe8SBQ==", + "license": "MIT", + "optional": true + }, "node_modules/pg-connection-string": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.1.tgz", "integrity": "sha512-w6ZzNu6oMmIzEAYVw+RLK0+nqHPt8K3ZnknKi+g48Ak2pr3dtljJW3o+D/n2zzCG07Zoe9VOX3aiKpj+BN0pjg==", "license": "MIT" }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz", + "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.2.tgz", + "integrity": "sha512-Ci7jy8PbaWxfsck2dwZdERcDG2A0MG8JoQILs+uZNjABFuBuItAZCWUNz8sXRDMoui24rJw7WlXqgpMdBSN/vQ==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pg/node_modules/pg-connection-string": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz", + "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==", + "license": "MIT" + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -14861,6 +14951,45 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -16981,6 +17110,15 @@ "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", "license": "CC0-1.0" }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", diff --git a/server/package.json b/server/package.json index 336e3696..4ee3aa1d 100644 --- a/server/package.json +++ b/server/package.json @@ -14,13 +14,13 @@ "upgrade": "npx @strapi/upgrade latest", "upgrade:dry": "npx @strapi/upgrade latest --dry", "cs": "config-sync" - }, "dependencies": { "@strapi/plugin-cloud": "5.13.0", "@strapi/plugin-users-permissions": "^5.16.0", "@strapi/strapi": "^5.16.0", "better-sqlite3": "11.3.0", + "pg": "^8.16.2", "react": "^18.0.0", "react-dom": "^18.0.0", "react-router-dom": "^6.0.0", diff --git a/setup-env.sh b/setup-env.sh new file mode 100755 index 00000000..1d1c511a --- /dev/null +++ b/setup-env.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Setup Environment Variables Script +echo "Setting up environment variables..." + +# Copy the docker-compose.env to .env if it doesn't exist +if [ ! -f .env ]; then + echo "Creating .env file from docker-compose.env..." + cp docker-compose.env .env + echo "✅ .env file created successfully!" +else + echo "⚠️ .env file already exists. Skipping..." +fi + +# Generate secure secrets if they haven't been changed from defaults +echo "" +echo "Checking for default secrets..." + +# Function to generate a random string (alphanumeric only) +generate_secret() { + openssl rand -hex 32 +} + +# Simple approach: create a new .env file with replacements +if grep -q "your-jwt-secret-here-change-this-in-production" .env; then + echo "Generating new JWT_SECRET..." + sed "s/your-jwt-secret-here-change-this-in-production/$(generate_secret)/g" .env > .env.tmp && mv .env.tmp .env +fi + +if grep -q "your-admin-jwt-secret-here-change-this-in-production" .env; then + echo "Generating new ADMIN_JWT_SECRET..." + sed "s/your-admin-jwt-secret-here-change-this-in-production/$(generate_secret)/g" .env > .env.tmp && mv .env.tmp .env +fi + +if grep -q "your-app-keys-here-change-this-in-production" .env; then + echo "Generating new APP_KEYS..." + sed "s/your-app-keys-here-change-this-in-production/$(generate_secret)/g" .env > .env.tmp && mv .env.tmp .env +fi + +if grep -q "your-api-token-salt-here-change-this-in-production" .env; then + echo "Generating new API_TOKEN_SALT..." + sed "s/your-api-token-salt-here-change-this-in-production/$(generate_secret)/g" .env > .env.tmp && mv .env.tmp .env +fi + +if grep -q "your-transfer-token-salt-here-change-this-in-production" .env; then + echo "Generating new TRANSFER_TOKEN_SALT..." + sed "s/your-transfer-token-salt-here-change-this-in-production/$(generate_secret)/g" .env > .env.tmp && mv .env.tmp .env +fi + +echo "" +echo "✅ Environment setup complete!" +echo "" +echo "Next steps:" +echo "1. Review and modify the .env file if needed" +echo "2. Run: docker-compose up -d" +echo "" +echo "Note: The .env file is gitignored for security reasons." \ No newline at end of file