#!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")/.." compose_file="${1:-docker-compose.yml}" env_file="${2:-.env}" app_port="${APP_PORT:-1226}" if ! command -v docker >/dev/null 2>&1; then echo "docker niet gevonden. Installeer Docker en probeer opnieuw." exit 1 fi if ! command -v python >/dev/null 2>&1; then echo "python niet gevonden. docker-deploy vereist python voor secrets." exit 1 fi if ! command -v curl >/dev/null 2>&1; then echo "curl niet gevonden; healthcheck wordt overgeslagen." export SKIP_HEALTHCHECK=1 fi if [[ ! -f "$env_file" ]]; then : > "$env_file" chmod 600 "$env_file" echo "Aangemaakte $env_file" fi generate_secret() { if command -v python >/dev/null 2>&1; then python scripts/generate_secret.py else date +%s | sha256sum | cut -d' ' -f1 fi } write_env() { local key="$1" local value="$2" local force="${3:-0}" local existing_line local existing_value existing_line="$(grep -m1 "^${key}=" "$env_file" || true)" if [[ -z "$existing_line" ]]; then printf '%s=%s\n' "$key" "$value" >> "$env_file" return fi existing_value="${existing_line#*=}" if [[ "$force" != "1" && -n "$existing_value" && \ "$existing_value" != CHANGE_ME* && \ "$existing_value" != dev-only-change-me && \ "$existing_value" != codex-local-only ]]; then return 0 fi local temp_env temp_env="$(mktemp)" while IFS= read -r env_line; do if [[ "$env_line" == "${key}="* ]]; then printf '%s=%s\n' "$key" "$value" >> "$temp_env" else printf '%s\n' "$env_line" >> "$temp_env" fi done < "$env_file" mv "$temp_env" "$env_file" chmod 600 "$env_file" } app_host_was_explicit=0 [[ -n "${APP_HOST:-}" ]] && app_host_was_explicit=1 app_host="${APP_HOST:-${HOSTNAME:-localhost}}" app_scheme="${APP_SCHEME:-http}" app_public_port="${APP_PUBLIC_PORT:-}" app_hostnames="${APP_HOSTS:-$app_host}" app_origin="${APP_ORIGINS:-}" app_base_url="" # De lokale healthcheck gebruikt 127.0.0.1. Houd die host en localhost altijd # toegestaan, ook wanneer APP_HOSTS expliciet door de runner is ingesteld. for required_host in 127.0.0.1 localhost; do if [[ ",$app_hostnames," != *",$required_host,"* ]]; then app_hostnames="${app_hostnames},${required_host}" fi done if [[ -z "$app_public_port" ]]; then if [[ "$app_scheme" == "https" ]]; then app_public_port="443" else app_public_port="$app_port" fi fi if [[ ( "$app_scheme" == "https" && "$app_public_port" == "443" ) || \ ( "$app_scheme" == "http" && "$app_public_port" == "80" ) ]]; then app_base_url="${app_scheme}://${app_host}" else app_base_url="${app_scheme}://${app_host}:${app_public_port}" fi if [[ -z "$app_origin" ]]; then app_origin="$app_base_url" fi secret_key="$(generate_secret)" postgres_password="${POSTGRES_PASSWORD:-$(generate_secret)}" admin_password="${VACATURERADAR_ADMIN_PASSWORD:-$(generate_secret | cut -c 1-24)}" db_url="postgresql://vacatureradar:${postgres_password}@postgres:5432/vacatureradar" debug="${DJANGO_DEBUG:-}" if [[ -z "$debug" ]]; then if [[ "$app_host_was_explicit" == "1" && "$app_scheme" == "https" ]]; then debug="0" else debug="1" fi fi if [[ "$debug" == "0" ]]; then session_secure="${SESSION_COOKIE_SECURE:-1}" csrf_secure="${CSRF_COOKIE_SECURE:-1}" ssl_redirect="${SECURE_SSL_REDIRECT:-1}" hsts_seconds="${SECURE_HSTS_SECONDS:-300}" else session_secure="${SESSION_COOKIE_SECURE:-0}" csrf_secure="${CSRF_COOKIE_SECURE:-0}" ssl_redirect="${SECURE_SSL_REDIRECT:-0}" hsts_seconds="${SECURE_HSTS_SECONDS:-0}" fi write_env "DJANGO_SECRET_KEY" "$secret_key" write_env "DJANGO_DEBUG" "$debug" "$app_host_was_explicit" write_env "DJANGO_ALLOWED_HOSTS" "$app_hostnames" "$app_host_was_explicit" write_env "DJANGO_CSRF_TRUSTED_ORIGINS" "$app_origin" "$app_host_was_explicit" if [[ "$app_host_was_explicit" == "1" ]]; then write_env "PUBLIC_BASE_URL" "$app_base_url" 1 if [[ "$app_scheme" == "https" ]]; then write_env "TRUST_PROXY_HEADERS" "1" 1 else write_env "TRUST_PROXY_HEADERS" "0" 1 fi write_env "USE_X_FORWARDED_HOST" "0" 1 fi write_env "DJANGO_TIME_ZONE" "Europe/Brussels" write_env "POSTGRES_DB" "vacatureradar" write_env "POSTGRES_USER" "vacatureradar" write_env "POSTGRES_PASSWORD" "$postgres_password" write_env "POSTGRES_HOST" "postgres" write_env "POSTGRES_PORT" "5432" write_env "DATABASE_URL" "$db_url" write_env "REDIS_URL" "redis://redis:6379/0" write_env "CACHE_URL" "redis://redis:6379/1" write_env "HEALTHCHECK_REQUIRE_CACHE" "1" write_env "CELERY_TASK_ALWAYS_EAGER" "0" write_env "VACATURERADAR_ADMIN_USERNAME" "admin" write_env "VACATURERADAR_ADMIN_PASSWORD" "$admin_password" write_env "VACATURERADAR_AUTO_BOOTSTRAP" "1" write_env "SESSION_COOKIE_SECURE" "$session_secure" write_env "CSRF_COOKIE_SECURE" "$csrf_secure" write_env "SECURE_SSL_REDIRECT" "$ssl_redirect" write_env "SECURE_HSTS_SECONDS" "$hsts_seconds" write_env "DEMO_READ_ONLY" "1" write_env "SEARCH_ENGINE_INDEXING_ENABLED" "0" write_env "EMAIL_BACKEND" "django.core.mail.backends.console.EmailBackend" write_env "DEFAULT_FROM_EMAIL" "VacatureRadar " write_env "SOURCE_POLICY_MODE" "strict" write_env "AUTH_LOGIN_RATE_LIMIT_MAX_ATTEMPTS" "8" write_env "AUTH_LOGIN_RATE_LIMIT_WINDOW_SECONDS" "300" write_env "AUTH_LOGIN_RATE_LIMIT_BLOCK_SECONDS" "300" write_env "MANUAL_IMPORT_RATE_LIMIT_MAX_ATTEMPTS" "12" write_env "MANUAL_IMPORT_RATE_LIMIT_WINDOW_SECONDS" "120" write_env "MANUAL_IMPORT_RATE_LIMIT_BLOCK_SECONDS" "300" export VACATURERADAR_ENV_FILE="$env_file" docker compose --env-file "$env_file" -f "$compose_file" up -d --build if [[ "${SKIP_HEALTHCHECK:-0}" != "1" ]]; then for i in {1..30}; do if curl -fsS "http://127.0.0.1:${app_port}/health/ready/" >/dev/null; then echo "Healthcheck geslaagd op poort ${app_port}." break fi if [[ "$i" == "30" ]]; then echo "Healthcheck niet geslaagd binnen 60 seconden." exit 1 fi sleep 2 done fi cat < APP_SCHEME=https DJANGO_DEBUG=0 voor publieke productie. - APP_PORT is de interne hostpoort; APP_PUBLIC_PORT is optioneel en standaard 443 bij HTTPS. - Hermaak de container na iedere environmentwijziging. EOF