| @@ -0,0 +1,95 @@ |
| 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 | |
| 47 | services: |
| 48 | skunkyart: |
| 49 | container_name: skunkyart |
| 50 | restart: unless-stopped |
| 51 | build: . |
| 52 | ports: |
| 53 | - "127.0.0.1:3003:3003" |
| 54 | security_opt: |
| 55 | - no-new-privileges:true |
| 56 | volumes: |
| 57 | - ./config.json:/config.json:ro |
| 58 | - ./cache:/cache # ensure this dir is owned 10000:10000 |
| 59 | environment: |
| 60 | # Empty by default = direct. Set SKUNKY_PROXY in .env to route via the VPN. |
| 61 | - HTTPS_PROXY=${SKUNKY_PROXY:-} |
| 62 | - HTTP_PROXY=${SKUNKY_PROXY:-} |
| 63 | - NO_PROXY=localhost,127.0.0.1 |
| 64 | depends_on: |
| 65 | gluetun: |
| 66 | condition: service_healthy |
| 67 | required: false # optional dep: skunky still starts if gluetun is off |
| 68 | # (needs Docker Compose v2.20+; drop this block on older) |
| 69 | |
| 70 | # --- optional VPN egress: only starts with the "vpn" profile --- |
| 71 | gluetun: |
| 72 | image: qmcgaw/gluetun:latest |
| 73 | container_name: gluetun-skunky |
| 74 | profiles: ["vpn"] |
| 75 | cap_add: |
| 76 | - NET_ADMIN |
| 77 | devices: |
| 78 | - /dev/net/tun:/dev/net/tun |
| 79 | ports: |
| 80 | - "127.0.0.1:8888:8888" # host-side, only for testing the proxy |
| 81 | environment: |
| 82 | # Provider + tunnel type — your choice (see gluetun wiki). |
| 83 | - VPN_SERVICE_PROVIDER=${VPN_SERVICE_PROVIDER:-} |
| 84 | - VPN_TYPE=${VPN_TYPE:-wireguard} |
| 85 | # WireGuard credentials (leave PRESHARED empty if your provider omits it). |
| 86 | - WIREGUARD_PRIVATE_KEY=${VPN_PRIVATE_KEY:-} |
| 87 | - WIREGUARD_PRESHARED_KEY=${VPN_PRESHARED_KEY:-} |
| 88 | - WIREGUARD_ADDRESSES=${VPN_ADDRESSES:-} |
| 89 | - SERVER_COUNTRIES=${VPN_COUNTRIES:-} |
| 90 | - HTTPPROXY=on # built-in HTTP proxy on :8888 |
| 91 | - TZ=${TZ:-Etc/UTC} |
| 92 | # If skunky can't reach the proxy while gluetun is healthy, uncomment to let |
| 93 | # gluetun's firewall accept the docker network: |
| 94 | # - FIREWALL_OUTBOUND_SUBNETS=172.16.0.0/12 |
| 95 | restart: unless-stopped |