DocsGo apps

Go apps

Install the Go toolchain, deploy a Go service from Git with automatic build and start commands, listen on PORT, set environment variables and fix common errors.

A Go application runs on ZoPanel as a server app: ZoPanel compiles it from source with the official Go toolchain, starts the binary as a service of the hosting account behind nginx, and releases new versions with no downtime. Use this page for HTTP services and APIs written in Go; the general mechanics (ports, blue/green releases, logs) are described in Node.js and Python apps.

Install Go on the server

An administrator installs Go once:

  1. Open Runtimes.
  2. In the Go card ("Official Go toolchain."), click Install latest.

ZoPanel downloads the newest stable release for the server's architecture (amd64 or arm64) from go.dev, verifies its SHA-256 checksum and installs it in /opt/zopanel/runtimes/go/<major.minor>, for example 1.25. Installing again later adds the newer minor version next to the old one. Remove a version with the trash icon on its badge.

Version selection: a deploy uses the installed version that matches the go line of go.mod (go 1.24 → 1.24), otherwise the newest installed version. When go.mod asks for a newer Go than the one used, Go 1.21 and later download the required toolchain automatically during the build (Go toolchains); installing the latest version avoids that download.

Prepare your app

Your program must listen on 127.0.0.1 at the port in the PORT environment variable. ZoPanel sets PORT (and HOST=127.0.0.1) for every release; the second blue/green slot uses another port, so never hard-code it.

package main

import (
	"net/http"
	"os"
)

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello from Go"))
	})
	http.ListenAndServe("127.0.0.1:"+os.Getenv("PORT"), mux)
}

nginx terminates SSL and forwards every request to the app with Host, X-Real-IP, X-Forwarded-For and X-Forwarded-Proto headers. Read the client address from X-Forwarded-For or X-Real-IP, not from r.RemoteAddr, which is always 127.0.0.1.

Deploy

  1. In Websites → New website, choose Git deploy, enter the Repository URL and Branch (and Root directory if go.mod is in a subfolder), then click Create website. For an existing website, use its Deploy tab.
  2. ZoPanel detects Go from go.mod and builds the first release.
  3. Add your settings in Environment variables and click Save & redeploy.

You can also upload the source to domains/<domain>/source and choose Uploaded files (File Manager) as the Source (see Git deploy).

Detected build and start commands

Repository layout Build command Start command
main.go at the root CGO_ENABLED=0 go build -o bin/<name> . ./bin/<name>
cmd/<cmd>/main.go mkdir -p bin && CGO_ENABLED=0 go build -o bin/ ./cmd/... ./bin/<first cmd in alphabetical order>
Neither CGO_ENABLED=0 go build -o bin/<name> . ./bin/<name>
  • <name> is the last element of the module path in go.mod (github.com/acme/api → api), or app.
  • The install command is go mod download.
  • With several commands in cmd/, the deploy log notes "Multiple commands found in cmd/, starting …". To start another one, turn Auto-detect off and edit Start command, for example ./bin/server.
  • bin/ is added to PATH when the app starts, so a Procfile line such as web: api works. A web: line in a Procfile always provides the start command.

To change any command, turn Auto-detect off in the Build & run card, edit it and click Save & deploy. Build steps chained with && stay on one line, for example go generate ./... && CGO_ENABLED=0 go build -o bin/api ..

Build environment

  • Builds run as the hosting account, inside its CPU and memory limits, with at most 30 minutes for the install command and 30 minutes for the build.
  • The module cache (GOPATH) and build cache (GOCACHE) live in the account's home and are kept between deploys, so later builds are faster.
  • CGO_ENABLED=0 produces a static binary. Packages that need cgo (for example github.com/mattn/go-sqlite3) need CGO_ENABLED=1 and a C compiler on the server; prefer pure-Go alternatives such as modernc.org/sqlite.

Environment variables

Put configuration and secrets in Environment variables on the Deploy tab. They are available during the build and at runtime; Paste .env adds many at once (up to 200 variables, single-line values). Members with view-only access cannot see the values.

Example for a MariaDB database created under Databases:

DATABASE_URL=alice_api:your-password@tcp(127.0.0.1:3306)/alice_api?parseTime=true

The format of the connection string depends on the driver you use; the host is 127.0.0.1 (see Databases).

Files that must survive a release, such as an upload folder or a SQLite database, go in Persistent paths (for example data). Everything else in the release folder is replaced on every deploy.

Releases, logs and restarts

  • A new release starts in the idle slot and must answer the Health check path (default /) with a status below 500 within 90 seconds. Only then does nginx switch to it and the old process stop. If the binary exits or never answers, the running release is kept.
  • Releases keeps the last 5 builds for Rollback.
  • Application output on the Deploy tab shows the last 400 lines your program writes to stdout and stderr; turn on Live to follow it. Write logs to stdout instead of files.
  • The service restarts automatically if the process exits. Stop the program cleanly on SIGTERM: during a release the old process gets 20 seconds before it is killed.

Memory, CPU and processes count toward the account's package (see Packages and limits).

Troubleshooting

Message or symptom What to do
"Go is not installed — install it under Runtimes" Ask the administrator to click Install latest in the Go card.
"the app did not respond on port … within 90s (it must listen on $PORT)" Listen on 127.0.0.1:$PORT. A fixed port such as :8080 never receives traffic.
"the app exited during startup" Read Application output: usually a missing environment variable or a failed database connection.
install failed during go mod download A private module cannot be fetched. Vendor your dependencies (go mod vendor), commit vendor/, then turn Auto-detect off and clear the Install command: go build uses vendor/ automatically.
go: go.mod requires go >= … Install the latest Go under Runtimes, or let the toolchain download complete.
Build fails with cgo errors Use a pure-Go package, or set CGO_ENABLED=1 in the build command if a C compiler is installed.
The repository is detected as Node.js A package.json at the root takes priority over go.mod. Turn Auto-detect off, set Runtime to go, Type to Server app (process) and enter the commands yourself.
502 Bad Gateway The process is not listening. Check Application output and Run diagnostics on the Logs tab.

← Laravel Ruby and Rails apps →