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
Goshrt can easily be deployed to NixOS server using module available in the flake.nix. Should provide instructions for traditional server and Docker.
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.
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
];
};
};
}
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
andconfig.services.goshrt.nginx.enable
is false both postgres and proxy must be setup manually.
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
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 && make test
go clean -testcache
ensures that all tests are run. Without it tests will be cached and for instance database migrations will not be run.
These commands are useful when working with test coverage in Go:
$ go tool cover -func cover.out // display test coverage in percentage
$ go tool cover -html="cover.out" // convert cover.out to html file with test coverage details