Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 29 additions & 128 deletions hetzner/deploy.sh
Original file line number Diff line number Diff line change
@@ -1,150 +1,51 @@
#!/bin/bash
set -e

# Parse --yes / -y so script can run non-interactively
AUTO_YES=false
ARGS=()
for a in "$@"; do
if [[ "$a" == "--yes" || "$a" == "-y" ]]; then
AUTO_YES=true
else
ARGS+=("$a")
fi
[[ "$a" == "--yes" || "$a" == "-y" ]] && AUTO_YES=true || ARGS+=("$a")
done

ACTION=${ARGS[0]}
SERVICE=${ARGS[1]}
ENVIRONMENT=${ARGS[2]:-staging}
ENVIRONMENT=${ARGS[2]}

# Check if first arg is an action (start/stop/restart)
if [ "$ACTION" = "start" ] || [ "$ACTION" = "stop" ] || [ "$ACTION" = "restart" ]; then
# First arg is an action, so SERVICE is $2
if [ -z "$SERVICE" ]; then
echo "Usage: $0 [--yes|-y] start|stop|restart <service> [staging|production]"
echo "Example: $0 start taginfo staging"
exit 1
fi
fi

if [ -z "$SERVICE" ]; then
echo "Usage: $0 [--yes|-y] [start|stop|restart] <service> [staging|production]"
echo " --yes, -y Skip confirmation prompts"
echo "Examples:"
echo " $0 taginfo staging # Start service"
echo " $0 --yes start taginfo production # Start without prompting"
echo " $0 stop taginfo staging # Stop service"
echo " $0 restart taginfo staging # Restart service"
if [ -z "$SERVICE" ] || [ -z "$ENVIRONMENT" ]; then
echo "Usage: $0 [--yes|-y] start|stop|restart <service> staging|production"
echo "Example: $0 start taginfo staging"
exit 1
fi

SERVICE_DIR="$(cd "$(dirname "$0")" && pwd)/$SERVICE"
BASE_FILE="$SERVICE_DIR/$SERVICE.base.yml"
ENV_FILE="$SERVICE_DIR/$SERVICE.$ENVIRONMENT.yml"

# Load environment variables from .env.traefik
HETZNER_DIR="$(cd "$(dirname "$0")" && pwd)"
if [ -f "$HETZNER_DIR/.env.traefik" ]; then
export $(grep -v '^#' "$HETZNER_DIR/.env.traefik" | xargs)
fi
BASE_FILE="$HETZNER_DIR/$SERVICE/$SERVICE.base.yml"
ENV_FILE="$HETZNER_DIR/$SERVICE/$SERVICE.$ENVIRONMENT.yml"

# For staging, only use base file. For production, use base + environment file
if [ "$ENVIRONMENT" = "staging" ]; then
COMPOSE_CMD="docker compose -f $BASE_FILE"
[ -f "$HETZNER_DIR/.env.traefik" ] && export $(grep -v '^#' "$HETZNER_DIR/.env.traefik" | xargs)

if [ -f "$ENV_FILE" ]; then
COMPOSE="docker compose -f $BASE_FILE -f $ENV_FILE"
else
COMPOSE_CMD="docker compose -f $BASE_FILE -f $ENV_FILE"
COMPOSE="docker compose -f $BASE_FILE"
fi

echo "================================================"
echo "Action: $ACTION"
echo "Service: $SERVICE"
echo "Environment: $ENVIRONMENT"
echo "Command: $COMPOSE_CMD"
echo "================================================"
echo "==> $ACTION $SERVICE ($ENVIRONMENT)"

# Confirm before start/restart (skip with --yes)
if [[ "$ACTION" == "start" || "$ACTION" == "restart" ]] && [ "$AUTO_YES" != "true" ]; then
[ "$ENVIRONMENT" = "production" ] && echo "WARNING: Deploying to PRODUCTION"
echo ""
$COMPOSE config
echo ""
read -p "Continue? (yes/no): " confirm
[ "$confirm" != "yes" ] && echo "Cancelled." && exit 0
fi

case "$ACTION" in
start)
# Show merged configuration before deploying
echo ""
echo "Preview of merged configuration:"
echo "================================================"

