Boilerplate for how I like to write a backend web service.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
AJ ONeal 80977071ff update go-gitver 1 week ago
assets add more CLI options and API scaffolding 1 week ago
examples add more CLI options and API scaffolding 1 week ago
internal add more CLI options and API scaffolding 1 week ago
public add more CLI options and API scaffolding 1 week ago
tools add more CLI options and API scaffolding 1 week ago
vendor update go-gitver 1 week ago
.gitignore add more CLI options and API scaffolding 1 week ago
.goreleaser.yml add more CLI options and API scaffolding 1 week ago
.ignore add more CLI options and API scaffolding 1 week ago
.prettierignore initial commit 1 month ago
.prettierrc initial commit 1 month ago
AUTHORS update LICENSE and AUTHORS 3 weeks ago
LICENSE initial commit 1 month ago
README.md add /api/version 1 week ago
doc.go add more CLI options and API scaffolding 1 week ago
go.mod update go-gitver 1 week ago
go.sum update go-gitver 1 week ago
main.go remove extraneous version newline 1 week ago

README.md

GoServ

“golang gopher with goggles”

Boilerplate for how I like to write a backend web service

Build

Goreleaser

See https://webinstall.dev/goreleaser

Local-only

goreleaser --snapshot --skip-publish --rm-dist

Publish

# Get a token at https://github.com/settings/tokens
export GITHUB_TOKEN=xxxxxxx

# Remove --snapshot to error on non-clean releases
goreleaser --snapshot --rm-dist

The platform, publish URL, and token file can be changed in .goreleaser.yml:

env_files:
    gitea_token: ~/.config/goreleaser/gitea_token
gitea_urls:
    api: https://try.gitea.io/api/v1/

Manually

git clone ssh://gitea@git.coolaj86.com:22042/coolaj86/goserv.git ./goserv
pushd ./goserv
bash ./examples/build.sh
export GOFLAGS="-mod=vendor"
go mod tidy
go mod vendor
go generate -mod=vendor ./...
go build -mod=vendor -o dist/goserv .

To build for another platform (such as Raspberry Pi) set GOOS and GOARCH`:

GOOS=linux GOARCH=arm64 go build -mod=vendor -o dist/goserv-linux-arm64 .

Run

./dist/goserv run --listen :3000 --trust-proxy --serve-path ./overrides

Examples and Config Templates

The example files are located in ./examples

  • Caddyfile (web server config)
  • .env (environment variables)
  • build.sh
export BASE_URL=https://example.com

Authentication

You can use an OIDC provider or sign your own tokens.

go install -mod=vendor git.rootprojects.org/root/keypairs/cmd/keypairs

# Generate a keypair
keypairs gen -o key.jwk.json --pub pub.jwk.json

Create an Admin token:

# Sign an Admin token
echo '{ "sub": "random_ppid", "email": "me@example.com", "iss": "'"${BASE_URL}"'" }' \
    > admin.claims.json
keypairs sign --exp 1h ./key.jwk.json ./admin.claims.json > admin.jwt.txt 2> admin.jws.json

# verify the Admin token
keypairs verify ./pub.jwk.json ./admin.jwt.txt

Create a User token:

# Sign a User token
echo '{ "sub": "random_ppid", "email": "me@example.com", "iss": "'"${BASE_URL}"'" }' \
    > user.claims.json
keypairs sign --exp 1h ./key.jwk.json ./user.claims.json > user.jwt.txt 2> user.jws.json

# verify the User token
keypairs verify ./pub.jwk.json ./user.jwt.txt

Impersonation can be accomplished by appending the token sub (aka PPID) to the url as ?user_id=.

REST API

All routes require authentication, except for those at /api/public.

Authentication: Bearer <token>

Here’s the API, in brief:

Base URL looks like https://example.com/api.

# Demo Mode Only
DELETE /public/reset                                    Drop database and re-initialize

# Public
GET  /public/ping                                       Health Check
POST /public/setup                  <= (none)           Bootstrap

# Admin-only
GET  /admin/ping                                        (authenticated) Health Check

# User
GET  /user/ping                                         (authenticated) Health Check

When you GET anything, it will be wrapped in the result.

Bootstrapping

The first user to hit the /api/setup endpoint will be the admin:

export TOKEN=$(cat admin.jwt.txt)
curl -X POST "${BASE_URL}/api/public/setup" -H "Authorization: Bearer ${TOKEN}"

Then the setup endpoint will be disabled:

curl -X POST "${BASE_URL}/api/public/setup" -H "Authorization: Bearer ${TOKEN}"

GoDoc

If the documentation is not public hosted you can view it with GoDoc:

godoc --http :6060

You can see abbreviated documentation with go's built-in doc, for example:

go doc git.example.com/example/goserv/internal/api

http://localhost:6060

Test

Create a test database. It must have test in the name.

DROP DATABASE "goserv_test"; CREATE DATABASE "goserv_test";

Run the tests:

export TEST_DATABASE_URL='postgres://postgres:postgres@localhost:5432/goserv_test'
go test -mod=vendor ./...

Dependencies

This setup can be run on a VPS, such as Digital Ocean, OVH, or Scaleway for $5/month with minimal dependencies:

  • VPS
  • Caddy
  • PostgreSQL
  • Serviceman

Mac, Linux:

curl -fsS https://webinstall.dev | bash
export PATH="$HOME:/.local/bin:$PATH"
webi caddy serviceman postgres

VPS Setup

You should have a domain pointing to a VPS and create a user account named app (because that’s a common convention). This script will create an app user, copying the authorized_keys from the root account.

my_vps='example.com'
ssh root@"$my_vps" 'curl -sS https://webinstall.dev/ssh-adduser | bash'

You can then login as a normal user.

ssh app@"$my_vps"

It is now safe to disable the root account.

Caddy (Automatic HTTPS Server)

curl -fsS https://webinstall.dev/caddy | bash

You can start Caddy as a system service under the app user like this:

sudo setcap 'cap_net_bind_service=+ep' "$(readlink $(command -v caddy))"

sudo env PATH="$PATH" \
    serviceman add --name caddy --username app \
    caddy run --config ./Caddyfile

See the Cheat Sheets at https://webinstall.dev/caddy and https://webinstall.dev/serviceman

PostgreSQL (Database)

curl -fsS https://webinstall.dev/postgres | bash

You can start Postgres as a system service under the app user like this:

sudo env PATH="$PATH" \
    serviceman add --name postgres --username app -- \
    postgres -D /home/app/.local/share/postgres/var -p 5432

Username and password are set to ‘postgres’ by default:

psql 'postgres://postgres:postgres@localhost:5432/postgres'

See the Cheat Sheets at https://webinstall.dev/postgres and https://webinstall.dev/serviceman

Licenses

Copyright 2020 The GoServ Authors. All rights reserved.

Exceptions

These are probably also in the Public Domain.
(gathering the official data from any source would yield the same dataset)