No ZIP, no .env: one small docker-compose.yml, then everything else happens in the player itself.
Prefer all options in a .env file (reverse proxy, Intel graphics, own user …)? Use the
normal installation instead – both end up with the same player.
Create a folder, put this docker-compose.yml into it (or paste it as a stack in Portainer):
services:
funscript-player:
image: ghcr.io/scripthost/funscript-player:latest
container_name: Funscript-Player
restart: unless-stopped
ports: ["8080:8080"]
volumes:
- funscript-data:/app/data
- /path/to/videos:/media:ro # optional: your video folder – delete this line if you only use Stash
read_only: true
tmpfs: [/tmp]
cap_drop: [ALL]
security_opt: [no-new-privileges:true]
volumes:
funscript-data:
name: funscript-datadocker compose up -dOpen http://<server>:8080 in your browser.
On the first visit the player asks for a login. You are logged in right away; other devices log in on the login page (“stay logged in” keeps you logged in for 30 days).
⚙️ Settings → Library → Change connection: enter the address of Stash as the container sees it – on the same
Docker network the container name, e.g. http://Stash:9999 (not localhost). If Stash has a login, add its API key
(Stash → Settings → Security). Test connection shows the version and the number of scenes.
Stash says HTTP 403? The player shows the exact public_whitelist line for Stash's config.yml right there –
see Stash 0.32+.
Tap Devices at the bottom:
- The Handy: enter the connection key (from the Handy app / handyfeeling.com) → Connect.
- Satisfyer: Bluetooth right in the browser – Chrome or Edge on Android or PC, on iPhone the Bluefy app. Bluetooth needs HTTPS (see below).
Then pick a scene in the Library and press play – the devices follow the video.
Browsers only allow Bluetooth and installing the app on https:// addresses. The simplest way is
Caddy, which fetches the certificate by itself. Add it to the same compose file:
caddy:
image: caddy:2
restart: unless-stopped
ports: ["80:80", "443:443"]
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data…and caddy-data: under volumes:. Next to it a file Caddyfile:
player.example.com {
reverse_proxy funscript-player:8080
}
Replace player.example.com with your own domain pointing to the server.
Already have a reverse proxy (Traefik, Nginx Proxy Manager …)? Point it to port 8080 of the container.
docker compose pull && docker compose up -dYour settings, login and own scripts stay in the funscript-data volume.
More: README · Security & proxy · FAQ