# Try to use colored output if available
if command -v bat &> /dev/null; then
$COMPOSE_CMD config | bat --language yaml --style=plain
elif command -v pygmentize &> /dev/null; then
$COMPOSE_CMD config | pygmentize -l yaml
elif command -v highlight &> /dev/null; then
$COMPOSE_CMD config | highlight --out-format=ansi --syntax=yaml
else
# Fallback: use basic colors with grep/awk
$COMPOSE_CMD config | while IFS= read -r line; do
if [[ "$line" =~ ^[[:space:]]*# ]]; then
# Comments in gray
echo -e "\033[0;90m$line\033[0m"
elif [[ "$line" =~ ^[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*: ]]; then
# Keys in yellow
key=$(echo "$line" | sed 's/:.*//')
rest=$(echo "$line" | sed 's/^[^:]*://')
echo -e "\033[0;33m$key\033[0m:\033[0;36m$rest\033[0m"
elif [[ "$line" =~ ^[[:space:]]*- ]]; then
# List items in cyan
echo -e "\033[0;36m$line\033[0m"
else
echo "$line"
fi
done
fi

echo "================================================"
echo ""

# Ask for confirmation (skip if --yes/-y)
if [ "$AUTO_YES" != "true" ]; then
if [ "$ENVIRONMENT" = "production" ]; then
echo "⚠️ WARNING: You are about to deploy to PRODUCTION"
echo ""
read -p "Do you want to continue? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "Deployment cancelled."
exit 0
fi
else
read -p "Do you want to continue with deployment? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "Deployment cancelled."
exit 0
fi
fi
fi

echo ""
echo "Starting deployment..."
$COMPOSE_CMD up -d
echo ""
echo "✓ Service started: $SERVICE ($ENVIRONMENT)"
echo ""
echo "================================================"
echo "Useful commands:"
echo "================================================"
echo ""
echo "# List running containers for this service:"
echo "docker ps | grep ${SERVICE}"
echo "docker exec -it ${SERVICE}_${ENVIRONMENT} bash"
echo ""
echo "# View logs:"
echo "$COMPOSE_CMD logs -f"
echo ""
;;
stop)
$COMPOSE_CMD down
echo "Service stopped: $SERVICE ($ENVIRONMENT)"
;;
restart)
$COMPOSE_CMD restart
echo "Service restarted: $SERVICE ($ENVIRONMENT)"
;;
*)
echo "Unknown action: $ACTION"
exit 1
;;
start) $COMPOSE up -d ;;
stop) $COMPOSE down ;;
restart) $COMPOSE up -d --force-recreate ;;
*) echo "Unknown action: $ACTION"; exit 1 ;;
esac

echo "Done: $ACTION $SERVICE ($ENVIRONMENT)"
14 changes: 9 additions & 5 deletions hetzner/osmcha/osmcha.base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ services:
image: postgis/postgis:17-3.5
container_name: osmcha-db
restart: always
env_file: ./.env.osmcha
env_file:
- ./.env.osmcha
volumes:
- osmcha_db_data:/var/lib/postgresql/data
- ./data_backup:/data_backup
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
test: ["CMD-SHELL", "pg_isready"]
interval: 5s
timeout: 5s
retries: 10
Expand All @@ -30,7 +31,8 @@ services:
python manage.py migrate &&
python manage.py collectstatic --noinput
"
env_file: ./.env.osmcha
env_file:
- ./.env.osmcha
volumes:
- staticfiles:/app/staticfiles
depends_on:
Expand All @@ -47,7 +49,8 @@ services:
command: gunicorn config.wsgi -b 0.0.0.0:5000 --access-logfile - --timeout 120 --workers 4 --threads 16
# ports:
# - "5100:5000"
env_file: ./.env.osmcha
env_file:
- ./.env.osmcha
volumes:
- staticfiles:/staticfiles
depends_on:
Expand Down Expand Up @@ -76,7 +79,8 @@ services:
osmcha-cron:
container_name: osmcha-cron
image: ghcr.io/openhistoricalmap/osmcha-django:1bd58e1
env_file: ./.env.osmcha
env_file:
- ./.env.osmcha
depends_on:
osmcha-db:
condition: service_healthy
Expand Down
10 changes: 5 additions & 5 deletions hetzner/osmcha/osmcha.production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ services:
volumes:
- ohmx_db:/data
- ${HOME}/.aws:/root/.aws:ro
- /production/services/images/ohmx-adiff-builder/config.sh:/app/config.sh
- /production/services/images/ohmx-adiff-builder/functions.sh:/app/functions.sh
- /production/services/images/ohmx-adiff-builder/start.sh:/app/start.sh
- /production/services/images/ohmx-adiff-builder/process_min_range.sh:/app/process_min_range.sh
- /production/services/images/ohmx-adiff-builder/update.sh:/app/update.sh
- ${PWD}/images/ohmx-adiff-builder/config.sh:/app/config.sh
- ${PWD}/images/ohmx-adiff-builder/functions.sh:/app/functions.sh
- ${PWD}/images/ohmx-adiff-builder/start.sh:/app/start.sh
- ${PWD}/images/ohmx-adiff-builder/process_min_range.sh:/app/process_min_range.sh
- ${PWD}/images/ohmx-adiff-builder/update.sh:/app/update.sh
networks:
- ohm_network
cpus: '8.0'
Expand Down
2 changes: 1 addition & 1 deletion hetzner/overpass/overpass.base.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
overpass:
image: developmentseed/osmseed-overpass-api:0.1.0-0.dev.git.956.h49d677b
image: ghcr.io/osm-seed/overpass-api:0.1.0-0.dev.git.985.h3b10440
container_name: overpass
# ports:
# - '8085:80'
Expand Down
20 changes: 18 additions & 2 deletions hetzner/start_all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,20 @@ set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

