| @@ -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 |