Add image-based deployment for control panels
docker-compose.panel.yml deploys every service from a published image. A control panel writes only a compose file and an .env into its project directory, so the build: stanzas of docker-compose.yml cannot resolve their context there. CI pushes api, migrate, web and daemon images to the Gitea container registry on v* tags. The migrate stage ships as its own image because the panel compose runs it as a one-shot service before the API starts. The web port is named HOST_PORT: panels reverse-proxy "the" port of an installation and need to know which one that is when a stack publishes more than one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -533,6 +533,82 @@ sudo ufw enable
|
||||
|
||||
---
|
||||
|
||||
## 4. Control Panel Deployment (pre-built images)
|
||||
|
||||
Sections 2 and 3 build from a checkout on the server. A control panel does not
|
||||
have one: it writes a compose file and an `.env` into its own project directory
|
||||
and runs `docker compose up`. Anything with a `build:` stanza fails there —
|
||||
the build context simply is not on disk.
|
||||
|
||||
`docker-compose.panel.yml` exists for that case. Every service references a
|
||||
published image, so the stack installs on a server that has never seen this
|
||||
repository. It was written against [WebPanel](https://gits.hibna.com.tr/hibna/Source-WebPanel)
|
||||
but nothing in it is panel-specific.
|
||||
|
||||
### 4.1 Publish the images
|
||||
|
||||
`.github/workflows/ci.yml` pushes four images to this Gitea instance's own
|
||||
container registry on every `v*` tag:
|
||||
|
||||
| Image | Contents |
|
||||
|---|---|
|
||||
| `gamepanel-api` | Fastify API |
|
||||
| `gamepanel-migrate` | The API Dockerfile's `migrate` stage, run once before the API starts |
|
||||
| `gamepanel-web` | SPA + nginx, built with `VITE_API_URL=/api` |
|
||||
| `gamepanel-daemon` | Rust daemon |
|
||||
|
||||
Add a `REGISTRY_TOKEN` repository secret with package write scope, then:
|
||||
|
||||
```bash
|
||||
git tag v0.1.0 && git push origin v0.1.0
|
||||
```
|
||||
|
||||
### 4.2 Prepare the host
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/gamepanel /var/lib/gamepanel/servers /var/lib/gamepanel/backups
|
||||
sudo cp daemon-config.yml /etc/gamepanel/daemon-config.yml
|
||||
sudo sed -i 's/CHANGE_ME_GENERATE_A_SECURE_TOKEN/'"$(openssl rand -hex 32)"'/' /etc/gamepanel/daemon-config.yml
|
||||
```
|
||||
|
||||
Note the token you generated — the panel needs the same value when you register
|
||||
the node. If the panel has a file manager, both steps can be done from it.
|
||||
|
||||
### 4.3 Install
|
||||
|
||||
Paste `docker-compose.panel.yml` into the panel's custom-compose screen and set:
|
||||
|
||||
| Variable | Example | Notes |
|
||||
|---|---|---|
|
||||
| `REGISTRY` | `gits.hibna.com.tr/hibna` | Namespace holding the four images |
|
||||
| `TAG` | `v0.1.0` | The tag you pushed |
|
||||
| `HOST_PORT` | `8096` | **Not 80** if the panel's own web server owns it |
|
||||
| `DB_PASSWORD`, `REDIS_PASSWORD` | `openssl rand -hex 24` | |
|
||||
| `JWT_SECRET`, `JWT_REFRESH_SECRET` | `openssl rand -hex 64` | |
|
||||
| `CORS_ORIGIN` | `https://panel.example.com` | Must match the address the browser uses |
|
||||
|
||||
The published port is called `HOST_PORT` because panels commonly reverse-proxy
|
||||
"the" port of an installation and need to know which one that is when a stack
|
||||
publishes more than one.
|
||||
|
||||
If the registry is private, the host needs `docker login` once — panels pull
|
||||
anonymously otherwise. On Gitea the package can also be made public while the
|
||||
repository stays private.
|
||||
|
||||
### 4.4 Notes
|
||||
|
||||
- **The daemon holds the Docker socket.** That is root-equivalent access to
|
||||
every container on the machine, the panel's own containers included. Running
|
||||
the daemon on a separate node — which the multi-node architecture is built
|
||||
for — keeps the game hosts and the control plane apart.
|
||||
- **Nothing publishes gRPC on a single host.** The API reaches the daemon over
|
||||
the compose network as `daemon:50051`. A remote node runs the `daemon`
|
||||
service on its own machine and publishes `50051` there.
|
||||
- **Game server ports** are opened by the daemon on the host; a panel with a
|
||||
default-deny firewall needs an explicit rule for the range you hand out.
|
||||
|
||||
---
|
||||
|
||||
## Post-Installation
|
||||
|
||||
### First Login
|
||||
|
||||
Reference in New Issue
Block a user