Skip to content

Setup wizard

The setup wizard, goiabada-setup, asks you a few questions and writes the configuration for your deployment, with every key and password already generated.

  1. Download the wizard for your platform.

    Terminal window
    curl -LO https://github.com/leodip/goiabada/releases/latest/download/goiabada-setup-linux-amd64
    chmod +x goiabada-setup-linux-amd64

    Every release has the same five binaries on the releases page.

  2. Run it in the directory where you want the files, and answer the questions. Pressing Enter takes the default shown in brackets.

    Terminal window
    ./goiabada-setup-linux-amd64
  3. Check the summary and answer yes to “Generate configuration files?”.

  4. Start Goiabada with the command the wizard prints at the end. It also prints both URLs and where to find the admin password.

  5. Sign in to the admin console.

The first question picks one of four deployments. Each writes its own files, in the current directory unless you pass --output.

Deployment Use it for Files it writes
1. Local testing Trying Goiabada on your machine. Plain HTTP on localhost. The Quickstart walks through it. docker-compose.yml and docker-compose.override.yml
2. Production with reverse proxy Docker Compose behind a proxy that serves HTTPS, such as Nginx or Cloudflare. docker-compose.yml and docker-compose.override.yml
3. Kubernetes cluster A cluster with Envoy Gateway and cert-manager. goiabada-k8s.yaml and goiabada-secrets.yaml
4. Native binaries Running the two binaries yourself, without containers. goiabada.env

The wizard asks only the questions that apply to your deployment, in this order, each under its step’s heading.

Question Asked for Default
Deployment type Every deployment. See Deployment types. 1, Local testing (--type has none)
Database type Every deployment. MySQL, PostgreSQL, SQL Server or SQLite. Kubernetes doesn’t offer SQLite. 1, MySQL (--db has none)
Domain names The auth server’s and the admin console’s URLs, for every deployment but local testing, which uses http://localhost:9090 and http://localhost:9091. On Kubernetes, each URL needs a host of its own. https://auth.example.com, then the admin console’s on the same domain: https://admin.example.com
Kubernetes namespace Kubernetes goiabada
Gateway traffic policy Kubernetes. Cluster works behind every load balancer, but Goiabada then sees a node’s address for every client. Local runs Envoy on every node and keeps each client’s own address, behind a load balancer that passes connections through rather than proxying them. Cluster
Network policy Kubernetes. Yes admits only Envoy to both servers, and the admin console to the auth server. It needs a network plugin that enforces NetworkPolicies. No
Reverse proxy Native binaries. Yes has both servers listen on 127.0.0.1 and trust the proxy’s forwarded headers. No has them listen on every interface and trust no forwarded header, and you set up their HTTPS yourself. Yes
Rate limiter Every deployment but local testing, which leaves it off. See why it’s off under Cluster. On, but off on Kubernetes under the Cluster policy
Metrics Kubernetes. None, pod annotations, or a PodMonitor for the Prometheus Operator. See Monitoring. None
Admin credentials Every deployment: the admin’s email and password. [email protected] for local testing, otherwise admin@ and the auth server’s domain. A generated password.
Database connection Kubernetes and native binaries, with any database but SQLite: host, port, name, user, password, TLS mode and, for verify-ca and verify-full, a CA file. Then an optional connection test, which connects as the auth server will. If it fails, you can enter them all again. The database’s usual port and user, the name goiabada, the TLS mode prefer, and the system’s roots
Database password Local testing and production, with any database but SQLite. The wizard runs that database for you, and writes the TLS mode prefer. A generated password

The wizard writes GOIABADA_DB_TLS_MODE, which decides how the auth server protects its connection to MySQL, PostgreSQL or SQL Server. Where the database sits explains each mode.

  • Local testing and production write prefer. The database runs on the Compose file’s own network, so the connection never leaves the host.
  • Kubernetes and native binaries ask you to pick one of disable, prefer, require, verify-ca and verify-full. Only verify-full makes sure the auth server reached your database and nothing in between. For verify-ca and verify-full, the wizard then asks for a CA file: a PEM file of the authorities your database’s certificate chains to. Leave it blank to trust the system’s roots. The wizard refuses a file the auth server would refuse: one it can’t read, or one that holds no certificate.
  • Native binaries write the CA file’s absolute path as GOIABADA_DB_TLS_CA_FILE, so keep the file where it is.
  • Kubernetes copies the certificates into a goiabada-db-ca ConfigMap, mounts it read-only into the auth server’s pods at /etc/goiabada/db-ca/ca.pem, and names that path as GOIABADA_DB_TLS_CA_FILE. A private key in the same file isn’t copied.

The wizard warns you whenever the mode it writes checks no certificate.

The rate limiter under the Cluster traffic policy

Section titled “The rate limiter under the Cluster traffic policy”

The auth server’s limits counted by a user or an email apply whether the rate limiter is on or off: wrong one-time codes, wrong passwords per account, and password-reset and registration mails per address among them. The rate limiter adds the limits counted by an IP address.

Under the Cluster policy, Goiabada sees a node’s address for every client. The per-address limits would then count every user who arrives through one node together, and throttle sign-ins on a busy site. That’s why it’s off by default there. Turned on, it also limits wrong passwords per email from one network, and every client through a node counts as one network: 10 wrong passwords block an email’s password sign-ins for 15 minutes for every client through that node. See the rate limits.

