diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5472e49 --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +DOMAIN=example.com + +DATABASE_ROOT_PASSWORD=reallysecurerootpassword +DATABASE_USER=optionalusername +DATABASE_PASSWORD=ghostpassword diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..53a70eb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,21 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is a Docker Compose setup for Ghost, a modern publishing platform. The repository currently contains a minimal structure with a `compose.yml` file for containerized deployment. + +## Common Commands + +Since this is a Docker Compose project, the primary commands will be: + +- `docker compose up -d` - Start Ghost services in detached mode +- `docker compose down` - Stop and remove Ghost services +- `docker compose logs` - View service logs +- `docker compose ps` - View running services +- `docker compose pull` - Pull latest images + +## Architecture + +The project uses Docker Compose to orchestrate Ghost and its dependencies (typically MySQL/MariaDB database). The main configuration is defined in `compose.yml`. diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..8712708 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,49 @@ +# Replace your-domain.com with your actual domain +{$DOMAIN} { + # Log all requests + log { + output stdout + format console + level INFO + } + + # Proxy analytics requests with any prefix (e.g. /.ghost/analytics/ or /blog/.ghost/analytics/) + @analytics_paths path_regexp analytics_match ^(.*)/\.ghost/analytics(.*)$ + handle @analytics_paths { + rewrite * {re.analytics_match.2} + reverse_proxy traffic-analytics:3000 + } + + # Default proxy to Ghost + handle { + reverse_proxy ghost:2368 + } + + # Optional: Enable gzip compression + encode gzip + + # Optional: Add security headers + header { + # Enable HSTS + Strict-Transport-Security max-age=31536000; + # Prevent embedding in frames + X-Frame-Options DENY + # Enable XSS protection + X-XSS-Protection "1; mode=block" + # Prevent MIME sniffing + X-Content-Type-Options nosniff + # Referrer policy + Referrer-Policy strict-origin-when-cross-origin + } +} + +# Redirect www to non-www (optional) +www.{$DOMAIN} { + # Log all requests + log { + output stdout + format console + level INFO + } + redir https://ghost.joegrigg.com{uri} +} diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..0c723ce --- /dev/null +++ b/compose.yml @@ -0,0 +1,73 @@ +services: + caddy: + image: caddy:2-alpine + restart: always + ports: + - "80:80" + - "443:443" + environment: + DOMAIN: ${DOMAIN:?DOMAIN environment variable is required} + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile + - caddy_data:/data + - caddy_config:/config + depends_on: + - ghost + networks: + - ghost_network + + ghost: + image: ghost:5-alpine + restart: always + expose: + - "2368" + environment: + database__client: mysql + database__connection__host: db + database__connection__user: ${DATABASE_USER:-ghost} + database__connection__password: ${DATABASE_PASSWORD:?DATABASE_PASSWORD environment variable is required} + database__connection__database: ghost + url: https://${DOMAIN:?DOMAIN environment variable is required} + volumes: + - ghost_content:/var/lib/ghost/content + depends_on: + - db + networks: + - ghost_network + + db: + image: mysql:8.0 + restart: always + ports: + - "3306:3306" + environment: + MYSQL_ROOT_PASSWORD: ${DATABASE_ROOT_PASSWORD:?DATABASE_ROOT_PASSWORD environment variable is required} + MYSQL_USER: ${DATABASE_USER:-ghost} + MYSQL_PASSWORD: ${DATABASE_PASSWORD:?DATABASE_PASSWORD environment variable is required} + MYSQL_DATABASE: ghost + MYSQL_MULTIPLE_DATABASES: activitypub + volumes: + - db_data:/var/lib/mysql + - ./mysql-init:/docker-entrypoint-initdb.d + networks: + - ghost_network + + traffic-analytics: + image: ghost/traffic-analytics:edge + restart: always + expose: + - "3000" + environment: + NODE_ENV: production + PROXY_TARGET: https://api.tinybird.co/v0/events + networks: + - ghost_network + +volumes: + ghost_content: + db_data: + caddy_data: + caddy_config: + +networks: + ghost_network: diff --git a/mysql-init/create-multiple-databases.sh b/mysql-init/create-multiple-databases.sh new file mode 100755 index 0000000..cb39c02 --- /dev/null +++ b/mysql-init/create-multiple-databases.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e +set -u + +if [ -n "$MYSQL_MULTIPLE_DATABASES" ]; then + echo "Creating multiple databases: $MYSQL_MULTIPLE_DATABASES" + + for db in $(echo $MYSQL_MULTIPLE_DATABASES | tr ',' ' '); do + echo "Creating database: $db" + mysql -u root -p"$MYSQL_ROOT_PASSWORD" <<-EOSQL + CREATE DATABASE IF NOT EXISTS \`$db\`; + GRANT ALL ON \`$db\`.* TO '$MYSQL_USER'@'%'; +EOSQL + done + + echo "Multiple databases created" +fi