Skip to main content
If you already have a Go app, you only need three things to deploy:
  1. A go.mod at the repo root.
  2. A main.go (at the root, or under cmd/<name>/main.go for monorepos).
  3. Your server listens on :$PORT and 0.0.0.0.
That’s it. Skip to Deploy below.

Starting from scratch

If you don’t have a Go app yet, here’s the smallest possible one:
mkdir hello-go && cd hello-go
go mod init github.com/yourname/hello-go
main.go:
main.go
package main

import (
    "fmt"
    "net/http"
    "os"
)

func main() {
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello from Go on Nubo!")
    })
    http.ListenAndServe(":"+port, nil)
}
Test it locally:
PORT=8080 go run .
# open http://localhost:8080
Commit and push to GitHub:
git init && git add . && git commit -m "init"
git remote add origin git@github.com:yourname/hello-go.git
git push -u origin main

Deploy

1

Open the New Frame modal

In your Nubo dashboard, open the Project and Space you want, then hit + Frame.
2

Pick the repo and branch

Connect your GitHub repo. The branch you pick is the one Nubo watches for pushes.
3

Confirm the port

Should match the port your app actually listens on (8080 for the example above).
4

Deploy

Hit deploy. The first build takes 30–60 seconds. You can follow it in the Logs tab.
Once the build finishes, your app is live at a *.nubo.onl URL shown in the dashboard. To redeploy, push to your tracked branch.

Monorepos and multiple binaries

If your repo has more than one binary (cmd/api/main.go, cmd/worker/main.go), Raypacks picks the alphabetically first one by default. Pin a specific binary with nubo.toml:
nubo.toml
[build]
entrypoint = "./cmd/api"
Deploy each binary as a separate Frame. They get their own URLs, env vars, and deploy history.

Things that trip people up

  • Hardcoded port. http.ListenAndServe(":8080", nil) works only if your Frame’s port is also 8080. Read os.Getenv("PORT") to be safe.
  • Binding to localhost. Listen on 0.0.0.0 (or empty host like ":8080"), not 127.0.0.1. Nothing outside the container can reach localhost.
  • Library repos. If your repo has no main.go anywhere, Raypacks won’t pick it up. You need a package main somewhere with a main().
  • CGO. The Go pack builds with CGO_ENABLED=0. If you depend on a C library, switch the Frame’s Builder to Paketo for now.

How the build works

This guide uses the Go pack of Raypacks, Nubo’s default builder. It produces a static binary on a scratch image. No Dockerfile, no go.mod version pinning, no BP_* env vars. If you need something the Go pack doesn’t support yet (ARM, custom -ldflags, CGO), switch the Frame’s Builder to Paketo in Frame Settings.