The wizard keeps every secret in one file, and the rest of the configuration in another, so you can commit the second one.

  • Docker Compose: the secrets are in docker-compose.override.yml. Docker Compose merges it into docker-compose.yml by itself, so docker compose up -d starts both.
  • Kubernetes: the secrets are in goiabada-secrets.yaml. Apply it before the manifest, so no pod starts with an older copy of the Secrets; both files create the namespace: kubectl apply -f goiabada-secrets.yaml -f goiabada-k8s.yaml.
  • Native binaries: goiabada.env is a single file that holds everything, secrets included.

Every file the wizard writes can be read by its owner only. When it writes into a Git working tree, it warns you and prints the line to add to .gitignore. It never edits .gitignore itself.

Running the wizard again where its files already are writes new secrets over them, so it warns first and asks before going on; without prompts, it stops unless you pass --overwrite. A database seeded with the old secrets can’t be used with the new ones, and without another copy of the old AES key, the data it encrypts can never be read again. So back the files up first, then either start over with an empty database, or copy your existing secrets over the new ones, as Secrets describes. Never apply the new secrets file to a deployment that already runs.

With --output, the files go into the directory it names. When it names a file instead, the secrets file is named after it: compose.yaml gets compose.override.yaml, and my-k8s.yaml gets my-k8s-secrets.yaml.

The wizard never prints a password. The summary says only whether each one was set or generated, and the last message tells you where the admin password is.

When you type a password at a terminal, the wizard doesn’t show it. The admin password must be at least 15 characters and at most 72 bytes. The wizard refuses any other and asks again, because the auth server would refuse to start with it. A password without an uppercase letter, a lowercase letter, a digit and a symbol gets a warning, and you choose whether to keep it.

Pass --type and the wizard asks nothing: it takes every answer from the flags and the defaults. That’s useful in scripts and CI.

Terminal window
./goiabada-setup-linux-amd64 --type=kubernetes --db=postgres \
--auth-url=https://auth.example.com \
--db-host=postgres.default.svc --db-password-file=/run/secrets/db-password

Without --type, the wizard asks every question and reads only --output and --no-color, and asks rather than reading --overwrite.

Prefer a generated password, or a password file, to --admin-password and --db-password. A password on the command line lands in your shell history and, while the wizard runs, in the process list. A password file can be - to read standard input, and one trailing line break is dropped.

Terminal window
printf '%s' "$DB_PASSWORD" | ./goiabada-setup-linux-amd64 --type=native --db=postgres \
--auth-url=https://auth.example.com --db-host=localhost --db-password-file=-

The wizard exits with 0 when it’s done or when you abort it, 1 when it can’t finish, and 2 when it can’t read a flag. It writes nothing until every answer is valid.

Flag What it does
--type The deployment: local, production, kubernetes or native. Giving it turns off the questions.
--db The database: mysql, postgres, mssql or sqlite. Required with --type.
--auth-url The auth server’s URL. Required with --type, except for local.
--admin-url The admin console’s URL. Default: https://admin. and the auth server’s domain, so https://admin.example.com for https://auth.example.com. Required when the auth server’s host is an IP address or a single word.
--namespace Kubernetes: the namespace. Default: goiabada.
--admin-email The first administrator’s email. Default: [email protected] for local, otherwise admin@ and the auth server’s domain. Required when the auth server’s host is an IP address or a single word.
--admin-password The first administrator’s password. Generated when you leave it out.
--admin-password-file Reads the admin password from a file, or from standard input with -.
--db-host Kubernetes and native: the database’s host. Required unless the database is SQLite.
--db-port Kubernetes and native: the database’s port. Default: 3306, 5432 or 1433, for MySQL, PostgreSQL and SQL Server.
--db-name Kubernetes and native: the database’s name. Default: goiabada.
--db-user Kubernetes and native: the database user. Default: root, postgres or sa.
--db-password The database password. Generated when you leave it out.
--db-password-file Reads the database password from a file, or from standard input with -.
--db-tls-mode Kubernetes and native: how the auth server protects its database connection: disable, prefer, require, verify-ca or verify-full. Default: prefer.
--db-tls-ca-file Kubernetes and native, with --db-tls-mode verify-ca or verify-full: the PEM file of the authorities your database’s certificate is checked against. Default: the system’s roots.
--skip-db-test Skips the database connection test. Without it, a failed test warns and the files are still written.
--gateway-traffic-policy Kubernetes: cluster or local. Default: cluster.
--network-policy Kubernetes: admits only Envoy and the admin console to the servers, with NetworkPolicies.
--metrics Kubernetes: none, annotations or podmonitor. Default: none.
--podmonitor-labels Kubernetes, with --metrics=podmonitor: the labels your Prometheus selects PodMonitors by, such as release=kube-prometheus-stack.
--metrics-namespace Kubernetes, with metrics and --network-policy: the namespace your metrics scraper runs in. Default: monitoring.
--rate-limiter Production, Kubernetes and native: true or false. Default: true, except on Kubernetes under the cluster policy.
--local-proxy Native: true when a reverse proxy on the same machine forwards to Goiabada. Default: true.
--output, -o Where to write the files: a directory, or the name of the main file. Default: the current directory.
--no-color Turns off colored output.
--overwrite Without prompts: writes over output files that already exist, and the secrets in them. Without it, the wizard stops.
--version, -v Prints the wizard’s version.