Open-source project
netlify/gotrue avatar
netlify/gotrue

GoTrue: user accounts as one small Go service and a pile of env vars

An JWT based API for managing users and issuing JWT tokens.

4,493 stars328 forksGoMIT

At a glance

What is it?
GoTrue is Netlify's MIT-licensed API written in Go, a self-standing service for user registration and authentication in Jamstack projects, built on OAuth2 and JWT and handling signup, authentication and custom user data. Everything is configured through a .env file or GOTRUE_ prefixed environment variables, from the JWT signing secret and token lifetime to four external OAuth providers and a full SMTP mailer, over a MySQL database.
Who is it for?
Deploy GoTrue when a static or Jamstack site needs real accounts without building an auth service, since signup, login, tokens, external providers and password recovery mail arrive in one small binary configured by environment. Note its constraints before committing, the database driver is MySQL only in this repository, tagged releases date to 2022 while development continues in the working tree, and tracing support is Datadog alone.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 29 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Auth as a standalone microservice

GoTrue is a small open source API written in Golang that acts as a self-standing API service for handling user registration and authentication for Jamstack projects, the architecture where the frontend is static and every dynamic concern belongs to an API. It is based on OAuth2 and JWT and handles user signup, authentication and custom user data, the three things a static site cannot do for itself. The multi-instance mode reveals the origin, an OPERATOR_TOKEN serves as a shared secret with an operator, usually Netlify, verifying that requests were proxied through it before trusting payload values, so the same binary served both Netlify's platform and self-hosted deployments. An API_EXPORT_SECRET can be set to allow exporting users for a migration to a different service, an exit door built into the entrance. The billing for the service is honest from the first paragraph, small, a single binary with a cobra CLI and a chi router, no framework ambitions, just enough process to hold a users table and a token endpoint.

Environment variables over file, with two exceptions

Configuration comes from a .env file, environment variables, or both, and the precedence rule is absolute, environment variables prefixed with GOTRUE_ always win over file values. The naming discipline has exactly two documented exceptions, PORT, the listen port defaulting to 8081, and LOG_LEVEL, the log verbosity defaulting to info with panic, fatal, error, warn, info and debug as choices, both living without the prefix. Everything else follows the scheme, SITE_URL for the base URL used to construct email links, API_HOST for the listen address, REQUEST_ID_HEADER to inherit a request ID from incoming requests, and LOG_FILE to direct logs to a path. The uniformity matters operationally, a deployment is fully described by one environment dump, and godotenv plus envconfig in the dependency list are the machinery making the file-or-variable duality work.

MySQL is the only driver

The database configuration is the least flexible part, DB_DRIVER is required and must be mysql, with DATABASE_URL beside it, a constraint that dates the design and anchors deployments to one engine. DB_NAMESPACE softens the coupling slightly by adding a prefix to all table names, letting a shared database host multiple instances. One operational rule is stated with emphasis, migrations are not applied automatically, so they must be run after building, ./gotrue migrate for a local binary or docker run --rm gotrue gotrue migrate for the container image, and the Dockerfile ships the migrations directory inside the image with GOTRUE_DB_MIGRATIONS_PATH pointing at it. The gobuffalo/pop ORM in the dependencies is the data layer, with the Cloud SQL proxy also present for Google-hosted MySQL. The migration commands, for both paths:

code
./gotrue migrate

and under Docker:

code
docker run --rm gotrue gotrue migrate

JWT knobs, groups, and the admin tier

Token behavior is env var driven end to end. JWT_SECRET is required, the signing key for every token issued. JWT_EXP sets validity in seconds, defaulting to 3600, one hour. JWT_AUD defines a default audience, and audiences double as a grouping mechanism, with JWT_ADMIN_GROUP_NAME naming the admin group, default admin, and JWT_DEFAULT_GROUP_NAME assigning every new user to a default group on creation. The group model is coarse but functional, an admin claim in the token plus a default tier for everyone else, enough for gating admin endpoints without a separate roles service. Rate limiting protects the token endpoint itself through GOTRUE_RATE_LIMIT_HEADER, choosing a request header to limit by, with the tollbooth library doing the counting.

