krz/skunky-art

clone: git clone https://gitbay.org/krz/skunky-art.git

main: compose.vpn_example.yml · raw

  1# SkunkyArt + optional VPN egress, in a single stack.
  2#
  3# Why: DeviantArt's API (AWS CloudFront + WAF) blocks some egress IPs on the
  4# /_puppy path, which makes every DA-backed page fail with
  5# `invalid character '<' looking for beginning of value` (Go trying to
  6# json.Unmarshal a CloudFront HTML 403 page). Routing SkunkyArt's outbound
  7# through a non-blocked VPN exit fixes it without any code change: devianter's
  8# HTTP client honors HTTPS_PROXY/HTTP_PROXY.
  9#
 10# The VPN sidecar (gluetun) is OPTIONAL — it only starts under the "vpn" profile.
 11# With the profile off, SkunkyArt runs exactly as the stock compose.yaml (direct).
 12#
 13# The VPN provider is YOUR choice: gluetun supports AirVPN, Mullvad, ProtonVPN,
 14# PIA, and many others. Set VPN_SERVICE_PROVIDER and supply that provider's
 15# required settings. Provider list + required variables:
 16#   https://github.com/qdm12/gluetun-wiki
 17#
 18# ---------------------------------------------------------------------------
 19# Setup:
 20#   1. Copy this file to compose.yaml (or run with `-f compose.vpn_example.yml`).
 21#   2. Create a .env next to it (and `echo ".env" >> .gitignore`):
 22#
 23#        # toggle VPN: uncomment both to route SkunkyArt through the VPN
 24#        #COMPOSE_PROFILES=vpn
 25#        #SKUNKY_PROXY=http://gluetun:8888
 26#
 27#        # pick your provider (see the gluetun wiki for the exact name/vars)
 28#        VPN_SERVICE_PROVIDER=airvpn
 29#        VPN_TYPE=wireguard
 30#
 31#        # WireGuard credentials (from your provider's config generator)
 32#        VPN_PRIVATE_KEY=<[Interface] PrivateKey>
 33#        VPN_PRESHARED_KEY=<[Peer] PresharedKey>   # optional; some providers omit it
 34#        VPN_ADDRESSES=<[Interface] Address, e.g. 10.128.x.x/32>
 35#        VPN_COUNTRIES=Netherlands
 36#        TZ=America/Chicago
 37#
 38#   3. VPN on:  uncomment the two toggle lines, then `docker compose up -d`.
 39#      VPN off: leave them commented, then `docker compose up -d`.
 40#
 41# Verify an exit is not blocked BEFORE trusting it:
 42#   curl -x http://127.0.0.1:8888 -s -o /dev/null -w "%{http_code}\n" \
 43#     "https://www.deviantart.com/_puppy/dabrowse/networkbar/rfy/deviations?page=0"
 44#   400 (JSON "csrf: missing") = clean exit.  403 (text/html) = blocked, rotate servers.
 45# ---------------------------------------------------------------------------
 46
 47services:
 48  skunkyart:
 49    container_name: skunkyart
 50    restart: unless-stopped
 51    # Published multi-arch image; pin a release tag (e.g. :1.3.3) for
 52    # reproducible upgrades. To build from this checkout instead, comment out
 53    # `image:` and uncomment `build:`, then `docker compose up -d --build`.
 54    image: ghcr.io/krazywarez/skunky-art:latest
 55    #build: .
 56    ports:
 57      - "127.0.0.1:3003:3003"
 58    security_opt:
 59      - no-new-privileges:true
 60    volumes:
 61      - ./config.json:/config.json:ro
 62      # The image runs as uid 10000, so the host cache dir must be writable by it:
 63      #   mkdir -p cache && sudo chown -R 10000:10000 cache
 64      - ./cache:/cache
 65    environment:
 66      # Empty by default = direct. Set SKUNKY_PROXY in .env to route via the VPN.
 67      - HTTPS_PROXY=${SKUNKY_PROXY:-}
 68      - HTTP_PROXY=${SKUNKY_PROXY:-}
 69      - NO_PROXY=localhost,127.0.0.1
 70    depends_on:
 71      gluetun:
 72        condition: service_healthy
 73        required: false           # optional dep: skunky still starts if gluetun is off
 74                                  # (needs Docker Compose v2.20+; drop this block on older)
 75
 76  # --- optional VPN egress: only starts with the "vpn" profile ---
 77  gluetun:
 78    image: qmcgaw/gluetun:latest
 79    container_name: gluetun-skunky
 80    profiles: ["vpn"]
 81    cap_add:
 82      - NET_ADMIN
 83    devices:
 84      - /dev/net/tun:/dev/net/tun
 85    ports:
 86      - "127.0.0.1:8888:8888"     # host-side, only for testing the proxy
 87    environment:
 88      # Provider + tunnel type — your choice (see gluetun wiki).
 89      - VPN_SERVICE_PROVIDER=${VPN_SERVICE_PROVIDER:-}
 90      - VPN_TYPE=${VPN_TYPE:-wireguard}
 91      # WireGuard credentials (leave PRESHARED empty if your provider omits it).
 92      - WIREGUARD_PRIVATE_KEY=${VPN_PRIVATE_KEY:-}
 93      - WIREGUARD_PRESHARED_KEY=${VPN_PRESHARED_KEY:-}
 94      - WIREGUARD_ADDRESSES=${VPN_ADDRESSES:-}
 95      - SERVER_COUNTRIES=${VPN_COUNTRIES:-}
 96      - HTTPPROXY=on              # built-in HTTP proxy on :8888
 97      - TZ=${TZ:-Etc/UTC}
 98      # If skunky can't reach the proxy while gluetun is healthy, uncomment to let
 99      # gluetun's firewall accept the docker network:
100      # - FIREWALL_OUTBOUND_SUBNETS=172.16.0.0/12
101    restart: unless-stopped