diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..796968e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+bin/*
+pkg
+releases
+src/github.com
diff --git a/README.md b/README.md
index e1fee1e..9d29474 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,23 @@
 RFLED-Server
-============
+==========
 
-Python Scripts to run UDP servers to emulate a LimitlessLED WiFi Bridge 4.0 unit.
+Golang binary to emulate a LimitlessLED WiFi Bridge 4.0 unit.
 
 Install
-=======
+----
+  1. Download the latest release from the [Releases](https://github.com/riptidewave93/RFLED-Server/releases)
+   page for your architecture.
+  2. Copy the contents of ./rfled-server/* to / on your disk as root
+  3. Configure your settings in /etc/default/rfled-server as needed
+  4. Enable the init.d script `systemctl enable rfled-server`
+  5. Start the service `service rfled-server start`
+  6. ???
+  7. Profit!
 
- * Change the variables in both scripts to meet your needs
- * Start the scripts and they will start the UDP listeners
-
-Startup Script
-==============
-
- * Place script into /etc/init.d/
- * a) Ensure scripts are in /usr/local/bin/ or
- * b) Adjust path in rfled-server script to path of the scripts
- * Run update-rc.d rfled-server defaults to set up
- 
-Running
-=======
-
- * Run "/etc/init.d/rfled-server start" to start scripts without a restart
+Build from Source
+----
+  1. Setup a go build environment, and run `./build.sh`
+  2. Once ran, you can run `./build.sh package` as root to generate a release .tar.gz
+  3. Follow the above Install steps with the tar.gz in ./releases for your architecture.
+  4. ?????
+  5. Profit!
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..6bd795e
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+# Set env vars for building
+export GOPATH=$PWD
+export GOBIN=$PWD/bin
+
+# Do we even have go installed?
+command -v go >/dev/null 2>&1 || { echo >&2 "I require go but it's not installed.  Aborting."; exit 1; }
+
+# Are we building or cleaning house?
+if [[ "$1" == "clean" ]]; then
+  rm $PWD/bin/* 2>/dev/null
+  rm -r $PWD/pkg 2>/dev/null
+  rm -fr $PWD/src/github.com 2>/dev/null
+  rm -r $PWD/releases 2>/dev/null
+else
+  # Download dependencies
+  if [ ! -d "$GOPATH/src/github.com/tarm/serial" ]; then
+    git clone https://github.com/tarm/serial.git $GOPATH/src/github.com/tarm/serial
+  fi
+
+  # Make required dir if needed
+  if [ ! -d "$GOBIN" ]; then
+    mkdir $GOBIN
+  fi
+
+  # build the things!
+  echo "Building amd64..."
+  env GOOS=linux GOARCH=amd64 go build -o $GOBIN/rfled-server-amd64 $PWD/src/rfled-server.go
+  echo "Building armv6..."
+  env GOOS=linux GOARCH=arm GOARM=6 go build -o $GOBIN/rfled-server-armv6 $PWD/src/rfled-server.go
+  echo "Building armv7..."
+  env GOOS=linux GOARCH=arm GOARM=7 go build -o $GOBIN/rfled-server-armv7 $PWD/src/rfled-server.go
+
+  # We finished!
+  if [ $? -eq 0 ]; then
+    echo "Build Complete! Binary is in $GOBIN"
+  fi
+
+  # Are we building shippable releases?
+  if [[ "$1" == "package" ]]; then
+    if [[ $EUID -ne 0 ]]; then
+      echo "Error, package mode must be ran as root" 1>&2
+      exit 1
+    fi
+    echo "Building Releases..."
+    for arch in amd64 armv6 armv7;
+    do
+      echo "Packaging $arch"
+      if [ ! -d "$GOPATH/releases/tmp/$arch/rfled-server/usr/sbin" ]; then
+          mkdir -p $GOPATH/releases/tmp/$arch/rfled-server/usr/sbin
+      fi
+      cp $GOBIN/rfled-server-$arch $GOPATH/releases/tmp/$arch/rfled-server/usr/sbin/rfled-server
+      chmod +x $GOPATH/releases/tmp/$arch/rfled-server/usr/sbin/rfled-server
+      cp -r $GOPATH/src/etc $GOPATH/releases/tmp/$arch/rfled-server/
+      chmod +x $GOPATH/releases/tmp/$arch/rfled-server/etc/init.d/rfled-server
+      chown -R root:root $GOPATH/releases/tmp/$arch/rfled-server
+      tar -pczf $GOPATH/releases/rfled-server-$arch-$(date +"%F-%H%M%S").tar.gz -C $GOPATH/releases/tmp/$arch ./rfled-server
+    done
+    rm -rf $GOPATH/releases/tmp/
+    echo "Done! :)"
+  fi
+fi
diff --git a/rfled-server b/rfled-server
deleted file mode 100755
index 97d4fa4..0000000
--- a/rfled-server
+++ /dev/null
@@ -1,33 +0,0 @@
-#! /bin/sh
-
-### BEGIN INIT INFO
-# Provides:          rfled-server
-# Required-Start:    $local_fs $remote_fs
-# Required-Stop:
-# Default-Start:     2 3 4 5
-# Default-Stop:
-# Short-Description: Provides a small python server for smart LED control
-# Description: Provides a small python server for smart LED control
-### END INIT INFO
-
-N=/etc/init.d/rfled-server
-RFLED_PATH=/usr/local/bin
-
-set -e
-
-case "$1" in
-  start)
-	# make sure privileges don't persist across reboots
-	/usr/bin/python3 ${RFLED_PATH}/led.py &
-	/usr/bin/python3 ${RFLED_PATH}/admin.py &
-	;;
-  stop|reload|restart|force-reload|status)
-	
-	;;
-  *)
-	echo "Usage: $N {start|stop|restart|force-reload|status}" >&2
-	exit 1
-	;;
-esac
-
-exit 0
diff --git a/source/admin.py b/source/admin.py
deleted file mode 100644
index 1d3ef01..0000000
--- a/source/admin.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env python
-
-import socket
-
-# Set admin server settings
-UDP_IP = '' # Leave empty for Broadcast support
-ADMIN_PORT = 48899
-
-# Local settings of your Raspberry Pi, used for app discovery
-INT_IP = '10.0.1.61'
-INT_MAC = '111a02bf232b'
-
-# Code Starts Here #
-
-# Create UDP socket, bind to it
-adminsock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
-adminsock.bind((UDP_IP, ADMIN_PORT))
-
-# Loop forever
-while True:
-    admindata, adminaddr = adminsock.recvfrom(64) # buffer size is 64 bytes
-    # Did we get a message?
-    if admindata is not None: 
-        # print("admin command: ", str(admindata)) # Debugging
-        # If the client app is syncing to a unit
-        if str(admindata).find("Link_Wi-Fi") != -1:
-            RETURN = INT_IP + ',' + INT_MAC + ',' # Return our IP/MAC 
-            # print("admin return: ", RETURN) # Debugging
-            adminsock.sendto(bytes(RETURN, "utf-8"),adminaddr) # Send Response
-        else:
-            adminsock.sendto(bytes('+ok', "utf-8"),adminaddr) # Send OK for each packet we get
-    else:
-        break
\ No newline at end of file
diff --git a/source/led.py b/source/led.py
deleted file mode 100644
index 34af0f6..0000000
--- a/source/led.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env python
-
-import socket
-import serial
-
-# Set LED Control server settings
-UDP_IP = '' # Leave empty for Broadcast support
-LED_PORT = 8899
-
-# Serial Settings
-TTL_PORT = "/dev/ttyAMA0"
-TTL_SPEED = 9600
-ser = serial.Serial(TTL_PORT, TTL_SPEED) # Connect to serial
-
-# Create UDP socket, bind to it
-sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
-sock.bind((UDP_IP, LED_PORT))
-
-while True:
-    data, addr = sock.recvfrom(64) # buffer size is 64 bytes
-
-    if data is not None:
-        # print("led command: ", str(data)) # Debugging
-        ser.write(data[:2]) # Write packet data out (2 bytes only)
diff --git a/src/etc/default/rfled-server b/src/etc/default/rfled-server
new file mode 100644
index 0000000..4923422
--- /dev/null
+++ b/src/etc/default/rfled-server
@@ -0,0 +1,6 @@
+# Default settings for rfled-server. This file is sourced by /bin/sh from
+# /etc/init.d/rfled-server.
+
+# Define any options you want to be used when running. You can run rfled-server -h
+# to get the list of available flags for this service.
+RFLED_OPTS=
diff --git a/src/etc/init.d/rfled-server b/src/etc/init.d/rfled-server
new file mode 100755
index 0000000..1139418
--- /dev/null
+++ b/src/etc/init.d/rfled-server
@@ -0,0 +1,114 @@
+#! /bin/sh
+
+### BEGIN INIT INFO
+# Provides:		rfled-server
+# Required-Start:	$remote_fs $syslog
+# Required-Stop:	$remote_fs $syslog
+# Default-Start:	2 3 4 5
+# Default-Stop:
+# Short-Description:	RFLED-Server for Milight LEDs
+### END INIT INFO
+
+set -e
+
+# /etc/init.d/rfled-server: start and stop the rfled-server service
+
+test -x /usr/sbin/rfled-server || exit 0
+( /usr/sbin/rfled-server -h 2>&1 | grep -q Usage ) 2>/dev/null || exit 0
+
+umask 022
+
+if test -f /etc/default/rfled-server; then
+    . /etc/default/rfled-server
+fi
+
+. /lib/lsb/init-functions
+
+if [ -n "$2" ]; then
+    RFLED_OPTS="$RFLED_OPTS $2"
+fi
+
+# Are we running from init?
+run_by_init() {
+    ([ "$previous" ] && [ "$runlevel" ]) || [ "$runlevel" = S ]
+}
+
+check_for_upstart() {
+    if init_is_upstart; then
+	exit $1
+    fi
+}
+
+export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
+
+case "$1" in
+  start)
+	check_for_upstart 1
+	log_daemon_msg "Starting rfled-server" "rfled-server" || true
+	if start-stop-daemon --start --quiet --oknodo --background --pidfile /var/run/rfled-server.pid --make-pidfile --exec /usr/sbin/rfled-server -- $RFLED_OPTS; then
+	    log_end_msg 0 || true
+	else
+	    log_end_msg 1 || true
+	fi
+	;;
+  stop)
+	check_for_upstart 0
+	log_daemon_msg "Stopping rfled-server" "rfled-server" || true
+	if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/rfled-server.pid; then
+	    log_end_msg 0 || true
+	else
+	    log_end_msg 1 || true
+	fi
+	;;
+
+  restart)
+	check_for_upstart 1
+	log_daemon_msg "Restarting rfled-server" "rfled-server" || true
+	start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/rfled-server.pid
+	check_dev_null log_end_msg
+	if start-stop-daemon --start --quiet --oknodo --background --pidfile /var/run/rfled-server.pid --make-pidfile --exec /usr/sbin/rfled-server -- $RFLED_OPTS; then
+	    log_end_msg 0 || true
+	else
+	    log_end_msg 1 || true
+	fi
+	;;
+
+  try-restart)
+	check_for_upstart 1
+	log_daemon_msg "Restarting rfled-server" "rfled-server" || true
+	RET=0
+	start-stop-daemon --stop --quiet --retry 30 --pidfile /var/run/rfled-server.pid || RET="$?"
+	case $RET in
+	    0)
+		# old daemon stopped
+		check_dev_null log_end_msg
+		if start-stop-daemon --start --quiet --oknodo --background --pidfile /var/run/rfled-server.pid --make-pidfile --exec /usr/sbin/rfled-server -- $RFLED_OPTS; then
+		    log_end_msg 0 || true
+		else
+		    log_end_msg 1 || true
+		fi
+		;;
+	    1)
+		# daemon not running
+		log_progress_msg "(not running)" || true
+		log_end_msg 0 || true
+		;;
+	    *)
+		# failed to stop
+		log_progress_msg "(failed to stop)" || true
+		log_end_msg 1 || true
+		;;
+	esac
+	;;
+
+  status)
+	check_for_upstart 1
+	status_of_proc -p /var/run/rfled-server.pid /usr/sbin/rfled-server rfled-server && exit 0 || exit $?
+	;;
+
+  *)
+	log_action_msg "Usage: /etc/init.d/rfled-server {start|stop|restart|try-restart|status}" || true
+	exit 1
+esac
+
+exit 0
diff --git a/src/rfled-server.go b/src/rfled-server.go
new file mode 100644
index 0000000..4fd320b
--- /dev/null
+++ b/src/rfled-server.go
@@ -0,0 +1,194 @@
+package main
+
+import (
+        "flag"
+        "log"
+        "net"
+        "os/exec"
+        "os/user"
+        "strconv"
+        "strings"
+        "time"
+        "github.com/tarm/serial"
+)
+
+// Logging function used by the application
+// w: false = log, true = fatal
+// x: debug flag
+// y: false = not debug output, true = debug output
+// z: message
+func applog(w bool, x bool, y bool, z string) {
+        if x && y {
+                if !w {
+                        log.Printf("DEBUG: %q \n", z)
+                } else {
+                        log.Fatal("DEBUG: ", z)
+                }
+        } else if !y {
+                if !w {
+                        log.Printf("%q \n", z)
+                } else {
+                        log.Fatal(z)
+                }
+        }
+}
+
+// Used to clean up all the error checks we do
+func error_check(err error, log bool) {
+        if err != nil {
+                applog(true, log, false, err.Error())
+        }
+}
+
+// Function to check and work with LED control packets
+func led_server(conn *net.UDPConn, log bool, s *serial.Port) {
+        buf := make([]byte, 64)
+        msg, remoteAddr, err := 0, new(net.UDPAddr), error(nil)
+        for err == nil {
+                msg, remoteAddr, err = conn.ReadFromUDP(buf)
+                error_check(err,log)
+                if buf != nil {
+                      applog(false, log, true, "LED: message was " + string(buf[:msg]) + " from " + remoteAddr.String())
+                      // Write to serial
+                      _, err = s.Write(buf[:msg])
+                      error_check(err,log)
+                }
+        }
+        error_check(err,log)
+}
+
+// Function to check and work with admin config packets
+func adm_server(conn *net.UDPConn, log bool, ip string, mac string) {
+        buf := make([]byte, 64)
+                msg, remoteAddr, err := 0, new(net.UDPAddr), error(nil)
+        for err == nil {
+                msg, remoteAddr, err = conn.ReadFromUDP(buf)
+                error_check(err,log)
+                if buf != nil {
+                        applog(false, log, true, "ADM: message was " + string(buf[:msg]) + " from " + remoteAddr.String())
+
+                        if strings.Contains(string(buf[:msg]),"Link_Wi-Fi") {
+                                _,err = conn.WriteToUDP([]byte(ip+","+mac+","),remoteAddr)
+                                error_check(err,log)
+                                applog(false, log, true, "ADM: replied "+ip+","+mac+",")
+                        } else {
+                                _,err = conn.WriteToUDP([]byte("+ok"),remoteAddr)
+                                error_check(err,log)
+                                applog(false, log, true, "ADM: replied +ok")
+                        }
+                }
+        }
+        error_check(err,log)
+}
+
+func main() {
+        // Set our UART vars
+        comport := flag.String("serial", "/dev/ttyAMA0", "Serial device to use")
+        comspeed := flag.Int("baud", 9600, "Serial baudrate")
+        debug := flag.Bool("debug", false, "Enable verbose debugging")
+
+        // Set our IP vars
+        ip := flag.String("ip", "0.0.0.0", "IP address to listen on (LED Server)")
+        interf := flag.String("int", "eth0", "Interface to listen on, used for mac address")
+        adm_port := flag.Int("admport", 48899, "Port for the admin server")
+        led_port := flag.Int("ledport", 8899, "Port for the led server")
+        flag.Parse()
+
+        // Check if we are root
+        usr,err := user.Current()
+        if err != nil {
+                applog(false, *debug, true, "Error with user.Current(), failing back...")
+                // If we are here, we are prob on arm which does NOT support user.Current()
+                usr, err := exec.Command("whoami").Output()
+                error_check(err,*debug)
+                if string(usr) != "root\n" {
+                        applog(false, *debug, true, "Current user us "+string(usr))
+                        applog(true, *debug, false, "Not running as root, exiting!")
+                }
+        } else if usr.Uid != "0" {
+                applog(true, *debug, false, "Not running as root, exiting!")
+        }
+
+        // Load our interface information based on user input, used for admin server
+        var ethz *net.Interface
+        if *ip == "0.0.0.0" {
+                // lookup interface using interf
+                ethz, err = net.InterfaceByName(*interf)
+                if err != nil {
+                        applog(true, *debug, false, "Error, unable to lookup interface "+*interf+"!")
+                }
+                applog(false, *debug, true, "IntLookup vars: eth="+string(ethz.Name)+" ip="+*ip)
+        } else {
+                // lookup interface using IP
+                applog(false, *debug, true,"Looking up all interfaces")
+                list, err := net.Interfaces()
+                found := false
+                error_check(err,*debug)
+                for _, iface := range list {
+                        applog(false, *debug, true, "Int="+iface.Name)
+                        addrs, err := iface.Addrs()
+                        error_check(err,*debug)
+                        for _, addr := range addrs {
+                                applog(false, *debug, true, "  IP="+addr.String())
+                                if strings.Contains(addr.String(),*ip) {
+                                        applog(false, *debug, true, "Found our interface!")
+                                        ethz = &iface
+                                        found = true
+                                        break
+                                }
+                        }
+                }
+                if !found {
+                        applog(true, *debug, false, "Error, unable to find an interface with the IP of "+*ip)
+                }
+        }
+
+        // Once we found our Interface we can then get the IP/Mac (unless we have one manually set)
+        mymac := strings.Replace(ethz.HardwareAddr.String(),":","",-1)
+        if *ip == "0.0.0.0" {
+                addrs, err := ethz.Addrs()
+                error_check(err,*debug)
+                for _, addr := range addrs {
+                        // Find and remove the SubNet from the IP and set to var
+                        *ip = addr.String()[:strings.Index(addr.String(),"/")]
+                        break
+                }
+        }
+        // Make sure we got our mac! (sometimes lo will not return one)
+        if len(mymac) < 12 {
+                applog(true, *debug, false, "Error, unable to lookup mac address for interface!")
+        }
+        applog(false, *debug, true,"Our Info: mac="+mymac+" ip="+*ip)
+
+        // load serial connection
+        c := &serial.Config{Name: *comport, Baud: *comspeed}
+        s, err := serial.OpenPort(c)
+        error_check(err,*debug)
+
+        // Start Admin server
+        adm_addr, err := net.ResolveUDPAddr("udp", ":"+strconv.Itoa(*adm_port))
+        error_check(err,*debug)
+        adm_listen, err := net.ListenUDP("udp", adm_addr)
+        error_check(err,*debug)
+        defer adm_listen.Close()
+
+        // Start LED server
+        led_addr, err := net.ResolveUDPAddr("udp", *ip+":"+strconv.Itoa(*led_port))
+        error_check(err,*debug)
+        led_listen, err := net.ListenUDP("udp", led_addr)
+        error_check(err,*debug)
+        defer led_listen.Close()
+
+        // Start main app loop!
+        applog(false, *debug, false, "rfled-server started!")
+        for {
+                // Function for Admin Server
+                go adm_server(adm_listen, *debug, *ip, mymac)
+
+                // Function for LED Server
+                go led_server(led_listen, *debug, s)
+
+                // Sleep so we don't just EAT the CPU
+                time.Sleep(100 * time.Millisecond)
+        }
+}