diff --git a/Makefile b/Makefile
index 33a2d6c2fafc7e5b46754bbb8dacba20e6064241..74c0c44375881dda56c12a8a810ce9c58fba6ecc 100644
--- a/Makefile
+++ b/Makefile
@@ -1,15 +1,20 @@
-.PHONY: all get build icon locales generate_locales clean
+.PHONY: all get build build_go icon locales generate_locales clean
+
+TAGS ?= gtk_3_18
 
 all: icon locales get build
 
 get:
-	go get -tags 'gtk_3_18' .
+	go get -tags $(TAGS) . ./bitmask_go
 
 build:
-	go build -tags 'gtk_3_18' -ldflags "-X main.version=`git describe --tags`"
+	go build -tags $(TAGS) -ldflags "-X main.version=`git describe --tags`"
 
 test:
-	go test -tags 'gtk_3_18' ./...
+	go test -tags $(TAGS) ./...
+
+build_go:
+	go build -tags "$(TAGS) bitmask_go" -ldflags "-X main.version=`git describe --tags`"
 
 clean:
 	make -C icon clean
diff --git a/bitmask/bitmask.go b/bitmask/bitmask.go
new file mode 100644
index 0000000000000000000000000000000000000000..f9b1cc9c7b20e109e04525af72bdb8c25478d711
--- /dev/null
+++ b/bitmask/bitmask.go
@@ -0,0 +1,29 @@
+// Copyright (C) 2018 LEAP
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package bitmask
+
+type Bitmask interface {
+	GetStatusCh() <-chan string
+	Close()
+	Version() (string, error)
+	StartVPN(provider string) error
+	StopVPN() error
+	GetStatus() (string, error)
+	InstallHelpers() error
+	VPNCheck() (helpers bool, priviledge bool, err error)
+	ListGateways(provider string) ([]string, error)
+	UseGateway(name string) error
+}
diff --git a/bitmask_go.go b/bitmask_go.go
new file mode 100644
index 0000000000000000000000000000000000000000..38ec289361dd5110dae6ff81aa7910b1350d0e3e
--- /dev/null
+++ b/bitmask_go.go
@@ -0,0 +1,26 @@
+// +build bitmask_go
+// Copyright (C) 2018 LEAP
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package main
+
+import (
+	"0xacab.org/leap/bitmask-systray/bitmask"
+	bitmask_go "0xacab.org/leap/bitmask-systray/bitmask_go"
+)
+
+func initBitmask() (bitmask.Bitmask, error) {
+	return bitmask_go.Init()
+}
diff --git a/bitmask_go/bonafide.go b/bitmask_go/bonafide.go
new file mode 100644
index 0000000000000000000000000000000000000000..25fa3023036453ff08ea1ce836419a8f3b2e9f9a
--- /dev/null
+++ b/bitmask_go/bonafide.go
@@ -0,0 +1,87 @@
+// Copyright (C) 2018 LEAP
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package bitmask
+
+import (
+	"crypto/tls"
+	"crypto/x509"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+)
+
+const (
+	certAPI = "https://api.black.riseup.net/1/cert"
+)
+
+var (
+	caCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBZMRgwFgYDVQQKDA9SaXNl
+dXAgTmV0d29ya3MxGzAZBgNVBAsMEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UE
+AwwXUmlzZXVwIE5ldHdvcmtzIFJvb3QgQ0EwHhcNMTQwNDI4MDAwMDAwWhcNMjQw
+NDI4MDAwMDAwWjBZMRgwFgYDVQQKDA9SaXNldXAgTmV0d29ya3MxGzAZBgNVBAsM
+Emh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UEAwwXUmlzZXVwIE5ldHdvcmtzIFJv
+b3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC76J4ciMJ8Sg0m
+TP7DF2DT9zNe0Csk4myoMFC57rfJeqsAlJCv1XMzBmXrw8wq/9z7XHv6n/0sWU7a
+7cF2hLR33ktjwODlx7vorU39/lXLndo492ZBhXQtG1INMShyv+nlmzO6GT7ESfNE
+LliFitEzwIegpMqxCIHXFuobGSCWF4N0qLHkq/SYUMoOJ96O3hmPSl1kFDRMtWXY
+iw1SEKjUvpyDJpVs3NGxeLCaA7bAWhDY5s5Yb2fA1o8ICAqhowurowJpW7n5ZuLK
+5VNTlNy6nZpkjt1QycYvNycffyPOFm/Q/RKDlvnorJIrihPkyniV3YY5cGgP+Qkx
+HUOT0uLA6LHtzfiyaOqkXwc4b0ZcQD5Vbf6Prd20Ppt6ei0zazkUPwxld3hgyw58
+m/4UIjG3PInWTNf293GngK2Bnz8Qx9e/6TueMSAn/3JBLem56E0WtmbLVjvko+LF
+PM5xA+m0BmuSJtrD1MUCXMhqYTtiOvgLBlUm5zkNxALzG+cXB28k6XikXt6MRG7q
+hzIPG38zwkooM55yy5i1YfcIi5NjMH6A+t4IJxxwb67MSb6UFOwg5kFokdONZcwj
+shczHdG9gLKSBIvrKa03Nd3W2dF9hMbRu//STcQxOailDBQCnXXfAATj9pYzdY4k
+ha8VCAREGAKTDAex9oXf1yRuktES4QIDAQABo2AwXjAdBgNVHQ4EFgQUC4tdmLVu
+f9hwfK4AGliaet5KkcgwDgYDVR0PAQH/BAQDAgIEMAwGA1UdEwQFMAMBAf8wHwYD
+VR0jBBgwFoAUC4tdmLVuf9hwfK4AGliaet5KkcgwDQYJKoZIhvcNAQENBQADggIB
+AGzL+GRnYu99zFoy0bXJKOGCF5XUXP/3gIXPRDqQf5g7Cu/jYMID9dB3No4Zmf7v
+qHjiSXiS8jx1j/6/Luk6PpFbT7QYm4QLs1f4BlfZOti2KE8r7KRDPIecUsUXW6P/
+3GJAVYH/+7OjA39za9AieM7+H5BELGccGrM5wfl7JeEz8in+V2ZWDzHQO4hMkiTQ
+4ZckuaL201F68YpiItBNnJ9N5nHr1MRiGyApHmLXY/wvlrOpclh95qn+lG6/2jk7
+3AmihLOKYMlPwPakJg4PYczm3icFLgTpjV5sq2md9bRyAg3oPGfAuWHmKj2Ikqch
+Td5CHKGxEEWbGUWEMP0s1A/JHWiCbDigc4Cfxhy56CWG4q0tYtnc2GMw8OAUO6Wf
+Xu5pYKNkzKSEtT/MrNJt44tTZWbKV/Pi/N2Fx36my7TgTUj7g3xcE9eF4JV2H/sg
+tsK3pwE0FEqGnT4qMFbixQmc8bGyuakr23wjMvfO7eZUxBuWYR2SkcP26sozF9PF
+tGhbZHQVGZUTVPyvwahMUEhbPGVerOW0IYpxkm0x/eaWdTc4vPpf/rIlgbAjarnJ
+UN9SaWRlWKSdP4haujnzCoJbM7dU9bjvlGZNyXEekgeT0W2qFeGGp+yyUWw8tNsp
+0BuC1b7uW/bBn/xKm319wXVDvBgZgcktMolak39V7DVO
+-----END CERTIFICATE-----`)
+)
+
+func getCertPem() ([]byte, error) {
+	certs := x509.NewCertPool()
+	certs.AppendCertsFromPEM(caCert)
+	client := &http.Client{
+		Transport: &http.Transport{
+			TLSClientConfig: &tls.Config{
+				RootCAs: certs,
+			},
+		},
+	}
+
+	resp, err := client.Post(certAPI, "", nil)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+
+	if resp.StatusCode != 200 {
+		return nil, fmt.Errorf("get vpn cert has failed with status: %s", resp.Status)
+	}
+
+	return ioutil.ReadAll(resp.Body)
+}
diff --git a/bitmask_go/bonafide_test.go b/bitmask_go/bonafide_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..c40c98da87b9af955e028728c7cede4e8a087a5f
--- /dev/null
+++ b/bitmask_go/bonafide_test.go
@@ -0,0 +1,26 @@
+package bitmask
+
+import (
+	"bytes"
+	"testing"
+)
+
+var (
+	privateKeyHeader = []byte("-----BEGIN RSA PRIVATE KEY-----")
+	certHeader       = []byte("-----BEGIN CERTIFICATE-----")
+)
+
+func TestGetCert(t *testing.T) {
+	cert, err := getCertPem()
+	if err != nil {
+		t.Fatal("get_cert returned an error: ", err)
+	}
+
+	if !bytes.Contains(cert, privateKeyHeader) {
+		t.Errorf("No private key present: \n%q", cert)
+	}
+
+	if !bytes.Equal(cert, certHeader) {
+		t.Errorf("No cert present: \n%q", cert)
+	}
+}
diff --git a/bitmask_go/launcher_linux.go b/bitmask_go/launcher_linux.go
new file mode 100644
index 0000000000000000000000000000000000000000..05398a68c6e643bc665f7a9a24463319696d6326
--- /dev/null
+++ b/bitmask_go/launcher_linux.go
@@ -0,0 +1,92 @@
+// +build linux
+// Copyright (C) 2018 LEAP
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package bitmask
+
+import (
+	"errors"
+	"log"
+	"os"
+	"os/exec"
+)
+
+const (
+	systemOpenvpnPath = "/usr/sbin/openvpn"
+	snapOpenvpnPath   = "/snap/bin/riseup-vpn.openvpn"
+)
+
+var bitmaskRootPaths = []string{
+	"/usr/sbin/bitmask-root",
+	"/usr/local/sbin/bitmask-root",
+	"/snap/bin/riseup-vpn.bitmask-root",
+}
+
+func openvpnStart(flags ...string) error {
+	log.Println("openvpn start: ", flags)
+	arg := []string{"openvpn", "start", getOpenvpnPath()}
+	arg = append(arg, flags...)
+	// TODO: check errors somehow instead of fire and forget
+	go runBitmaskRoot(arg...)
+	return nil
+}
+
+func openvpnStop() error {
+	log.Println("openvpn stop")
+	return runBitmaskRoot("openvpn", "stop")
+}
+
+func firewallStart(gateways []string) error {
+	log.Println("firewall start")
+	arg := []string{"firewall", "start"}
+	arg = append(arg, gateways...)
+	return runBitmaskRoot(arg...)
+}
+
+func firewallStop() error {
+	log.Println("firewall stop")
+	return runBitmaskRoot("firewall", "stop")
+}
+
+func runBitmaskRoot(arg ...string) error {
+	bitmaskRoot, err := bitmaskRootPath()
+	if err != nil {
+		return err
+	}
+	arg = append([]string{bitmaskRoot}, arg...)
+
+	cmd := exec.Command("pkexec", arg...)
+	err = cmd.Run()
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func bitmaskRootPath() (string, error) {
+	for _, path := range bitmaskRootPaths {
+		if _, err := os.Stat(path); !os.IsNotExist(err) {
+			return path, nil
+		}
+	}
+	return "", errors.New("No bitmask-root found")
+}
+
+func getOpenvpnPath() string {
+	if os.Getenv("SNAP") != "" {
+		return snapOpenvpnPath
+	}
+	return systemOpenvpnPath
+}
diff --git a/bitmask_go/main.go b/bitmask_go/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..49f803a688e9cd68178b42d9918baedef4dddd11
--- /dev/null
+++ b/bitmask_go/main.go
@@ -0,0 +1,78 @@
+// Copyright (C) 2018 LEAP
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package bitmask
+
+import (
+	"io/ioutil"
+	"log"
+	"os"
+
+	"github.com/apparentlymart/go-openvpn-mgmt/openvpn"
+)
+
+// Bitmask holds the bitmask client data
+type Bitmask struct {
+	tempdir          string
+	statusCh         chan string
+	managementClient *openvpn.MgmtClient
+}
+
+// Init the connection to bitmask
+func Init() (*Bitmask, error) {
+	statusCh := make(chan string, 10)
+	tempdir, err := ioutil.TempDir("", "leap-")
+	if err != nil {
+		return nil, err
+	}
+	b := Bitmask{tempdir, statusCh, nil}
+
+	err = b.StopVPN()
+	if err != nil {
+		return nil, err
+	}
+
+	cert, err := getCertPem()
+	if err != nil {
+		return nil, err
+	}
+	err = ioutil.WriteFile(b.getCertPemPath(), cert, 0600)
+	if err != nil {
+		return nil, err
+	}
+	err = ioutil.WriteFile(b.getCaCertPath(), caCert, 0600)
+
+	go b.openvpnManagement()
+	return &b, err
+}
+
+// GetStatusCh returns a channel that will recieve VPN status changes
+func (b *Bitmask) GetStatusCh() <-chan string {
+	return b.statusCh
+}
+
+// Close the connection to bitmask
+func (b *Bitmask) Close() {
+	b.StopVPN()
+	err := os.RemoveAll(b.tempdir)
+	if err != nil {
+		log.Printf("There was an error removing temp dir: %v", err)
+	}
+}
+
+// Version gets the bitmask version string
+func (b *Bitmask) Version() (string, error) {
+	return "", nil
+}
diff --git a/bitmask_go/status.go b/bitmask_go/status.go
new file mode 100644
index 0000000000000000000000000000000000000000..5a1ee3d3c19f9708353f339be4dccf380c756978
--- /dev/null
+++ b/bitmask_go/status.go
@@ -0,0 +1,91 @@
+// Copyright (C) 2018 LEAP
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package bitmask
+
+import (
+	"fmt"
+	"log"
+
+	"github.com/apparentlymart/go-openvpn-mgmt/openvpn"
+)
+
+const (
+	On       = "on"
+	Off      = "off"
+	Starting = "starting"
+	Stopping = "stopping"
+	Failed   = "failed"
+)
+
+var statusNames = map[string]string{
+	"CONNECTING":   Starting,
+	"WAIT":         Starting,
+	"AUTH":         Starting,
+	"GET_CONFIG":   Starting,
+	"ASSIGN_IP":    Starting,
+	"ADD_ROUTES":   Starting,
+	"CONNECTED":    On,
+	"RECONNECTING": Starting,
+	"EXITING":      Stopping,
+	"OFF":          Off,
+	"FAILED":       Off,
+}
+
+func (b *Bitmask) openvpnManagement() {
+	// TODO: we should warn the user on ListenAndServe errors
+	newConnection := func(conn openvpn.IncomingConn) {
+		eventCh := make(chan openvpn.Event, 10)
+		log.Println("New connection into the management")
+		b.managementClient = conn.Open(eventCh)
+		b.managementClient.SetStateEvents(true)
+		b.eventHandler(eventCh)
+	}
+	log.Fatal(openvpn.ListenAndServe(
+		fmt.Sprintf("%s:%s", openvpnManagementAddr, openvpnManagementPort),
+		openvpn.IncomingConnHandlerFunc(newConnection),
+	))
+}
+
+func (b *Bitmask) eventHandler(eventCh <-chan openvpn.Event) {
+	// TODO: we are reporing only openvpn status, missing firewall status
+	for event := range eventCh {
+		log.Printf("Event: %v", event)
+		stateEvent, ok := event.(*openvpn.StateEvent)
+		if !ok {
+			continue
+		}
+		status, ok := statusNames[stateEvent.NewState()]
+		if ok {
+			b.statusCh <- status
+		}
+	}
+	b.statusCh <- Off
+}
+
+func (b *Bitmask) getOpenvpnState() (string, error) {
+	if b.managementClient == nil {
+		return "", fmt.Errorf("No management connected")
+	}
+	stateEvent, err := b.managementClient.LatestState()
+	if err != nil {
+		return "", err
+	}
+	status, ok := statusNames[stateEvent.NewState()]
+	if !ok {
+		return "", fmt.Errorf("Unkonw status")
+	}
+	return status, nil
+}
diff --git a/bitmask_go/vpn.go b/bitmask_go/vpn.go
new file mode 100644
index 0000000000000000000000000000000000000000..09adcf0845398d4502cc5c01ea843b0a26263cda
--- /dev/null
+++ b/bitmask_go/vpn.go
@@ -0,0 +1,98 @@
+// Copyright (C) 2018 LEAP
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package bitmask
+
+import (
+	"path"
+)
+
+const (
+	openvpnManagementAddr = "127.0.0.1"
+	openvpnManagementPort = "6061"
+)
+
+var gateways = []string{
+	"5.79.86.180",
+	"199.58.81.145",
+	"198.252.153.28",
+}
+
+// StartVPN for provider
+func (b *Bitmask) StartVPN(provider string) error {
+	// TODO: openvpn args are hardcoded
+	err := firewallStart(gateways)
+	if err != nil {
+		return err
+	}
+
+	arg := []string{"--nobind", "--verb", "1"}
+	for _, gw := range gateways {
+		arg = append(arg, "--remote", gw, "443", "tcp4")
+	}
+	certPemPath := b.getCertPemPath()
+	arg = append(arg, "--client", "--tls-client", "--remote-cert-tls", "server", "--tls-cipher", "DHE-RSA-AES128-SHA", "--cipher", "AES-128-CBC", "--tun-ipv6", "--auth", "SHA1", "--keepalive", "10 30", "--management-client", "--management", openvpnManagementAddr+" "+openvpnManagementPort, "--ca", b.getCaCertPath(), "--cert", certPemPath, "--key", certPemPath)
+	return openvpnStart(arg...)
+}
+
+// StopVPN or cancel
+func (b *Bitmask) StopVPN() error {
+	err := firewallStop()
+	if err != nil {
+		return err
+	}
+	return openvpnStop()
+}
+
+// GetStatus returns the VPN status
+func (b *Bitmask) GetStatus() (string, error) {
+	status, err := b.getOpenvpnState()
+	if err != nil {
+		status = Off
+	}
+	return status, nil
+}
+
+// InstallHelpers into the system
+func (b *Bitmask) InstallHelpers() error {
+	// TODO
+	return nil
+}
+
+// VPNCheck returns if the helpers are installed and up to date and if polkit is running
+func (b *Bitmask) VPNCheck() (helpers bool, priviledge bool, err error) {
+	// TODO
+	return true, true, nil
+}
+
+// ListGateways return the names of the gateways
+func (b *Bitmask) ListGateways(provider string) ([]string, error) {
+	// TODO
+	return []string{}, nil
+}
+
+// UseGateway selects name as the default gateway
+func (b *Bitmask) UseGateway(name string) error {
+	// TODO
+	return nil
+}
+
+func (b *Bitmask) getCertPemPath() string {
+	return path.Join(b.tempdir, "openvpn.pem")
+}
+
+func (b *Bitmask) getCaCertPath() string {
+	return path.Join(b.tempdir, "cacert.pem")
+}
diff --git a/bitmaskd.go b/bitmaskd.go
new file mode 100644
index 0000000000000000000000000000000000000000..aa94ca0dea6453d2ec5c8ac6d90e9935fee1a0e3
--- /dev/null
+++ b/bitmaskd.go
@@ -0,0 +1,26 @@
+// +build !bitmask_go
+// Copyright (C) 2018 LEAP
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package main
+
+import (
+	"0xacab.org/leap/bitmask-systray/bitmask"
+	bitmaskd "0xacab.org/leap/bitmask-systray/bitmaskd"
+)
+
+func initBitmask() (bitmask.Bitmask, error) {
+	return bitmaskd.Init()
+}
diff --git a/bitmask/events.go b/bitmaskd/events.go
similarity index 100%
rename from bitmask/events.go
rename to bitmaskd/events.go
diff --git a/bitmask/main.go b/bitmaskd/main.go
similarity index 96%
rename from bitmask/main.go
rename to bitmaskd/main.go
index e0bf4a09feaf3098f9703b1599598b0d0591c454..2ff2268247c4e30030e053dce4444eef9e06db42 100644
--- a/bitmask/main.go
+++ b/bitmaskd/main.go
@@ -24,6 +24,8 @@ import (
 	"net/http"
 	"path"
 	"time"
+
+	"0xacab.org/leap/bitmask-systray/bitmask"
 )
 
 const (
@@ -62,7 +64,7 @@ func Init() (*Bitmask, error) {
 }
 
 // GetStatusCh returns a channel that will recieve VPN status changes
-func (b *Bitmask) GetStatusCh() chan string {
+func (b *Bitmask) GetStatusCh() <-chan string {
 	return b.statusCh
 }
 
@@ -148,7 +150,7 @@ func parseResponse(resJSON []byte) (interface{}, error) {
 
 func getToken() (string, error) {
 	var err error
-	path := path.Join(ConfigPath, "authtoken")
+	path := path.Join(bitmask.ConfigPath, "authtoken")
 	for i := 0; i < 30; i++ {
 		b, err := ioutil.ReadFile(path)
 		if err == nil {
diff --git a/bitmask/vpn.go b/bitmaskd/vpn.go
similarity index 100%
rename from bitmask/vpn.go
rename to bitmaskd/vpn.go
diff --git a/main.go b/main.go
index 5c8c74c5dcabb5a8f0e01207d08d1eba906fcf3a..617bdf1028f9f0715be3f86da5bf52da39e0fca5 100644
--- a/main.go
+++ b/main.go
@@ -62,7 +62,7 @@ func main() {
 
 	notify := newNotificator(conf)
 
-	b, err := bitmask.Init()
+	b, err := initBitmask()
 	if err != nil {
 		log.Print(err)
 		notify.bitmaskNotRunning()
@@ -74,7 +74,7 @@ func main() {
 	run(b, conf, notify)
 }
 
-func checkAndStartBitmask(b *bitmask.Bitmask, notify *notificator, conf *systrayConfig) {
+func checkAndStartBitmask(b bitmask.Bitmask, notify *notificator, conf *systrayConfig) {
 	err := checkAndInstallHelpers(b, notify)
 	if err != nil {
 		log.Printf("Is bitmask running? %v", err)
@@ -87,7 +87,7 @@ func checkAndStartBitmask(b *bitmask.Bitmask, notify *notificator, conf *systray
 	}
 }
 
-func checkAndInstallHelpers(b *bitmask.Bitmask, notify *notificator) error {
+func checkAndInstallHelpers(b bitmask.Bitmask, notify *notificator) error {
 	helpers, priviledge, err := b.VPNCheck()
 	if (err != nil && err.Error() == "nopolkit") || (err == nil && !priviledge) {
 		log.Printf("No polkit found")
@@ -106,7 +106,7 @@ func checkAndInstallHelpers(b *bitmask.Bitmask, notify *notificator) error {
 	return nil
 }
 
-func maybeStartVPN(b *bitmask.Bitmask, conf *systrayConfig) error {
+func maybeStartVPN(b bitmask.Bitmask, conf *systrayConfig) error {
 	if conf.UserStoppedVPN {
 		return nil
 	}
diff --git a/systray.go b/systray.go
index dd8a77cfe0a7c67bd2a66e58072e473744767277..aea8d04629cff40ce17be2271bd38397eb7a38ef 100644
--- a/systray.go
+++ b/systray.go
@@ -27,7 +27,7 @@ import (
 )
 
 type bmTray struct {
-	bm            *bitmask.Bitmask
+	bm            bitmask.Bitmask
 	conf          *systrayConfig
 	notify        *notificator
 	waitCh        chan bool
@@ -44,7 +44,7 @@ type gatewayTray struct {
 	name     string
 }
 
-func run(bm *bitmask.Bitmask, conf *systrayConfig, notify *notificator) {
+func run(bm bitmask.Bitmask, conf *systrayConfig, notify *notificator) {
 	bt := bmTray{bm: bm, conf: conf, notify: notify}
 	systray.Run(bt.onReady, bt.onExit)
 }
@@ -117,13 +117,13 @@ func (bt *bmTray) onReady() {
 				open.Run("https://riseup.net/vpn/donate")
 			case <-mAbout.ClickedCh:
 				bitmaskVersion, err := bt.bm.Version()
+				versionStr := version
 				if err != nil {
 					log.Printf("Error getting version: %v", err)
-					bt.notify.about(version)
-				} else {
-					versionStr := fmt.Sprintf("%s (bitmaskd %s)", version, bitmaskVersion)
-					bt.notify.about(versionStr)
+				} else if bitmaskVersion != "" {
+					versionStr = fmt.Sprintf("%s (bitmaskd %s)", version, bitmaskVersion)
 				}
+				bt.notify.about(versionStr)
 
 			case <-mQuit.ClickedCh:
 				systray.Quit()