Skip to main content

Go on Miren

Miren auto-detects Go apps from go.mod, builds them to a single binary at /bin/app, and ships it on a minimal runtime image — no Dockerfile required.

Let your agent do this

Ask your AI coding agent to "set up this Go app on Miren" after installing the Miren agent skills. It finds your main package, proposes a start command, wires up environment variables, and deploys — using this page as its reference.

Do you need a Dockerfile?

No. Miren detects Go from go.mod and compiles the binary for you. The Go version comes from the go directive in your go.mod (falling back to 1.23). Provide a Dockerfile.miren only for custom build steps — see Using Dockerfile.miren.

Set up the app

From your project root:

miren init
miren deploy

Preview what Miren detects — main package, version, entrypoint — without building:

miren deploy --analyze

Which package gets built

Miren looks for your main package in cmd/:

  1. If cmd/ has a single subdirectory, that one is built.
  2. If cmd/ has a subdirectory matching the app name, that one is built.
  3. Otherwise, Miren builds from the project root.

If your project has a vendor/ directory, Miren builds with -mod=vendor for faster, network-free builds.

Start command

The compiled binary is at /bin/app. Your server must bind to 0.0.0.0 on $PORT — Miren injects PORT and routes traffic to it. Read it with os.Getenv("PORT"):

port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Fatal(http.ListenAndServe("0.0.0.0:"+port, nil))

Use a Procfile to set flags or define additional processes:

# Run the compiled binary
web: /bin/app

# With flags
web: /bin/app -addr=0.0.0.0:$PORT

# Background worker
worker: /bin/app -mode=worker

See Services for running multiple processes.

Runtime files

The runtime image is minimal but carries your non-Go files (templates, migrations, static assets, data directories) alongside the binary so the app can read them at runtime relative to /app. Go source, go.mod, go.sum, and vendor/ are excluded — the compiled binary needs none of them.

Prefer go:embed for required assets

If your app depends on files it must have at runtime, embed them with go:embed rather than relying on them being copied. Embedded files are compiled into the binary and always present.

Environment variables

Set variables with miren env set-e for plain values, -s for secrets (masked in output and logs):

miren env set -e LOG_LEVEL=info
miren env set -s DATABASE_URL
miren env set -s API_TOKEN

miren env set -s API_TOKEN (no value) prompts with masked input. You can also declare variables in .miren/app.toml:

[[env]]
key = "DATABASE_URL"
value = ""
required = true
sensitive = true
description = "Postgres connection string"

See App Configuration — Environment Variables.

Agent quick reference

  • Detection: go.mod in the project
  • Version: parsed from the go directive in go.mod (fallback 1.23)
  • Binary: built to /bin/app; main package resolved from cmd/ (see rules above)
  • Vendored deps: vendor/ present → build uses -mod=vendor
  • Start command: web: /bin/app; bind 0.0.0.0:$PORT via os.Getenv("PORT")
  • Runtime files: non-Go files carried to /app; prefer go:embed for required assets
  • Env vars: miren env set -e KEY=VALUE, -s for secrets, or [[env]] in app.toml
  • Dockerfile: not needed; add Dockerfile.miren only for custom builds

Next steps