Four external providers, and gitlab's extras

External authentication supports bitbucket, github, gitlab and google, configured per provider under the EXTERNAL_ namespace with an ENABLED flag, CLIENT_ID and SECRET from the provider's registration. Gitlab alone requires more, EXTERNAL_X_REDIRECT_URI for the OAuth2 redirect carrying code and state, and EXTERNAL_X_URL for the base URL used in constructing authorization and token requests, defaulting to gitlab.com, the knobs that make self-hosted Gitlab instances work as identity providers. None of the providers are required, and the configuration section is explicit that you provide the values only for those you enable, so the minimum deployment is email and password alone, with external identity added per provider as needed.

The mailer, with anti-spoofing built in

Email is optional but highly recommended for password recovery, and when enabled requires SMTP_ADMIN_EMAIL, HOST and PORT, with USER and PASS for authenticated servers. The details show operational experience, SMTP_MAX_FREQUENCY enforces a minimum interval of 900 seconds by default between confirmation or reset emails, damping resend abuse, and SMTP_RESERVED_DOMAINS lists domains that cannot be used as the sender address, preventing spoofing of domains your service owns, a small anti-phishing control most auth services omit. MAILER_AUTOCONFIRM skips email confirmation when set, and four URL path settings shape the links in invite, confirmation, recovery and email change mail, each defaulting to the site root, with customizable subject lines completing the template surface. The confirmation flow is the mailer's main job in practice, signups wait on a confirmation click unless autoconfirm short-circuits it, and the URL path settings exist so that link can land on a route the frontend actually implements rather than a bare domain root.

SAML in the tree, Datadog-only tracing, old tags

The dependency list tells the fuller story of where the project went beyond its README sections, gosaml2 and goxmldsig for SAML assertions, chi for routing, cobra for the CLI including that migrate subcommand, mailme for templating, and the metering directory in the source tree for usage accounting. Tracing is OpenTracing shaped but only the Datadog tracer is supported, configured through host, port, tags and service name variables. The Dockerfile builds on golang:1.25-alpine and ships an alpine:3.19 runtime as an unprivileged user, and an app.json beside it offers Heroku deployment. The release tags are old, v1.0.0 in December 2020 and v1.0.1 in February 2022, but development continues in the master branch, last pushed 2026-09-02, so the working tree, not the tags, defines the current software. For anyone evaluating age, the honest reading is that the last tagged release is four years old, the branch is a month old, and the changelog between them lives in the commit history rather than release notes, so review recent commits before deploying what the tags do not describe.

Editorial conclusion

Deploy GoTrue when a static or Jamstack site needs real accounts without building an auth service, since signup, login, tokens, external providers and password recovery mail arrive in one small binary configured by environment. Note its constraints before committing, the database driver is MySQL only in this repository, tagged releases date to 2022 while development continues in the working tree, and tracing support is Datadog alone. Verify the JWT secret handling and token lifetime fit your security posture, set SMTP reserved domains to prevent sender spoofing of domains you own, and remember migrations never run automatically, the explicit migrate command is part of every deployment.

Frequently asked questions

What is GoTrue?

GoTrue is a small open source API written in Go that serves as a self-standing user registration and authentication service for Jamstack projects, based on OAuth2 and JWT. It handles signup, authentication and custom user data, supports bitbucket, github, gitlab and google as external providers, and is configured through .env files and GOTRUE_ environment variables over a MySQL database.

How do you run GoTrue migrations?

Migrations are not applied automatically, so run them explicitly after building, with ./gotrue migrate for a local binary or docker run --rm gotrue gotrue migrate under Docker. The container image ships the migrations directory and points GOTRUE_DB_MIGRATIONS_PATH at it.

Which external login providers does GoTrue support?

Bitbucket, GitHub, GitLab and Google are supported, each enabled with EXTERNAL_X_ENABLED plus the client ID and secret from the provider. GitLab additionally requires a redirect URI and optionally a base URL for self-hosted instances, and no provider is mandatory.

Official sources

  1. License: MIT
  2. netlify/gotrue on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/netlify-gotrue.svg)](https://hysenlabs.com/projects/netlify-gotrue)