# Deploy a Go Webserver on Flakery

This guide will go over creating a go http server and serving it using flakery.

# Create a new directory and initialize a new flake

mkdir go-webserver
cd go-webserver
nix flake init -t github:getflakery/flakes#go-webserver
1
2
3

this will add the following files to your directory:

wrote: /home/alice/go-webserver/gomod2nix.toml
wrote: /home/alice/go-webserver/.envrc
wrote: /home/alice/go-webserver/default.nix
wrote: /home/alice/go-webserver/shell.nix
wrote: /home/alice/go-webserver/flakery.nix
wrote: /home/alice/go-webserver/flake.nix
wrote: /home/alice/go-webserver/.gitignore
wrote: /home/alice/go-webserver/main.go
wrote: /home/alice/go-webserver/go.mod
1
2
3
4
5
6
7
8
9

Lets take a moment to examine the files that were created and what they do.

# Project Structure

  • the gomod2nix.toml file is used to convert the go.mod file to a nix expression. This converts the go dependencies to nix dependencies.

  • the .envrc file is used to load the nix environment when using direnv. This is useful for setting up the environment for development.

  • the default.nix file is used to build the go project. This file is used by the flake.nix file to build the go project.

  • the shell.nix file is used to create a nix shell for the go project. This file is used by the flake.nix file to create a nix shell for the go project.

  • the flakery.nix file is used to create a nixos module for the go project. This file is used by the flake.nix file to create a nixos module for the go project.

  • the flake.nix file is used to create a flake for the go project. This file is used by the flake.nix file to create a flake for the go project.

  • the .gitignore file is used to ignore files when using git. This file is used by the flake.nix file to ignore files when using git.

  • the main.go file is used to create the go webserver. This file is used by the flake.nix file to create the go webserver.

  • the go.mod file is used to manage the go dependencies. This file is used by the flake.nix file to manage the go dependencies.

# Examining Build Configuration

In the flake.nix file in the project root, the go project's derivation is built using the callPackage (opens new window) design pattern.

# flake.nix






















 
 
 





















