#!/bin/bash
# post-receive hook on your bare Git repository # The bare repository is usually at /var/repo/myproject.-weight: 500;">git
# The working directory for your application is at /var/www/myproject # Git hook variables
read oldrev newrev refname # Ensure we're pushing to the main branch
if [ "$refname" = "refs/heads/main" ]; then echo "Push received for main branch. Deploying..." cd /var/www/myproject || exit # Pull the latest changes unset GIT_DIR # Important for non-bare repo operations -weight: 500;">git pull origin main # Install dependencies (if any) /usr/bin/-weight: 500;">pip -weight: 500;">install -r requirements.txt # Run database migrations (if any) /usr/bin/python manage.py migrate # Restart the application -weight: 500;">service /usr/bin/-weight: 500;">systemctl -weight: 500;">restart myproject-backend.-weight: 500;">service echo "Deployment complete for main branch."
else echo "Push received for $refname. No deployment triggered."
fi
#!/bin/bash
# post-receive hook on your bare Git repository # The bare repository is usually at /var/repo/myproject.-weight: 500;">git
# The working directory for your application is at /var/www/myproject # Git hook variables
read oldrev newrev refname # Ensure we're pushing to the main branch
if [ "$refname" = "refs/heads/main" ]; then echo "Push received for main branch. Deploying..." cd /var/www/myproject || exit # Pull the latest changes unset GIT_DIR # Important for non-bare repo operations -weight: 500;">git pull origin main # Install dependencies (if any) /usr/bin/-weight: 500;">pip -weight: 500;">install -r requirements.txt # Run database migrations (if any) /usr/bin/python manage.py migrate # Restart the application -weight: 500;">service /usr/bin/-weight: 500;">systemctl -weight: 500;">restart myproject-backend.-weight: 500;">service echo "Deployment complete for main branch."
else echo "Push received for $refname. No deployment triggered."
fi
#!/bin/bash
# post-receive hook on your bare Git repository # The bare repository is usually at /var/repo/myproject.-weight: 500;">git
# The working directory for your application is at /var/www/myproject # Git hook variables
read oldrev newrev refname # Ensure we're pushing to the main branch
if [ "$refname" = "refs/heads/main" ]; then echo "Push received for main branch. Deploying..." cd /var/www/myproject || exit # Pull the latest changes unset GIT_DIR # Important for non-bare repo operations -weight: 500;">git pull origin main # Install dependencies (if any) /usr/bin/-weight: 500;">pip -weight: 500;">install -r requirements.txt # Run database migrations (if any) /usr/bin/python manage.py migrate # Restart the application -weight: 500;">service /usr/bin/-weight: 500;">systemctl -weight: 500;">restart myproject-backend.-weight: 500;">service echo "Deployment complete for main branch."
else echo "Push received for $refname. No deployment triggered."
fi
version: '3.8' services: web: build: . ports: - "8000:8000" volumes: - .:/app environment: DATABASE_URL: postgres://user:password@db:5432/mydatabase REDIS_URL: redis://redis:6379/0 depends_on: - db - redis # Add resource limits for side projects to prevent runaway processes deploy: resources: limits: memory: 512M reservations: memory: 256M -weight: 500;">restart: always db: image: postgres:14-alpine environment: POSTGRES_DB: mydatabase POSTGRES_USER: user POSTGRES_PASSWORD: password volumes: - pgdata:/var/lib/postgresql/data deploy: resources: limits: memory: 1G reservations: memory: 512M -weight: 500;">restart: always redis: image: redis:7-alpine deploy: resources: limits: memory: 256M reservations: memory: 128M -weight: 500;">restart: always volumes: pgdata:
version: '3.8' services: web: build: . ports: - "8000:8000" volumes: - .:/app environment: DATABASE_URL: postgres://user:password@db:5432/mydatabase REDIS_URL: redis://redis:6379/0 depends_on: - db - redis # Add resource limits for side projects to prevent runaway processes deploy: resources: limits: memory: 512M reservations: memory: 256M -weight: 500;">restart: always db: image: postgres:14-alpine environment: POSTGRES_DB: mydatabase POSTGRES_USER: user POSTGRES_PASSWORD: password volumes: - pgdata:/var/lib/postgresql/data deploy: resources: limits: memory: 1G reservations: memory: 512M -weight: 500;">restart: always redis: image: redis:7-alpine deploy: resources: limits: memory: 256M reservations: memory: 128M -weight: 500;">restart: always volumes: pgdata:
version: '3.8' services: web: build: . ports: - "8000:8000" volumes: - .:/app environment: DATABASE_URL: postgres://user:password@db:5432/mydatabase REDIS_URL: redis://redis:6379/0 depends_on: - db - redis # Add resource limits for side projects to prevent runaway processes deploy: resources: limits: memory: 512M reservations: memory: 256M -weight: 500;">restart: always db: image: postgres:14-alpine environment: POSTGRES_DB: mydatabase POSTGRES_USER: user POSTGRES_PASSWORD: password volumes: - pgdata:/var/lib/postgresql/data deploy: resources: limits: memory: 1G reservations: memory: 512M -weight: 500;">restart: always redis: image: redis:7-alpine deploy: resources: limits: memory: 256M reservations: memory: 128M -weight: 500;">restart: always volumes: pgdata:
name: CI for My Side Project on: push: branches: - main pull_request: branches: - main jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.10' - name: Install dependencies run: | python -m -weight: 500;">pip -weight: 500;">install ---weight: 500;">upgrade -weight: 500;">pip -weight: 500;">pip -weight: 500;">install -r requirements.txt - name: Run Flake8 Linter run: | -weight: 500;">pip -weight: 500;">install flake8 flake8 . --max-line-length=120 --exclude .-weight: 500;">git,__pycache__,venv - name: Run Pytest run: | -weight: 500;">pip -weight: 500;">install pytest pytest
name: CI for My Side Project on: push: branches: - main pull_request: branches: - main jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.10' - name: Install dependencies run: | python -m -weight: 500;">pip -weight: 500;">install ---weight: 500;">upgrade -weight: 500;">pip -weight: 500;">pip -weight: 500;">install -r requirements.txt - name: Run Flake8 Linter run: | -weight: 500;">pip -weight: 500;">install flake8 flake8 . --max-line-length=120 --exclude .-weight: 500;">git,__pycache__,venv - name: Run Pytest run: | -weight: 500;">pip -weight: 500;">install pytest pytest
name: CI for My Side Project on: push: branches: - main pull_request: branches: - main jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.10' - name: Install dependencies run: | python -m -weight: 500;">pip -weight: 500;">install ---weight: 500;">upgrade -weight: 500;">pip -weight: 500;">pip -weight: 500;">install -r requirements.txt - name: Run Flake8 Linter run: | -weight: 500;">pip -weight: 500;">install flake8 flake8 . --max-line-length=120 --exclude .-weight: 500;">git,__pycache__,venv - name: Run Pytest run: | -weight: 500;">pip -weight: 500;">install pytest pytest
#!/bin/bash
# Simple Blue-Green style deploy script APP_DIR="/var/www/myproject"
CURRENT_RELEASE_DIR="$APP_DIR/current"
RELEASE_DIR_A="$APP_DIR/releases/release_a"
RELEASE_DIR_B="$APP_DIR/releases/release_b"
GIT_REPO="/var/repo/myproject.-weight: 500;">git" # Determine which release directory is currently active
if [ -L "$CURRENT_RELEASE_DIR" ] && [ "$(readlink "$CURRENT_RELEASE_DIR")" == "$RELEASE_DIR_A" ]; then TARGET_RELEASE_DIR="$RELEASE_DIR_B" OLD_RELEASE_DIR="$RELEASE_DIR_A"
else TARGET_RELEASE_DIR="$RELEASE_DIR_A" OLD_RELEASE_DIR="$RELEASE_DIR_B"
fi echo "Deploying to $TARGET_RELEASE_DIR" # Clean target directory and clone/pull latest code
rm -rf "$TARGET_RELEASE_DIR"/*
mkdir -p "$TARGET_RELEASE_DIR"
-weight: 500;">git clone "$GIT_REPO" "$TARGET_RELEASE_DIR" # Or -weight: 500;">git pull if directory exists and is a repo cd "$TARGET_RELEASE_DIR" || exit # Install dependencies, run migrations, build frontend etc.
/usr/bin/-weight: 500;">pip -weight: 500;">install -r requirements.txt
/usr/bin/python manage.py migrate --noinput
-weight: 500;">npm -weight: 500;">install && -weight: 500;">npm run build # If you have a frontend # Test if the new version is working (e.g., health check)
# A simple -weight: 500;">curl to a health endpoint could work here
# -weight: 500;">curl -f http://localhost:8001/health || { echo "Health check failed!"; exit 1; } # Switch the symlink
ln -snf "$TARGET_RELEASE_DIR" "$CURRENT_RELEASE_DIR"
echo "Switched to new release: $(readlink "$CURRENT_RELEASE_DIR")" # Restart application -weight: 500;">service (using systemd for example)
/usr/bin/-weight: 500;">systemctl -weight: 500;">restart myproject-backend.-weight: 500;">service echo "Deployment finished. Old release is in $OLD_RELEASE_DIR for rollback."
#!/bin/bash
# Simple Blue-Green style deploy script APP_DIR="/var/www/myproject"
CURRENT_RELEASE_DIR="$APP_DIR/current"
RELEASE_DIR_A="$APP_DIR/releases/release_a"
RELEASE_DIR_B="$APP_DIR/releases/release_b"
GIT_REPO="/var/repo/myproject.-weight: 500;">git" # Determine which release directory is currently active
if [ -L "$CURRENT_RELEASE_DIR" ] && [ "$(readlink "$CURRENT_RELEASE_DIR")" == "$RELEASE_DIR_A" ]; then TARGET_RELEASE_DIR="$RELEASE_DIR_B" OLD_RELEASE_DIR="$RELEASE_DIR_A"
else TARGET_RELEASE_DIR="$RELEASE_DIR_A" OLD_RELEASE_DIR="$RELEASE_DIR_B"
fi echo "Deploying to $TARGET_RELEASE_DIR" # Clean target directory and clone/pull latest code
rm -rf "$TARGET_RELEASE_DIR"/*
mkdir -p "$TARGET_RELEASE_DIR"
-weight: 500;">git clone "$GIT_REPO" "$TARGET_RELEASE_DIR" # Or -weight: 500;">git pull if directory exists and is a repo cd "$TARGET_RELEASE_DIR" || exit # Install dependencies, run migrations, build frontend etc.
/usr/bin/-weight: 500;">pip -weight: 500;">install -r requirements.txt
/usr/bin/python manage.py migrate --noinput
-weight: 500;">npm -weight: 500;">install && -weight: 500;">npm run build # If you have a frontend # Test if the new version is working (e.g., health check)
# A simple -weight: 500;">curl to a health endpoint could work here
# -weight: 500;">curl -f http://localhost:8001/health || { echo "Health check failed!"; exit 1; } # Switch the symlink
ln -snf "$TARGET_RELEASE_DIR" "$CURRENT_RELEASE_DIR"
echo "Switched to new release: $(readlink "$CURRENT_RELEASE_DIR")" # Restart application -weight: 500;">service (using systemd for example)
/usr/bin/-weight: 500;">systemctl -weight: 500;">restart myproject-backend.-weight: 500;">service echo "Deployment finished. Old release is in $OLD_RELEASE_DIR for rollback."
#!/bin/bash
# Simple Blue-Green style deploy script APP_DIR="/var/www/myproject"
CURRENT_RELEASE_DIR="$APP_DIR/current"
RELEASE_DIR_A="$APP_DIR/releases/release_a"
RELEASE_DIR_B="$APP_DIR/releases/release_b"
GIT_REPO="/var/repo/myproject.-weight: 500;">git" # Determine which release directory is currently active
if [ -L "$CURRENT_RELEASE_DIR" ] && [ "$(readlink "$CURRENT_RELEASE_DIR")" == "$RELEASE_DIR_A" ]; then TARGET_RELEASE_DIR="$RELEASE_DIR_B" OLD_RELEASE_DIR="$RELEASE_DIR_A"
else TARGET_RELEASE_DIR="$RELEASE_DIR_A" OLD_RELEASE_DIR="$RELEASE_DIR_B"
fi echo "Deploying to $TARGET_RELEASE_DIR" # Clean target directory and clone/pull latest code
rm -rf "$TARGET_RELEASE_DIR"/*
mkdir -p "$TARGET_RELEASE_DIR"
-weight: 500;">git clone "$GIT_REPO" "$TARGET_RELEASE_DIR" # Or -weight: 500;">git pull if directory exists and is a repo cd "$TARGET_RELEASE_DIR" || exit # Install dependencies, run migrations, build frontend etc.
/usr/bin/-weight: 500;">pip -weight: 500;">install -r requirements.txt
/usr/bin/python manage.py migrate --noinput
-weight: 500;">npm -weight: 500;">install && -weight: 500;">npm run build # If you have a frontend # Test if the new version is working (e.g., health check)
# A simple -weight: 500;">curl to a health endpoint could work here
# -weight: 500;">curl -f http://localhost:8001/health || { echo "Health check failed!"; exit 1; } # Switch the symlink
ln -snf "$TARGET_RELEASE_DIR" "$CURRENT_RELEASE_DIR"
echo "Switched to new release: $(readlink "$CURRENT_RELEASE_DIR")" # Restart application -weight: 500;">service (using systemd for example)
/usr/bin/-weight: 500;">systemctl -weight: 500;">restart myproject-backend.-weight: 500;">service echo "Deployment finished. Old release is in $OLD_RELEASE_DIR for rollback."
[Unit]
Description=My Side Project Backend
After=network.target postgresql.-weight: 500;">service redis.-weight: 500;">service [Service]
User=myuser
WorkingDirectory=/var/www/myproject/current
ExecStart=/usr/bin/python /var/www/myproject/current/app.py
Restart=always
StandardOutput=journal
StandardError=journal
# Add memory limits for the -weight: 500;">service
MemoryHigh=256M
MemoryMax=512M [Install]
WantedBy=multi-user.target
[Unit]
Description=My Side Project Backend
After=network.target postgresql.-weight: 500;">service redis.-weight: 500;">service [Service]
User=myuser
WorkingDirectory=/var/www/myproject/current
ExecStart=/usr/bin/python /var/www/myproject/current/app.py
Restart=always
StandardOutput=journal
StandardError=journal
# Add memory limits for the -weight: 500;">service
MemoryHigh=256M
MemoryMax=512M [Install]
WantedBy=multi-user.target
[Unit]
Description=My Side Project Backend
After=network.target postgresql.-weight: 500;">service redis.-weight: 500;">service [Service]
User=myuser
WorkingDirectory=/var/www/myproject/current
ExecStart=/usr/bin/python /var/www/myproject/current/app.py
Restart=always
StandardOutput=journal
StandardError=journal
# Add memory limits for the -weight: 500;">service
MemoryHigh=256M
MemoryMax=512M [Install]
WantedBy=multi-user.target
# Dependency scanning step in CI/CD pipeline
-weight: 500;">pip -weight: 500;">install -weight: 500;">pip-audit
-weight: 500;">pip-audit -r requirements.txt
# Dependency scanning step in CI/CD pipeline
-weight: 500;">pip -weight: 500;">install -weight: 500;">pip-audit
-weight: 500;">pip-audit -r requirements.txt
# Example of rate limiting in Nginx
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s; server { # ... location /api/ { limit_req zone=mylimit burst=20 nodelay; # ... }
}
# Example of rate limiting in Nginx
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s; server { # ... location /api/ { limit_req zone=mylimit burst=20 nodelay; # ... }
}
# /etc/modprobe.d/blacklist.conf
blacklist algif_aead
# /etc/modprobe.d/blacklist.conf
blacklist algif_aead - Dependency Scanning: I check for known vulnerabilities in the libraries I use. The -weight: 500;">pip-audit tool is great for this in Python projects. # Dependency scanning step in CI/CD pipeline
-weight: 500;">pip -weight: 500;">install -weight: 500;">pip-audit
-weight: 500;">pip-audit -r requirements.txt This command scans all dependencies in the requirements.txt file against known CVEs and warns if any are found. In a production ERP, we realized a critical vulnerability in an old library too late, and it cost us dearly. Since then, I don't skip this step.
- Basic Security Configurations: At the application level, I follow best practices for rate limiting and JWT/OAuth2 patterns. If I use Nginx, I limit requests to my API with simple limit_req directives. # Example of rate limiting in Nginx
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s; server { # ... location /api/ { limit_req zone=mylimit burst=20 nodelay; # ... }
} This configuration limits requests to 10 per second from a specific IP and allows a "burst" of up to 20 requests. This is my first line of defense against simple DDoS attacks or excessive usage.
- Kernel Module Blacklisting: Rarely, some kernel modules can lead to security vulnerabilities or consume unnecessary resources. On my own VPS, I blacklist non-critical kernel modules like algif_aead to create an additional layer against potential vulnerabilities like CVE-2026-31431. # /etc/modprobe.d/blacklist.conf
blacklist algif_aead This is a small but effective step I take to improve overall system security.