Files
MineGeo/docs/dokploy-deployment.md
pavel444-byte 690fe12c2c
All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 5m17s
Fix restricted map controls and release verification
2026-10-20 16:46:36 +05:00

157 lines
8.3 KiB
Markdown

# Dokploy deployment
The Gitea Actions workflow in `.gitea/workflows/deploy-dokploy.yml` deploys
commits from `master` to Dokploy. The act_runner service runs in Docker on the
MacBook, and this workflow selects its Linux Docker job environment with the
`ubuntu-latest` label. The job checks out the private repository, creates a ZIP
from the committed files only, and uploads it to Dokploy over HTTPS. Dokploy
builds the Docker image from the repository's root `Dockerfile` on the VPS and
performs the deployment. No image registry is used, and the workflow does not
use SSH or the VPS root password.
## One-time Dokploy setup
Create a Dokploy Application for MineGeo with the **Drop** (drag-and-drop)
source provider. If the current Gitea-linked application cannot switch its
provider, create a separate application and move the domain after its first
successful deployment. Configure its build type as **Dockerfile**, with the
Dockerfile and build context both at the repository root.
In the Dokploy application, open **Environment** and add both values under
**Build Time Arguments** (not only under the regular runtime environment
variables):
```text
NEXT_PUBLIC_SUPABASE_URL=<your Supabase project URL>
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=<your Supabase publishable key>
```
These values are used by Next.js while compiling browser code. Setting them
only as runtime environment variables does not populate Dockerfile `ARG`
values, which causes the build error that says they were empty. Both values
are public client configuration; do not put `SUPABASE_SECRET_KEY` in Build
Time Arguments.
Also set the following in Dokploy's regular runtime environment:
- `NEXT_PUBLIC_SUPABASE_URL`
- `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY`
- `SUPABASE_SECRET_KEY` (server-only; never a build argument)
- `MINEGEO_URL=https://minegeo.site` (the public HTTPS site origin)
- `MINEGEO_ALLOW_ANY_ORIGIN=false`
Add any optional production variables from `.env.example` in Dokploy's
environment settings. Do not upload `.env.local` or add it to the repository.
## Building on a 2 GiB VPS
The Dockerfile uses `npm run build:docker`. It generates route types and runs
the full TypeScript check in a separate process before compiling with Webpack.
Next.js skips its duplicate TypeScript check only after the separate check
succeeds. The Docker build enables Webpack's build worker and memory
optimizations, and keeps page collection at one worker. Each build Node process
has a 640 MiB JavaScript heap ceiling; this is not a limit on the total memory
used by all processes or native libraries.
Dependencies are installed once, then pruned after compilation. The dependency
installation for the final image no longer runs independently alongside the
application build. Normal `npm run build` retains its usual type checking and
bundler behavior. See Next.js's [memory usage
guide](https://nextjs.org/docs/app/guides/memory-usage) for the build options.
In Dokploy, keep builds concurrency at **1** on this VPS. Dokploy, PostgreSQL,
Redis, Traefik, the running application, and the new build share the host's RAM.
Avoid starting a panorama render during a deployment. Application runtime
resource limits do not necessarily limit the Docker image build.
If the host freezes, capture these read-only diagnostics from the VPS shell
before retrying. They print resource figures and Dokploy container state without
environment values, API keys, private addresses, or repository names:
```sh
free -m
df -h /
vmstat 1 5
journalctl -k --since '30 minutes ago' --no-pager -o cat |
awk '/oom-kill|Out of memory|Killed process/ {n++} END {print "Kernel OOM messages:", n+0}'
docker ps -aq --filter label=com.docker.swarm.service.name=dokploy |
xargs -r docker inspect --format 'OOMKilled={{.State.OOMKilled}} ExitCode={{.State.ExitCode}} Started={{.State.StartedAt}} Finished={{.State.FinishedAt}}'
```
A startup log containing `Cancelled 1 deployments` is Dokploy's startup cleanup,
not proof of a deployment timeout. Correlate container start/finish times and
kernel OOM messages with the failed build. `OOMKilled=false` for Dokploy does not
rule out a different process being killed or host-wide memory pressure. Journal
permissions or missing history can also prevent the OOM count from being useful.
If swap is absent and memory pressure is confirmed, adding swap can prevent
abrupt memory exhaustion, but it consumes disk space and can make builds slower.
Approve server configuration changes separately; the repository changes do not
create swap, restart services, or change server resource limits. If builds still
exceed available memory, move image compilation to the MacBook runner and use a
private image-transfer or private-registry workflow.
## Gitea Actions secrets
Add the following repository Actions secrets in Gitea. The workflow pins Dokploy
to `https://dokploy.minegeo.site` with a readonly shell assignment. Environment
variables, `.env` files, and any existing `DOKPLOY_URL` secret cannot override
that address. Changing the deployment domain requires editing the workflow.
- `DOKPLOY_API_KEY` (create this in Dokploy)
- `DOKPLOY_APPLICATION_ID` (copy this from the target Application)
In the runner's Gitea configuration, ensure `ubuntu-latest` is registered with
the Docker schema, for example:
```text
ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest
```
The workflow uses `runs-on: ubuntu-latest`, so it runs inside that Linux job
container rather than directly on macOS or inside the act_runner service
container. If your runner uses another Docker label, change `runs-on` to that
label. The selected image needs `git`, `curl`, and Node.js so the job can archive
the commit, upload it, and inspect deployment status. Gitea documents how
runner labels select host versus Docker execution in the [runner
documentation](https://gitea.com/gitea/runner/src/branch/main/README.md#labels).
Every push to `master` triggers a deployment. The job logs the pinned target,
commit, curl/TLS runtime versions, DNS results, proxy configuration (without
credentials), CA configuration status, and source archive size. Each request logs
curl's exit code, HTTP status, connection IPs, certificate verification result,
transfer sizes, and DNS/TCP/TLS/first-byte/total timings. Curl errors are preserved
and common DNS, connection, proxy, timeout and certificate failures include hints.
Failed responses include selected headers, JSON error/message fields, or an HTML
page title. API keys and application IDs are redacted; cookies, source archives,
deployment payloads and complete response bodies are not printed. The workflow
does not enable shell tracing, disable TLS verification, follow authenticated
redirects, or retry source uploads automatically. HTTP `000` means no HTTP
response was received; inspect the curl exit code and error immediately above it.
The job waits for Dokploy's deployment status and fails if the upload or deployment
fails. Status polling tolerates up to six consecutive transient network/server
failures after an upload has been accepted, and retries only the read-only status
request. Authentication and certificate verification errors still stop the job.
All deployment IDs present before the upload are excluded from completion checks,
so an older successful build cannot be mistaken for the new release. Build logs
remain available in the Dokploy dashboard.
`git archive` sends tracked files from that commit only. It does not include
`.git` metadata, local environment files, untracked files, or local caches. The
public Windows installer remains in the site image because MineGeo serves it
from `/desktop/`; the large JVM heap dump was removed because it is neither
application code nor a runtime asset. The Docker build also excludes the
Minecraft Java workspace, Gradle caches, build output, and heap dumps.
The ZIP still contains the required Windows installer (about 96 MiB), so the
Dokploy endpoint and any reverse proxy in front of it must accept the archive's
full size. If the upload is rejected with a size-related HTTP error, use the
Dokploy deployment logs to distinguish an upload limit from a build failure.
Dokploy documents the upload endpoint and deployment-status API in its
[Application API](https://docs.dokploy.com/docs/api/application) and
[Deployment API](https://docs.dokploy.com/docs/api/deployment). This workflow
uses TLS certificate verification and does not publish the image or source to
a public service.