Boilerplate for how I like to write a backend web service.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
AJ ONeal 3d80901551 docs: update header gopher pilot image 2 年前
assets add more CLI options and API scaffolding 4 年前
examples add more CLI options and API scaffolding 4 年前
internal add more CLI options and API scaffolding 4 年前
public add more CLI options and API scaffolding 4 年前
tools add more CLI options and API scaffolding 4 年前
vendor update go-gitver 4 年前
.gitignore add more CLI options and API scaffolding 4 年前
.goreleaser.yml add more CLI options and API scaffolding 4 年前
.ignore add more CLI options and API scaffolding 4 年前
.prettierignore initial commit 4 年前
.prettierrc initial commit 4 年前
AUTHORS update LICENSE and AUTHORS 4 年前
LICENSE initial commit 4 年前
README.md docs: update header gopher pilot image 2 年前
doc.go add more CLI options and API scaffolding 4 年前
go.mod update go-gitver 4 年前
go.sum update go-gitver 4 年前
main.go remove extraneous version newline 4 年前

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)