{
  description = "A basic gomod2nix flake";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";
  inputs.gomod2nix.url = "github:nix-community/gomod2nix";
  inputs.gomod2nix.inputs.nixpkgs.follows = "nixpkgs";
  inputs.gomod2nix.inputs.flake-utils.follows = "flake-utils";
  inputs.flakery.url = "github:getflakery/flakes";


  outputs = inputs@{ self, nixpkgs, flake-utils, gomod2nix, flakery }:
    (flake-utils.lib.eachDefaultSystem
      (system:
        let
          pkgs = nixpkgs.legacyPackages.${system};

          # The current default sdk for macOS fails to compile go projects, so we use a newer one for now.
          # This has no effect on other platforms.
          callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage;

          app = callPackage ./. {
            inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
          };
          appModule = (import ./flakery.nix) app;

        in
        {
          packages.default = app;
          devShells.default = callPackage ./shell.nix {
            inherit (gomod2nix.legacyPackages.${system}) mkGoEnv gomod2nix;
          };

          packages.nixosConfigurations.flakery = nixpkgs.lib.nixosSystem {
            system = system;
            modules = [
              flakery.nixosModules.flakery
              appModule
            ];
          };

        })
    );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

this app derivation is then used in two places:

  • passed int to the imported flakery.nix file to create a nixos module for the go project
  • used to create a default build target for this flake

# flake.nix

























 


 
















{
  description = "A basic gomod2nix flake";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";
  inputs.gomod2nix.url = "github:nix-community/gomod2nix";
  inputs.gomod2nix.inputs.nixpkgs.follows = "nixpkgs";
  inputs.gomod2nix.inputs.flake-utils.follows = "flake-utils";
  inputs.flakery.url = "github:getflakery/flakes";


  outputs = inputs@{ self, nixpkgs, flake-utils, gomod2nix, flakery }:
    (flake-utils.lib.eachDefaultSystem
      (system:
        let
          pkgs = nixpkgs.legacyPackages.${system};

          # The current default sdk for macOS fails to compile go projects, so we use a newer one for now.
          # This has no effect on other platforms.
          callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage;

          app = callPackage ./. {
            inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
          };
          appModule = (import ./flakery.nix) app;
        in
        {
          packages.default = app;
          devShells.default = callPackage ./shell.nix {
            inherit (gomod2nix.legacyPackages.${system}) mkGoEnv gomod2nix;
          };

          packages.nixosConfigurations.flakery = nixpkgs.lib.nixosSystem {
            system = system;
            modules = [
              flakery.nixosModules.flakery
              appModule
            ];
          };

        })
    );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

We can see the result of this default package defined on line 28 by running the command nix build in the project root. This will build the go project and create a result symlink in the project root.

nix build
1

run the result with the following command:

./result/bin/app
1

If we then examine the flakery.nix file, we can see that the app derivation is used to create a nixos module for the go project.

# flakery.nix

app:
{ config, lib, pkgs, ... }:
let
  flakeryDomain = builtins.readFile /metadata/flakery-domain;
in
{
  networking.firewall.allowedTCPPorts = [ 80 443 ];

  systemd.services.go-webserver = {
    description = "go webserver";
    after = [ "network.target" ];
    wantedBy = [ "multi-user.target" ];
    serviceConfig = {
      ExecStart = "${app}/bin/app";
      Restart = "always";
      KillMode = "process";
    };
  };

  services.caddy = {
    enable = true;
    virtualHosts."${flakeryDomain}".extraConfig = ''
      handle /* {
        reverse_proxy http://127.0.0.1:8080
      }
    '';
  };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

This file defines a function that takes an arguement app and returns a nixos module. Passing the app into flakery.dev like this ensures that the same derivation (package) is used when building locally and deploying on flakery.

The NixOS module we have defined contains a systemd service definition, which will be activated on boot. The service starts our app binary defined in our derivation, and the caddy service serves a reverse proxy and SSL certificate for the flakery domain.

Looking back at our flake.nix we can see that the NixOS module defined by flakery.nix used in the definition of the flake level NixOS configuration, called flakery. We have also inclued the flakery nixos module flakery.nixosModules.flakery to include the necessary boilerplate to configure NixOS to work on flakery.

# flake.nix

























 











 







{
  description = "A basic gomod2nix flake";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";
  inputs.gomod2nix.url = "github:nix-community/gomod2nix";
  inputs.gomod2nix.inputs.nixpkgs.follows = "nixpkgs";
  inputs.gomod2nix.inputs.flake-utils.follows = "flake-utils";
  inputs.flakery.url = "github:getflakery/flakes";


  outputs = inputs@{ self, nixpkgs, flake-utils, gomod2nix, flakery }:
    (flake-utils.lib.eachDefaultSystem
      (system:
        let
          pkgs = nixpkgs.legacyPackages.${system};

          # The current default sdk for macOS fails to compile go projects, so we use a newer one for now.
          # This has no effect on other platforms.
          callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage;

          app = callPackage ./. {
            inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
          };
          appModule = (import ./flakery.nix) app;
        in
        {
          packages.default = app;
          devShells.default = callPackage ./shell.nix {
            inherit (gomod2nix.legacyPackages.${system}) mkGoEnv gomod2nix;
          };

          packages.nixosConfigurations.flakery = nixpkgs.lib.nixosSystem {
            system = system;
            modules = [
              flakery.nixosModules.flakery
              appModule
            ];
          };

        })
    );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

Great! so in this project we have:

  • a go http server that we can build using nix
  • a nix flake that defines a NixOS configuration that runs that http server

Now all thats left is creating a git repository and deploying it on Flakery.

# Create a git repository and push your flake

Initialize a git repository and create an initial commit.

git init
git add .
git commit -m "initial commit"
1
2
3

Create a new repository on GitHub (opens new window) and push your flake to the repository.

git branch -M main
git remote add origin git@github.com:$YOUR_USERNAME/go-webserver.git
git push -u origin main
1
2
3

TIP

Replace $YOUR_USERNAME with your Github username.

Now that you have created a flake and pushed it to a git repository, you can deploy it on Flakery.

# Deploy your NixOS Configuration on Flakery

# Create a Deployment Template

To deploy a NixOS configuration on Flakery, you need to create a deployment template. You can do this by visiting the Flakery website (opens new window) and adding your flake to the input field. the url should look something like this: github:$YOUR_USERNAME/go-webserver#flakery.

Alt text

TIP

Replace $YOUR_USERNAME with your Github username.

You should see your newly created deployment template below.

Alt text

# Deploy your NixOS Configuration

Click on the deployment template to view its details page.

Alt text

Click on the Create Deployment in the upper right hand corner of the screen to create a deployment of your nix flake. You should then see a deployment created at the bottom of your screen.

Alt text

Click on the the deployment to view its details

Alt text

after a few minutes, when the flake is finished applying, you can navigate to the domain linked in the deployment details page to view your Hello World web server's response.

Alt text