This guide provides comprehensive instructions for setting up and deploying the ECL Calculator application in various environments. Whether you're looking to set up a local development environment or deploy to a production server, this document will walk you through the necessary steps.
The ECL Calculator is a full-stack application with:
This guide assumes familiarity with basic system administration, command-line operations, and web application architecture. Specific sections may require more specialized knowledge of database management, containerization, or cloud services.
Clone the repository from your version control system:
git clone https://github.com/your-organization/ecl-calculator.git
cd ecl-calculator
The ECL Calculator requires a PostgreSQL database. Here's how to set it up locally:
On Ubuntu/Debian:
sudo apt update
sudo apt install postgresql postgresql-contrib
On macOS with Homebrew:
brew install postgresql
brew services start postgresql
On Windows:
Download and install PostgreSQL from the official website.
sudo -u postgres psql
CREATE DATABASE ecl_calculator;
CREATE USER ecl_user WITH PASSWORD 'your_secure_password';
ALTER ROLE ecl_user SET client_encoding TO 'utf8';
ALTER ROLE ecl_user SET default_transaction_isolation TO 'read committed';
ALTER ROLE ecl_user SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE ecl_calculator TO ecl_user;
\q
Always use strong, unique passwords in production. The example password above is for demonstration purposes only.
python -m venv venv
source venv/bin/activate # On Windows, use: venv\Scripts\activate
pip install -r requirements.txt
If requirements.txt is not available, install the necessary packages:
pip install flask flask-cors flask-login flask-sqlalchemy flask-wtf gunicorn
pip install psycopg2-binary pandas numpy email-validator werkzeug
cd react-ecl-calculator
npm install
npm run build
For development, you can use:
npm start
Create a .env file in the project root with the following variables:
FLASK_APP=main.py
FLASK_ENV=development # Use 'production' for production deployments
DATABASE_URL=postgresql://ecl_user:your_secure_password@localhost/ecl_calculator
SESSION_SECRET=your_session_secret_key
ADMIN_EMAIL=admin@example.com
Configure the API base URL in react-ecl-calculator/src/config/environments.js:
// For local development
const development = {
apiBaseUrl: 'http://localhost:5000/api'
};
// For testing
const testing = {
apiBaseUrl: 'http://test-server.example.com/api'
};
// For production
const production = {
apiBaseUrl: 'https://production-server.example.com/api'
};
From the project root directory:
python -m flask run
For production-like setup with Gunicorn:
gunicorn --bind 0.0.0.0:5000 --workers 4 main:app
In a separate terminal, navigate to the React directory:
cd react-ecl-calculator
npm start
When running both Flask and React development servers, your React app will be available at http://localhost:3000, while the Flask server will be at http://localhost:5000. The React development server will proxy API requests to the Flask backend.
To access the application, you'll need an admin user. You can create one using the provided script:
python create_demo_admin.py
This will create a user with the credentials specified in the script (usually admin@example.com / Admin123!).
Ensure your security group allows the following inbound traffic:
ssh -i /path/to/your-key.pem ec2-user@your-instance-public-dns
For Ubuntu instances, use:
ssh -i /path/to/your-key.pem ubuntu@your-instance-public-dns
sudo apt update
sudo apt upgrade -y
sudo apt install postgresql postgresql-contrib -y
sudo -u postgres psql
CREATE DATABASE ecl_calculator;
CREATE USER ecl_user WITH PASSWORD 'your_production_password';
ALTER ROLE ecl_user SET client_encoding TO 'utf8';
ALTER ROLE ecl_user SET default_transaction_isolation TO 'read committed';
ALTER ROLE ecl_user SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE ecl_calculator TO ecl_user;
\q
If your database will be on a separate server, you'll need to enable remote access:
Edit the PostgreSQL configuration file:
sudo nano /etc/postgresql/12/main/postgresql.conf
Find and uncomment the line:
#listen_addresses = 'localhost'
Change it to:
listen_addresses = '*'
Edit the client authentication configuration:
sudo nano /etc/postgresql/12/main/pg_hba.conf
Add the following line to allow access from your application server:
host all all your_app_server_ip/32 md5
Restart PostgreSQL:
sudo systemctl restart postgresql
Exposing PostgreSQL to the internet is a significant security risk. Consider using VPC, security groups, or SSH tunneling to secure database connections instead of opening direct access.
sudo apt install python3-pip python3-venv nginx git -y
sudo adduser ecl_app
sudo usermod -aG sudo ecl_app
su - ecl_app
git clone https://github.com/your-organization/ecl-calculator.git
cd ecl-calculator
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install gunicorn
cd react-ecl-calculator
npm install
npm run build
cd ..
Create a .env file:
nano .env
Add the following content:
FLASK_APP=main.py
FLASK_ENV=production
DATABASE_URL=postgresql://ecl_user:your_production_password@localhost/ecl_calculator
SESSION_SECRET=your_production_secret_key
ADMIN_EMAIL=admin@your-company.com
Load environment variables in systemd service (see systemd section below)
sudo nano /etc/nginx/sites-available/ecl-calculator
Add the following configuration:
server {
listen 80;
server_name your-domain.com www.your-domain.com;
location /static {
alias /home/ecl_app/ecl-calculator/static;
expires 30d;
}
location /react {
alias /home/ecl_app/ecl-calculator/react-ecl-calculator/build;
try_files $uri $uri/ /react/index.html;
expires 30d;
}
location / {
proxy_pass http://localhost:5000;
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;
}
}
sudo ln -s /etc/nginx/sites-available/ecl-calculator /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your-domain.com -d www.your-domain.com
Follow the prompts to configure HTTPS.
Certbot sets up auto-renewal automatically. You can test it with:
sudo certbot renew --dry-run
sudo nano /etc/systemd/system/ecl-calculator.service
Add the following content:
[Unit]
Description=ECL Calculator Application
After=network.target postgresql.service
[Service]
User=ecl_app
Group=www-data
WorkingDirectory=/home/ecl_app/ecl-calculator
Environment="PATH=/home/ecl_app/ecl-calculator/venv/bin"
EnvironmentFile=/home/ecl_app/ecl-calculator/.env
ExecStart=/home/ecl_app/ecl-calculator/venv/bin/gunicorn --workers 4 --bind 0.0.0.0:5000 main:app
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl start ecl-calculator
sudo systemctl enable ecl-calculator
sudo systemctl status ecl-calculator
You can monitor the application logs with:
sudo journalctl -u ecl-calculator -f
Create a Dockerfile in the project root:
FROM python:3.9-slim
WORKDIR /app
# Install dependencies for building Python packages
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install gunicorn
# Copy the application code
COPY . .
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV FLASK_APP=main.py
ENV FLASK_ENV=production
# Expose the application port
EXPOSE 5000
# Command to run the application
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "main:app"]
Create a docker-compose.yml file:
version: '3.8'
services:
db:
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_PASSWORD=your_secure_password
- POSTGRES_USER=ecl_user
- POSTGRES_DB=ecl_calculator
restart: always
web:
build: .
restart: always
depends_on:
- db
environment:
- DATABASE_URL=postgresql://ecl_user:your_secure_password@db/ecl_calculator
- SESSION_SECRET=your_docker_secret_key
- ADMIN_EMAIL=admin@example.com
ports:
- "5000:5000"
nginx:
image: nginx:1.21
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/ssl:/etc/nginx/ssl
- ./static:/app/static
- ./react-ecl-calculator/build:/app/react
depends_on:
- web
restart: always
volumes:
postgres_data:
Create the Nginx configuration:
mkdir -p nginx/conf
nano nginx/conf/default.conf
Add the following configuration:
server {
listen 80;
server_name localhost;
location /static {
alias /app/static;
expires 30d;
}
location /react {
alias /app/react;
try_files $uri $uri/ /react/index.html;
expires 30d;
}
location / {
proxy_pass http://web:5000;
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;
}
}
cd react-ecl-calculator
npm install
npm run build
cd ..
docker-compose up -d
docker-compose exec web python create_demo_admin.py
docker-compose down
For scaling in production, you may want to separate the database into its own managed service (like AWS RDS or Azure Database for PostgreSQL) rather than running it in a container.
Create a directory for Kubernetes manifests:
mkdir -p kubernetes
cat > kubernetes/namespace.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
name: ecl-calculator
EOF
cat > kubernetes/configmap.yaml << EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: ecl-calculator-config
namespace: ecl-calculator
data:
FLASK_APP: "main.py"
FLASK_ENV: "production"
ADMIN_EMAIL: "admin@example.com"
EOF
cat > kubernetes/secret.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
name: ecl-calculator-secrets
namespace: ecl-calculator
type: Opaque
data:
DATABASE_URL: BASE64_ENCODED_DB_URL
SESSION_SECRET: BASE64_ENCODED_SECRET
EOF
Replace BASE64_ENCODED_* with the actual base64-encoded values:
echo -n "postgresql://ecl_user:your_password@postgres-service/ecl_calculator" | base64
echo -n "your_kubernetes_secret_key" | base64
cat > kubernetes/postgres-pv.yaml << EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: ecl-calculator
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
EOF
cat > kubernetes/postgres-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: ecl-calculator
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:13
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: ecl_calculator
- name: POSTGRES_USER
value: ecl_user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: ecl-calculator-secrets
key: POSTGRES_PASSWORD
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
EOF
cat > kubernetes/postgres-service.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: postgres-service
namespace: ecl-calculator
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
EOF
cat > kubernetes/web-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: ecl-calculator
namespace: ecl-calculator
spec:
replicas: 3
selector:
matchLabels:
app: ecl-calculator
template:
metadata:
labels:
app: ecl-calculator
spec:
containers:
- name: ecl-calculator
image: your-docker-registry/ecl-calculator:latest
ports:
- containerPort: 5000
envFrom:
- configMapRef:
name: ecl-calculator-config
- secretRef:
name: ecl-calculator-secrets
readinessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 15
periodSeconds: 20
EOF
cat > kubernetes/web-service.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: ecl-calculator-service
namespace: ecl-calculator
spec:
selector:
app: ecl-calculator
ports:
- port: 80
targetPort: 5000
type: ClusterIP
EOF
cat > kubernetes/ingress.yaml << EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ecl-calculator-ingress
namespace: ecl-calculator
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- ecl-calculator.example.com
secretName: ecl-calculator-tls
rules:
- host: ecl-calculator.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ecl-calculator-service
port:
number: 80
EOF
# Build the image
docker build -t your-docker-registry/ecl-calculator:latest .
# Push to registry
docker push your-docker-registry/ecl-calculator:latest
kubectl apply -f kubernetes/namespace.yaml
kubectl apply -f kubernetes/configmap.yaml
kubectl apply -f kubernetes/secret.yaml
kubectl apply -f kubernetes/postgres-pv.yaml
kubectl apply -f kubernetes/postgres-deployment.yaml
kubectl apply -f kubernetes/postgres-service.yaml
kubectl apply -f kubernetes/web-deployment.yaml
kubectl apply -f kubernetes/web-service.yaml
kubectl apply -f kubernetes/ingress.yaml
kubectl get pods -n ecl-calculator
kubectl get services -n ecl-calculator
kubectl get ingress -n ecl-calculator
kubectl exec -it -n ecl-calculator \
$(kubectl get pods -n ecl-calculator -l app=ecl-calculator -o jsonpath="{.items[0].metadata.name}") \
-- python create_demo_admin.py
Create a GitHub Actions workflow file:
mkdir -p .github/workflows
nano .github/workflows/ci-cd.yml
Add the following content:
name: ECL Calculator CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:13
env:
POSTGRES_USER: ecl_user
POSTGRES_PASSWORD: postgres
POSTGRES_DB: ecl_calculator_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install pytest pytest-cov
- name: Test with pytest
env:
DATABASE_URL: postgresql://ecl_user:postgres@localhost/ecl_calculator_test
SESSION_SECRET: github_actions_secret
run: |
pytest --cov=./ --cov-report=xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
build:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Build React app
run: |
cd react-ecl-calculator
npm install
npm run build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: your-docker-registry/ecl-calculator:latest
deploy:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- name: Install kubectl
uses: azure/setup-kubectl@v1
- name: Set Kubernetes context
uses: azure/k8s-set-context@v1
with:
kubeconfig: ${{ secrets.KUBE_CONFIG }}
- name: Deploy to Kubernetes
run: |
kubectl apply -f kubernetes/web-deployment.yaml
kubectl rollout restart deployment/ecl-calculator -n ecl-calculator
Create a Jenkinsfile in the project root:
pipeline {
agent {
docker {
image 'python:3.9'
}
}
environment {
DATABASE_URL = credentials('ecl-calculator-db-url')
SESSION_SECRET = credentials('ecl-calculator-session-secret')
}
stages {
stage('Build') {
steps {
sh 'pip install -r requirements.txt'
sh 'cd react-ecl-calculator && npm install && npm run build'
}
}
stage('Test') {
steps {
sh 'pip install pytest pytest-cov'
sh 'python -m pytest --cov=./ --cov-report=xml'
}
}
stage('Build and Push Docker Image') {
when {
branch 'main'
}
steps {
script {
docker.withRegistry('https://registry.example.com', 'docker-credentials') {
def customImage = docker.build("your-registry/ecl-calculator:${env.BUILD_ID}")
customImage.push()
customImage.push('latest')
}
}
}
}
stage('Deploy to Production') {
when {
branch 'main'
}
steps {
withKubeConfig([credentialsId: 'kubeconfig']) {
sh 'kubectl apply -f kubernetes/web-deployment.yaml'
sh 'kubectl rollout restart deployment/ecl-calculator -n ecl-calculator'
}
}
}
}
post {
always {
junit 'test-results/*.xml'
publishHTML(target: [
allowMissing: false,
alwaysLinkToLastBuild: false,
keepAll: true,
reportDir: 'coverage',
reportFiles: 'index.html',
reportName: 'Coverage Report'
])
}
}
}
If using AWS CodePipeline, create a buildspec.yml file:
version: 0.2
phases:
install:
runtime-versions:
python: 3.9
nodejs: 14
commands:
- npm install -g npm@latest
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
- pip install -r requirements.txt
- cd react-ecl-calculator && npm install && npm run build && cd ..
- pip install pytest pytest-cov
- python -m pytest
build:
commands:
- echo Building the Docker image...
- docker build -t $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ecl-calculator:latest .
- docker tag $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ecl-calculator:latest $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ecl-calculator:$CODEBUILD_RESOLVED_SOURCE_VERSION
post_build:
commands:
- echo Pushing the Docker image...
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ecl-calculator:latest
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ecl-calculator:$CODEBUILD_RESOLVED_SOURCE_VERSION
- echo Writing image definitions file...
- echo "{\"ImageURI\":\"$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ecl-calculator:$CODEBUILD_RESOLVED_SOURCE_VERSION\"}" > imageDefinition.json
artifacts:
files:
- imageDefinition.json
- appspec.yml
- taskdef.json
Set up application logging in your main.py or app.py file:
import logging
import os
from logging.handlers import RotatingFileHandler
def setup_logging(app):
log_level = os.environ.get('LOG_LEVEL', 'INFO')
log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
log_dir = 'logs'
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# File handler for all logs
file_handler = RotatingFileHandler(
os.path.join(log_dir, 'ecl-calculator.log'),
maxBytes=10485760, # 10MB
backupCount=10
)
file_handler.setFormatter(logging.Formatter(log_format))
# Error log handler
error_handler = RotatingFileHandler(
os.path.join(log_dir, 'error.log'),
maxBytes=10485760, # 10MB
backupCount=10
)
error_handler.setLevel(logging.ERROR)
error_handler.setFormatter(logging.Formatter(log_format))
# Set up root logger
root_logger = logging.getLogger()
root_logger.setLevel(getattr(logging, log_level))
root_logger.addHandler(file_handler)
root_logger.addHandler(error_handler)
# Set up app logger if Flask app is provided
if app:
app.logger.setLevel(getattr(logging, log_level))
app.logger.addHandler(file_handler)
app.logger.addHandler(error_handler)
app.logger.info('Application logging initialized')
Enable detailed access and error logs in Nginx:
server {
# ... other configuration ...
access_log /var/log/nginx/ecl-calculator-access.log;
error_log /var/log/nginx/ecl-calculator-error.log;
# ... rest of configuration ...
}
Set up log rotation for Nginx logs:
sudo nano /etc/logrotate.d/ecl-calculator
Add the following:
/var/log/nginx/ecl-calculator-*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
/usr/bin/systemctl reload nginx
endscript
}
Install Prometheus client for Python:
pip install prometheus-client
Add Prometheus metrics to your application:
from prometheus_client import Counter, Histogram, start_http_server
import time
# Create metrics
REQUEST_COUNT = Counter(
'request_count', 'App Request Count',
['app_name', 'method', 'endpoint', 'http_status']
)
REQUEST_LATENCY = Histogram(
'request_latency_seconds', 'Request latency',
['app_name', 'method', 'endpoint']
)
# Set up a Flask middleware to collect metrics
@app.before_request
def start_timer():
g.start = time.time()
@app.after_request
def record_request(response):
request_latency = time.time() - g.start
REQUEST_LATENCY.labels(
'ecl_calculator',
request.method,
request.path
).observe(request_latency)
REQUEST_COUNT.labels(
'ecl_calculator',
request.method,
request.path,
response.status_code
).inc()
return response
# Start Prometheus HTTP server on port 8000
start_http_server(8000)
Set up a basic Grafana dashboard to visualize Prometheus metrics.
Add a health check endpoint to your Flask application:
@app.route('/health')
def health_check():
try:
# Check database connection
db.session.execute('SELECT 1')
return jsonify(status='ok'), 200
except Exception as e:
app.logger.error(f"Health check failed: {str(e)}")
return jsonify(status='error', message=str(e)), 500
Create a script for automated PostgreSQL backups:
#!/bin/bash
# backup.sh
# Configuration
BACKUP_DIR="/path/to/backups"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
PGUSER="ecl_user"
PGPASSWORD="your_production_password"
DATABASE="ecl_calculator"
RETENTION_DAYS=14
# Create backup directory if it doesn't exist
mkdir -p $BACKUP_DIR
# Create the backup
pg_dump -U $PGUSER $DATABASE | gzip > $BACKUP_DIR/ecl_calculator_$TIMESTAMP.sql.gz
# Delete old backups
find $BACKUP_DIR -name "ecl_calculator_*.sql.gz" -type f -mtime +$RETENTION_DAYS -delete
Set up a cron job to run the backup script:
sudo crontab -e
Add this line to run the backup daily at 2 AM:
0 2 * * * /path/to/backup.sh
#!/bin/bash
# restore.sh
# Configuration
BACKUP_FILE=$1
PGUSER="ecl_user"
PGPASSWORD="your_production_password"
DATABASE="ecl_calculator"
# Check if backup file is provided
if [ -z "$BACKUP_FILE" ]; then
echo "Usage: $0 "
exit 1
fi
# Check if backup file exists
if [ ! -f "$BACKUP_FILE" ]; then
echo "Backup file not found: $BACKUP_FILE"
exit 1
fi
# Create a temporary database
psql -U $PGUSER -c "DROP DATABASE IF EXISTS ${DATABASE}_restore"
psql -U $PGUSER -c "CREATE DATABASE ${DATABASE}_restore"
# Restore to the temporary database
if [[ "$BACKUP_FILE" == *.gz ]]; then
gunzip -c "$BACKUP_FILE" | psql -U $PGUSER -d ${DATABASE}_restore
else
psql -U $PGUSER -d ${DATABASE}_restore -f "$BACKUP_FILE"
fi
# If successful, swap the databases
if [ $? -eq 0 ]; then
echo "Restore to temporary database successful. Swapping databases..."
# Disconnect all clients
psql -U $PGUSER -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$DATABASE'"
psql -U $PGUSER -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '${DATABASE}_restore'"
# Rename databases
psql -U $PGUSER -c "ALTER DATABASE $DATABASE RENAME TO ${DATABASE}_old"
psql -U $PGUSER -c "ALTER DATABASE ${DATABASE}_restore RENAME TO $DATABASE"
# Drop old database
psql -U $PGUSER -c "DROP DATABASE ${DATABASE}_old"
echo "Restore completed successfully"
else
echo "Restore failed!"
psql -U $PGUSER -c "DROP DATABASE ${DATABASE}_restore"
exit 1
fi
Back up the entire application directory:
tar -czvf /path/to/backups/ecl-calculator-app-$(date +"%Y%m%d").tar.gz /path/to/ecl-calculator
Symptoms: Application fails to start with database connection errors
Solutions:
sudo systemctl status postgresqlsudo -u postgres psql -c '\du'nc -zv <db_host> <db_port>Symptoms: Gunicorn fails to start the application
Solutions:
sudo journalctl -u ecl-calculator -n 100pip listflask runpython -m py_compile main.pySymptoms: "502 Bad Gateway" or "504 Gateway Timeout" errors
Solutions:
sudo tail -f /var/log/nginx/error.logsudo nginx -tps aux | grep gunicorncurl -v http://localhost:5000/healthSymptoms: Frontend not loading or displaying errors
Solutions:
curl -v http://your-domain.com/api/auth/usernpm run buildSymptoms: Slow application response or timeouts
Solutions:
top, free -m, df -hps aux | grep gunicorn | wc -l--workers=2*CPU_CORES+1| Command | Purpose |
|---|---|
sudo systemctl status ecl-calculator |
Check application service status |
sudo journalctl -u ecl-calculator -f |
Real-time application logs |
sudo tail -f /var/log/nginx/error.log |
Nginx error logs |
sudo -u postgres psql -c 'SELECT now();' |
Verify PostgreSQL is running |
docker-compose logs -f |
Check Docker container logs |
kubectl logs -f deployment/ecl-calculator -n ecl-calculator |
Check Kubernetes pod logs |
Security is an ongoing process, not a one-time task. Regularly review your security measures, monitor for new vulnerabilities, and update your application and infrastructure accordingly.