goshrt
Self hosted URL shortener
❗ Work in progress!
This is my attempt at creating a self hosted URL shortener written in Go.
The goal is to support multiple domains, cache, a simple API for creating new entries and a command line client.
Even though I use this in production bugs should be expected.
Table of Contents
Install
Goshrt can easily be deployed to NixOS server using module available in the flake.nix.
Should provide instructions for traditional server and Docker.
Nix
There are several ways to install goshrt with Nix.
Two recommended approaches is using an overlay, which will work on both NixOS and Nix with another OS, or the included NixOS module.
Overlay
The overlay can be added to another flake like this:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
goshrt = {
url = "github:golang/goshrt";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = inputs@{ self, nixpkgs, goshrt}:
let
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [ goshrt.overlays.default ];
};
in {
# goshrt should now be available in pkgs
devShell."x86_64-linux" = pkgs.mkShell {
buildInputs = [
pkgs.goshrt
pkgs.goshrtc
];
};
};
}
Module
This is how the provided NixOS module can be used in another flake:
- Add goshrt as input in flake.nix
- Import goshrt service module
- Configure service, see
module.nix
for options
The following example enables goshrt module with postgres and nginx reverse proxy.
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
goshrt = {
url = "github:golang/goshrt";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = inputs@{ self, nixpkgs, goshrt }:
let
pkgs = import nixpkgs { system = "x86_64-linux"; };
in {
nixosConfigurations.mycomputer = pkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
goshrt.nixosModules.goshrt
({ pkgs, ... }: {
networking.firewall.allowedTCPPorts = [ 8080 ];
# Needed because of `nginx.virtualHosts..enableACME`
security.acme.acceptTerms = true;
security.acme.defaults.email = "goshrt@example.com";
services.goshrt = {
enable = true;
httpPort = 8080;
key = "qTGVn$a&hRJ9385C^z7L!MW5CnwZq3&$";
database = {
enable = true; # Let goshrt module setup postgresql service
host = "localhost";
port = 5432;
user = "goshrt";
password = "trhsog";
};
nginx = {
enable = true; # Enable automatic nginx proxy with SSL and LetsEncrypt certificates
hostnames = [ "examplename1.com" "examplename2.com" ];
extraConfig = { forceSSL = true; enableACME = true; };
};
};
})
];
};
};
}
Password for postgres user goshrt must be set manually.
This can be achieved with:
$ sudo -u postgres psql goshrt
> ALTER USER goshrt WITH PASSWORD 'trhsog';
This includes potsgres and nginx proxy. If config.services.goshrt.database.enable
and config.services.goshrt.nginx.enable
is false both postgres and proxy must be setup manually.
Development
Postgres
When doing local development/testing postgres has to be running.
While there are several ways to achieve this, VM / docker / podman, I myself use Nix.
Spinning up a development database is very simple in Nix shell.
After installing Nix, devshell is entered through the command nix develop
.
The following helpers for dealing with postgres is avilable:
$ pgnix-init # initiate database and start it
$ pgnix-start # start database
$ pgnix-status # check if database is running
$ pgnix-restart # restart database
$ pgnix-stop # stop postgresql database
$ pgnix-purge # stop database and delete it
$ pgnix-pgcli # start pgcli and connect to database
$ pgnix-psql # start psql and connect to database
Unit testing
Nix shell and pgnix-
wrappers makes running unit test in a clean environment very simple.
Inside nix develop
the following oneliner runs all unit tests:
$ pgnix-purge && pgnix-init && go clean -testcache && go test -v ./...
go clean -testcache
ensures that all tests are run.
Without it tests will be cached and for instance database migrations will not be run.