Render, Heroku, and Railway
Docker is not required on any of these three. Each also has a
native runtime path that builds straight from your repo's Go source,
no Dockerfile involved. Pick whichever
your platform dashboard offers; both end up running the same binary
the same way.
Shared setup
-
Connect this repository. Choose Docker (uses the root
Dockerfile) or a native/Go runtime if your platform offers one; see each platform's section below for the exact build/start commands either way. -
Set
FITGUARD_CONFIGto the complete production YAML, pasted as one multi-line environment variable. See What goes where if you haven't yet. Reference secrets as${OPENAI_API_KEY}inside it, then add those secrets separately as their own env vars in the platform settings. -
Set
port: ${PORT}in the YAML and configure the platform health check as/healthz. - Use one instance first. Add Redis before adding replicas.
Render
Docker path: create a Web Service
from GitHub, choose Docker, and add environment variables under
Advanced. Render forwards traffic to the port in
PORT and provides HTTPS on its
onrender.com domain.
Native path (no Dockerfile, if your Render plan offers a Go environment): same Web Service flow, but choose Go instead of Docker, and set:
Build Command: go build -o fitguard ./cmd/fitguard Start Command: ./fitguard run
Render compiles the binary itself from this repo's go.mod
during the build step. There's no curl/install step to write, the same way
pip install -r requirements.txt needs no separate download step for a Python
service. Config still comes from FITGUARD_CONFIG, same as the Docker path.
FITGUARD_URL on your existing service's environment variables. See
using FitGuard alongside an existing Dockerfile for the
same idea applied to Docker.
For SQLite history (either path), attach a paid persistent disk under
Disks and mount it at
/var/data. Set
data_dir: /var/data. A disk is
single-instance and disables zero-downtime deploys, so do not scale
this service horizontally with the disk attached.
Heroku
Heroku dyno filesystems are ephemeral, so do not use Heroku for durable SQLite history. Add Heroku Key-Value Store or another TLS Redis service for shared budget state. The entry-level KVS plan is not persistent, so use a production plan when Redis durability matters.
Heroku's container path (below) is the one documented here in full; a classic Go buildpack path also exists on Heroku if you'd rather not use Docker, but isn't covered step-by-step in this guide.
heroku login heroku create fitguard-prod --stack container # config.production.yaml here is just a local file on your machine — name it # anything, it's never committed (see "What goes where" on the overview page): heroku config:set -a fitguard-prod \ FITGUARD_CONFIG="$(cat config.production.yaml)" \ OPENAI_API_KEY="..." heroku addons:create heroku-redis:mini -a fitguard-prod heroku container:login # Build on Apple Silicon for Heroku's x86_64 container runtime: docker build --platform linux/amd64 -t fitguard . heroku container:push web -a fitguard-prod heroku container:release web -a fitguard-prod
Heroku provides PORT and the add-on
provides REDIS_URL. The container image's
EXPOSE line is not the port configuration.
Check
https://<app>.herokuapp.com/healthz.
Railway
Create a service from this GitHub repository. Railway detects the root
Dockerfile and uses it automatically; delete or rename it in a
throwaway clone first if you'd rather Railway's own Nixpacks builder detect and build the Go
project directly (via go.mod) with no Dockerfile at all; both
produce the same running binary. Add
FITGUARD_CONFIG and secrets under
Variables either way. Generate a public domain and set the service health check
to /healthz.
Attach a Railway Volume at /var/data and
set data_dir: /var/data if SQLite history
must survive. Railway volumes cannot be used with replicas. For
multiple replicas, use Redis for budget and cache state and treat
SQLite dashboards as per-instance.