diff --git a/Connector_HTTP/Makefile b/Connector_HTTP/Makefile
index 8de41895..9c30642e 100644
--- a/Connector_HTTP/Makefile
+++ b/Connector_HTTP/Makefile
@@ -1,17 +1,18 @@
-SRC = main.cpp ../util/socket.cpp ../util/http_parser.cpp ../util/flv_tag.cpp ../util/amf.cpp
+SRC = main.cpp ../util/socket.cpp ../util/http_parser.cpp ../util/flv_tag.cpp ../util/amf.cpp ../util/util.cpp
 OBJ = $(SRC:.cpp=.o)
 OUT = DDV_Conn_HTTP
 INCLUDES = 
 DEBUG = 4
 OPTIMIZE = -g
-CCFLAGS = -Wall -Wextra -funsigned-char $(OPTIMIZE) -DDEBUG=$(DEBUG)
+CCFLAGS = -Wall -Wextra -funsigned-char $(OPTIMIZE) -DDEBUG=$(DEBUG) -DVERSION=$(VERSION)
+VERSION = `git describe --tags`
 CC = $(CROSS)g++
 LD = $(CROSS)ld
 AR = $(CROSS)ar
 LIBS=
 .SUFFIXES: .cpp 
 .PHONY: clean default
-default: $(OUT)
+default: cversion $(OUT)
 .cpp.o:
 	$(CC) $(INCLUDES) $(CCFLAGS) $(LIBS) -c $< -o $@
 $(OUT): $(OBJ)
@@ -23,4 +24,6 @@ install: $(OUT)
 	cp -f ./$(OUT) /usr/bin/
 	cp -f ./HTTP_Conn /etc/init.d/
 	service HTTP_Conn start
+cversion:
+	rm -rf ../util/util.o
 
diff --git a/Connector_RTMP/Makefile b/Connector_RTMP/Makefile
index 319768ac..588797d0 100644
--- a/Connector_RTMP/Makefile
+++ b/Connector_RTMP/Makefile
@@ -1,18 +1,19 @@
-SRC = main.cpp ../util/socket.cpp ../util/flv_tag.cpp ../util/amf.cpp ../util/rtmpchunks.cpp ../util/crypto.cpp
+SRC = main.cpp ../util/socket.cpp ../util/flv_tag.cpp ../util/amf.cpp ../util/rtmpchunks.cpp ../util/crypto.cpp ../util/util.cpp
 OBJ = $(SRC:.cpp=.o)
 OUT = DDV_Conn_RTMP
 INCLUDES =
 STATIC =
 DEBUG = 4
 OPTIMIZE = -g
-CCFLAGS = -Wall -Wextra -funsigned-char $(OPTIMIZE) -DDEBUG=$(DEBUG)
+CCFLAGS = -Wall -Wextra -funsigned-char $(OPTIMIZE) -DDEBUG=$(DEBUG) -DVERSION=$(VERSION)
 CC = $(CROSS)g++
 LD = $(CROSS)ld
 AR = $(CROSS)ar
+VERSION = `git describe --tags`
 LIBS = -lssl -lcrypto
 .SUFFIXES: .cpp 
 .PHONY: clean default
-default: $(OUT)
+default: cversion $(OUT)
 .cpp.o:
 	$(CC) $(INCLUDES) $(CCFLAGS) -c $< -o $@
 $(OUT): $(OBJ)
@@ -24,4 +25,6 @@ install: $(OUT)
 	cp -f ./$(OUT) /usr/bin/
 	cp -f ./RTMP_Conn /etc/init.d/
 	service RTMP_Conn start
+cversion:
+	rm -rf ../util/util.o
 
diff --git a/DDV_Controller/Makefile b/DDV_Controller/Makefile
index da3ec0d7..521067db 100644
--- a/DDV_Controller/Makefile
+++ b/DDV_Controller/Makefile
@@ -15,10 +15,13 @@ AR = $(CROSS)ar
 LIBS = -lssl -lcrypto
 .SUFFIXES: .cpp 
 .PHONY: clean default
-default: $(OUT)
+default: cversion $(OUT)
 .cpp.o:
 	$(CC) $(INCLUDES) $(CCFLAGS) $(LIBS) -c $< -o $@
 $(OUT): $(OBJ)
 	$(CC) $(LIBS) -o $(OUT) $(OBJ)
 clean:
 	rm -rf $(OBJ) $(OUT) Makefile.bak *~
+cversion:
+	rm -rf ../util/util.o
+
diff --git a/DDV_Controller/main.cpp b/DDV_Controller/main.cpp
index c74ff6c2..f72f452a 100644
--- a/DDV_Controller/main.cpp
+++ b/DDV_Controller/main.cpp
@@ -30,9 +30,6 @@
 
 #define UPLINK_INTERVAL 30
 
