# FrankMD Docker Compose # # Quick start: # docker compose up -d # # With custom notes directory: # NOTES_PATH=~/my-notes docker compose up -d # # Generate secret key (first time only): # echo "SECRET_KEY_BASE=$(openssl rand -hex 64)" >> .env # # Run as current user (for volume permissions): # echo "UID=$(id -u)" >> .env # echo "GID=$(id -g)" >> .env services: frankmd: image: akitaonrails/frankmd:latest # Or build locally: # build: . container_name: frankmd restart: unless-stopped # Run as host user for proper volume permissions user: "${UID:-1000}:${GID:-1000}" ports: # Host bind address defaults to all interfaces (preserves existing # behavior). Set FRANKMD_BIND_ADDRESS=127.0.0.1 for local-only access, # including VPN-protected setups where broad LAN access is firewalled. - "${FRANKMD_BIND_ADDRESS:-0.0.0.0}:${PORT:-7591}:80" volumes: # Notes directory - default to ./notes, override with NOTES_PATH env var - ${NOTES_PATH:-./notes}:/rails/notes # Images directory (optional) - for local image browsing - ${IMAGES_PATH:-./images}:/rails/images environment: # Generated by the entrypoint when unset - SECRET_KEY_BASE=${SECRET_KEY_BASE:-} - NOTES_PATH=/rails/notes - IMAGES_PATH=/rails/images - EXTERNAL_PORT=${PORT:-7591} - FRANKMD_AUTH_TOKEN=${FRANKMD_AUTH_TOKEN:-} - FRANKMD_ALLOWED_HOSTS=${FRANKMD_ALLOWED_HOSTS:-} # Optional: AWS S3 for image uploads - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-} - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-} - AWS_S3_BUCKET=${AWS_S3_BUCKET:-} - AWS_REGION=${AWS_REGION:-} # Optional: YouTube search - YOUTUBE_API_KEY=${YOUTUBE_API_KEY:-} # Optional: Google Image search - GOOGLE_API_KEY=${GOOGLE_API_KEY:-} - GOOGLE_CSE_ID=${GOOGLE_CSE_ID:-} # Optional: AI/LLM grammar checking - AI_PROVIDER=${AI_PROVIDER:-} - AI_MODEL=${AI_MODEL:-} - OLLAMA_API_BASE=${OLLAMA_API_BASE:-} - OLLAMA_MODEL=${OLLAMA_MODEL:-} - OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-} - OPENROUTER_MODEL=${OPENROUTER_MODEL:-} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} - ANTHROPIC_MODEL=${ANTHROPIC_MODEL:-} - GEMINI_API_KEY=${GEMINI_API_KEY:-} - GEMINI_MODEL=${GEMINI_MODEL:-} - OPENAI_API_KEY=${OPENAI_API_KEY:-} - OPENAI_MODEL=${OPENAI_MODEL:-} - CHEAPERINFERENCE_API_KEY=${CHEAPERINFERENCE_API_KEY:-} - CHEAPERINFERENCE_MODEL=${CHEAPERINFERENCE_MODEL:-} - IMAGE_GENERATION_MODEL=${IMAGE_GENERATION_MODEL:-} # Optional: Locale (en, pt-BR, pt-PT, es, he, ja, ko) - FRANKMD_LOCALE=${FRANKMD_LOCALE:-} - FRANKMD_AUTH_TOKEN=${FRANKMD_AUTH_TOKEN:-} - FRANKMD_ALLOWED_HOSTS=${FRANKMD_ALLOWED_HOSTS:-} healthcheck: test: ["CMD", "curl", "-f", "http://localhost:80/up"] interval: 30s timeout: 10s retries: 3 start_period: 40s # Uncomment for Cloudflare Tunnel (secure remote access) # # cloudflared: # image: cloudflare/cloudflared:latest # container_name: frankmd-tunnel # restart: unless-stopped # command: tunnel --no-autoupdate run --token ${CLOUDFLARE_TUNNEL_TOKEN} # depends_on: # - frankmd # # Configure tunnel in Cloudflare Zero Trust dashboard: # # - Create tunnel at https://one.dash.cloudflare.com/ # # - Add public hostname pointing to http://frankmd:80 # # - Copy tunnel token to .env as CLOUDFLARE_TUNNEL_TOKEN