Server setup (Docker Compose)
The backend + filebrowser + nginx (with frontend) can be deployed with one docker-compose.yml.
Requirements
- A Linux server with a public IP address
- A domain name
- Docker + Docker Compose plugin installed
Quickstart
- Download
docker-compose.ymland.env.examplefrom the repository.
bash
mkdir potato-launcher-backend
cd potato-launcher-backend
wget https://raw.githubusercontent.com/Petr1Furious/potato-launcher/refs/heads/master/docker-compose.yml
wget -O .env https://raw.githubusercontent.com/Petr1Furious/potato-launcher/refs/heads/master/.env.example- Edit
.envand set at least:
ADMIN_JWT_SECRET: JWT signing secret (generate withopenssl rand -base64 48)ADMIN_SECRET_TOKEN: admin “password” used to log in (pick a long random password)DOWNLOAD_SERVER_BASE: public URL where your server will host generated instance files (usuallyhttps://<your-domain>/data)
Other useful variables from .env.example:
REPLACE_DOWNLOAD_URLS: iftrue, instance builds serve libraries and assets from your server instead of Mojang/upstream URLs. Can also be toggled later in the admin Settings page. Default:falseRESOURCES_URL_BASE: optional override for the assets base URL passed to the builderVITE_GITHUB_URL: repository link shown on the public downloads pagePORT: host port nginx listens on. Default:8000PUID/PGID: user/group IDs for container file ownership. Default:1000CONTAINER_NAME_PREFIX: prefix for Docker container names. Default:potato-launcher
- Start the setup:
bash
docker compose up -d- Setup a reverse proxy.
- By default, nginx is exposed on port 8000 on the host (see
docker-compose.yml). You can changePORTto any other value. - Choose any reverse proxy and setup TLS certificates. A couple of common options: Caddy, Traefik (both with automatic Let’s Encrypt) and nginx + Certbot (more manual approach).
- Point the proxy at
http://127.0.0.1:8000(or whateverPORTyou chose). The URLs below assume you access the site through the proxy on standard HTTPS, without the port in the URL.
What gets served where
When the setup is up:
- Downloads page:
https://<your-domain>/ - Backend API:
https://<your-domain>/api/v1/ - API docs:
https://<your-domain>/api/v1/docs - Generated instances & metadata:
https://<your-domain>/data/ - Admin panel:
https://<your-domain>/admin/(requires login) - Filebrowser (uploaded instance files):
https://<your-domain>/filebrowser/(requires login)
Logging in
Open https://<your-domain>/admin and log in using your ADMIN_SECRET_TOKEN.
Persistent data / backups
All persistent state lives under ./state/ by default:
state/internal: instances spec + uploaded instances storagestate/generated: generated output served under/datastate/workdir: builder working directory (can be thought of as a cache for the builder)state/launcher: uploaded launcher artifactsstate/filebrowser-db: Filebrowser database
Back up the whole state/ directory.
WARNING
Do not share ADMIN_SECRET_TOKEN or ADMIN_JWT_SECRET. Anyone with the admin token can log in and upload/modify instances and launchers.