AI prompts
base on Reverse Tunnels in Go over HTTP/3 and QUIC reverst: HTTP reverse tunnels over QUIC
---------------------------------------
<p align="center">
<img width="300" height="300" src="./docs/gopher-glasses.svg" alt="Tunnel Gopher">
</p>
> Ti esrever dna ti pilf nwod gnaht ym tup i
Reverst is a (load-balanced) reverse-tunnel server and Go server-client library built on QUIC and HTTP/3.
- Go Powered: Written in Go using [quic-go](https://github.com/quic-go/quic-go)
- Compatible: The Go `client` package is built on `net/http` standard-library abstractions
- Load-balanced: Run multiple instances of your services behind the same tunnel
- Performant: Built on top of QUIC and HTTP/3
## Use-case
Reverst is for exposing services on the public internet from within restrictive networks (e.g. behind NAT gateways).
The tunnel binary is intended to be deployed on the public internet.
Client servers then dial out to the tunnels and register themselves on target tunnel groups.
A tunnel group is a load-balanced set of client-servers, which is exposed through the reverst tunnel HTTP interface.
## Client
[![Go Reference](https://pkg.go.dev/badge/go.flipt.io/reverst/client.svg)](https://pkg.go.dev/go.flipt.io/reverst/client)
The following section refers to the Go tunnel client code.
This can be added as a dependency to any Go code that requires exposing through a `reverstd` tunnel server.
### Install
```console
go get go.flipt.io/reverst/client
```
### Building
```console
go install ./client/...
```
## Server and CLI
### Building
The following builds both `reverstd` (tunnel server) and `reverst` (tunnel cli client).
```console
go install ./cmd/...
```
### Testing
Reverst uses Dagger to setup and run an integration test suite.
#### Unit
```console
dagger call testUnit --source=.
```
#### Integration
```console
dagger call testIntegration --source=.
```
The test suite sets up a tunnel, registers a server-client to the tunnel and then requests the service through the tunnels HTTP interface.
### Examples
Head over to the [examples](./examples) directory for some walkthroughs running `reverstd` and `reverst`.
### Usage and Configuration
#### Command-Line Flags and Environment Variables
The following flags can be used to configure a running instance of the `reverst` server.
```console
ā reverstd -h
COMMAND
reverstd
USAGE
reverstd [FLAGS]
FLAGS
-l, --log LEVEL debug, info, warn or error (default: INFO)
-a, --tunnel-address STRING address for accepting tunnelling quic connections (default: 127.0.0.1:7171)
-s, --http-address STRING address for serving HTTP requests (default: 0.0.0.0:8181)
-n, --server-name STRING server name used to identify tunnel via TLS (required)
-k, --private-key-path STRING path to TLS private key PEM file (required)
-c, --certificate-path STRING path to TLS certificate PEM file (required)
-g, --tunnel-groups STRING path to file or k8s configmap identifier (default: groups.yml)
-w, --watch-groups watch tunnel groups sources for updates
--management-address STRING HTTP address for management API
--max-idle-timeout DURATION maximum time a connection can be idle (default: 1m0s)
--keep-alive-period DURATION period between keep-alive events (default: 30s)
```
The long form names of each flag can also be referenced as environment variable names.
To do so, prefix them with `REVERST_`, replace each `-` with `_` and uppercase the letters.
For example, `--tunnel-address` becomes `REVERST_TUNNEL_ADDRESS`.
#### Tunnel Groups Configuration YAML
**configuring**
Currently, the tunnel groups configuration can be sourced from two different locations types (`file` and `k8s`).
Both tunnel group sources support watching sources for changes over time (see `-w` flag).
- Local filesystem (`file://[path]`)
The standard and simplest method is to point `reverstd` at your configuration YAML file on your machine via its path.
```console
reverstd -g path/to/configuration.yml
// alternatively:
reverstd -g file:///path/to/configuration.yml
```
- Kubernetes ConfigMap `k8s://configmap/[namespace]/[name]/[key]`
Alternatively, you can configure reverst to connect to a Kubernetes API server and fetch / watch configuration from.
```console
reverstd -g k8s://configmap/default/tunnelconfig/groups.yml
```
**defining**
The `reverstd` server take a path to a YAML encoded file, which identifies the tunnel groups to be hosted.
A tunnel group is a load-balancer on which tunneled servers can register themselves.
The file contains a top-level key groups, under which each tunnel group is uniquely named.
```yaml
groups:
"group-name":
hosts:
- "some.host.address.dev" # Host for routing inbound HTTP requests to tunnel group
authentication:
basic:
username: "user"
password: "pass"
```
Each group body contains import details for configuring the tunnel groups.
**hosts**
This is an array of strings which is used in routing HTTP requests to the tunnel group when one of the hostnames matches.
**authentication**
This identifies how to authenticate new tunnels attempting to register with the group.
Multiple authentication strategies can be enabled at once.
The following types are supported:
- `basic` supports username and password authentication (default scheme `Basic`)
- `bearer` supports static token based matching (default scheme `Bearer`)
- `external` supports offloading authentication and authorization to an external service (default scheme `Bearer`)
> [!Note]
> If enabling both `bearer` and `external` you will need to override one of their schemes to distinguish them.
<details>
<summary>Example configuration with multiple authentication strategies</summary>
The following contains all three strategies (basic, bearer and external) enabled at once with different schemes:
```yaml
groups:
"group-name":
hosts:
- "some.host.address.dev" # Host for routing inbound HTTP requests to tunnel group
authentication:
basic:
username: "user"
password: "pass"
bearer:
token: "some-token"
external:
scheme: "JWT"
endpoint: "http://some-external-endpoint/auth/ext"
```
</details>
If no strategies are supplied then authentication is disabled (strongly discouraged).
", Assign "at most 3 tags" to the expected json: {"id":"9220","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"