ENVIRONMENT=${ENVIRONMENT:-staging}
ENVIRONMENT=${ENVIRONMENT}

# Validate ENVIRONMENT is set and is either staging or production
if [ -z "$ENVIRONMENT" ]; then
echo ""
echo "Need to set ENVIRONMENT variable:"
echo " export ENVIRONMENT=staging"
echo " export ENVIRONMENT=production"
exit 1
fi

echo "########################## ENVIRONMENT -> $ENVIRONMENT ##########################"

# Load environment variables from .env.traefik
# Load environment variables from .env.traefik, make sure the domain is set
source "$SCRIPT_DIR/.env.traefik"
echo "########################## OHM_DOMAIN -> $OHM_DOMAIN ##########################"

Expand Down Expand Up @@ -38,3 +49,8 @@ if [ "$ENVIRONMENT" = "staging" ]; then
docker stop tiler_db
docker stop tiler_imposm
fi

## In production we need to clean the tiler cache
docker stop tiler_s3_cleaner
## clean tiler cache
# docker compose -f hetzner/tiler/tiler.base.yml -f hetzner/tiler/tiler.production.yml run tiler_s3_cleaner tiler-cache-cleaner clean_by_prefix
6 changes: 2 additions & 4 deletions hetzner/taginfo/taginfo.base.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
services:
taginfo_web:
container_name: taginfo_web
image: ghcr.io/osm-seed/taginfo-web:0.1.0-0.dev.git.983.h32750c8
volumes:
- ${HOME}/data/staging/taginfo_data:/usr/src/app/data
image: ghcr.io/osm-seed/taginfo-web:0.1.0-0.dev.git.986.h0fae372
env_file:
- ./.env.sample
- ./.env.taginfo
restart: always
networks:
- ohm_network
Expand Down
26 changes: 19 additions & 7 deletions hetzner/taginfo/taginfo.production.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
services:

taginfo_data:
container_name: taginfo_data
image: ghcr.io/osm-seed/taginfo:0.1.0-0.dev.git.984.hb289ff1
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${HOME}/data/production/taginfo_data:/usr/src/app/data
- ${HOME}/data/production/taginfo_data_planet:/osm/planet/var
environment:
- AWS_S3_BUCKET=planet.openhistoricalmap.org
- DOCKER_CONFIG_ENVIRONMENT=production
command:
- /bin/bash
- -lc
- |
set -ex
# Run every 3 days at 3:00 AM
echo "0 3 1-31/3 * * /usr/src/app/start.sh >> /var/log/taginfo-cron.log 2>&1" > /tmp/cron_logs
crontab /tmp/cron_logs
echo "#!/bin/bash
/usr/src/app/start.sh
sleep 7200
# restart web container
curl -X POST --unix-socket /var/run/docker.sock http://v1.41/containers/taginfo_web/restart" > /run_task.sh
chmod +x /run_task.sh

# 2. Set cron: Run every 3 days at 3:00 AM
echo "0 3 */3 * * /run_task.sh >> /var/log/taginfo-cron.log 2>&1" | crontab -

touch /var/log/taginfo-cron.log
cron -f

taginfo_web:
volumes:
- ${HOME}/data/production/taginfo_data_proceced:/usr/src/app/data
env_file:
- ./.env.taginfo
networks:
- ohm_network
Loading
Loading