6.3 KiB
GoServ
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
- http://localhost:6060/pkg/git.example.com/example/goserv/
- http://localhost:6060/pkg/git.example.com/example/goserv/internal/api
- http://localhost:6060/pkg/git.example.com/example/goserv/internal/db
You can see abbreviated documentation with go
's built-in doc
, for example:
go doc git.example.com/example/goserv/internal/api
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
countries.json
LGPL, taken from https://github.com/stefangabos/world_countriesflags.json
MIT, taken from https://github.com/matiassingers/emoji-flags
These are probably also in the Public Domain.
(gathering the official data from any source would yield the same dataset)