mosswill/bond

By mosswill

Updated 6 months ago

Self-hostable headless QR code generator

Image
API Management

148

Bond

Self-hostable headless QR code generator
Generate QR codes with a one-endpoint API

Introduction

Bond is a tiny, simple, and self-hostable service that enables you to generate QR codes by calling an API. It was born out of a need to generate QR codes for my business when I couldn't find a fully free and secure API without limitations, along with Google shutting down their service. I also wanted something rudimentary without gimmicks or customization (colors, redirection, logo, shapes, etc.), hence I decided to make it myself.

Features

Bond has all these features implemented :

  • Generate a QR code of any size with any content
  • Simple security using a defined secret to deter bots
  • Support for HTTP and HTTPS
  • Support for standalone / proxy deployment

On top of these, one may appreciate the following characteristics :

  • Written in Go
  • Holds in a single file with few dependencies
  • Holds in a ~14 MB compressed Docker image

For more information, read about Configuration and API Reference.

Deployment and Examples

Deploy with Docker

You can run Bond with Docker on the command line very quickly.

You can use the following commands :

# Create a .env file
touch .env

# Edit .env file ...

# Option 1 : Run Bond attached to the terminal (useful for debugging)
docker run --env-file .env -p <YOUR-PORT-MAPPING> mosswill/bond

# Option 2 : Run Bond as a daemon
docker run -d --env-file .env -p <YOUR-PORT-MAPPING> mosswill/bond
Deploy with Docker Compose

To help you get started quickly, multiple example docker-compose files are located in the "examples/" directory.

Here's a description of every example :

  • docker-compose.simple.yml: Run Bond as a front-facing service on port 80., with environment variables supplied in the docker-compose file directly.

  • docker-compose.volume.yml: Run Bond as a front-facing service on port 80, with environment variables supplied as a .env file mounted as a volume.

  • docker-compose.ssl.yml: Run Bond as a front-facing service on port 443, listening for HTTPS requests, with certificate and private key provided as mounted volumes.

  • docker-compose.proxy.yml: A full setup with Bond running on port 80, behind a proxy listening on port 443, and Gotenberg running as well while not being exposed to external requests.

When your docker-compose file is on point, you can use the following commands :

# Run Bond in the current terminal (useful for debugging)
docker-compose up

# Run Bond in a detached terminal (most common)
docker-compose up -d

# Show the logs written by Bond (useful for debugging)
docker logs <NAME-OF-YOUR-CONTAINER>
Deploy as a standalone application

Deploying Bond as a standalone application assumes the following prerequisites :

  • You have Go installed on your server
  • You have properly filled your .env file
  • Your DNS and networking configuration is on point

When all the prerequisites are met, you can run the following commands in your terminal :

# Retrieve the code
git clone https://github.com/will-moss/bond
cd bond

# Create a new .env file
cp sample.env .env

# Edit .env file ...

# Build the code into an executable
go build -o bond main.go

# Option 1 : Run Bond in the current terminal
./bond

# Option 2 : Run Bond as a background process
./bond &

# Option 3 : Run Bond using screen
screen -S bond
./bond
<CTRL+A> <D>

Configuration

To run Bond, you will need to set the following environment variables in a .env file located next to your executable :

Note : Regular environment variables provided on the commandline work too

ParameterTypeDescriptionDefault
SSLbooleanWhether HTTPS should be used in place of HTTP. When configured, Bond will look for certificate.pem and key.pem next to the executable for configuring SSL. Note that if Bond is behind a proxy that already handles SSL, this should be set to false.False
PORTintegerThe port Bond listens on.80
SECRETstringThe secret used to secure your Bond instance against bots / malicious usage. (This parameter can be left empty to disable security)a-very-long-and-complicated-secret
MAX_SIZEintegerThe max size for your QR codes, in pixels, such that a QR code can never be greater than MAX_SIZE x MAX_SIZE pixels.1024
RECOVERY_LEVELstringThe recovery level used to generate the QR codes. One of : Low, Medium, High, and Highest (case-insensitive).Medium
ENABLE_LOGSbooleanWhether all the HTTP requests should be displayed in the console / logs.TRUE

Note : Boolean values are case-insensitive, and can be represented via "ON" / "OFF" / "TRUE" / "FALSE" / 0 / 1.

Tip : You can generate a random secret with the following command :

head -c 1024 /dev/urandom | base64 | tr -cd "[:lower:][:upper:][:digit:]" | head -c 32

API Reference

Bond exposes the following API, consisting of a single endpoint :

Generate a QR code

  GET /
ParameterTypeDescription
secretstringRequired. Your server secret (can be empty if your SECRET setting is empty).
sizestringRequired. The size (in pixels) of the QR code to generate. (The QR code will be size x size pixels.)
contentstringRequired. The data to encode in the QR code.

The API will directly return the image representing the QR code generated using your settings.

Usage

To generate QR codes using Bond, you can copy and adapt the following examples :

curl
curl -o qr-code.png "https://bond.your-domain.tld/?content=YOUR-CONTENT&size=512&secret=YOUR-SECRET"
wget
wget -O qr-code.png "https://bond.your-domain.tld/?content=YOUR-CONTENT&size=512&secret=YOUR-SECRET"
Javascript
async function to_qrcode(text) {
  const url = `https://bond.your-domain.tld/?` + new URLSearchParams({
    size: 512,
    content: text,
    secret: 'YOUR-SECRET'
  });
  let response = await fetch(url);

  if (response.status !== 200) {
    console.log('HTTP-Error: ' + response.status);
    return null;
  }

  const blob = await response.blob();
  const objectURL = URL.createObjectURL(blob);

  const image = document.createElement('img');
  image.src = objectURL;

  const container = document.getElementById('YOUR-CONTAINER');
  container.append(image);
}

await to_qrcode("YOUR-CONTENT");

Troubleshoot

Should you encounter any issue running Bond, please refer to the following common problems that may occur.

If none of these matches your case, feel free to open an issue.

Bond is unreachable over HTTP / HTTPS

Please make sure that the following requirements are met :

  • If Bond runs as a standalone application without proxy :

    • Make sure your server / firewall accepts incoming connections on Bond's port.
    • Make sure your DNS configuration is correct. (Usually, such record should suffice : A bond XXX.XXX.XXX.XXX for https://bond.your-server-tld)
    • Make sure your .env file is well configured according to the Configuration section.
  • If Bond runs behind Docker / a proxy :

    • Perform the previous (standalone) verifications first.
    • Make sure that PORT (Bond's port) is well set in .env.
    • Check your proxy forwarding rules.

In any case, the crucial part is Configuration.

Bond returns an error 4xx instead of a QR code

Please make sure that :

  • You're using the GET HTTP method.
  • You've included the secret parameter, and the value of it equals the value of the SECRET defined in your .env.
  • The size you requested fits within the range 1 <= size <= MAX_SIZE.

Something else

Please feel free to open an issue, explaining what happens, and describing your environment.

Credits

Hey hey ! It's always a good idea to say thank you and mention the people and projects that help us move forward.

Big thanks to the individuals / teams behind these projects :

And don't forget to mention Bond if you like it or if it helps you in any way!

Docker Pull Command

docker pull mosswill/bond