Deployment
ShipQ generates self-contained Go projects that can be deployed anywhere Go runs. The shipq docker command generates production-ready Dockerfiles to make containerized deployment straightforward.
Generating Dockerfiles
Section titled “Generating Dockerfiles”shipq dockerThis generates production Dockerfiles for your application:
Dockerfile(orDockerfile.server) — Multi-stage build for the HTTP serverDockerfile.worker— Multi-stage build for the background worker (if you’ve set upshipq workers)
The generated Dockerfiles use multi-stage builds to keep the final image small: the first stage compiles your Go binary, and the second stage copies only the binary into a minimal base image.
Building and Running
Section titled “Building and Running”Server only
Section titled “Server only”docker build -t myapp-server .docker run -p 8080:8080 \ -e DATABASE_URL="postgres://user:pass@db-host:5432/myapp" \ -e COOKIE_SECRET="your-secret-here" \ myapp-serverWith a background worker
Section titled “With a background worker”# Build both imagesdocker build -t myapp-server -f Dockerfile.server .docker build -t myapp-worker -f Dockerfile.worker .
# Run serverdocker run -p 8080:8080 \ -e DATABASE_URL="postgres://user:pass@db-host:5432/myapp" \ -e COOKIE_SECRET="your-secret-here" \ myapp-server
# Run workerdocker run \ -e DATABASE_URL="postgres://user:pass@db-host:5432/myapp" \ -e REDIS_URL="redis://redis-host:6379" \ myapp-workerEnvironment Variables
Section titled “Environment Variables”ShipQ-generated applications read configuration from environment variables in production. Here are the key variables you need to configure:
Required
Section titled “Required”| Variable | Description |
|---|---|
DATABASE_URL | Production database connection URL (Postgres, MySQL, or SQLite) |
COOKIE_SECRET | Secret key used to sign session cookies (must be kept secret) |
Authentication (if shipq auth was used)
Section titled “Authentication (if shipq auth was used)”| Variable | Description |
|---|---|
COOKIE_SECRET | HMAC secret for signing session cookies |
OAuth (if configured)
Section titled “OAuth (if configured)”| Variable | Description |
|---|---|
GOOGLE_CLIENT_ID | Google OAuth client ID |
GOOGLE_CLIENT_SECRET | Google OAuth client secret |
GOOGLE_REDIRECT_URL | Google OAuth callback URL (production URL) |
GITHUB_CLIENT_ID | GitHub OAuth app client ID |
GITHUB_CLIENT_SECRET | GitHub OAuth app client secret |
GITHUB_REDIRECT_URL | GitHub OAuth callback URL (production URL) |
File Uploads (if shipq files was used)
Section titled “File Uploads (if shipq files was used)”| Variable | Description |
|---|---|
S3_BUCKET | S3 bucket name |
S3_REGION | AWS region (e.g., us-east-1) |
S3_ENDPOINT | S3 endpoint URL (empty for AWS; set for MinIO, GCS, R2) |
AWS_ACCESS_KEY_ID | AWS access key |
AWS_SECRET_ACCESS_KEY | AWS secret key |
Workers & Channels (if shipq workers was used)
Section titled “Workers & Channels (if shipq workers was used)”| Variable | Description |
|---|---|
REDIS_URL | Redis connection URL for the job queue |
CENTRIFUGO_URL | Centrifugo API URL |
CENTRIFUGO_API_KEY | Centrifugo API key |
CENTRIFUGO_SECRET | Centrifugo HMAC secret for Centrifugo connection JWTs (separate from session cookies) |
Custom Environment Variables
Section titled “Custom Environment Variables”If you’ve declared additional required environment variables in shipq.ini:
[env]STRIPE_SECRET_KEY = requiredSENDGRID_API_KEY = requiredShipQ’s generated config loader validates these at startup. The application will refuse to start if any required variable is missing, giving you a clear error message instead of a silent runtime failure.
Database Considerations
Section titled “Database Considerations”Postgres (Recommended for Production)
Section titled “Postgres (Recommended for Production)”Postgres is the most battle-tested database for ShipQ applications:
DATABASE_URL="postgres://user:password@db-host:5432/myapp?sslmode=require"Use sslmode=require (or sslmode=verify-full) for production connections.
DATABASE_URL="mysql://user:password@tcp(db-host:3306)/myapp?tls=true"SQLite
Section titled “SQLite”SQLite works well for single-instance deployments or edge computing scenarios:
DATABASE_URL="sqlite:///data/myapp.db"Dev vs. Production Behavior
Section titled “Dev vs. Production Behavior”ShipQ-generated servers behave differently in production:
| Feature | Dev/Test | Production |
|---|---|---|
GET /openapi | ✅ Serves OpenAPI 3.1 JSON spec | ❌ Disabled |
GET /docs | ✅ Interactive API docs UI | ❌ Disabled |
| Admin UI | ✅ Available | ❌ Disabled |
| Error details | ✅ Verbose error messages | ❌ Generic error responses |
The environment is typically determined by a GO_ENV or equivalent environment variable. Check your generated cmd/server/main.go for the specific mechanism.
Docker Compose Example
Section titled “Docker Compose Example”For local development that mirrors production, you can use Docker Compose:
version: "3.8"services: db: image: postgres:16 environment: POSTGRES_USER: myapp POSTGRES_PASSWORD: secret POSTGRES_DB: myapp ports: - "5432:5432" volumes: - pgdata:/var/lib/postgresql/data
redis: image: redis:7-alpine ports: - "6379:6379"
server: build: . ports: - "8080:8080" environment: DATABASE_URL: "postgres://myapp:secret@db:5432/myapp?sslmode=disable" COOKIE_SECRET: "dev-secret-change-in-production" REDIS_URL: "redis://redis:6379" depends_on: - db - redis
worker: build: context: . dockerfile: Dockerfile.worker environment: DATABASE_URL: "postgres://myapp:secret@db:5432/myapp?sslmode=disable" REDIS_URL: "redis://redis:6379" depends_on: - db - redis
volumes: pgdata:Nix-Based Deployment
Section titled “Nix-Based Deployment”If you use Nix, ShipQ can generate a shell.nix for reproducible builds:
shipq nixThis pins your development environment to a specific nixpkgs revision, ensuring that all team members and CI systems use the exact same toolchain versions.
Pre-Deployment Checklist
Section titled “Pre-Deployment Checklist”Before deploying to production, make sure you have:
- All tests passing:
go test ./... -v -
DATABASE_URLpointing to your production database -
COOKIE_SECRETset to a strong, random value (not the dev default) - OAuth redirect URLs updated to production domains (if using OAuth)
- S3 credentials configured (if using file uploads)
- Redis and Centrifugo accessible (if using workers/channels)
- All
[env]required variables present - TLS/SSL enabled for database connections
- A reverse proxy (nginx, Caddy, or a cloud load balancer) in front of the Go server
Since ShipQ generates self-contained Go projects, your CI/CD pipeline doesn’t need ShipQ installed. A typical pipeline looks like:
# Install Go dependenciesgo mod download
# Run tests (needs a test database)go test ./... -v
# Build the binarygo build -o server ./cmd/server
# Build Docker imagedocker build -t myapp-server .
# Deploydocker push myapp-server:latestThe key insight is that ShipQ is a development-time tool. Once your code is generated and committed, the build and deployment pipeline only needs Go and Docker.