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:
- Open Runtimes.
- 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
- In Websites → New website, choose Git deploy, enter the Repository URL and Branch (and Root directory if
go.modis in a subfolder), then click Create website. For an existing website, use its Deploy tab. - ZoPanel detects Go from
go.modand builds the first release. - 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 themodulepath ingo.mod(github.com/acme/api→api), orapp.- 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 toPATHwhen the app starts, so aProcfileline such asweb: apiworks. Aweb:line in aProcfilealways 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=0produces a static binary. Packages that need cgo (for examplegithub.com/mattn/go-sqlite3) needCGO_ENABLED=1and a C compiler on the server; prefer pure-Go alternatives such asmodernc.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. |