-#define STRINGIFY(x) #x
-#define TOSTRING(x) STRINGIFY(x)
-
 Socket::Server API_Socket; ///< Main connection socket.
 
 /// Basic signal handler. Disconnects the server_socket if it receives
diff --git a/util/server_setup.cpp b/util/server_setup.cpp
index 34327442..75ac19fe 100644
--- a/util/server_setup.cpp
+++ b/util/server_setup.cpp
@@ -22,12 +22,11 @@
 #endif
 
 #include "socket.h" //Socket library
+#include "util.h" //utilities for process spawning and config management
 #include <signal.h>
 #include <sys/types.h>
 #include <pwd.h>
 #include <fstream>
-#define defstr(x) #x ///< converts a define name to string
-#define defstrh(x) "[" defstr(x) "]" ///< converts define name to [string]
 Socket::Server server_socket(-1); ///< Placeholder for the server socket
 
 /// Basic signal handler. Disconnects the server_socket if it receives
@@ -81,115 +80,28 @@ int main(int argc, char ** argv){
   sigaction(SIGTERM, &new_action, NULL);
   sigaction(SIGPIPE, &new_action, NULL);
   sigaction(SIGCHLD, &new_action, NULL);
-  
-  //default values
-  int listen_port = DEFAULT_PORT;
-  bool daemon_mode = true;
-  std::string interface = "0.0.0.0";
-  std::string configfile = "/etc/ddvtech.conf";
-  std::string username = "root";
-  bool ignore_daemon = false;
-  bool ignore_interface = false;
-  bool ignore_port = false;
-  bool ignore_user = false;
-  
-  int opt = 0;
-  static const char *optString = "ndp:i:u:c:h?";
-  static const struct option longOpts[] = {
-    {"help",0,0,'h'},
-    {"port",1,0,'p'},
-    {"interface",1,0,'i'},
-    {"username",1,0,'u'},
-    {"no-daemon",0,0,'n'},
-    {"daemon",0,0,'d'},
-    {"configfile",1,0,'c'}
-  };
-  while ((opt = getopt_long(argc, argv, optString, longOpts, 0)) != -1){
-    switch (opt){
-      case 'p': listen_port = atoi(optarg); ignore_port = true; break;
-      case 'i': interface = optarg; ignore_interface = true; break;
-      case 'n': daemon_mode = false; ignore_daemon = true; break;
-      case 'd': daemon_mode = true; ignore_daemon = true; break;
-      case 'c': configfile = optarg; break;
-      case 'u': username = optarg; ignore_user = true; break;
-      case 'h':
-      case '?':
-        printf("Options: -h[elp], -?, -n[odaemon], -d[aemon], -p[ort] VAL, -i[nterface] VAL, -c[onfigfile] VAL, -u[sername] VAL\n");
-        printf("Defaults:\n  interface: 0.0.0.0\n  port: %i\n  daemon mode: true\n  configfile: /etc/ddvtech.conf\n  username: root\n", listen_port);
-        printf("Username root means no change to UID, no matter what the UID is.\n");
-        printf("If the configfile exists, it is always loaded first. Commandline settings then overwrite the config file.\n");
-        printf("\nThis process takes it directives from the %s section of the configfile.\n", defstrh(CONFIGSECT));
-        return 1;
-        break;
-    }
-  }//commandline options parser
 
-  std::ifstream conf(configfile.c_str(), std::ifstream::in);
-  std::string tmpstr;
-  bool acc_comm = false;
-  size_t foundeq;
-  if (conf.fail()){
-    #if DEBUG >= 3
-    fprintf(stderr, "Configuration file %s not found - using build-in defaults...\n", configfile.c_str());
-    #endif
-  }else{
-    while (conf.good()){
-      getline(conf, tmpstr);
-      if (tmpstr[0] == '['){//new section? check if we care.
-        if (tmpstr == defstrh(CONFIGSECT)){acc_comm = true;}else{acc_comm = false;}
-      }else{
-        if (!acc_comm){break;}//skip all lines in this section if we do not care about it
-        foundeq = tmpstr.find('=');
-        if (foundeq != std::string::npos){
-          if ((tmpstr.substr(0, foundeq) == "port") && !ignore_port){listen_port = atoi(tmpstr.substr(foundeq+1).c_str());}
-          if ((tmpstr.substr(0, foundeq) == "interface") && !ignore_interface){interface = tmpstr.substr(foundeq+1);}
-          if ((tmpstr.substr(0, foundeq) == "username") && !ignore_user){username = tmpstr.substr(foundeq+1);}
-          if ((tmpstr.substr(0, foundeq) == "daemon") && !ignore_daemon){daemon_mode = true;}
-          if ((tmpstr.substr(0, foundeq) == "nodaemon") && !ignore_daemon){daemon_mode = false;}
-        }//found equals sign
-      }//section contents
-    }//configfile line loop
-  }//configuration
+  //set and parse configuration
+  Util::Config C;
+  C.confsection = TOSTRING(CONFIGSECT);
+  C.listen_port = DEFAULT_PORT;
+  C.parseArgs(argc, argv);
+  C.parseFile();
 
   //setup a new server socket, for the correct interface and port
-  server_socket = Socket::Server(listen_port, interface);
+  server_socket = Socket::Server(C.listen_port, C.interface);
   #if DEBUG >= 3
-  fprintf(stderr, "Made a listening socket on %s:%i...\n", interface.c_str(), listen_port);
+  fprintf(stderr, "Made a listening socket on %s:%i...\n", C.interface.c_str(), C.listen_port);
   #endif
-  if (server_socket.connected()){
-    //if setup success, enter daemon mode if requested
-    if (daemon_mode){
-      #if DEBUG >= 3
-      fprintf(stderr, "Going into background mode...\n");
-      #endif
-      daemon(1, 0);
-    }
-  }else{
+  if (!server_socket.connected()){
     #if DEBUG >= 1
     fprintf(stderr, "Error: could not make listening socket\n");
     #endif
     return 1;
   }
 
-  if (username != "root"){
-    struct passwd * user_info = getpwnam(username.c_str());
-    if (!user_info){
-      #if DEBUG >= 1
-      fprintf(stderr, "Error: could not setuid %s: could not get PID\n", username.c_str());
-      #endif
-      return 1;
-    }else{
-      if (setuid(user_info->pw_uid) != 0){
-        #if DEBUG >= 1
-        fprintf(stderr, "Error: could not setuid %s: not allowed\n", username.c_str());
-        #endif
-      }else{
-        #if DEBUG >= 3
-        fprintf(stderr, "Changed user to %s\n", username.c_str());
-        #endif
-      }
-    }
-  }
+  Util::setUser(C.username);
+  if (C.daemon_mode){Util::Daemonize();}
 
   while (server_socket.connected()){
     S = server_socket.accept();
diff --git a/util/util.cpp b/util/util.cpp
index 06a1ace1..9ac0997e 100644
--- a/util/util.cpp
+++ b/util/util.cpp
@@ -276,7 +276,7 @@ Util::Config::Config(){
 /// Assumes confsection is set.
 void Util::Config::parseArgs(int argc, char ** argv){
   int opt = 0;
-  static const char *optString = "ndp:i:u:c:h?";
+  static const char *optString = "ndvp:i:u:c:h?";
   static const struct option longOpts[] = {
     {"help",0,0,'h'},
     {"port",1,0,'p'},
@@ -284,7 +284,8 @@ void Util::Config::parseArgs(int argc, char ** argv){
     {"username",1,0,'u'},
     {"no-daemon",0,0,'n'},
     {"daemon",0,0,'d'},
-    {"configfile",1,0,'c'}
+    {"configfile",1,0,'c'},
+    {"version",0,0,'v'}
   };
   while ((opt = getopt_long(argc, argv, optString, longOpts, 0)) != -1){
     switch (opt){
@@ -294,13 +295,18 @@ void Util::Config::parseArgs(int argc, char ** argv){
       case 'd': daemon_mode = true; ignore_daemon = true; break;
       case 'c': configfile = optarg; break;
       case 'u': username = optarg; ignore_user = true; break;
+      case 'v':
+        printf("%s\n", TOSTRING(VERSION));
+        exit(1);
+        break;
       case 'h':
       case '?':
-        printf("Options: -h[elp], -?, -n[odaemon], -d[aemon], -p[ort] VAL, -i[nterface] VAL, -c[onfigfile] VAL, -u[sername] VAL\n");
+        printf("Options: -h[elp], -?, -v[ersion], -n[odaemon], -d[aemon], -p[ort] VAL, -i[nterface] VAL, -c[onfigfile] VAL, -u[sername] VAL\n");
         printf("Defaults:\n  interface: 0.0.0.0\n  port: %i\n  daemon mode: true\n  configfile: /etc/ddvtech.conf\n  username: root\n", listen_port);
         printf("Username root means no change to UID, no matter what the UID is.\n");
         printf("If the configfile exists, it is always loaded first. Commandline settings then overwrite the config file.\n");
         printf("\nThis process takes it directives from the %s section of the configfile.\n", confsection.c_str());
+        printf("This is %s version %s\n", argv[0], TOSTRING(VERSION));
         exit(1);
         break;
     }
@@ -343,5 +349,8 @@ void Util::Config::parseFile(){
 /// Does not change directory to root.
 /// Does redirect output to /dev/null
 void Util::Daemonize(){
+  #if DEBUG >= 3
+  fprintf(stderr, "Going into background mode...\n");
+  #endif
   daemon(1, 0);
 }
diff --git a/util/util.h b/util/util.h
index 31c8c3aa..a92b67f0 100644
--- a/util/util.h
+++ b/util/util.h
@@ -5,6 +5,9 @@
 #include <string>
 #include <map>
 
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+
 /// Contains utility code, not directly related to streaming media
 namespace Util{